精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

網絡安全編程:遠程線程編程

安全
關于遠程線程的知識,本文介紹3個例子,分別是DLL的注入、卸載遠程DLL和不依賴DLL進行代碼注入。

[[385466]]

 Windows操作系統下,為了避免各個進程相互影響,每個進程地址空間都是被隔離的。所謂 “遠程線程”,并不是跨計算機的,而是跨進程的。簡單來說,就是進程A要在進程B中創建一個線程,這就叫遠程線程。

遠程線程被木馬、外掛等程序廣泛使用,反病毒軟件中也離不開遠程線程的技術。技術應用的兩面性取決于自己的個人行為意識,良性的技術學習對自己的人生發展是非常有好處的,就算談不上好處,至少不會給自己帶來不必要的麻煩。

關于遠程線程的知識,本文介紹3個例子,分別是DLL的注入、卸載遠程DLL和不依賴DLL進行代碼注入。

1. DLL遠程注入

木馬或病毒編寫的好壞取決于其隱藏的程度,而不在于其功能的多少。無論是木馬還是病毒,都是可執行程序。如果它們是EXE文件的話,那么在運行時必定會產生一個進程,就很容易被發現。為了不被發現,在編寫木馬或病毒時可以選擇將其編寫為DLL文件。DLL文件的運行不會單獨創建一個進程,它的運行被加載到進程的地址空間中,因此其隱蔽性相對較好。DLL文件如果不被進程加載又如何在進程的地址空間中運行呢?方式是強制讓某進程加載DLL文件到其地址空間中去,這個強制的手段就是現在要介紹的遠程線程。

創建遠程線程的函數CreateRemoteThread()的定義如下: 

  1. HANDLE CreateRemoteThread(  
  2.  HANDLE hProcess,  
  3.  LPSECURITY_ATTRIBUTES lpThreadAttributes,  
  4.  DWORD dwStackSize,  
  5.  LPTHREAD_START_ROUTINE lpStartAddress,  
  6.  LPVOID lpParameter,  
  7.  DWORD dwCreationFlags,  
  8.  LPDWORD lpThreadId  
  9. ); 

該函數的功能是創建一個遠程的線程。我們把CreateThread()函數和CreateRemoteThread()函數進行比較。對于CreateThread()函數來說,CreateRem oteThread()函數比其多了一個hProcess參數,該參數是指定要創建線程的進程句柄。其實CreateThread()函數的內容實現就是依賴于CreateRemoteThread()函數來完成的。CreateThread()函數的代碼實現如下: 

  1. /*  
  2.   * @implemented  
  3. */  
  4. HANDLE  
  5. WINAPI  
  6. CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,  
  7.   DWORD dwStackSize, 
  8.   LPTHREAD_START_ROUTINE lpStartAddress,  
  9.   LPVOID lpParameter,  
  10.   DWORD dwCreationFlags,  
  11.   LPDWORD lpThreadId)  
  12.  
  13.   /* 創建遠程線程  
  14.   return CreateRemoteThread(NtCurrentProcess(), 
  15.     lpThreadAttributes,  
  16.     dwStackSize,  
  17.     lpStartAddress, 
  18.     lpParameter,  
  19.     dwCreationFlags,  
  20.     lpThreadId);  

在上面的代碼中,NtGetCurrentProcess()函數的功能是獲得當前進程的句柄。

CreateRemoteThread()函數是給其他進程創建線程使用的,其第一個參數是指定某進程的句柄,獲取進程的句柄使用API函數OpenProcess(),該函數需要提供PID作為參數。

除了hProcess參數以外,剩余的關鍵參數就只有lpStartAddress和lpParameter兩個了。lpStartAddress指定線程函數的地址,lpParameter指定傳遞給線程函數的參數。前面提到,每個進程的地址空間是隔離的,那么新創建的線程函數的地址也應該在目標進程中,而不應該在調用CreateRemoteThread()函數的進程中。同樣,傳遞給線程函數的參數也應該在目標進程中。

如何讓線程函數的地址在目標進程中呢?如何讓線程函數的參數也可以傳遞到目標進程中呢?在討論這個問題以前,先來考慮線程函數要完成的功能。這里主要完成的功能是注入一個DLL文件到目標進程中,那么線程函數的功能就是加載DLL文件。加載DLL文件使用的是LoadLibrary()函數。LoadLibrary()函數的定義: 

  1. HMODULE LoadLibrary(  
  2.  LPCTSTR lpFileName  
  3. );  
  4. 看一下線程函數的定義格式,具體如下: 
  5. DWORD WINAPI ThreadProc(  
  6.  LPVOID lpParameter  
  7. ); 

比較兩個函數可以發現,除了函數的返回值類型和參數類型以外,其函數格式是相同的。這里只考慮其相同的部分。因為其函數的格式相同,首先調用約定相同,都是WINAPI(也就是__stdcall方式);其次函數個數相同,都只有一個。那么,可以直接把LoadLibrary()函數作為線程函數創建到指定的進程中。LoadLibrary()的參數是欲加載的DLL文件的完整路徑,只要在CreateRemoteThread()函數中賦值一個指向DLL文件完整路徑的指針給LoadLibrary()函數即可。這樣使用CreateRemoteThread()函數就可以創建一個遠程線程了。不過,還有兩個問題沒有解決,首先是如何將LoadLibrary()函數的地址放到目標進程空間中讓CreateRemoteThread()調用,其次是傳遞給LoadLibrary()函數的參數也需要在目標進程空間中,并且要通過CreateRemoteThread()函數指定給LoadLibrary()函數。

首先解決第1個問題,即如何將LoadLibrary()函數的地址放到目標進程空間中。LoadLibrary()函數是系統中的Kernel32.dll的導出函數,Kernel32.dll這個DLL文件在任何進程中的加載位置都是相同的,也就是說,LoadLibrary()函數的地址在任何進程中的地址都是相同的。因此,只要在進程中獲得LoadLibrary()函數的地址,那么該地址在目標進程中也可以使用。CreateRemoteThread()函數的線程地址參數直接傳遞LoadLibrary()函數的地址即可。

其次解決第2個問題,即如何將欲加載的DLL文件完整路徑寫入目標進程中。這需要借助WriteProcessMemory()函數,其定義如下: 

  1. BOOL WriteProcessMemory(  
  2.  HANDLE hProcess, // handle to process  
  3.  LPVOID lpBaseAddress, // base of memory area  
  4.  LPVOID lpBuffer, // data buffer  
  5.  DWORD nSize, // number of bytes to write  
  6.  LPDWORD lpNumberOfBytesWritten // number of bytes written  
  7. ); 

該函數的功能是把lpBuffer中的內容寫到進程句柄是hProcess進程的lpBaseAddress地址處,寫入長度為nSize。

參數說明如下。

hProcess:該參數是指定進程的進程句柄。

lpBaseAddress:該參數是指定寫入目標進程內存的起始地址。

lpBuffer:該參數是要寫入目標進程內存的緩沖區起始地址。

nSize:該參數是指定寫入目標內存中的緩沖區的長度。

lpNumberOfBytesWritten:該參數用于接收實際寫入內容的長度。

該函數的功能非常強大,比如在破解方面,用該函數可以實現一個“內存補丁”;在開發方面,該函數可以用于修改目標進程中指定的值(比如游戲修改器可以修改游戲中的錢、紅、藍等)。

使用該函數可以把DLL文件的完整路徑寫入到目標進程的內存地址中,這樣就可以在目標進程中用LoadLibrary()函數加載指定的DLL文件了。解決了上面的兩個問題,還有第3個問題需要解決。WriteProcessMemory()函數的第2個參數是指定寫入目標進程內存的緩沖區起始地址。這個地址在目標進程中,那么這個地址在目標進程的哪個位置呢?目標進程中的內存塊允許把DLL文件的路徑寫進去嗎?

第3個要解決的問題是如何確定應該將DLL文件的完整路徑寫入目標進程的哪個地址。對于目標進程來說,事先是不會準備一塊地址讓用戶進行寫入的,用戶能做的是自己在目標進程中申請一塊內存,然后把DLL文件的路徑進行寫入,寫入在目標進程新申請到的內存空間中。在目標進程中申請內存的函數是VirtualAllocEx(),其定義如下: 

  1. LPVOID VirtualAllocEx(  
  2.  HANDLE hProcess,  
  3.  LPVOID lpAddress,  
  4.  SIZE_T dwSize,  
  5.  DWORD flAllocationType,  
  6.  DWORD flProtect  
  7. ); 

VirtualAllocEx()函數的參數說明如下。

hProcess:該參數是指定進程的進程句柄。

lpAddress:該參數是指在目標進程中申請內存的起始地址。

dwSize:該參數是指在目標進程中申請內存的長度。

flAllocationType:該參數指定申請內存的狀態類型。

flProtect:該參數指定申請內存的屬性。

該函數的返回值是在目標進程申請到的內存塊的起始地址。

到此,關于編寫一個DLL注入的所有知識都已經具備了。現在開始編寫一個DLL注入的工具,其界面如圖1所示。

圖1  DLL注入/卸載器

該工具有2個作用,分別是注入DLL和卸載被注入的DLL。關于卸載被注入的DLL的功能,將在后面進行介紹。在界面上要求輸入兩部分內容,第1部分是欲注入的DLL文件的完整路徑(一定要是完整路徑),第2部分是進程的名稱。

首先看一下關于界面的操作,代碼如下: 

  1. void CInjectDllDlg::OnBtnInject()  
  2.  
  3.   // 添加處理程序代碼  
  4.   char szDllName[MAX_PATH] = { 0 };  
  5.   char szProcessName[MAXBYTE] = { 0 };  
  6.   DWORD dwPid = 0 
  7.   GetDlgItemText(IDC_EDIT_DLLFILE, szDllName, MAX_PATH);  
  8.   GetDlgItemText(IDC_EDIT_PROCESSNAME, szProcessName, MAXBYTE);  
  9.   // 由進程名獲得 PID  
  10.   dwPid = GetProcId(szProcessName);  
  11.   // 注入 szDllName 到 dwPid  
  12.   InjectDll(dwPid, szDllName);  

代碼中調用了另外兩個函數,第1個是由進程名獲得PID的函數,第2個是用于DLL注入的函數。GetProcId()函數的代碼如下: 

  1. DWORD CInjectDllDlg::GetProcId(char *szProcessName)  
  2.  
  3.   BOOL bRet;  
  4.   PROCESSENTRY32 pe32;  
  5.   HANDLE hSnap;  
  6.   hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);  
  7.   pe32.dwSize = sizeof(pe32);  
  8.   bRet = Process32First(hSnap, &pe32);  
  9.   while ( bRet )  
  10.   {  
  11.     // strupr()函數是將字符串轉化為大寫  
  12.     if ( lstrcmp(strupr(pe32.szExeFile),strupr(szProcessName)) == 0 )  
  13.     {  
  14.       return pe32.th32ProcessID;  
  15.     }  
  16.     bRet = Process32Next(hSnap, &pe32);  
  17.   }  
  18.   return 0;  
  19. } +

InjectDll()函數的代碼如下: 

  1. VOID CInjectDllDlg::InjectDll(DWORD dwPid, char *szDllName)  
  2.  
  3.   if ( dwPid == 0 || lstrlen(szDllName) == 0 ) 
  4.   {  
  5.     return ;  
  6.   }  
  7.   char *pFunName = "LoadLibraryA" 
  8.   // 打開目標進程  
  9.   HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwPid);  
  10.   if ( hProcess == NULL )  
  11.   {  
  12.     return ;  
  13.   }  
  14.   // 計算欲注入 DLL 文件完整路徑的長度  
  15.   int nDllLen = lstrlen(szDllName) + sizeof(char);  
  16.   // 在目標進程申請一塊長度為 nDllLen 大小的內存空間  
  17.   PVOID pDllAddr = VirtualAllocEx(hProcess,NULL, nDllLen,MEM_COMMIT,PAGE_READWRITE);  
  18.   if ( pDllAddr == NULL )  
  19.   {  
  20.     CloseHandle(hProcess);  
  21.     return ;  
  22.   }  
  23.   DWORD dwWriteNum = 0 
  24.   // 將欲注入 DLL 文件的完整路徑寫入在目標進程中申請的空間內  
  25.   WriteProcessMemory(hProcess, pDllAddr, szDllName,nDllLen, &dwWriteNum);  
  26.   // 獲得 LoadLibraryA()函數的地址  
  27.   FARPROC pFunAddr = GetProcAddress(GetModuleHandle("kernel32.dll"),pFunName);  
  28.   // 創建遠程線程  
  29.   HANDLE hThread = CreateRemoteThread(hProcess,NULL, 0,(LPTHREAD_START_ROUTINE)pFunAddr,pDllAddr, 0, NULL);  
  30.   WaitForSingleObject(hThread, INFINITE);  
  31.   CloseHandle(hThread);  
  32.   CloseHandle(hProcess);  

InjectDll()函數有 2 個參數,分別是目標進程的 ID 值和要被注入的 DLL 文件的完整路徑。在代碼中獲得的不是 LoadLibrary()函數的地址,而是 LoadLibraryA()函數的地址。在系統中其實沒有 LoadLibrary()函數,有的只是 LoadLibraryA()和 LoadLibraryW()兩個函數。這兩個函數分別針對 ANSI 字符串和 UNICODE 字符串。而 LoadLibrary()函數只是一個宏。在編寫程序的時候,直接使用該宏是可以的。如果要獲取 LoadLibrary()函數的地址,就要明確指定是獲取 LoadLibraryA()還是 LoadLibraryW()。

LoadLibrary()宏定義如下: 

  1. #ifdef UNICODE  
  2. #define LoadLibrary LoadLibraryW  
  3. #else  
  4. #define LoadLibrary LoadLibraryA  
  5. #endif // !UNICODE 

只要涉及字符串的函數,都會有相應的ANSI版本和UNICODE版本;其余不涉及字符串的函數,沒有ANSI版本和UNICODE版本的區別。

為了測試DLL加載是否成功,在代碼的DllMain()函數中加入如下代碼: 

  1. case DLL_PROCESS_ATTACH:  
  2.  
  3.   MsgBox("!DLL_PROCESS_ATTACH!");  
  4.   break;  
  5. }  

現在測試一下注入的效果,如圖2和圖3所示。

圖2  DLL文件被注入成功的提示

圖3  查看進程中的DLL列表確認被裝載成功

在圖2中,彈出的對話框是DLL程序在DLL_PROCESS_ATTACH時出現的。其所在的進程為notepad.exe。從圖2中可以看出,彈出提示框的標題處是notepad.exe進程的路徑。圖3是用工具查看進程中所加載的DLL文件列表,可以看出,通過注入工具注入的DLL文件已經被加載到notepad.exe的進程空間中。

如果要對系統進程進行注入的話,由于進程權限的關系是無法注入成功的。在打開目標進程時用到了OpenProcess()函數,由于權限不夠,會導致無法打開進程并獲得進程句柄。通過調整當前進程的權限,可以打開系統進程并獲得進程句柄。如果在Win8或更高版本上運行注入程序的話,需要選中注入工具單擊右鍵,選擇“以管理員身份運行”才可以完成注入。

2. 卸載被注入的DLL文件

DLL注入如果應用在木馬方面,危害很大,這里完成一個卸載被注入DLL的程序。卸載被注入DLL程序的思路和注入的思路是一樣的,而且代碼的改動也非常小。區別在于現在的功能是卸載,而不是注入。

DLL卸載使用的API函數是FreeLiabrary(),其定義如下: 

  1. BOOL FreeLibrary(  
  2.  HMODULE hModule // handle to DLL module  
  3. ); 

該函數的參數是要卸載的模塊的句柄。

FreeLibrary()函數使用的模塊句柄可以通過Module32First()和Module32Next()兩個函數獲取。在使用Module32First()和Module32Next()兩個函數的時候,需要用到MODULEENTRY32結構體,該結構體中保存了模塊的句柄。MODULEENTRY32結構體的定義如下: 

  1. typedef struct tagMODULEENTRY32 {  
  2.  DWORD dwSize;  
  3.  DWORD th32ModuleID;  
  4.  DWORD th32ProcessID;  
  5.  DWORD GlblcntUsage;  
  6.  DWORD ProccntUsage;  
  7.  BYTE * modBaseAddr;  
  8.  DWORD modBaseSize;  
  9.  HMODULE hModule;  
  10.  TCHAR szModule[MAX_MODULE_NAME32 + 1];  
  11.  TCHAR szExePath[MAX_PATH];  
  12.  } MODULEENTRY32;  
  13. typedef MODULEENTRY32 *PMODULEENTRY32; 

該結構體中的hModule為模塊的句柄,szModule為模塊的名稱,szExePath是完整的模塊的名稱(所謂完整,包括路徑和模塊名稱)。

卸載遠程進程中DLL模塊的代碼如下: 

  1. VOID CInjectDllDlg::UnInjectDll(DWORD dwPid, char *szDllName)  
  2.  
  3.   if ( dwPid == 0 || lstrlen(szDllName) == 0 )  
  4.   { 
  5.     return ;  
  6.   }  
  7.   HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,dwPid);  
  8.   MODULEENTRY32 me32;  
  9.   me32.dwSize = sizeof(me32);  
  10.   // 查找匹配的進程名稱  
  11.   BOOL bRet = Module32First(hSnap, &me32);  
  12.   while ( bRet )  
  13.   {  
  14.     if ( lstrcmp(strupr(me32.szExePath),  
  15.     strupr(szDllName)) == 0 )  
  16.     {  
  17.       break;  
  18.     }  
  19.     bRet = Module32Next(hSnap, &me32);  
  20.   }  
  21.   CloseHandle(hSnap);  
  22.   char *pFunName = "FreeLibrary" 
  23.   HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwPid);  
  24.   if ( hProcess == NULL )  
  25.   {  
  26.     return ;  
  27.   }  
  28.   FARPROC pFunAddr = GetProcAddress(GetModuleHandle("kernel32.dll"),pFunName);  
  29.   HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,  
  30.     (LPTHREAD_START_ROUTINE)pFunAddr,me32.hModule, 0, NULL);  
  31.   WaitForSingleObject(hThread, INFINITE);  
  32.   CloseHandle(hThread);  
  33.   CloseHandle(hProcess);  

卸載遠程進程中DLL的實現代碼比DLL注入的代碼要簡單,這里就不做過多的介紹了。

3. 無DLL的代碼注入

DLL文件的注入與卸載都完成了,整個注入與卸載的過程其實就是讓遠程線程執行一次LoadLibrary()函數或FreeLibrary()函數。遠程線程裝載一個DLL文件,通過DllMain()調用DLL中的具體功能代碼,這樣注入DLL后就可以讓DLL做很多事情了。是否可以不依賴DLL文件直接向目標進程寫入要執行的代碼,以完成特定的功能呢?答案是可以。

要在目標進程中完成一定的功能,就需要使用相關的API函數,不同的API函數實現在不同的DLL中。Kernel32.dll文件在每個進程中的地址是相同的,但是并不代表其他DLL文件在每個進程中的地址都是一樣的。這樣,在目標進程中調用API函數時,必須使用LoadLibrary()函數和GetProcAddress()函數動態調用用到的每個API函數。把想要使用的API函數及API函數所在的DLL文件都封裝到一個結構體中,直接寫入目標進程的空間中。同時也直接把要在遠程執行的代碼也寫入目標進程的內存空間中,最后調用CreateRemoteThread()函數即可將其運行。

通過實現一個簡單的例子讓遠程線程彈出一個提示對話框,但是不借助于DLL。本程序所使用的API函數在前面都已經介紹過了。根據前面的步驟先來定義一個結構體,其定義如下: 

  1. #define STRLEN 20  
  2. typedef struct _DATA  
  3.  
  4.  DWORD dwLoadLibrary;  
  5.  DWORD dwGetProcAddress;  
  6.  DWORD dwGetModuleHandle;  
  7.  DWORD dwGetModuleFileName;  
  8.  char User32Dll[STRLEN];  
  9.  char MessageBox[STRLEN];  
  10.  char Str[STRLEN];  
  11. }DATA, *PDATA; 

該結構體中保存了LoadLibraryA()、GetProcAddress()、GetModuleHandle()和GetModu leFileName()四個API函數的地址。這四個API函數都屬于Kernel32.dll的導出函數,因此可以在注入前進行獲取。User32Dll中保存“User32.dll”字符串,因為MessageBoxA()函數是由User32.dll的導出函數。Str中保存的是通過MessageBoxA()函數彈出的字符串。

注入代碼類似于前面介紹的注入代碼,不過需要在注入代碼中定義一個結構體變量,并進行相應的初始化,代碼如下: 

  1. VOID CNoDllInjectDlg::InjectCode(DWORD dwPid)  
  2.  
  3.   // 打開進程并獲取進程句柄  
  4.   HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwPid);  
  5.   if ( hProcess == NULL )  
  6.   {  
  7.     return ;  
  8.   }  
  9.   DATA Data = { 0 };  
  10.   // 獲取 kernel32.dll 中相關的導出函數  
  11.   Data.dwLoadLibrary = (DWORD)GetProcAddress(  
  12.     GetModuleHandle("kernel32.dll"),"LoadLibraryA");  
  13.   Data.dwGetProcAddress = (DWORD)GetProcAddress(  
  14.     GetModuleHandle("kernel32.dll"),"GetProcAddress");  
  15.   Data.dwGetModuleHandle = (DWORD)GetProcAddress(  
  16.     GetModuleHandle("kernel32.dll"),"GetModuleHandleA");  
  17.   Data.dwGetModuleFileName = (DWORD)GetProcAddress(  
  18.     GetModuleHandle("kernel32.dll"),"GetModuleFileNameA");  
  19.   // 需要的其他 DLL 和導出函數  
  20.   lstrcpy(Data.User32Dll, "user32.dll");  
  21.   lstrcpy(Data.MessageBox, "MessageBoxA");  
  22.   // MessageBoxA()彈出的字符串  
  23.   lstrcpy(Data.Str, "Inject Code !!!");  
  24.   // 在目標進程申請空間  
  25.   LPVOID lpData = VirtualAllocEx(hProcess, NULL, sizeof(Data),  
  26.     MEM_COMMIT | MEM_RELEASE,PAGE_READWRITE);  
  27.   DWORD dwWriteNum = 0 
  28.   WriteProcessMemory(hProcess, lpData, &Data,  
  29.     sizeof(Data), &dwWriteNum);  
  30.   // 在目標進程空間申請的用于保存代碼的長度  
  31.   DWORD dwFunSize = 0x4000 
  32.   LPVOID lpCode = VirtualAllocEx(hProcess, NULL, dwFunSize,  
  33.     MEM_COMMIT,PAGE_EXECUTE_READWRITE); 
  34.   WriteProcessMemory(hProcess, lpCode, &RemoteThreadProc,  
  35.     dwFunSize, &dwWriteNum); 
  36.   HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0 
  37.     (LPTHREAD_START_ROUTINE)lpCode,lpData, 0, NULL);  
  38.   WaitForSingleObject(hThread, INFINITE);  
  39.   CloseHandle(hThread);  
  40.   CloseHandle(hProcess);  

上面的注入代碼除了對結構體變量初始化外,還將線程函數代碼寫入目標進程空間的內存中。線程函數的代碼如下: 

  1. DWORD WINAPI RemoteThreadProc(LPVOID lpParam)  
  2.  
  3.   PDATA pData = (PDATA)lpParam;  
  4.   // 定義 API 函數原型  
  5.   HMODULE (__stdcall *MyLoadLibrary)(LPCTSTR); 
  6.    FARPROC (__stdcall *MyGetProcAddress)(HMODULE, LPCSTR);  
  7.   HMODULE (__stdcall *MyGetModuleHandle)(LPCTSTR);  
  8.   int (__stdcall *MyMessageBox)(HWND, LPCTSTR, LPCTSTR, UINT);  
  9.   DWORD (__stdcall *MyGetModuleFileName)(HMODULE, LPTSTR, DWORD);  
  10.   // 對各函數地址進行賦值  
  11.   MyLoadLibrary = (HMODULE (__stdcall *)(LPCTSTR))  
  12.     pData->dwLoadLibrary;  
  13.   MyGetProcAddress = (FARPROC (__stdcall *)(HMODULE, LPCSTR))  
  14.     pData->dwGetProcAddress;  
  15.   MyGetModuleHandle = (HMODULE (__stdcall *)(LPCSTR))  
  16.     pData->dwGetModuleHandle;  
  17.   MyGetModuleFileName = (DWORD (__stdcall *)(HMODULE, LPTSTR, DWORD))  
  18.     pData->dwGetModuleFileName;  
  19.   // 加載 User32.dll  
  20.   HMODULE hModule = MyLoadLibrary(pData->User32Dll);  
  21.   // 獲得 MessageBoxA 函數的地址  
  22.   MyMessageBox = (int (__stdcall *)(HWND, LPCTSTR, LPCTSTR, UINT))  
  23.     MyGetProcAddress(hModule, pData->MessageBox);  
  24.   char szModuleFileName[MAX_PATH] = { 0 };  
  25.   MyGetModuleFileName(NULL, szModuleFileName, MAX_PATH);  
  26.   MyMessageBox(NULL, pData->Str, szModuleFileName, MB_OK);  
  27.   return 0; 
  28. }

上面就是無DLL注入的全部代碼,編譯連接并運行它。啟動一個記事本程序來進行測試,可惜報錯了。問題出在哪里呢?VC6的默認編譯是Debug版本,這樣會加入很多調試信息。而某些調試信息并不存在于代碼中,而是在其他DLL模塊中。這樣,當執行到調試相關的代碼時會訪問不存在的DLL模塊中的代碼,就導致了報錯。

將以上代碼使用Release方式進行編譯連接,然后可以無誤地執行,如圖4所示。

圖4  Release方式下編譯注入成功

編譯的Debug版也可以進行無DLL的注入,只是實現起來略有不同。 

 

責任編輯:龐桂玉 來源: 計算機與網絡安全
相關推薦

2021-03-03 12:20:42

網絡安全DLL編程

2021-03-01 11:20:13

網絡安全多線程代碼

2021-01-26 13:45:03

網絡安全Winsock編程

2021-02-21 18:19:43

網絡安全網絡安全編程創建進程

2021-02-23 10:20:07

網絡安全進程代碼

2016-10-10 00:18:27

2021-06-18 09:55:09

網絡安全目錄監控

2021-04-30 18:50:44

網絡安全PE編程添加節區

2021-04-26 10:32:38

網絡安全PE編程工具

2021-01-18 10:35:18

網絡安全Windows代碼

2021-05-12 14:57:13

網絡安全密碼代碼

2021-02-04 10:50:11

網絡安全非阻塞模Winsock編程

2021-06-24 08:37:34

網絡安全內核代碼

2021-06-15 11:16:24

網絡安全U盤軟件

2021-04-19 10:26:41

網絡安全PE文件

2021-05-24 11:55:55

網絡安全Windows鉤子函數

2021-04-28 14:35:48

網絡安全PE編程代碼

2021-04-25 21:25:09

網絡安全網絡安全編程PE編程

2021-06-11 13:40:17

網絡安全專殺工具病毒

2021-02-05 15:20:06

網絡安全套接字命令
點贊
收藏

51CTO技術棧公眾號

99免费在线观看视频| 日韩av网站导航| 一本色道久久99精品综合| 自拍偷拍第八页| 亚洲久久久久| 精品国产a毛片| 国产一级片黄色| 大片免费在线看视频| 国产成人精品免费一区二区| 81精品国产乱码久久久久久| 国产91丝袜美女在线播放| 亚洲国产伊人| 欧美日韩亚洲高清| 亚洲一区二区在| 视频污在线观看| 激情深爱一区二区| 57pao成人国产永久免费| 亚洲欧美精品久久| 一道在线中文一区二区三区| 91精品久久久久久蜜臀| 50路60路老熟妇啪啪| 青草青在线视频| 国产精品久久三| 久久久久久一区| 国产黄色一区二区| 免费观看成人av| 欧美一级淫片丝袜脚交| 亚洲av鲁丝一区二区三区| 加勒比久久综合| 日韩成人在线观看| 逼特逼视频在线观看| 天天综合91| 欧美在线观看一区二区| 黄色国产一级视频| 免费在线中文字幕| 亚洲日本中文字幕区| 色播五月综合| 欧美男男激情freegay| 国产91精品一区二区麻豆亚洲| 国内精品400部情侣激情| 成人免费精品动漫网站| 色777狠狠狠综合伊人| 亚洲人成电影网站色www| 熟妇高潮一区二区| 最新国产精品精品视频| 91精品国产综合久久福利| 中文字幕第88页| а√天堂资源国产精品| 日韩欧美在线字幕| 国产日产欧美视频| 英国三级经典在线观看| 天天影视网天天综合色在线播放| 天天操天天干天天玩| 欧美激情视频在线播放| 国产精品电影一区二区| 性欧美.com| 91社区在线高清| 欧美激情综合网| 亚洲国产精品视频一区| av播放在线| 国产精品成人在线观看| 制服国产精品| 91黄色在线| 亚洲一级电影视频| 波多野结衣之无限发射| 中文在线中文资源| 欧美伊人久久久久久午夜久久久久| 国产a级一级片| 欧洲一区二区三区精品| 欧美主播一区二区三区美女| 2025韩国理伦片在线观看| 91精品国产自产观看在线| 欧美一区二区三区在线观看| 少妇熟女视频一区二区三区| 欧美有码在线| 在线日韩日本国产亚洲| 亚洲精品久久久久久国| 国产精品久久| 欧美在线观看视频| 中文字幕在线观看国产| 国产精品白丝jk白祙喷水网站 | 成人综合在线视频| 欧美大肚乱孕交hd孕妇| 少妇激情一区二区三区视频| 中国av一区| 日韩亚洲第一页| 久久午夜无码鲁丝片| 西西裸体人体做爰大胆久久久| 97成人在线视频| 中文字幕精品无码亚| 国产成人综合在线| 欧美极品jizzhd欧美| 五月婷婷在线观看| 午夜精品福利在线| 校园春色 亚洲色图| 91精品国产乱码久久久竹菊| 国产视频一区在线| 极品久久久久久| 欧美一级播放| 91视频免费进入| 好男人免费精品视频| 亚洲精品高清视频在线观看| 国产成人久久婷婷精品流白浆| 日本久久一区| 亚洲精品二三区| 国内毛片毛片毛片毛片毛片| 99精品国产福利在线观看免费| 欧美一级大片视频| 精品乱子伦一区二区| 国产清纯在线一区二区www| 国产精品三级一区二区| av成人亚洲| 欧美精品一区二区三区高清aⅴ | 91精品国产自产在线丝袜啪| 亚洲区一区二区| 国产精品18p| 久草中文综合在线| 欧美二区三区在线| 国产精品探花在线| 678五月天丁香亚洲综合网| 91精品人妻一区二区| 欧美视频在线观看| 国产精品欧美风情| 性xxxfllreexxx少妇| 亚洲免费在线视频一区 二区| 一女被多男玩喷潮视频| 亚洲国产精品免费视频| 中文字幕亚洲综合久久| 日本免费在线观看视频| av影院午夜一区| 国产在线xxxx| 日韩av综合| 久久成年人视频| 国产又粗又黄又爽的视频| 国产色产综合色产在线视频| 男女高潮又爽又黄又无遮挡| 凹凸成人在线| 欧美巨大黑人极品精男| 国产精品爽爽久久| 中文字幕一区二区三区av | 日本成人中文字幕在线视频| 狠狠色综合网站久久久久久久| 超碰在线无需免费| 在线播放欧美女士性生活| 国产视频123区| 奇米精品一区二区三区四区| 日韩欧美亚洲日产国| 亚洲高清黄色| 国产亚洲视频在线观看| 亚洲av无码不卡| 国产欧美精品一区二区色综合 | 高清国产一区二区| 亚洲色婷婷久久精品av蜜桃| 精品一级视频| 色综合久久悠悠| 人妻视频一区二区三区| 婷婷综合五月天| 一级性生活毛片| 人人精品人人爱| 亚洲一区二区在线免费观看| 国产精品久久久久久久久免费高清 | 青草在线视频在线观看| 欧美一级二级三级蜜桃| 国产亚洲精品av| av影院午夜一区| 男人靠女人免费视频网站| 免费看日本一区二区| 国产精品免费观看在线| www免费在线观看| 欧美大片在线观看一区| xxxx.国产| 欧美激情一区二区三区不卡| 久久成年人网站| 精品动漫3d一区二区三区免费| 成人免费观看网站| 中国字幕a在线看韩国电影| 中文字幕日韩在线视频| 精品人妻一区二区三区换脸明星| 亚洲精品国产品国语在线app| 少妇精品无码一区二区| 亚洲男女自偷自拍| 视频一区视频二区视频三区高| 高清欧美日韩| 久久久久女教师免费一区| 欧洲一区av| 欧美一区二区三区免费观看视频| 九九免费精品视频| 国产午夜精品一区二区三区嫩草| 青青草原av在线播放| 香蕉av一区二区| 久久99久久精品国产| 亚洲国产天堂| 日本成人在线视频网址| 国产美女在线观看| 亚洲欧美日韩国产中文专区| 99久久久无码国产精品免费| 欧美午夜xxx| 欧美成人片在线观看| 国产亚洲视频系列| 亚洲精品乱码久久久久久蜜桃欧美| 亚洲一区二区毛片| 国产精品99久久久久久大便| 欧美亚洲国产日韩| 91免费欧美精品| 丝袜美腿诱惑一区二区三区| 久久91超碰青草是什么| 你懂的视频在线| 日韩精品最新网址| 亚洲一区二区三区网站| 懂色av一区二区三区| 手机在线免费看毛片| 国产网红主播福利一区二区| 香蕉视频污视频| 国内精品免费**视频| 欧美日韩亚洲一二三| 亚洲视频成人| 少妇一晚三次一区二区三区| 欧美3p在线观看| 欧美一区二区三区四区五区六区| 国产精品亚洲一区二区在线观看| 91av网站在线播放| 最新黄网在线观看| 日韩有码在线观看| 福利在线观看| 亚洲深夜福利在线| 深夜福利视频在线观看| 精品久久久久久久久久久久久久久久久| 黄色一级视频免费看| 午夜精品在线视频一区| 久久免费视频精品| 一区二区三区中文字幕精品精品| 日本欧美一区二区三区不卡视频| 99久久er热在这里只有精品66| 日韩av加勒比| 狠狠色狠狠色综合| 第一区免费在线观看| 久久精品二区亚洲w码| 99视频精品免费| 久久精品九九| 午夜免费一区二区| 青娱乐精品视频| 欧美特级aaa| 毛片av中文字幕一区二区| 国产一级特黄a大片免费| 日韩高清不卡一区二区| 欧美日韩在线中文| 欧美一级网站| 国产精品久久久久9999小说| 日韩一区精品视频| 五月婷婷丁香综合网| 蜜桃视频第一区免费观看| 中日韩av在线播放| 韩国一区二区视频| 欧美xxxx黑人| 成人午夜伦理影院| 日韩av无码一区二区三区不卡| 国产·精品毛片| 午夜不卡久久精品无码免费| 99精品视频一区二区| 国产特级黄色录像| 国产精品日韩成人| 一区二区三区四区五区| 亚洲综合成人在线| av资源免费观看| 欧美日韩一级黄| 国产ts人妖调教重口男| 亚洲а∨天堂久久精品9966| 日本韩国精品一区二区| 中文字幕不卡av| av网站在线免费| 91精品国产91久久久久久| 三级成人在线| 亚洲www在线| 久久a级毛片毛片免费观看| 欧美视频1区| 久久久国产精品| 日本福利视频一区| 久久综合狠狠| 日本高清免费观看| 久久综合一区二区| 国产传媒免费在线观看| 亚洲成人一区二区在线观看| 中文字幕手机在线视频| 欧美一区二区高清| 欧美女v视频| 欧美大成色www永久网站婷| 女人让男人操自己视频在线观看 | 国产成人综合在线观看| 中文字字幕码一二三区| 国产精品国产成人国产三级 | 欧美a级片网站| 久久久久久久久久网| 日韩国产精品久久久久久亚洲| 看看黄色一级片| 99精品在线观看视频| 欧美88888| 欧美日韩在线视频首页| 国产免费视频一区二区三区| 亚洲美女自拍视频| 污污视频在线看| 国产精品久久久久久久久久东京 | 久久精品视频8| 欧美日韩在线播| 五月婷婷丁香网| 欧美精品一本久久男人的天堂| 性欧美freesex顶级少妇| 91视频88av| 第一社区sis001原创亚洲| 婷婷五月综合缴情在线视频| 精品一区二区三区久久久| 精品成人av一区二区三区| 亚洲国产一区二区视频| 国产精品人人妻人人爽| 亚洲网站视频福利| 黄色在线观看www| 成人av播放| 国产精品成人a在线观看| 日韩精品无码一区二区三区免费| 国产乱国产乱300精品| 日本欧美一区二区三区不卡视频| 亚洲不卡av一区二区三区| 国产视频www| 中文字幕国产精品久久| 免费电影日韩网站| 精品无人区一区二区三区竹菊 | 久久久激情视频| 日韩三级视频在线| 精品久久久久久亚洲综合网| 黄网站在线播放| 国产精品第一第二| 久久成人高清| 成人在线观看a| 国产亚洲欧美在线| 精品人妻一区二区三区潮喷在线 | 一级毛片视频在线| 国产精品黄色av| 国产亚洲一区二区三区不卡| 激情六月丁香婷婷| 久久婷婷成人综合色| 日韩黄色在线播放| 精品伊人久久97| 高潮一区二区| 欧美日韩国产综合视频在线| 免费视频一区| 黄免费在线观看| 欧美亚洲一区三区| 日本最新在线视频| 国产日韩在线看片| 亚洲精品一区二区妖精| 亚洲国产欧美91| 亚洲国产精品久久不卡毛片| 黄色小视频免费在线观看| 97国产suv精品一区二区62| 欧美一性一交| 九一精品在线观看| 中文字幕一区二区三区蜜月| 国产乱码一区二区| 欧美丰满少妇xxxxx| 国产精品毛片视频| 国产精品后入内射日本在线观看| av网站免费线看精品| www亚洲视频| 日韩资源在线观看| 国产精选久久| 91视频 -- 69xx| 欧美激情综合在线| av网站免费大全| 69久久夜色精品国产69| 国产一区二区精品福利地址| 亚洲国产成人va在线观看麻豆| 中文字幕一区日韩精品欧美| 国产xxxx在线观看| 欧美亚洲国产另类| 日韩三级在线| 师生出轨h灌满了1v1| 欧美午夜电影在线| 国产原创在线观看| 精品无码久久久久久久动漫| 青草av.久久免费一区| 久操免费在线视频| 亚洲视频在线免费观看| www久久久| 哪个网站能看毛片| 18成人在线视频| 天天操天天干天天插| 欧美怡春院一区二区三区| 亚洲高清影视| 黄色在线观看av| 91精品蜜臀在线一区尤物| 久久青青视频| 日韩成人手机在线| 中文字幕精品综合| 欧美熟妇交换久久久久久分类 | 亚洲一区中文| 日本午夜精品视频| 亚洲激情视频在线播放| 久久久久久久性潮| 青青青国产在线观看| 日韩美女视频一区二区| 香蕉视频国产在线|