返回列表 发帖

[原创]winxp下监视进程的创建

在winxp下进程的创建无非是使用System,Winexec,ShellExecute,CreateProcess等库函数和系统API.但是为了实现对进程创建的监视,我们一般都是拦截这些api,这样工作量会很大.而实际上这些函数最终都会调用ntdll.dll所导出的ZwCreateProcessEx函数,由他填入服务索引号,并软中断进入内核模式.只要Hook了该函数就能有效地从用户层监视进程的创建.但是有人会说,在2000和Xp下不是有NtCreateProcess和ZwCreateProcess么,实际上今天晚上我自己动手试了下,上述这两者,首先他们是一个函数,其次,在Xp下创建进程的时候,根本不会使用到他们... 首先看下ZwCreateProcessEx的定义(参考win2k/xp native api refernce): typedef NTSTATUS (*NTCREATEPROCESSEX)( OUT PHANDLE ProcessHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL, IN HANDLE ParentProcess, IN BOOLEAN InheritObjectTable, IN HANDLE SectionHandle OPTIONAL, IN HANDLE DebugPort OPTIONAL, IN HANDLE ExceptionPort OPTIONAL, IN HANDLE Unknown ); 我们需要的只是拦截他,目前暂时具体参数的功能就不谈了,具体实现方式就不说了,在前面的<用户层下拦截API的原理与实现>中已经讲得很清楚拉.如果你忘记了,具体见:http://redcoder.blog.sohu.com/2183228.html下面是这次实验的代码,拦截了ZwCreateProcessEx函数: 编译环境:WinXp Sp2 + vc6.0
  1. &#35;include <stdio.h>
  2. &#35;include <windows.h>
  3. &#35;define STATUS_SUCCESS 0
  4. &#35;define HOOKFUCTIONSIZE 10240 //定义拦截函数体的大小,以字节为单位,且以4kb为基本单位
  5. &#35;define HOOKEDAPIPARAMNUMINBYTE 36 //定义被拦截的api的函数的参数的大小,以字节为单位
  6. typedef unsigned long NTSTATUS;
  7. typedef unsigned long SYSTEM_INFORMATION_CLASS;
  8. typedef struct _RemoteParam{
  9. LPVOID lpFunAddr;
  10. LPVOID lpWriteProcessMemory;
  11. unsigned char szOldCode[12];
  12. unsigned char szNewCode[12];
  13. LPVOID lpMessageBox;
  14. }RemoteParam, * PRemoteParam;
  15. typedef BOOL (__stdcall * PFN_WRITEPROCESSMEMORY)(HANDLE, LPVOID, LPCVOID, SIZE_T, SIZE_T*);
  16. typedef int (__stdcall * PFN_MESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, DWORD);
  17. typedef
  18. NTSTATUS
  19. (__stdcall * PFN_ZWCREATEPROCESSEX)(
  20. PHANDLE,
  21. ACCESS_MASK,
  22. LPVOID,
  23. HANDLE,
  24. BOOLEAN,
  25. HANDLE,
  26. HANDLE,
  27. HANDLE,
  28. HANDLE
  29. );
  30. VOID HookApi(LPVOID lParam)
  31. {
  32. RemoteParam* Rpm = (RemoteParam*)lParam;
  33. PFN_ZWCREATEPROCESSEX pfnZwCreateprocessEx = (PFN_ZWCREATEPROCESSEX)Rpm->lpFunAddr;
  34. PFN_WRITEPROCESSMEMORY pfnWriteProcessMemory = (PFN_WRITEPROCESSMEMORY)Rpm->lpWriteProcessMemory;
  35. PFN_MESSAGEBOX pfnMessageBox = (PFN_MESSAGEBOX)Rpm->lpMessageBox;
  36. char sztest[8] = {';h';, ';e';, ';l';, ';l';, ';o';, ';.';, ';.';, ';\0';};
  37. PHANDLE ProcessHandle = NULL;
  38. ACCESS_MASK DesiredAccess = 0;
  39. LPVOID ObjectAttributes = NULL;
  40. HANDLE InheritFromProcessHandle = NULL;
  41. BOOLEAN InheritHandles = TRUE;
  42. HANDLE SectionHandle = NULL;
  43. HANDLE DebugPort = NULL;
  44. HANDLE ExceptionPort = NULL;
  45. HANDLE reserv = NULL;
  46. NTSTATUS Retvalue = STATUS_SUCCESS; //定义要拦截的api的默认返回植
  47. DWORD NextIpAddr = 0;
  48. DWORD dwParamaAddr = 0;
  49. DWORD temp1 = 0;
  50. __asm
  51. {
  52. MOV EAX, [EBP + 12]
  53. MOV [NextIpAddr], EAX
  54. MOV EAX, [EBP + 16]
  55. MOV [ProcessHandle], EAX
  56. MOV EAX, [EBP + 20]
  57. MOV [DesiredAccess], EAX
  58. MOV EAX, [EBP + 24]
  59. MOV [ObjectAttributes], EAX
  60. MOV EAX, [EBP + 28]
  61. MOV [InheritFromProcessHandle], EAX
  62. MOV EAX, [EBP + 32]
  63. MOV [temp1], EAX
  64. MOV EAX, [EBP + 36]
  65. MOV [SectionHandle], EAX
  66. MOV EAX, [EBP + 40]
  67. MOV [DebugPort], EAX
  68. MOV EAX, [EBP + 44]
  69. MOV [ExceptionPort], EAX
  70. MOV EAX, [EBP + 48]
  71. MOV [reserv], EAX
  72. }
  73. InheritHandles = (BOOLEAN)temp1;
  74. //这里可以做你的事情了,比如我只想弹出一个对话框,其实也可以在让api完成之后再做些东西
  75. pfnMessageBox(NULL, sztest, sztest, 0);
  76. pfnWriteProcessMemory((HANDLE)0XFFFFFFFF, Rpm->lpFunAddr, (LPCVOID)Rpm->szOldCode, 12, NULL);
  77. //让api真正执行,这里换成你要拦截的api
  78. Retvalue = pfnZwCreateprocessEx(ProcessHandle,
  79. DesiredAccess,
  80. ObjectAttributes,
  81. InheritFromProcessHandle,
  82. InheritHandles,
  83. SectionHandle,
  84. DebugPort,
  85. ExceptionPort,
  86. reserv);
  87. //再次恢复对他的拦截
  88. pfnWriteProcessMemory((HANDLE)0XFFFFFFFF, Rpm->lpFunAddr, (LPCVOID)Rpm->szNewCode, 12, NULL);
  89. DWORD dwStackSize = 12 + HOOKEDAPIPARAMNUMINBYTE;
  90. //这里对拦截函数堆栈的恢复,必须放在最后
  91. __asm
  92. {
  93. POP EDI //注意如果你编译生成的debug版本的程序则需要把这
  94. POP ESI //三个注释去掉
  95. POP EBX
  96. MOV ECX, [dwStackSize]
  97. MOV EDX, [NextIpAddr]
  98. MOV EAX, [Retvalue]
  99. MOV ESP, EBP
  100. POP EBP
  101. ADD ESP, ECX //12 + HOOKEDAPIPARAMNUMINBYTE //恢复堆栈
  102. PUSH EDX
  103. RET
  104. }
  105. }
  106. //////////////////////////////////////////////////////////////////////////
  107. //************************************************************************
  108. //模块名字:AdjustProcessPrivileges(LPCSTR)
  109. //模块功能:修改调用进程的权限
  110. //返回数值:成功返回TRUE,失败返回FALSE
  111. //参数可以为下列值:
  112. // &#35;define SE_BACKUP_NAME TEXT("SeBackupPrivilege")
  113. // &#35;define SE_RESTORE_NAME TEXT("SeRestorePrivilege")
  114. // &#35;define SE_SHUTDOWN_NAME TEXT("SeShutdownPrivilege")
  115. // &#35;define SE_DEBUG_NAME TEXT("SeDebugPrivilege")
  116. //////////////////////////////////////////////////////////////////////////
  117. BOOL AdjustProcessPrivileges(LPCSTR lpPrivilegesName)
  118. {
  119. HANDLE hToken;
  120. TOKEN_PRIVILEGES tkp;
  121. if(!OpenProcessToken((HANDLE)0XFFFFFFFF,
  122. TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
  123. {
  124. return FALSE;
  125. }
  126. if(!LookupPrivilegeV&#97;lue(NULL, lpPrivilegesName, &tkp.Privileges[0].Luid))
  127. {
  128. CloseHandle(hToken);
  129. return FALSE;
  130. }
  131. tkp.PrivilegeCount = 1;
  132. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  133. if(!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL))
  134. {
  135. CloseHandle(hToken);
  136. return FALSE;
  137. }
  138. CloseHandle(hToken);
  139. return TRUE;
  140. }
  141. int SetHook(DWORD dwPid, LPCTSTR lpApiName, LPCTSTR lpExportDllName, LPVOID lpHookFunAddr)
  142. {
  143. if(!AdjustProcessPrivileges(SE_DEBUG_NAME))
  144. {
  145. printf("-----AdjustProcessPrivileges error..\n");
  146. return -1;
  147. }
  148. printf("1:AdjustProcessPrivileges ok\n");
  149. //获取要拦截的api的地址
  150. HMODULE hExportDll = LoadLibrary(lpExportDllName);
  151. if(hExportDll == NULL)
  152. {
  153. printf("-----LoadLibrary error..\n");
  154. return -1;
  155. }
  156. LPVOID lpApiAddr = GetProcAddress(hExportDll, lpApiName);
  157. if(lpApiAddr == NULL)
  158. {
  159. printf("-----GetProcAddress %s error..\n", lpApiName);
  160. FreeLibrary(hExportDll);
  161. return -1;
  162. }
  163. //打开进程句柄
  164. HANDLE hTargetProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
  165. FALSE, dwPid);
  166. if(hTargetProcess == NULL)
  167. {
  168. printf("-----OpenProcess %d error..\n", dwPid);
  169. FreeLibrary(hExportDll);
  170. return -1;
  171. }
  172. //申请拦截函数内存空间
  173. LPVOID lpFunAddr = VirtualAllocEx(hTargetProcess, NULL, HOOKFUCTIONSIZE,
  174. MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  175. if(lpFunAddr == NULL)
  176. {
  177. printf("-----VirtualAllocEx for remotefuction error..\n");
  178. FreeLibrary(hExportDll);
  179. CloseHandle(hTargetProcess);
  180. return -1;
  181. }
  182. //申请远程参数空间
  183. LPVOID lpParamaAddr = VirtualAllocEx(hTargetProcess, NULL, sizeof(RemoteParam),
  184. MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  185. if(lpParamaAddr == NULL)
  186. {
  187. printf("-----VirtualAllocEx for remoteparam error..\n");
  188. FreeLibrary(hExportDll);
  189. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  190. CloseHandle(hTargetProcess);
  191. return -1;
  192. }
  193. printf("2:Alloc remote memory for the hook fuction and param ok\n");
  194. //设置远程参数,下一步要把参数写入要拦截的远程进程地址空间
  195. RemoteParam RParam;
  196. ZeroMemory(&RParam, sizeof(RParam));
  197. unsigned char oldcode[12];
  198. unsigned char newcode[12];
  199. DWORD dwError = 0;
  200. if(!ReadProcessMemory((HANDLE)0XFFFFFFFF,
  201. lpApiAddr,
  202. oldcode,
  203. 12,
  204. &dwError))
  205. {
  206. printf("-----ReadProcessMemory from lpApiName error..\n");
  207. FreeLibrary(hExportDll);
  208. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  209. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  210. CloseHandle(hTargetProcess);
  211. return -1;
  212. }
  213. //生成跳转指令,这将覆盖要拦截的api的前十个字节
  214. int praadd = (int)lpParamaAddr;
  215. int threadadd = (int)lpFunAddr;
  216. newcode[4] = praadd>>24;
  217. newcode[3] = (praadd<<8)>>24;
  218. newcode[2] = (praadd<<16)>>24;
  219. newcode[1] = (praadd<<24)>>24;
  220. newcode[0] = 0x68; //PUSH lpParamaAddr
  221. int offsetaddr = threadadd - (int)lpApiAddr - 10 ;
  222. newcode[9] = offsetaddr>>24;
  223. newcode[8] = (offsetaddr<<8)>>24;
  224. newcode[7] = (offsetaddr<<16)>>24;
  225. newcode[6] = (offsetaddr<<24)>>24;
  226. newcode[5] = 0xE8; //CALL lpFunAddr
  227. newcode[10] = 0x90;
  228. newcode[11] = 0x90;
  229. for(int j = 0; j < 12; j++)
  230. {
  231. RParam.szOldCode[j] = oldcode[j];
  232. RParam.szNewCode[j] = newcode[j];
  233. }
  234. RParam.lpFunAddr = lpApiAddr;
  235. HMODULE hKernel32 = LoadLibrary("Kernel32.dll");
  236. if(hKernel32 == NULL)
  237. {
  238. printf("-----LoadLibrary Kernel32.dll error..\n");
  239. FreeLibrary(hExportDll);
  240. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  241. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  242. CloseHandle(hTargetProcess);
  243. return -1;
  244. }
  245. RParam.lpWriteProcessMemory = GetProcAddress(hKernel32, "WriteProcessMemory");
  246. if(RParam.lpWriteProcessMemory == NULL)
  247. {
  248. printf("-----GetProcAddress WriteProcessMemory from Kernel32.dll error..\n");
  249. FreeLibrary(hExportDll);
  250. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  251. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  252. CloseHandle(hTargetProcess);
  253. FreeLibrary(hKernel32);
  254. return -1;
  255. }
  256. //以上皆为必须,下面可以为自己的拦截函数中所需要用的一些变量以及系统api放到参数中去
  257. HMODULE hUser32 = LoadLibrary("User32.dll");
  258. if(hUser32 == NULL)
  259. {
  260. printf("-----LoadLibrary User32.dll error..\n");
  261. FreeLibrary(hExportDll);
  262. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  263. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  264. CloseHandle(hTargetProcess);
  265. FreeLibrary(hKernel32);
  266. return -1;
  267. }
  268. RParam.lpMessageBox = GetProcAddress(hUser32, "MessageBoxA");
  269. if(RParam.lpMessageBox == NULL)
  270. {
  271. printf("-----GetProcAddress MessageBoxA from User32.dll error..\n");
  272. FreeLibrary(hExportDll);
  273. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  274. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  275. CloseHandle(hTargetProcess);
  276. FreeLibrary(hKernel32);
  277. FreeLibrary(hUser32);
  278. return -1;
  279. }
  280. FreeLibrary(hUser32);
  281. printf("3:Generate remoteparam ok\n");
  282. //下面为必须部分
  283. //把参数写入要拦截的远程进程地址空间
  284. if(!WriteProcessMemory(hTargetProcess, lpParamaAddr, (LPVOID)&RParam, sizeof(RParam), &dwError))
  285. {
  286. printf("-----WriteProcessMemory for remoteparam error..\n");
  287. FreeLibrary(hExportDll);
  288. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  289. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  290. CloseHandle(hTargetProcess);
  291. FreeLibrary(hKernel32);
  292. return -1;
  293. }
  294. printf("4:WriteProcessMemory for remoteparam ok\n");
  295. //把拦截函数体写入目标进程地址空间
  296. if(!WriteProcessMemory(hTargetProcess, lpFunAddr, lpHookFunAddr, HOOKFUCTIONSIZE, &dwError))
  297. {
  298. printf("-----WriteProcessMemory for remotefuction error..\n");
  299. FreeLibrary(hExportDll);
  300. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  301. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  302. CloseHandle(hTargetProcess);
  303. FreeLibrary(hKernel32);
  304. return -1;
  305. }
  306. printf("5:WriteProcessMemory for remotefuction ok\n");
  307. //把新的跳转指令写入要拦截的目标进程的要拦截的api的函数的前十字节
  308. if(!WriteProcessMemory(hTargetProcess, lpApiAddr , (LPVOID)newcode, 12, &dwError))
  309. {
  310. printf("-----Modify remote api error..\n");
  311. FreeLibrary(hExportDll);
  312. VirtualFreeEx(hTargetProcess, lpFunAddr, 0, MEM_RELEASE);
  313. VirtualFreeEx(hTargetProcess, lpParamaAddr, 0, MEM_RELEASE);
  314. CloseHandle(hTargetProcess);
  315. FreeLibrary(hKernel32);
  316. return -1;
  317. }
  318. printf("6:Modify remote api %s ok\n", lpApiName);
  319. //show..
  320. printf("---------------------------------------------------------------------------\n"
  321. "You hava hooked pid: %d ,and the infomation of this hooking are as follows:\n"
  322. "API name: %s\n"
  323. "API addr: 0x%.8x\n"
  324. "Module name: %s\n"
  325. "Module addr: 0x%.8x\n"
  326. "Remote parama addr: 0x%.8x\n"
  327. "Remote thread addr: 0x%.8x\n"
  328. "RemoteParam.lpFunAddr: 0x%.8x\n"
  329. "RemoteParam.lpWriteProcessMemory: 0x%.8x\n"
  330. "RemoteParam.lpMessageBox: 0x%.8x\n",
  331. dwPid,
  332. lpApiName,
  333. lpApiAddr,
  334. lpExportDllName,
  335. hExportDll,
  336. lpParamaAddr,
  337. lpFunAddr,
  338. RParam.lpFunAddr,
  339. RParam.lpWriteProcessMemory,
  340. RParam.lpMessageBox);
  341. printf("RemoteParam.szOldCode: ");
  342. for(int i = 0; i < 12; i++)
  343. {
  344. printf("0x%x ", RParam.szOldCode[i]);
  345. }
  346. printf("\nRemoteParam.szNewCode: ");
  347. for(i = 0; i < 12; i++)
  348. {
  349. printf("0x%x ", RParam.szNewCode[i]);
  350. }
  351. printf("\nThat';s all, good luck ^_^\n");
  352. Sleep(10000);
  353. //收工,清理资源
  354. FreeLibrary(hExportDll);
  355. CloseHandle(hTargetProcess);
  356. FreeLibrary(hKernel32);
  357. return 0;
  358. }
  359. int main(void)
  360. {//注意这里第一个参数是你要选择监视的进程的ID,我这里是选的我的explorer.exe
  361. SetHook(1564, "NtCreateProcessEx", "ntdll.dll", &HookApi);
  362. return 0;
  363. }
复制代码
最后当你的文件夹或者其他地方双击鼠标来运行一个程序的时候,首先会弹出一个hello窗口,点ok,该程序才会运行.

[原创]winxp下监视进程的创建

看得似懂非懂啊,我的VC编程真是要命,还得在学啊.

TOP

[原创]winxp下监视进程的创建

不错,其实操作系统提供给了我们在进程创建的时候进程回调操作的机会,看一下DDK里的
NTSTATUS
  PsSetCreateProcessNotifyRoutine(
    IN PCREATE_PROCESS_NOTIFY_ROUTINE  NotifyRoutine,
    IN BOOLEAN  Remove
    );

TOP

返回列表 回复 发帖