1. 程式人生 > 實用技巧 >動態載入dll的實現

動態載入dll的實現

1.在目標程序中申請記憶體
2.向目標程序記憶體中寫入shellcode(沒有特徵,編碼比較麻煩)
3.建立遠執行緒執行shellcode

之前可以看到shellcode很難編寫還要去依賴庫,去字串區等等很麻煩,為了讓被注入程式碼更容易編寫,最好的方法就是通過dll來編寫

dll載入:
1.靜態呼叫:通過在我們的程式中新增標頭檔案,以及lib檔案來完成呼叫,前提就是獲取dll然後還有標頭檔案
2.動態呼叫:僅僅只需要一個dll即可完成呼叫

先寫個試一下

#include <Windows.h>

__declspec(dllexport) void Test(){
	MessageBox(NULL, NULL, NULL, NULL);
}

可以看到我們的Test,但是這種方式會對Test進行名稱粉碎,由c++編譯器新增的,需要告訴編譯器使用c的方式來命名函式,所以我們這麼寫,然後還需要指明函式引數的呼叫約定
1.__stdcall 標準 棧傳參,函式內部(被呼叫者)平棧
2. __cdecl c 棧傳參,函式外部(呼叫者)平棧
3. __fastcall 快速 暫存器傳參
4. __thiscall 類的thiscall呼叫約定,使用ecx暫存器來傳遞this指標

extern "C"{
	__declspec(dllexport) void __stdcall Test(){
		MessageBox(NULL, NULL, NULL, NULL);
	}
}

上面寫到__stdcall是函式內部平參這裡來看看

void __stdcall test(int n1, int n2){
	
	return;
}

int main()
{
	test(1, 2);

	return 0;
}

兩個返回8一個返回4

void __stdcall test(int n1, int n2){
002013C0  push        ebp  
002013C1  mov         ebp,esp  
002013C3  sub         esp,0C0h  
002013C9  push        ebx  
002013CA  push        esi  
002013CB  push        edi  
002013CC  lea         edi,[ebp-0C0h]  
002013D2  mov         ecx,30h  
002013D7  mov         eax,0CCCCCCCCh  
002013DC  rep stos    dword ptr es:[edi]  
	
	return;
}
002013DE  pop         edi  
002013DF  pop         esi  
002013E0  pop         ebx  
002013E1  mov         esp,ebp  
002013E3  pop         ebp  
002013E4  ret         8  

很明顯改變了引數返回的時候值就會變化而且是函式內部的變化所以是函式內部平棧,絕大部分的windows api都是stdcall,但是也有特例,比如wsprintf

char szBuf[256] = {0};
wsprintfA(szBuf,"%s","1234");

這裡很明顯因為他是由外界傳入的引數來決定多少,所以是函式外部平參

繼續回到動態載入dll
1.將目標dll載入到我們程序中

HMODULE hDll = LoadLibraryA("./TestDLL.dll");

返回值是模組控制代碼

這裡就可以看到我們的dll完全被載入到我們的記憶體裡面來了,所以說返回的模組控制代碼也就是當前dll在當前程序中的首地址,載入過程是由我們的作業系統來完成的(包括各節的擴充套件分配記憶體,重定位等等),有時候也可以自己寫loadlibraby因為用這個函式太官方了,自己寫就叫做記憶體載入,這是很多病毒的手法

2.計算函式的位置
都有個偏移

可以看到偏移是11122

LPVOID lp = GetProcAddress(hDll, "Test");

可以看到20000+11122 = 31122

也可以寫個def

LIBRARY
EXPORTS
Test

這裡得到的就是個函式指標

typedef void(*PFN_FPP)();
PFN_FPP lp = (PFN_FPP)GetProcAddress(hDll, "Test");

最後再呼叫就可以了

lp();

但是如何要求目標程序呼叫Loadlibrary來載入我們的dll,最後執行我們的dll中的匯出函式

可以看到Loadlibrary是存在於Kernel32.dll中的,所以先去找目標程序中的Kernel32.dll的位置,一般程式中都有Kernel32.dll這個,因為他是個很基本的dll
然後再找到該dll匯出的loadlibraryA或W函式的位置