[转]注入小结

一.Windows消息钩取:SetWindowsHookEx

HHOOK SetWindowsHookEx(

intidHook,// hook type 就是HOOK的消息种类,如WH_KEYBOARD,WH_MOUSE....见MSDN

HOOKPROClpfn,// hook procedure 钩子过程,安装消息钩子时候,钩子过程一定要位于某个DLL内部

HINSTANCEhMod,// handle to application instance 钩子过程的DLL句柄(为NULL则是局部钩子)

DWORDdwThreadId // thread identifie想要挂上钩子的线程ID(为NULL则为全局钩子)

);   

把SetWindowsHookEx的钩子过程放在DLL中(SetWindowsHookEx本身可以放在DLL内部外部都可以)这样只要有消息事件发生,就会自动把Dll加载至目标进程,这样加载时候DllMain可以获取目标进程的句柄。

不用之后要卸载Hook,调用API,  UnhookWindowsHookEx(SetWindowsHookEx返回的句柄)

HookMain:

[cpp] view plain copy
  1. #include "stdio.h"  
  2. #include "conio.h"  
  3. #include "windows.h"  
  4.   
  5. #define DEF_DLL_NAME "KeyHook.dll"  
  6. #define DEF_HOOKSTART "HookStart"  
  7. #define DEF_HOOKSTOP "HookStop"  
  8.   
  9. typedef void(*PFN_HOOKSTART)();  
  10. typedef void(*PFN_HOOKSTOP)();  
  11.   
  12. void main()  
  13. {  
  14.     HMODULE hDll = NULL;  
  15.     PFN_HOOKSTART HookStart = NULL;  
  16.     PFN_HOOKSTOP HookStop = NULL;  
  17.     char ch = 0;  
  18.   
  19.     hDll = LoadLibraryA(DEF_DLL_NAME);  
  20.   
  21.     HookStart = (PFN_HOOKSTART)GetProcAddress(hDll, DEF_HOOKSTART);  
  22.     HookStop = (PFN_HOOKSTOP)GetProcAddress(hDll, DEF_HOOKSTOP);  
  23.   
  24.     HookStart();  
  25.   
  26.     printf("press 'q' to quit!\n");  
  27.     while (_getch() != 'q');  
  28.   
  29.     HookStop();  
  30.   
  31.     FreeLibrary(hDll);  
  32. }  

HookDll:

[cpp] view plain copy
  1. #include <stdio.h>  
  2. #include <windows.h>  
  3.   
  4. #define DEF_PROCESS_NAME "notepad.exe"  
  5.   
  6. HINSTANCE g_hInstance = NULL;  
  7. HHOOK g_hHook = NULL;  
  8. HWND g_hWnd = NULL;  
  9.   
  10. BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD dwReason, LPVOID lpvReserved)  
  11. {  
  12.     switch (dwReason)  
  13.     {  
  14.     case DLL_PROCESS_ATTACH:  
  15.         g_hInstance = hinstDll;  
  16.         break;  
  17.   
  18.     case DLL_PROCESS_DETACH:  
  19.         break;  
  20.     }  
  21.     return TRUE;  
  22. }  
  23.   
  24. LRESULT CALLBACK KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)  
  25. {  
  26.     char szPath[MAX_PATH] = { 0 };  
  27.     char *p = NULL;  
  28.   
  29.     if (nCode >= 0)  
  30.     {  
  31.         if (!(lParam & 0x80000000))  
  32.         {  
  33.             GetModuleFileNameA(NULL, szPath, MAX_PATH);  
  34.             p = strrchr(szPath, '\\');  
  35.   
  36.             if (!_stricmp(p + 1, DEF_PROCESS_NAME))  
  37.                 return 1;  
  38.         }  
  39.     }  
  40.     return CallNextHookEx(g_hHook, nCode, wParam, lParam);  
  41. }  
  42.   
  43. #ifdef __cplusplus  
  44. extern "C" {  
  45. #endif  
  46.   
  47.     __declspec(dllexportvoid HookStart()  
  48.     {  
  49.         g_hHook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_hInstance, 0);  
  50.     }  
  51.     __declspec(dllexportvoid HookStop()  
  52.     {  
  53.         if (g_hHook)  
  54.         {  
  55.             UnhookWindowsHookEx(g_hHook);  
  56.             g_hHook = NULL;  
  57.         }  
  58.     }  
  59.   
  60. #ifdef __cplusplus  
  61. }  
  62. #endif  


二.创建远程线程注入Dll(CreateRemoteThread)

dll注入原理就是从外部使目标进程调用LoadLibrary()来加载Dll

      步骤:

1.OpenProcess来获取目标进程的进程句柄

2.VirtualAllocEx来在目标进程中分配要注入的DLL路径名长度大小的空间

3.WriteProcessMemory在目标进程分配的空间进行写入DLL路径(相当于)

4.GetModuleHandle + GetProcAddress获取LoadLibrary的地址(因为kernel32.dll加载的地址一样,所以目标进程一样可以加载)

5.CreateRemoteThread在目标进程运行LoadLibrary加载Dll,VirtualAllocEx分配空间为LoadLibrary的参数

6.DllMain中再CreateThread来创建线程干自己想干的事

注入Main程序:

[cpp] view plain copy
  1. #include<windows.h>  
  2. #include<stdio.h>  
  3. #include"tchar.h"  
  4.   
  5. BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath);  
  6.   
  7. int _tmain(int argc, TCHAR *argv[])  
  8. {  
  9.     if (argc != 3)  
  10.     {  
  11.         _tprintf(TEXT("%s参数不足"), argv[0]);  
  12.         getchar();  
  13.         return 1;  
  14.     }  
  15.       
  16.     if (InjectDll((DWORD)_tstol(argv[1]), argv[2]))  
  17.     {  
  18.         _tprintf(TEXT("InjectDll %s success!!!\n"), argv[2]);  
  19.     }  
  20.     else  
  21.     {  
  22.         _tprintf(TEXT("InjectDll %s failed!!!\n"), argv[2]);  
  23.     }  
  24.     getchar();  
  25.     return 0;  
  26. }  
  27.   
  28.   
  29. BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)  
  30. {  
  31.     HANDLE hProcess = NULL, hThread = NULL;  
  32.     HMODULE hMod = NULL;  
  33.     LPVOID pRemoteBuf = NULL;  
  34.     DWORD dwBufSize = (DWORD)((_tcslen(szDllPath) + 1) * sizeof(TCHAR));  
  35.     LPTHREAD_START_ROUTINE pThreadProc;  
  36.   
  37.     if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))                        //以PROCESS_ALL_ACCESS打开进程获取句柄  
  38.     {  
  39.         _tprintf(TEXT("OpenProcess %d PID failed!!! [%d]\n"), dwPID,GetLastError());  
  40.         return FALSE;  
  41.     }  
  42.   
  43.     pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);     //在目标进程中分配dll路径长度的内存空间返回到pRemoteBuf  
  44.   
  45.     WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);           //在目标进程中写入进程的路径  
  46.   
  47.     hMod = GetModuleHandle(TEXT("kernel32.dll"));                                           //获取kernel32.dll的模块地址(每个进程这个地址都一样)  
  48.     pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, TEXT("LoadLibraryA"));       //LoadLibraryA  
  49.     if (NULL == pThreadProc)  
  50.     {  
  51.         _tprintf(TEXT("GetLastError = [%d]\n"), GetLastError());  
  52.         return FALSE;  
  53.     }  
  54.   
  55.     hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);      //用远程线程在目标进程创建出线程来调用LoadLibrary  
  56.     if (NULL == hThread)      
  57.     {  
  58.         _tprintf(TEXT("GetLastError = [%d]\n"), GetLastError());  
  59.     }  
  60.     WaitForSingleObject(hThread, INFINITE);  
  61.     CloseHandle(hThread);  
  62.     CloseHandle(hProcess);  
  63.   
  64.     return TRUE;  
  65. }  

注入的Dll:

[cpp] view plain copy
  1. #include<windows.h>  
  2. #include "tchar.h"  
  3.   
  4. #pragma comment(lib,"urlmon.lib")  
  5.   
  6. #define DEF_FILE_NAME (TEXT("index.html"))  
  7. #define DEF_URL (TEXT("http://www/naver.com/index.html"))  
  8.   
  9.   
  10. HMODULE g_hMod = NULL;  
  11.   
  12. DWORD WINAPI ThreadProc(LPVOID lParam)                                          //线程函数,实现功能  
  13. {  
  14.     TCHAR szPath[MAX_PATH] = { 0 };  
  15.     if (!GetModuleFileName(g_hMod, szPath, MAX_PATH))  
  16.         return FALSE;  
  17.   
  18.     TCHAR *p = _tcsrchr(szPath, '\\');  
  19.     if (!p)  
  20.         return FALSE;  
  21.   
  22.     _tcscpy_s(p + 1, MAX_PATH, DEF_FILE_NAME);  
  23.   
  24.     URLDownloadToFile(NULL, DEF_URL, szPath, 0, NULL);  
  25.   
  26.     return 0;  
  27. }  
  28.   
  29. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)  
  30. {  
  31.     HANDLE hThread = NULL;  
  32.     g_hMod = (HMODULE)hinstDLL;  
  33.   
  34.     switch (fdwReason)  
  35.     {  
  36.     case DLL_PROCESS_ATTACH:  
  37.         MessageBox(NULL,TEXT("注入成功!"),TEXT("Success!"),NULL);  
  38.         hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);         //DLL中创建线程  
  39.         CloseHandle(hThread);  
  40.         break;  
  41.     }  
  42.   
  43.     return TRUE;  
  44. }  


三,使用注册表

   原理:User32.dll加载时候会读取AppInit_DLLs,若有值则会LoadLibrary加载用户DLL

在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows

1.要注入的DLL路径写入AppInit_DLLs中

2.把LoadAppInit_DLLs注册表项的值设为1


这样DLL就会注入到所有加载user32.dll的进程


四,Dll卸载(只适用于自己注入的DLL,PE记载的不能卸载)

原理:使目标去调用FreeLibrary去卸载DLL

过程:

1.遍历进程查找获得对应程序的PID(CreateToolhelp32Snapshot-》PROCESSENTRY32)

2.提高进程权限(获取进程访问的令牌句柄OpenProcessToken -> 获取对应权限的LUID(LookupPrivilegevalue)->改变令牌权限(AdjustTokenPrivileges))

3.查找目标进程的模板(CreateToolhelp32Snapshot-》MODULEENTRY32),获取对应的DLL的handle

4.用CreateRemoteThread来调用FreeLibrary去卸载注入DLL

[cpp] view plain copy
  1. #include<stdio.h>  
  2. #include<windows.h>  
  3. #include<tlhelp32.h>  
  4. #include<tchar.h>  
  5.   
  6. DWORD FindProcessID(LPCTSTR szProcessName);  
  7. BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege);  
  8. BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName);  
  9. #define DEF_PROC_NAME (TEXT("notepad.exe"))  
  10. #define DEF_DLL_NAME (TEXT("myhack.dll"))  
  11.   
  12. int _tmain()  
  13. {  
  14.     DWORD dwPID = 0xFFFFFFFF;  
  15.       
  16.     dwPID = FindProcessID(DEF_PROC_NAME);  
  17.     if (dwPID == 0XFFFFFFFF)  
  18.     {  
  19.         _tprintf(TEXT("没有找到这个process"));  
  20.         getchar();  
  21.         return 1;  
  22.     }  
  23.   
  24.     _tprintf(TEXT("PID of \"%s\" is %d\n"), DEF_PROC_NAME, dwPID);  
  25.   
  26.     if (!SetPrivilege(SE_DEBUG_NAME, TRUE))  
  27.     {  
  28.         getchar();  
  29.         return 1;  
  30.     }  
  31.   
  32.     if (EjectDll(dwPID, DEF_DLL_NAME))  
  33.     {  
  34.         _tprintf(TEXT("EjectDll(%d  \"%s\") success!!!\n"), dwPID, DEF_DLL_NAME);  
  35.     }  
  36.     else  
  37.     {  
  38.         _tprintf(TEXT("EjectDll(%d  \"%s\") falied!!!\n"), dwPID, DEF_DLL_NAME);  
  39.     }  
  40.   
  41.     getchar();  
  42.     return 0;  
  43. }  
  44.   
  45.   
  46. DWORD FindProcessID(LPCTSTR szProcessName)                            
  47. {  
  48.     DWORD dwPID = 0XFFFFFFFF;  
  49.     HANDLE hSnapshot = INVALID_HANDLE_VALUE;  
  50.     PROCESSENTRY32 pe;  
  51.   
  52.     pe.dwSize = sizeof(PROCESSENTRY32);  
  53.     hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL,NULL);      //获取进程的句柄  
  54.   
  55.     Process32First(hSnapshot,&pe);                                  //获取指定进程名的PID  
  56.     do  
  57.     {  
  58.         if (!_tcsicmp(pe.szExeFile, DEF_PROC_NAME))  
  59.         {  
  60.             dwPID = pe.th32ProcessID;  
  61.             break;  
  62.         }  
  63.     } while (Process32Next(hSnapshot, &pe));  
  64.   
  65.     CloseHandle(hSnapshot);  
  66.   
  67.     return dwPID;  
  68.       
  69. }  
  70. BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)     //提升程序权限  
  71. {  
  72.     TOKEN_PRIVILEGES tp;  
  73.     HANDLE hToken;  
  74.     LUID luid;  
  75.   
  76.     if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))     //获取令牌句柄  
  77.     {  
  78.         _tprintf(TEXT("OpenProcessToken error : %u\n"), GetLastError());  
  79.         return FALSE;  
  80.     }  
  81.           
  82.     LookupPrivilegeValue(NULL,lpszPrivilege,&luid);                                                 //获取指定权限的LUID  
  83.   
  84.     tp.PrivilegeCount = 1;  
  85.     tp.Privileges[0].Luid = luid;  
  86.     if (bEnablePrivilege)  
  87.         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;                                       
  88.     else  
  89.         tp.Privileges[0].Attributes = 0;  
  90.   
  91.     if (!AdjustTokenPrivileges(hToken,          //令牌句柄  
  92.                                 FALSE,          //FALSE则修改权限  
  93.                                   &tp,          //令牌权限的结构(包括LUID和tp中的数组个数吗)  
  94.              sizeof(TOKEN_PRIVILEGES),   
  95.               (PTOKEN_PRIVILEGES)NULL,    
  96.                         (PDWORD)NULL))  
  97.     {  
  98.         _tprintf(TEXT("AdjustTokenPrivileges error : %u\n"), GetLastError());  
  99.         return FALSE;  
  100.     }                                                                                           //调整进程的权限  
  101.   
  102.     if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)  
  103.     {  
  104.         _tprintf(TEXT("The Token does not have the specified privilege. \n"));  
  105.         return FALSE;  
  106.     }  
  107.   
  108.     return TRUE;  
  109. }  
  110.   
  111.   
  112. BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName)  
  113. {  
  114.     BOOL bMore = FALSE, bFound = FALSE;  
  115.     HANDLE hSnapshot, hProcess, hThread;  
  116.     HMODULE hModule = NULL;  
  117.     MODULEENTRY32 me = { sizeof(me) };  
  118.     LPTHREAD_START_ROUTINE pThreadProc;  
  119.   
  120.     hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL,dwPID);         //获取寻找到的模块表的模块列表  
  121.     bMore = Module32First(hSnapshot, &me);                              //查找是否有myhack.dll这个dll模块,并且模块dll的名字保存在me结构体中  
  122.     for (; bMore; bMore = Module32Next(hSnapshot, &me))  
  123.     {  
  124.         if (!_tcsicmp((LPCTSTR)me.szExePath, szDllName) | !_tcsicmp((LPCTSTR)me.szModule, szDllName))  
  125.         {  
  126.             bFound = TRUE;  
  127.             break;  
  128.         }  
  129.     }  
  130.   
  131.     if (!bFound)  
  132.     {  
  133.         CloseHandle(hSnapshot);  
  134.         return FALSE;  
  135.     }  
  136.   
  137.     if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)))                        //获得进程的句柄  
  138.     {  
  139.         _tprintf(TEXT("OpenProcess falied"));  
  140.         return FALSE;  
  141.     }     
  142.     hModule = GetModuleHandle(TEXT("kernel32.dll"));                                        //获得kernel.dll中的FreeLibrary函数地址  
  143.     pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule,TEXT("FreeLibrary"));      //找到ProcAddress  
  144.     hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,me.modBaseAddr,0,NULL);          
  145.     WaitForSingleObject(hThread, INFINITE);  
  146.     CloseHandle(hThread);  
  147.     CloseHandle(hProcess);  
  148.     CloseHandle(hSnapshot);  
  149.   
  150.     return TRUE;  
  151. }  

五,修改PE来加载DLL

原理:修改导入表来实现加载DLL

   步骤:

1.查看IDT(IMPORT Directory Table)是否有足够空间来增加一个新的IID

2.有足够空间就直接新增一个IID并修改导入表的SIZE(没有足够空间就转移导入表并修改导入表的RVA以及SIZE)

3.将新增的IID的INT 和 IAT以及NAME都修改

4.删除BOUND IMPORT表

5.修改导入表的节区属性可写

6.不修改导入表节区属性可以将新增的IID的FirstThunk改为IAT的末尾地址

DLL代码:

[cpp] view plain copy
  1. #include<windows.h>  
  2. #include<string.h>  
  3. #include<tchar.h>  
  4.   
  5. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)  
  6. {  
  7.     switch (fdwReason)  
  8.     {  
  9.     case DLL_PROCESS_ATTACH:  
  10.         MessageBox(NULL,TEXT("注入成功"),TEXT("Success!"),MB_OK);  
  11.         break;  
  12.   
  13.     default:  
  14.         break;  
  15.     }  
  16.     return TRUE;  
  17. }  
  18.   
  19. #ifdef __cplusplus  
  20. extern "C" {  
  21. #endif  
  22.     _declspec(dllexportvoid Fun()                     //无意义的函数只为了PE格式  
  23.     {  
  24.         return;  
  25.     }  
  26. #ifdef __cplusplus  
  27. }  
  28. #endif  

强行导入一个Fun是为了保存完整性,能够加载DLL



六,代码注入

与DLL注入不一样,代码注入仅向目标进程注入必要的代码而不是整个DLL

原理:用一个结构体来保存要注入代码使用的API地址(一般是user32.dll中的)以及所需要用到的数据(如MessageBoxA函数所需要的信息框名字和标题),并将这个结构体也注入进目标进程,再将线程过程代码都注入进目标进程。(一样利用OpenProcess -> VirtualAllocEx -> WriteProcessMemory -> CreateRemoteThread)

[cpp] view plain copy
  1. #include<windows.h>  
  2. #include<stdio.h>  
  3. #include<string.h>  
  4.   
  5. DWORD WINAPI ThreadProc(LPVOID lParam);  
  6. BOOL CodeInject(DWORD dwPID);  
  7. typedef struct _THREAD_PARAM  
  8. {  
  9.     FARPROC pFun[2];        //GetProcAddress() 和 LoadLibraryA()的地址  
  10.     char szBuf[4][128];     //二维数组,表示四个参数“user32.dll”,“MessageBoxA”,“内容”,“标题”  
  11. }THREAD_PARAM, *PTHREAD_PARAM;  
  12.   
  13. typedef HMODULE (WINAPI *PFAR_LOADLIBRARYA)  
  14. (  
  15.     LPCSTR lpLibFileName  
  16. );  
  17.   
  18. typedef HMODULE(WINAPI *PFAR_GETPROCADDRESS)  
  19. (  
  20.     HMODULE hModule,  
  21.     LPCSTR lpProcName  
  22. );  
  23.   
  24. typedef int (WINAPI *PFMESSAGEBOXA)  
  25. (  
  26.     HWND hWnd,  
  27.     LPCSTR lpText,  
  28.     LPCTSTR lpCaption,  
  29.     UINT type  
  30. );  
  31.   
  32. int main(int argc, char *argv[])  
  33. {  
  34.     DWORD dwPID = 0;  
  35.       
  36.     if (argc != 2)  
  37.     {  
  38.         printf("请输入要注入程序的PID!\n");  
  39.         getchar();  
  40.         return 1;  
  41.     }  
  42.   
  43.     dwPID = (DWORD)atol(argv[1]);  
  44.     CodeInject(dwPID);  
  45.   
  46.     return 0;  
  47. }  
  48.   
  49. DWORD WINAPI ThreadProc(LPVOID lParam)  
  50. {  
  51.     PTHREAD_PARAM pParam = (PTHREAD_PARAM)lParam;  
  52.     HMODULE hMod = NULL;  
  53.     FARPROC pFunc = NULL;  
  54.   
  55.     //pParam->pFun[0] 是 LoadLibraryA  
  56.     //pParam->szBuf[0] 是 "user32.dll"  
  57.     hMod = ((PFAR_LOADLIBRARYA)pParam->pFun[0])(pParam->szBuf[0]);  
  58.   
  59.     pFunc = (FARPROC)((PFAR_GETPROCADDRESS)pParam->pFun[1])(hMod,pParam->szBuf[1]);  
  60.   
  61.     ((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);  
  62.   
  63.     return 0;  
  64. }  
  65.   
  66. BOOL CodeInject(DWORD dwPID)  
  67. {  
  68.      HMODULE hMod = NULL;  
  69.      HANDLE hProcess = NULL;  
  70.      HANDLE hThread = NULL;  
  71.      DWORD dwSIZE = 0;  
  72.      THREAD_PARAM param = {0};  
  73.      LPVOID pRemoteBuf[2] = {0};  
  74.       
  75.     hMod = GetModuleHandleA("kernel32.dll");  
  76.   
  77.     //初始化结构体pParam  
  78.     param.pFun[0] = GetProcAddress(hMod, "LoadLibraryA");  
  79.     param.pFun[1] = GetProcAddress(hMod, "GetProcAddress");  
  80.     strcpy_s(param.szBuf[0],sizeof("user32.dll"),"user32.dll");  
  81.     strcpy_s(param.szBuf[1], sizeof("MessageBoxA"),"MessageBoxA");  
  82.     strcpy_s(param.szBuf[2], sizeof("Inject Success!"),"Inject Success!");  
  83.     strcpy_s(param.szBuf[3], sizeof("Success!"),"Success!");  
  84.   
  85.   
  86.     //获取进程句柄  
  87.     hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPID);  
  88.   
  89.     //分配内存空间  
  90.     dwSIZE = sizeof(THREAD_PARAM);  
  91.     pRemoteBuf[0] = VirtualAllocEx(hProcess,  
  92.                                     NULL,                   //为NULL不指定具体分配哪个地址  
  93.                                     dwSIZE,                 //分配空间的大小  
  94.                                     MEM_COMMIT,  
  95.                                     PAGE_READWRITE);  
  96.   
  97.     WriteProcessMemory(hProcess,  
  98.                        pRemoteBuf[0],  
  99.                        (LPVOID)¶m,  
  100.                        dwSIZE,  
  101.                         NULL);    //指定写入指定进程的字节数,为NULL则忽略  
  102.   
  103.     dwSIZE = (DWORD)CodeInject - (DWORD)ThreadProc;         //两个函数地址相减,一定要在Release下优化编译!!!!!!!  
  104.     pRemoteBuf[1] = VirtualAllocEx(hProcess,  
  105.                                     NULL,   
  106.                                     dwSIZE,  
  107.                                     MEM_COMMIT,   
  108.                                     PAGE_EXECUTE_READWRITE);  
  109.   
  110.     WriteProcessMemory(hProcess,pRemoteBuf[1],(LPVOID)ThreadProc,dwSIZE,NULL);  
  111.   
  112.     hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteBuf[1], pRemoteBuf[0], 0, NULL);  
  113.     WaitForSingleObject(hThread, INFINITE);  
  114.     CloseHandle(hThread);  
  115.     CloseHandle(hProcess);  
  116.   
  117.     return TRUE;  
  118. }  

七,汇编代码注入

原理:将汇编代码的注入部分(CreateRemoteThread的传入的过程代码)用十六进制保存,再传入一个结构体(CreateRemoteThread的传入的参数),结构体有LoadLibrary和GetProcAddress两个API的地址,再在汇编代码中进行调用这个结构体这两个地址。

[cpp] view plain copy
  1. #include<windows.h>  
  2. #include<stdio.h>  
  3.   
  4. BOOL InjectCode(DWORD dwPID);  
  5. BYTE g_InjectionCode[] = {  
  6.     0x55,0x8B,0xEC,0x8B,0x75,0x08,0x68,0x6C,  
  7.     0x6C,0x00,0x00,0x68,0x33,0x32,0x2E,0x64,  
  8.     0x68,0x75,0x73,0x65,0x72,0x54,0xFF,0x16,  
  9.     0x68,0x6F,0x78,0x41,0x00,0x68,0x61,0x67,  
  10.     0x65,0x42,0x68,0x4D,0x65,0x73,0x73,0x54,  
  11.     0x50,0xFF,0x56,0x04,0x6A,0x00,0xE8,0x0C,  
  12.     0x00,0x00,0x00,0x52,0x65,0x76,0x65,0x72,  
  13.     0x73,0x65,0x43,0x6F,0x72,0x65,0x00,0xE8,  
  14.     0x14,0x00,0x00,0x00,0x77,0x77,0x77,0x2E,  
  15.     0x72,0x65,0x76,0x65,0x72,0x73,0x65,0x63,  
  16.     0x6F,0x72,0x65,0x2E,0x63,0x6F,0x6D,0x00,  
  17.     0x6A,0x00,0xFF,0xD0,0x33,0xC0,0x8B,0xE5,  
  18.     0x5D,0xC3  
  19. };  
  20.   
  21. typedef struct _THREAD_PARAM  
  22. {  
  23.     FARPROC pFunc[2];  
  24. }THREAD_PARAM, *PTHREAD_PARAM;  
  25.   
  26. int main()  
  27. {  
  28.     DWORD dwPID = 12056;  
  29.   
  30.     InjectCode(dwPID);  
  31.     getchar();  
  32.     return 0;  
  33. }  
  34.   
  35. BOOL InjectCode(DWORD dwPID)  
  36. {  
  37.     HMODULE         hMod = NULL;  
  38.     THREAD_PARAM    param = { 0, };  
  39.     HANDLE          hProcess = NULL;  
  40.     HANDLE          hThread = NULL;  
  41.     LPVOID          pRemoteBuf[2] = { 0, };  
  42.   
  43.     hMod = GetModuleHandleA("kernel32.dll");  
  44.   
  45.     // set THREAD_PARAM  
  46.     param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");  
  47.     param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");  
  48.   
  49.     // Open Process  
  50.     if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS,               // dwDesiredAccess  
  51.         FALSE,                            // bInheritHandle  
  52.         dwPID)))                         // dwProcessId  
  53.     {  
  54.         printf("OpenProcess() fail : err_code = %d\n", GetLastError());  
  55.         return FALSE;  
  56.     }  
  57.   
  58.     // Allocation for THREAD_PARAM  
  59.     if (!(pRemoteBuf[0] = VirtualAllocEx(hProcess,                  // hProcess  
  60.         NULL,                      // lpAddress  
  61.         sizeof(THREAD_PARAM),      // dwSize  
  62.         MEM_COMMIT,                // flAllocationType  
  63.         PAGE_READWRITE)))         // flProtect  
  64.     {  
  65.         printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());  
  66.         return FALSE;  
  67.     }  
  68.   
  69.     if (!WriteProcessMemory(hProcess,                               // hProcess  
  70.         pRemoteBuf[0],                          // lpBaseAddress  
  71.         (LPVOID)¶m,                         // lpBuffer  
  72.         sizeof(THREAD_PARAM),                   // nSize  
  73.         NULL))                                 // [out] lpNumberOfBytesWritten  
  74.     {  
  75.         printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());  
  76.         return FALSE;  
  77.     }  
  78.   
  79.     // Allocation for ThreadProc()  
  80.     if (!(pRemoteBuf[1] = VirtualAllocEx(hProcess,                  // hProcess  
  81.         NULL,                      // lpAddress  
  82.         sizeof(g_InjectionCode),   // dwSize  
  83.         MEM_COMMIT,                // flAllocationType  
  84.         PAGE_EXECUTE_READWRITE))) // flProtect  
  85.     {  
  86.         printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());  
  87.         return FALSE;  
  88.     }  
  89.   
  90.     if (!WriteProcessMemory(hProcess,                               // hProcess  
  91.         pRemoteBuf[1],                          // lpBaseAddress  
  92.         (LPVOID)&g_InjectionCode,               // lpBuffer  
  93.         sizeof(g_InjectionCode),                // nSize  
  94.         NULL))                                 // [out] lpNumberOfBytesWritten  
  95.     {  
  96.         printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());  
  97.         return FALSE;  
  98.     }  
  99.   
  100.     if (!(hThread = CreateRemoteThread(hProcess,                    // hProcess  
  101.         NULL,                        // lpThreadAttributes  
  102.         0,                           // dwStackSize  
  103.         (LPTHREAD_START_ROUTINE)pRemoteBuf[1],  
  104.         pRemoteBuf[0],               // lpParameter  
  105.         0,                           // dwCreationFlags  
  106.         NULL)))                     // lpThreadId  
  107.     {  
  108.         printf("CreateRemoteThread() fail : err_code = %d\n", GetLastError());  
  109.         return FALSE;  
  110.     }  
  111.   
  112.     WaitForSingleObject(hThread, INFINITE);  
  113.   
  114.     CloseHandle(hThread);  
  115.     CloseHandle(hProcess);  
  116.   
  117.     return TRUE;  
  118. }  

十六进制部分所代表的汇编代码:

[plain] view plain copy
  1. /*  
  2. 004010ED    55               PUSH EBP  
  3. 004010EE    8BEC             MOV EBP,ESP  
  4. 004010F0    8B75 08          MOV ESI,DWORD PTR SS:[EBP+8]       ; ESI = 结构体的地址,地址表示的是API所代表的地址             
  5. 004010F3    68 6C6C0000      PUSH 6C6C                        
  6. 004010F8    68 33322E64      PUSH 642E3233  
  7. 004010FD    68 75736572      PUSH 72657375<span style="white-space:pre">            </span>; 三行表示的是"user32.dll"逆序push  
  8. 00401102    54               PUSH ESP                           ; ESP表示的是 "user32.dll"字符串的首地址  
  9. 00401103    FF16             CALL DWORD PTR DS:[ESI]            ; 调用LoadLibraryA("user32.dll")  
  10. 00401105    68 6F784100      PUSH 41786F  
  11. 0040110A    68 61676542      PUSH 42656761  
  12. 0040110F    68 4D657373      PUSH 7373654D  
  13. 00401114    54               PUSH ESP                           ; - 字符串"MessageBoxA"的首地址  
  14. 00401115    50               PUSH EAX                           ; - 前面LoadLibrary所返回的hMod  
  15. 00401116    FF56 04          CALL DWORD PTR DS:[ESI+4]          ; - GetProcAddress(hMod, "MessageBoxA")  
  16. 00401119    6A 00            PUSH 0                             ; - MB_OK (0)  
  17. 0040111B    E8 0C000000      CALL 0040112C<span style="white-space:pre">            </span>; CALL后面的是ASCLL,CALL的意思是PUSH EIP,相当于PUSH了后面字符串的首地址  
  18. 00401120                     <ASCII>                            ; - "ReverseCore", 0  
  19. 0040112C    E8 14000000      CALL 00401145  
  20. 00401131                     <ASCII>                            ; - "www.reversecore.com", 0  
  21. 00401145    6A 00            PUSH 0                             ; - hWnd (0)  
  22. 00401147    FFD0             CALL EAX                           ; EAX是GetProcAddress所获得的地址存放在eax - MessageBoxA(0, "www.reversecore.com", "ReverseCore", 0)  
  23. 00401149    33C0             XOR EAX,EAX                      <span style="white-space:pre">    </span>; API结果要返回0 到EAX中   
  24. 0040114B    8BE5             MOV ESP,EBP  
  25. 0040114D    5D               POP EBP                            ; 清除堆栈  
  26. 0040114E    C3               RETN  
  27. */  


原文链接: [转]注入小结 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://www.gyarmy.com/post-378.html )

发表评论

0则评论给“[转]注入小结”