e內核自帶flash方案要比webkit復雜
Ie的flash插件是個ocx,也是com組件。
Windows Com組件的加載過程如下:
1、 通過組件的DllRegisterServer注冊com組件,會在注冊表生成com組件的路徑,guid,progid,threadtype等等
2、 Client通過guid查找到注冊表中com組件的地址,loadlibrary加載這個組件,調用com組件的DllGetClassObject接口,此接口返回工廠類IClassFactory接口指針
3、 client通過IClassFactory接口,調用其createInstance接口或者QueryInterface接口可以獲取到真正的com應用接口
采用com庫函數CoCreateInstance,CoGetClassObject或者CoGetClassObjecFromUrl直接實現了上述過程
第一階段:
由於ie內核的封閉性,所以ie內核自帶flash方案一開始就確定了hookCoCreateInstance,CoGetClassObject、CoGetClassObjecFromUrl,修改ie內核加載flash組件的過程,讓ie內核加載我們自帶的flash組件
通過調試,發現ie內核是通過CoGetClassObject來加載flash ocx的,不調用CoCreateInstance,所以我們只hook了CoGetClassObject、CoGetClassObjecFromUrl。在hook CoGetClassObject,讓ie內核加載了我們的flash ocx,按道理是可以在瀏覽器上正常顯示flash插件了,但是事物的發展通常都是螺旋性的,雖然瀏覽器拿到了flash的IClassFactory,但是還是沒顯示成功
第二階段:
無奈之下只能分析其他瀏覽器,
在windbg中輸入
bp ole32!CoGetClassObject
bp Kernel32!LoadLibraryEx
該瀏覽器也hook了CoGetClassObject函數,通過ida分析和windbg動態調試,該瀏覽器的方案是和我們一致的,但是他可以,為什么我們不可以呢
通過processexplorer觀察發現,該瀏覽器進程內包含了兩個flash的ocx,通常一個進程加載同一個dll在進程空間只會有一個,但是為什么該瀏覽器有兩個呢,通過仔細發現,這里面有個dll是mapping的data,這個可以通過LoadLibraryEx,最后一個參數傳遞LOAD_LIBRARY_AS_DATAFILE或者LOAD_LIBRARY_AS_IMAGE_RESOURCE來實現,這樣就把dll或者exe通過資源的方式mapping到進程空間,段的屬性也是變成”只讀”而不是”執行”
通過這個發現,得到了新的思路,就是要把我們的flash也要再加載一次,通過data的方式,於是通過windbg在該瀏覽器的LoadLibraryEx,CreateFileMapping等處設置斷點,想通過這些函數的輸入參數來發現點什么,但是結果沒發現該瀏覽器直接LoadLibraryEx(LOAD_LIBRARY_AS_DATAFILE)或者CreateFileMapping
第三階段:
CreateFileMapping,在做文件映射mapping的時候,他的第一個參數是HANDLE hFile,,如果要用到handle,必定要先CreateFile。於是在我們的瀏覽器內hook了CreateFile,發現flash插件果然會來調用createfile來加載flash ocx的資源,這時候我們如果修改這個路徑,讓他調用我們自帶的flash ocx,這樣是可以了,我們瀏覽器可以通過我們自帶的flash播放了。但是createfile調用比較頻繁,hook這個函數在性能上不划算
再想想com的原理,com要找到自己的dll肯定要去注冊表找,在看下vc下調試的堆棧,在調用createfile前,flash會先調用oleaut32的接口
通過研究HRESULT LoadRegTypeLib(
REFGUID rguid,
unsigned short wVerMajor,
unsigned short wVerMinor,
LCID lcid,
ITypeLib FAR* FAR *pptlib
);
HRESULT LoadTypeLib(
const OLECHAR FAR *szFile,
ITypeLib FAR* FAR *pptlib
);
The function LoadRegTypeLib defers to LoadTypeLib to load the file.
我們得出了結論flash內部會調用LoadRegTypeLib,這個函數會去注冊表通過guid找到flash的ocx路徑,然后通過LoadTypeLib去加載這個ocx
所以我們hook了LoadRegTypeLib,在此函數內,調用LoadTypeLib來加載我們自帶的flash插件。由於LoadRegTypeLib調用很少,所以性能比hookcreatefile好
最后發現該瀏覽器也hook了這個函數,由於之前不知道這個函數是什么用的,所以走了些彎路。看來對com還不夠深入,歡迎兄弟們一起切磋討論