《逆向工程核心原理》--注入学习

Windows消息钩取

一、钩子和消息钩子

钩子,英文Hook,泛指偷看或截取信息时所用的手段或工具。

Windows操作系统向用户提供GUI,它是以事件驱动(Event Driven)方式工作。事件发生后,OS将事先定义好的消息发送给相应的应用程序,应用程序分析收到的消息后执行相应动作。以敲击键盘为例,

常规Windows消息流:

  1. 发生键盘输入事件,WM_KEYDOWN消息被添加到OS消息队列;
  2. OS判断哪个应用程序发生了事件,从OS消息队列中取出消息,添加到相应应用程序的app消息队列;
  3. 应用程序监视自身的消息队列,发现新添加的WM_KEYDOWN消息,调用相应的事件处理程序进行处理。

附带钩子的信息流:

  1. 发生键盘输入事件,WM_KEYDOWN消息被添加到OS消息队列;
  2. OS判断哪个应用程序发生了事件,从OS消息队列中取出消息,发送给应用程序;
  3. 钩子程序截取信息,对消息采取一定的动作(因钩子目的而定);
  4. 如钩子程序不拦截消息,消息最终传输给应用程序,此时的消息可能经过了钩子程序的修改。

 

DLL注入

DLL注入:向运行中的其他进程强制插入特定的DLL文件,主要是命令其他进程自行调用LoadLibrary() API,加载用户指定的DLL文件。

DLL注入与一般DLL加载的主要区别是加载的目标进程是其自身或其他进程。

DLL

DLL(Dynamic Linked Library,动态链接库),DLL被加载到进程后会自动运行DllMain函数,用户可以把想要执行的额代码放到DllMain函数,每当加载DLL时,添加的代码就会自动得到执行。利用该特性可以修复程序BUG,或向程序添加新功能

  1 // CodeInject.cpp : 定义控制台应用程序的入口点。
  2 //
  3  
  4 //#include "stdafx.h"
  5 #include "windows.h"
  6 #include "stdio.h"
  7 #include <iostream>
  8 #include <cstring> 
  9 #include "string.h" 
 10 using namespace std; 
 11 //该结构体用于接收API和4个字符串
 12 typedef struct _THREAD_PARAM {
 13     FARPROC pFunc[2];
 14     char szBuf[4][128];
 15 } THREAD_PARAM, *PTHREAD_PARAM;
 16  
 17 typedef HMODULE (WINAPI *PFLOADLIBRARYA)
 18 (
 19     LPCSTR lpLibFileName
 20 );
 21  
 22 typedef FARPROC (WINAPI *PFGETPROCADDRESS)
 23 (
 24     HMODULE hModule,
 25     LPCSTR lpProcName
 26 );
 27  
 28 typedef int (WINAPI *PFMESSAGEBOXA)
 29 (
 30     HWND hWnd,
 31     LPCSTR lpText,
 32     LPCSTR lpCaption,
 33     UINT uType
 34 );
 35  
 36 DWORD WINAPI ThreadProc(LPVOID lParam){
 37     PTHREAD_PARAM pParam = (PTHREAD_PARAM)lParam;
 38     HMODULE hMod = NULL;
 39     FARPROC pFunc = NULL;
 40  
 41     //未直接调用相关API和未直接定义使用字符串,而通过THREAD_PARAM结构体以线程参数的形式传递使用
 42     // LoadLibrary()
 43     hMod = ((PFLOADLIBRARYA)pParam->pFunc[0])(pParam->szBuf[0]);    // "user32.dll"
 44     if( !hMod ){
 45         return 1;
 46     }
 47         
 48  
 49     // GetProcAddress()
 50     pFunc = (FARPROC)((PFGETPROCADDRESS)pParam->pFunc[1])(hMod, pParam->szBuf[1]);  // "MessageBoxA"
 51     if( !pFunc ){
 52         return 1;
 53     }
 54  
 55     // MessageBoxA()
 56     ((PFMESSAGEBOXA)pFunc)(NULL, pParam->szBuf[2], pParam->szBuf[3], MB_OK);
 57  
 58     return 0;
 59 }
 60  
 61 BOOL InjectCode(DWORD dwPID){
 62     HMODULE hMod = NULL;
 63     THREAD_PARAM param = {0,};
 64     HANDLE hProcess = NULL;
 65     HANDLE hThread = NULL;
 66     LPVOID pRemoteBuf[2] = {0,};
 67     DWORD dwSize = 0;
 68  
 69     hMod = GetModuleHandleA("kernel32.dll");
 70  
 71     //设置THREAD_PARAM结构体
 72     //加载到所有进程的kernel32.dll的地址都相同,因此从本进程获取的API与在notepad进程中获取的API地址是一样的
 73     param.pFunc[0] = GetProcAddress(hMod, "LoadLibraryA");
 74     param.pFunc[1] = GetProcAddress(hMod, "GetProcAddress");
 75     strcpy(param.szBuf[0], "user32.dll");
 76     strcpy(param.szBuf[1], "MessageBoxA");
 77     strcpy(param.szBuf[2], "代码注入 By SKI12");
 78     strcpy(param.szBuf[3], "blog.csdn.net/ski_12");
 79  
 80     // Open Process
 81     if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS,   // dwDesiredAccess
 82                                   FALSE,                // bInheritHandle
 83                                   dwPID)) )             // dwProcessId
 84     {
 85         printf("OpenProcess() fail : err_code = %d\n", GetLastError());
 86         return FALSE;
 87     }
 88  
 89     // Allocation for THREAD_PARAM
 90     //注入数据部分到进程
 91     dwSize = sizeof(THREAD_PARAM);
 92     if( !(pRemoteBuf[0] = VirtualAllocEx(hProcess,          // hProcess
 93                                       NULL,                 // lpAddress
 94                                       dwSize,               // dwSize
 95                                       MEM_COMMIT,           // flAllocationType
 96                                       PAGE_READWRITE)) )    // flProtect
 97     {
 98         printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
 99         return FALSE;
100     }
101     //param参数值为数据
102     if( !WriteProcessMemory(hProcess,                       // hProcess
103                             pRemoteBuf[0],                  // lpBaseAddress
104                             (LPVOID)&param,                 // lpBuffer
105                             dwSize,                         // nSize
106                             NULL) )                         // [out] lpNumberOfBytesWritten
107     {
108         printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
109         return FALSE;
110     }
111  
112     // Allocation for ThreadProc()
113     //注入代码部分到进程
114     dwSize = (DWORD)InjectCode - (DWORD)ThreadProc;
115     if( !(pRemoteBuf[1] = VirtualAllocEx(hProcess,          // hProcess
116                                       NULL,                 // lpAddress
117                                       dwSize,               // dwSize
118                                       MEM_COMMIT,           // flAllocationType
119                                       PAGE_EXECUTE_READWRITE)) )    // flProtect
120     {
121         printf("VirtualAllocEx() fail : err_code = %d\n", GetLastError());
122         return FALSE;
123     }
124     //ThreadProc()函数为操作代码
125     if( !WriteProcessMemory(hProcess,                       // hProcess
126                             pRemoteBuf[1],                  // lpBaseAddress
127                             (LPVOID)ThreadProc,             // lpBuffer
128                             dwSize,                         // nSize
129                             NULL) )                         // [out] lpNumberOfBytesWritten
130     {
131         printf("WriteProcessMemory() fail : err_code = %d\n", GetLastError());
132         return FALSE;
133     }
134  
135     //将数据与代码注入到进程内存后,调用CreateRemoteThread()执行远程线程
136     if( !(hThread = CreateRemoteThread(hProcess,            // hProcess
137                                        NULL,                // lpThreadAttributes
138                                        0,                   // dwStackSize
139                                        (LPTHREAD_START_ROUTINE)pRemoteBuf[1],     // dwStackSize
140                                        pRemoteBuf[0],       // lpParameter
141                                        0,                   // dwCreationFlags
142                                        NULL)) )             // lpThreadId
143     {
144         printf("CreateRemoteThread() fail : err_code = %d\n", GetLastError());
145         return FALSE;
146     }
147  
148     WaitForSingleObject(hThread, INFINITE);    
149  
150     CloseHandle(hThread);
151     CloseHandle(hProcess);
152  
153     return TRUE;
154 }
155  
156 BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {
157     TOKEN_PRIVILEGES tp;
158     HANDLE hToken;
159     LUID luid;
160  
161     if( !OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ){
162         printf("OpenProcessToken error: %u\n", GetLastError());
163         return FALSE;
164     }
165  
166     if( !LookupPrivilegeValue(NULL,           // lookup privilege on local system
167                               lpszPrivilege,  // privilege to lookup 
168                               &luid) )        // receives LUID of privilege
169     {
170         printf("LookupPrivilegeValue error: %u\n", GetLastError() ); 
171         return FALSE; 
172     }
173  
174     tp.PrivilegeCount = 1;
175     tp.Privileges[0].Luid = luid;
176     if( bEnablePrivilege )
177         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
178     else
179         tp.Privileges[0].Attributes = 0;
180  
181     // Enable the privilege or disable all privileges.
182     if( !AdjustTokenPrivileges(hToken, 
183                                FALSE, 
184                                &tp, 
185                                sizeof(TOKEN_PRIVILEGES), 
186                                (PTOKEN_PRIVILEGES) NULL, 
187                                (PDWORD) NULL) )
188     { 
189         printf("AdjustTokenPrivileges error: %u\n", GetLastError() ); 
190         return FALSE; 
191     } 
192  
193     if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ){
194         printf("The token does not have the specified privilege. \n");
195         return FALSE;
196     } 
197  
198     return TRUE;
199 }
200  
201 int main(int argc, char* argv[]){
202     DWORD dwPID = 0;
203     if( argc != 2 ){
204         printf("\n USAGE  : %s <pid>\n", argv[0]);
205         return 1;
206     }
207  
208     // change privilege
209     if( !SetPrivilege(SE_DEBUG_NAME, TRUE) ){
210         return 1;
211     }
212  
213     // code injection
214     //将字符串转换为长整型
215     dwPID = (DWORD)atol(argv[1]);
216     InjectCode(dwPID);
217  
218     return 0;
219 }
220  

 

待续。。。

posted @ 2020-05-30 22:05  坚持,每天进步一点点  阅读(385)  评论(0编辑  收藏  举报