1.關於dll
問題:如果有多個進程加載同一個dll,其中一個進程修改了dll的導出變量,是否影響其他進程中的變量值?
不會, 這算是一種寫實拷貝技術,修改的時候修改的不是原來 的內存,是新的內存。
一個進程啟動時,系統會為每個進程都預留了4G內存,不同進程的高2g內存都指向了物理內存條的系統領空(內核),低2G映射到物理內存條不同的位置,進程上的內存稱之為虛擬內存,內存條上內存稱為物理內存,原則上系統內存不能訪問,所以進程最多訪問2G內存。
進程中我們修改自己內存時,實際上修改的是映射上物理內存上的某個值
當不同進程加載一個dll時,A、B加載dll,dll首先加載到物理內存,
然后會映射dll內容分別到A、B進程的某個地址范圍。A、B讀內容時是互不影響的,但如果A修改dll,系統會把數據單獨拷貝出來(寫實拷貝),放在物理內存其他地方,A修改的是系統開辟的那塊新空間
所以不同進程之間,雖然訪問的是同一個dll的一個的導出的變量,
但實際上他們直接的讀寫和修改是相互不影響的,這叫做寫實拷貝
2.LoadLibrary和FreeLibrary計數器
操作系統為每一個庫文件維護各種的計數器(引用記數),每次使
用LoadLibrary裝載庫文件時候,計數器遞增,每次FreeLibrary時計數器遞減。
直到計數器減到0,也就是庫文件沒有被任何程序使用的時候,操
作系統才會將它從物理地址內存中真正釋放掉,否則只是某個進程的地址空間中解除內存映射關系。
每一個應用程序中使用FreeLibrary函數並不影響另一個exe使用
同一庫文件。
2.dllmain
微軟為dll提供了一個main函數(入口函數),當dll加載時,這
個函數會自動調用或執行(系統自動調用)。
dllMain主要用於dll的初始化和反初始化
BOOL WINAPI DllMain( HANDLE hinstDLL, //dll加載到進程的基質 (=HMODULE) DWORD dwReason, //表明dllmain什么時候被調用的 DLL_PROCESS_ATTACH - 進程加載dll, 當dll被映射到進程虛擬地址空間中 DLL_PROCESS_DETACH - 進程卸載dll, 當dll從進程虛擬地址空間中取消映射的時候 LPVOID lpvReserved);
測試dllmain:
BOOL WINAPI DllMain( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved ) { OutputDebugString("DLLMain"); return TRUE; } return TRUE ;告訴系統初始化成功
隱式加載 - 會彈出一個0xc0000142錯誤,並且會再次調用dllmain,並傳入DLL_PROCESS_DETACH
顯示加載 - loadlibrary會返回NULL,並且會再次調用dllmain,並傳入DLL_PROCESS_DETACH
加載這個dll
調試DLL的方法:
配置屬性->調試->命令,填入加載此dll的exe的路徑
就可選擇相應的exe調試dll 顯示加載 - loadli
3.DLL劫持
問題:
有個a.exe,加載了b.dll, 我有個自己的c.dll,如果在保證a的功能正常的前提下,讓a加載自己的c.dll?
答:c改名成b.dll,b.dll改名成bo.dll,c導出所有和bo.dll同名的函數,並全部轉發給bo.dll,從而實現讓a加載c.dll。
函數轉發: 雖然有導出函數名,但是本dll並未實現此函數,此函數的實現在其他dll里面
用Dependency Walker 打開user32可以看到:
所謂dll劫持就是:
病毒通過一些手段來劫持或者替換正常的DLL,欺騙正常程序加載預先准備好的惡意DLL。