{"id":955,"date":"2022-12-10T23:35:00","date_gmt":"2022-12-10T15:35:00","guid":{"rendered":"http:\/\/www.aqwu.net\/wp\/?p=955"},"modified":"2022-12-10T23:40:26","modified_gmt":"2022-12-10T15:40:26","slug":"stealthhook-%e4%b8%80%e7%a7%8d%e5%9c%a8%e4%b8%8d%e4%bf%ae%e6%94%b9%e5%86%85%e5%ad%98%e4%bf%9d%e6%8a%a4%e7%9a%84%e6%83%85%e5%86%b5%e4%b8%8b%e6%8c%82%e6%8e%a5%e5%87%bd%e6%95%b0%e7%9a%84%e6%96%b9","status":"publish","type":"post","link":"https:\/\/www.aqwu.net\/wp\/?p=955","title":{"rendered":"StealthHook &#8211; \u4e00\u79cd\u5728\u4e0d\u4fee\u6539\u5185\u5b58\u4fdd\u62a4\u7684\u60c5\u51b5\u4e0b\u6302\u63a5\u51fd\u6570\u7684\u65b9\u6cd5"},"content":{"rendered":"\n<p>\u5e38\u89c1\u7684\u7528\u6237\u6a21\u5f0f\u51fd\u6570\u622a\u83b7\u65b9\u6cd5\u5305\u62ec\u5185\u8054\u4ee3\u7801\u6302\u94a9\u3001IAT \u6302\u94a9\u548c\u786c\u4ef6\u65ad\u70b9\u6302\u94a9\u3002\u8fd9\u4e9b\u65b9\u6cd5\u5f88\u6709\u6548\uff0c\u4f46\u5b83\u4eec\u9700\u8981\u4fee\u6539&nbsp;.text&nbsp;\u90e8\u5206\u3001\u4f7f\u7528&nbsp;NtProtectVirtualMemory&nbsp;\u66f4\u6539\u5185\u5b58\u4fdd\u62a4\u6216\u81ea\u5b9a\u4e49\u5f02\u5e38\u5904\u7406\u7a0b\u5e8f\uff0c\u6240\u6709\u8fd9\u4e9b\u90fd\u53ef\u80fd\u662f\u201c\u5e72\u6270\u201d\u3002\u8fd9\u7bc7\u6587\u7ae0\u63cf\u8ff0\u4e86\u4e00\u79cd\u5728\u4e0d\u4fee\u6539\u5185\u5b58\u4fdd\u62a4\u7684\u60c5\u51b5\u4e0b\u79d8\u5bc6\u6302\u63a5\u51fd\u6570\u7684\u65b9\u6cd5\u3002\u901a\u8fc7\u8986\u76d6\u5d4c\u5957\u5728\u76ee\u6807\u51fd\u6570\u4e2d\u7684\u5168\u5c40\u6307\u9488\u6216\u865a\u62df\u8868\u6761\u76ee\uff0c\u53ef\u4ee5\u6302\u94a9\u51fd\u6570\u800c\u4e0d\u4f1a\u5f15\u8d77\u6000\u7591\uff0c\u56e0\u4e3a\u5176\u4e2d\u8bb8\u591a\u5185\u5b58\u533a\u57df\u5df2\u7ecf\u542f\u7528\u4e86\u5199\u5165\u6743\u9650\u3002\u8fd9\u662f\u6211\u591a\u5e74\u6765\u4e00\u76f4\u4f7f\u7528\u7684\u65b9\u6cd5\uff0c\u6548\u679c\u5f88\u597d\u3002<\/p>\n\n\n\n<p>\u539f\u6587\u94fe\u63a5\uff1ahttps:\/\/www.x86matthew.com\/view_post?id=stealth_hook<\/p>\n\n\n\n<p>\u5982\u679c\u6211\u4eec\u80fd\u591f\u622a\u83b7\u5d4c\u5957\u5728\u76ee\u6807\u51fd\u6570\u4e2d\u7684\u5b50\u51fd\u6570\uff0c\u6211\u4eec\u5c31\u53ef\u4ee5\u64cd\u7eb5\u539f\u59cb\u51fd\u6570\u7684\u6267\u884c\u6d41\u548c\u8fd4\u56de\u503c\u3002\u901a\u8fc7\u4ece\u5d4c\u5957\u51fd\u6570\u904d\u5386\u5806\u6808\uff0c\u6211\u4eec\u53ef\u4ee5\u627e\u5230\u539f\u59cb\u76ee\u6807\u51fd\u6570\u7684\u8fd4\u56de\u5730\u5740\u3002\u7136\u540e\uff0c\u6211\u4eec\u53ef\u4ee5\u7528\u65b0\u503c\u8986\u76d6\u539f\u59cb\u8fd4\u56de\u5730\u5740\uff0c\u5f3a\u5236\u7a0b\u5e8f\u5728\u7ee7\u7eed\u4f7f\u7528\u539f\u59cb\u4ee3\u7801\u4e4b\u524d\u6267\u884c\u8fdb\u4e00\u6b65\u7684\u6307\u4ee4\u3002\u8fd9\u79cd\u51fd\u6570\u6302\u94a9\u65b9\u6cd5\u4e0d\u9700\u8981\u5bf9\u53ef\u6267\u884c\u4ee3\u7801\u8fdb\u884c\u4efb\u4f55\u4fee\u6539\uff0c\u4e5f\u4e0d\u9700\u8981\u4efb\u4f55\u5185\u5b58\u4fdd\u62a4\u66f4\u6539\uff0c\u56e0\u6b64\u5f88\u96be\u4f7f\u7528\u4f20\u7edf\u6280\u672f\u8fdb\u884c\u68c0\u6d4b\u3002<\/p>\n\n\n\n<p>\u6b64\u65b9\u6cd5\u80cc\u540e\u7684\u6982\u5ff5\u76f8\u5bf9\u7b80\u5355\uff0c\u4f46\u624b\u52a8\u67e5\u627e\u5408\u9002\u7684\u6302\u94a9\u70b9\u53ef\u80fd\u65e2\u56f0\u96be\u53c8\u8017\u65f6\uff0c\u5c24\u5176\u662f\u5728\u5927\u578b\u51fd\u6570\u4e2d\u3002\u4e3a\u4e86\u7b80\u5316\u6b64\u8fc7\u7a0b\uff0c\u6211\u5f00\u53d1\u4e86\u4e00\u4e2a\u5de5\u5177\uff0c\u53ef\u4ee5\u81ea\u52a8\u6267\u884c\u6b64\u8fc7\u7a0b\uff0c\u5e76\u4e3a\u4efb\u4f55\u7ed9\u5b9a\u51fd\u6570\u5feb\u901f\u627e\u5230\u5408\u9002\u7684\u94a9\u70b9\uff08\u5982\u679c\u5b58\u5728\uff09\u3002\u8fd9\u4f7f\u5f97\u5728\u5b9e\u8df5\u4e2d\u5b9e\u73b0\u6b64\u65b9\u6cd5\u53d8\u5f97\u5bb9\u6613\uff0c\u5e76\u4e14\u540c\u65f6\u652f\u6301 32 \u4f4d\u548c 64 \u4f4d\u4ee3\u7801\u3002<\/p>\n\n\n\n<p>\u8be5\u7a0b\u5e8f\u901a\u8fc7\u626b\u63cf\u6307\u5411\u76ee\u6807\u51fd\u6570\u4e2d\u6307\u4ee4\u7684\u53ef\u5199\u6307\u9488\u6765\u6784\u5efa\u5f15\u7528\u5217\u8868\u3002\u5b83\u901a\u8fc7\u5b89\u88c5\u81ea\u5b9a\u4e49\u5f02\u5e38\u5904\u7406\u7a0b\u5e8f\u5e76\u5355\u6b65\u6267\u884c\u51fd\u6570\uff08\u4e00\u6b21\u4e00\u6761\u6307\u4ee4\uff09\u6765\u5b9e\u73b0\u6b64\u76ee\u7684\u3002\u5bf9\u4e8e\u6bcf\u6761\u6307\u4ee4\uff0c\u7a0b\u5e8f\u4f1a\u626b\u63cf\u6bcf\u4e2a\u52a0\u8f7d\u7684\u6a21\u5757\uff0c\u4ee5\u67e5\u770b\u662f\u5426\u5b58\u5728\u6307\u5411\u5f53\u524d\u6307\u4ee4\u7684\u53ef\u5199\u6307\u9488\u3002\u5f02\u5e38\u5904\u7406\u7a0b\u5e8f\u4ec5\u7531\u5f00\u53d1\u4eba\u5458\u7528\u4e8e\u521d\u59cb\u53d1\u73b0\u6f5c\u5728\u7684\u6302\u94a9\u70b9\uff0c\u6700\u7ec8\u7684\u6302\u94a9\u4ee3\u7801\u4e0d\u9700\u8981\u5b89\u88c5\u81ea\u5b9a\u4e49\u5f02\u5e38\u5904\u7406\u7a0b\u5e8f\u3002<\/p>\n\n\n\n<p>\u5728 WoW64 \u8fdb\u7a0b\u4e2d\u8fd0\u884c\u65f6\uff0c\u6211\u4eec\u65e0\u6cd5\u5355\u6b65\u8fdb\u5165\u672c\u673a 64 \u4f4d\u4ee3\u7801 &#8211; \u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u7a0b\u5e8f\u5728&nbsp;Wow64Transition&nbsp;\u51fd\u6570\u4e2d\u6355\u83b7\u4ece 32 \u4f4d\u5230 64 \u4f4d\u6a21\u5f0f\u7684\u8f6c\u6362\uff0c\u5e76\u5728\u8fd4\u56de\u5730\u5740\u8bbe\u7f6e\u786c\u4ef6\u65ad\u70b9\u3002\u5355\u6b65\u6267\u884c\u6682\u65f6\u7981\u7528\uff0c\u76f4\u5230\u76ee\u6807\u51fd\u6570\u8fd4\u56de\u5230 32 \u4f4d\u6a21\u5f0f\uff0c\u6b64\u65f6\u5b83\u5c06\u6062\u590d\u5e76\u7ee7\u7eed\u76d1\u89c6\u51fd\u6570\u3002<\/p>\n\n\n\n<p>\u521b\u5efa\u5f15\u7528\u5217\u8868\u540e\uff0c\u7a0b\u5e8f\u5c06\u4e00\u6b21\u8986\u76d6\u5217\u8868\u4e2d\u7684\u6bcf\u4e2a\u6307\u9488\uff0c\u7136\u540e\u518d\u6b21\u8fd0\u884c\u76ee\u6807\u51fd\u6570\u3002\u5982\u679c\u5728\u8fd0\u884c\u671f\u95f4\u6267\u884c\u8986\u76d6\u7684\u6307\u9488\uff0c\u5219\u8868\u660e\u5b83\u662f\u4e00\u4e2a\u6210\u529f\u7684\u6302\u94a9\u70b9\uff0c\u7a0b\u5e8f\u5c06\u4ee5\u6b64\u65b9\u5f0f\u6807\u8bb0\u5b83\u3002\u5bf9\u5217\u8868\u4e2d\u7684\u6240\u6709\u6307\u9488\u91cd\u590d\u6b64\u8fc7\u7a0b\uff0c\u76f4\u5230\u6d4b\u8bd5\u5b8c\u6240\u6709\u6f5c\u5728\u7684\u6302\u94a9\u70b9\u3002<\/p>\n\n\n\n<p>\u8be5\u7a0b\u5e8f\u8fd8\u8ba1\u7b97\u5e76\u663e\u793a\u5806\u6808\u589e\u91cf\uff0c\u8fd9\u662f\u9700\u8981\u5411\u4e0b\u79fb\u52a8\u5230\u5806\u6808\u4e2d\u7684\u5b57\u8282\u6570\u6216der \u8986\u76d6\u5b83\u6807\u8bc6\u7684\u6bcf\u4e2a\u6302\u94a9\u70b9\u7684\u539f\u59cb\u8fd4\u56de\u5730\u5740\u3002<\/p>\n\n\n\n<p>\u91cd\u8981\u7684\u662f\u8981\u8003\u8651\u6307\u5411\u6b63\u5728\u6302\u94a9\u7684\u5b50\u51fd\u6570\u7684\u6307\u9488\u53ef\u80fd\u88ab\u7a0b\u5e8f\u4e2d\u7684\u5176\u4ed6\u51fd\u6570\u8c03\u7528\u7684\u53ef\u80fd\u6027\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u5fc5\u987b\u6ce8\u610f\u786e\u4fdd\u8c03\u7528\u65b9\u662f\u76ee\u6807\u51fd\u6570\uff0c\u800c\u4e0d\u662f\u53ef\u80fd\u4f7f\u7528\u76f8\u540c\u5b50\u51fd\u6570\u7684\u5176\u4ed6\u51fd\u6570\u3002<\/p>\n\n\n\n<p>\u4f7f\u7528\u6b64\u65b9\u6cd5\u7684\u4e00\u4e2a\u6f5c\u5728\u7f3a\u70b9\u662f\u76ee\u6807\u51fd\u6570\u4e2d\u7684\u4ee3\u7801\u6d41\u53ef\u80fd\u56e0\u76ee\u6807\u6a21\u5757\u7684\u4e0d\u540c\u7248\u672c\u800c\u5f02 &#8211; \u8fd9\u53ef\u80fd\u4f1a\u4f7f\u53ef\u9760\u5730\u62e6\u622a\u51fd\u6570\u8c03\u7528\u53d8\u5f97\u66f4\u52a0\u56f0\u96be\u3002\u4e3a\u4e86\u4f7f\u7528\u6b64\u65b9\u6cd5\u63d0\u9ad8\u94a9\u5b50\u7684\u53ef\u9760\u6027\uff0c\u6211\u5efa\u8bae\u6b63\u786e\u679a\u4e3e\u5806\u6808\u5e27\uff0c\u800c\u4e0d\u662f\u4f7f\u7528\u56fa\u5b9a\u5806\u6808\u589e\u91cf\u3002\u73b0\u4ee3\u63a7\u5236\u6d41\u5f3a\u5236\u65b9\u6cd5\u5c06\u6765\u53ef\u80fd\u4f1a\u6709\u6548\u5730\u9632\u6b62\u8fd9\u4e9b\u7c7b\u578b\u7684\u94a9\u5b50\u3002<\/p>\n\n\n\n<p>\u4e3a\u4e86\u6f14\u793a\uff0c\u6211\u4eec\u5c06\u4f7f\u7528\u8be5\u5de5\u5177\u5728&nbsp;CreateFileA&nbsp;\u51fd\u6570\u4e2d\u641c\u7d22\u6302\u94a9\u70b9\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>StealthHook - x86matthew\nwww.x86matthew.com\n\nSearching for hooking points...\n\nInstruction 0x777B3440 referenced at KERNELBASE.dll!0x7785FA7C (sect: .data, virt_addr: 0x1DFA7C, stack delta: 0x30)\nInstruction 0x77783AB0 referenced at KERNELBASE.dll!0x7785F650 (sect: .data, virt_addr: 0x1DF650, stack delta: 0x100)\n\nFound 2 potential hooking points, testing...\n\nOverwriting reference: 0x7785FA7C...\nCalling target function...\nHook caught successfully!\n\nOverwriting reference: 0x7785F650...\nCalling target function...\nHook caught successfully!\n\nFinished - found 2 successful hooking points<\/code><\/pre>\n\n\n\n<p>\u6b63\u5982\u6211\u4eec\u5728\u4e0a\u9762\u770b\u5230\u7684\uff0c\u8be5\u5de5\u5177\u53d1\u73b0\u4e86\u4e24\u4e2a\u9002\u5408\u6302\u94a9&nbsp;CreateFileA&nbsp;\u7684\u53ef\u5199\u5168\u5c40\u6307\u9488\u3002\u901a\u8fc7\u67e5\u770b\u8c03\u8bd5\u7b26\u53f7\uff0c\u6211\u4eec\u53ef\u4ee5\u770b\u5230\u8fd9\u4e24\u4e2a\u51fd\u6570\u5206\u522b\u662f_pfnEightBitStringToUnicodeString\u548cfeclient_EfsClientFreeProtectorList\u3002\u7531\u4e8efeclient_EfsClientFreeProtectorList\u51fd\u6570\u4e0d\u5e38\u7528\uff08\u4e0e_pfnEightBitStringToUnicodeString\u4e0d\u540c\uff09\uff0c\u56e0\u6b64\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\u4f7f\u7528\u8fd9\u662f\u6700\u4f73\u9009\u62e9\u3002<\/p>\n\n\n\n<p>\u4e0b\u9762\u7684\u4ee3\u7801\u5c55\u793a\u4e86\u5982\u4f55\u4f7f\u7528\u4e0a\u9762\u53d1\u73b0\u7684\u4fe1\u606f\u5728 32 \u4f4d\u6d4b\u8bd5\u7a0b\u5e8f\u4e2d\u94a9\u4f4f\u548c\u64cd\u4f5c&nbsp;CreateFileA&nbsp;\u8c03\u7528\u7684\u8fd4\u56de\u503c\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code has-small-font-size\"><code>#include &lt;stdio.h&gt;\n#include &lt;windows.h&gt;\n\nDWORD dwGlobal_OrigCreateFileReturnAddr = 0;\nDWORD dwGlobal_OrigReferenceAddr = 0;\n\nvoid __declspec(naked) ModifyReturnValue()\n{\n\t\/\/ the original return address for the CreateFile call redirects to here\n\t_asm\n\t{\n\t\t\/\/ CreateFile complete - overwrite return value\n\t\tmov eax, 0x12345678\n\n\t\t\/\/ continue original execution flow (ecx is safe to overwrite at this point)\n\t\tmov ecx, dwGlobal_OrigCreateFileReturnAddr\n\t\tjmp ecx\n\t}\n}\n\nvoid __declspec(naked) HookStub()\n{\n\t\/\/ the hooked global pointer nested within CreateFile redirects to here\n\t_asm\n\t{\n\t\t\/\/ store original CreateFile return address\n\t\tmov eax, dword ptr &#91;esp + 0x100]\n\t\tmov dwGlobal_OrigCreateFileReturnAddr, eax\n\n\t\t\/\/ overwrite the CreateFile return address\n\t\tlea eax, ModifyReturnValue\n\t\tmov dword ptr &#91;esp + 0x100], eax\n\n\t\t\/\/ continue original execution flow\n\t\tmov eax, dwGlobal_OrigReferenceAddr\n\t\tjmp eax\n\t}\n}\n\nDWORD InstallHook()\n{\n\tBYTE *pModuleBase = NULL;\n\tBYTE *pHookAddr = NULL;\n\n\t\/\/ get base address of kernelbase.dll\n\tpModuleBase = (BYTE*)GetModuleHandle(\"kernelbase.dll\");\n\tif(pModuleBase == NULL)\n\t{\n\t\treturn 1;\n\t}\n\n\t\/\/ get ptr to function reference\n\tpHookAddr = pModuleBase + 0x1DF650;\n\n\t\/\/ store original value\n\tdwGlobal_OrigReferenceAddr = *(DWORD*)pHookAddr;\n\n\t\/\/ overwrite ptr to call HookStub\n\t*(DWORD*)pHookAddr = (DWORD)HookStub;\n\n\treturn 0;\n}\n\nint main()\n{\n\tHANDLE hFile = NULL;\n\n\t\/\/ create temporary file (without hook)\n\tprintf(\"Creating file #1...\\n\");\n\thFile = CreateFile(\"temp_file_1.txt\", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\n\tprintf(\"hFile: 0x%X\\n\\n\", hFile);\n\n\t\/\/ install hook\n\tprintf(\"Installing hook...\\n\\n\");\n\tif(InstallHook() != 0)\n\t{\n\t\treturn 1;\n\t}\n\n\t\/\/ create temporary file (with hook)\n\tprintf(\"Creating file #2...\\n\");\n\thFile = CreateFile(\"temp_file_2.txt\", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\n\tprintf(\"hFile: 0x%X\\n\\n\", hFile);\n\n\treturn 0;\n}\n<\/code><\/pre>\n\n\n\n<p>\u8be5\u6d4b\u8bd5\u7a0b\u5e8f\u7684\u7ed3\u679c\u5982\u4e0b\u6240\u793a\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Creating file #1...\nhFile: 0xDC\n\nInstalling hook...\n\nCreating file #2...\nhFile: 0x12345678<\/code><\/pre>\n\n\n\n<p>\u8f93\u51fa\u663e\u793a\u7b2c\u4e00\u4e2a\u521b\u5efa\u6587\u4ef6\u8c03\u7528\u6b63\u5e38\u5b8c\u6210\u3002\u5b89\u88c5\u94a9\u5b50\u540e\u7684\u7b2c\u4e8c\u4e2a\u8c03\u7528\u8fd4\u56de\u4e86\u6211\u4eec\u7684\u94a9\u5b50\u503c&nbsp;0x12345678\u3002<\/p>\n\n\n\n<p>\u8be5\u5de5\u5177\u7684\u5b8c\u6574\u6e90\u4ee3\u7801\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;stdio.h>\n#include &lt;windows.h>\n\n#define DEBUG_REGISTER_EXEC_DR0 0x1\n#define DEBUG_REGISTER_EXEC_DR1 0x4\n#define DEBUG_REGISTER_EXEC_DR2 0x10\n#define DEBUG_REGISTER_EXEC_DR3 0x40\n\n#define SINGLE_STEP_FLAG 0x100\n\n#define MAXIMUM_STORED_ADDRESS_COUNT 1024\n\n#define OVERWRITE_REFERENCE_ADDRESS_VALUE 1\n\n#if _WIN64\n#define NATIVE_VALUE ULONGLONG\n#define CURRENT_EXCEPTION_STACK_PTR ExceptionInfo->ContextRecord->Rsp\n#define CURRENT_EXCEPTION_INSTRUCTION_PTR ExceptionInfo->ContextRecord->Rip\n#else\n#define NATIVE_VALUE DWORD\n#define CURRENT_EXCEPTION_STACK_PTR ExceptionInfo->ContextRecord->Esp\n#define CURRENT_EXCEPTION_INSTRUCTION_PTR ExceptionInfo->ContextRecord->Eip\n#endif\n\nstruct UNICODE_STRING\n{\n\tUSHORT Length;\n\tUSHORT MaximumLength;\n\tPWSTR Buffer;\n};\n\nstruct PEB_LDR_DATA\n{\n\tDWORD Length;\n\tDWORD Initialized;\n\tPVOID SsHandle;\n\tLIST_ENTRY InLoadOrderModuleList;\n\tLIST_ENTRY InMemoryOrderModuleList;\n\tLIST_ENTRY InInitializationOrderModuleList;\n};\n\nstruct LDR_DATA_TABLE_ENTRY\n{\n\tLIST_ENTRY InLoadOrderLinks;\n\tLIST_ENTRY InMemoryOrderLinks;\n\tLIST_ENTRY InInitializationOrderLinks;\n\tPVOID DllBase;\n\tPVOID EntryPoint;\n\tPVOID SizeOfImage;\n\tUNICODE_STRING FullDllName;\n\tUNICODE_STRING BaseDllName;\n\tPVOID Reserved5&#91;3];\n\tPVOID Reserved6;\n\tULONG TimeDateStamp;\n};\n\nstruct PEB\n{\n\tBYTE Reserved1&#91;2];\n\tBYTE BeingDebugged;\n\tBYTE Reserved2&#91;1];\n\tPVOID Reserved3&#91;1];\n\tPVOID ImageBaseAddress;\n\tPEB_LDR_DATA *Ldr;\n\t\/\/ .....\n};\n\nDWORD dwGlobal_TraceStarted = 0;\nDWORD dwGlobal_AddressCount = 0;\nDWORD dwGlobal_SuccessfulHookCount = 0;\nDWORD dwGlobal_CurrHookExecuted = 0;\nNATIVE_VALUE dwGlobal_Wow64TransitionStub = 0;\nNATIVE_VALUE dwGlobal_InitialStackPtr = 0;\nNATIVE_VALUE dwGlobal_OriginalReferenceValue = 0;\nNATIVE_VALUE dwGlobal_AddressList&#91;MAXIMUM_STORED_ADDRESS_COUNT];\nBYTE *pGlobal_ExeBase = NULL;\n\nDWORD ExecuteTargetFunction();\n\nDWORD ScanModuleForAddress(BYTE *pModuleBase, char *pModuleName, NATIVE_VALUE dwAddr, NATIVE_VALUE dwStackPtr)\n{\n\tIMAGE_DOS_HEADER *pImageDosHeader = NULL;\n\tIMAGE_NT_HEADERS *pImageNtHeader = NULL;\n\tIMAGE_SECTION_HEADER *pCurrSectionHeader = NULL;\n\tDWORD dwReadOffset = 0;\n\tBYTE *pCurrPtr = NULL;\n\tMEMORY_BASIC_INFORMATION MemoryBasicInfo;\n\tDWORD dwStackDelta = 0;\n\n\t\/\/ get dos header\n\tpImageDosHeader = (IMAGE_DOS_HEADER *)pModuleBase;\n\tif(pImageDosHeader->e_magic != 0x5A4D)\n\t{\n\t\treturn 1;\n\t}\n\n\t\/\/ get nt header\n\tpImageNtHeader = (IMAGE_NT_HEADERS *)(pModuleBase + pImageDosHeader->e_lfanew);\n\tif(pImageNtHeader->Signature != IMAGE_NT_SIGNATURE)\n\t{\n\t\treturn 1;\n\t}\n\n\t\/\/ loop through all sections\n\tfor(DWORD i = 0; i &lt; pImageNtHeader->FileHeader.NumberOfSections; i++)\n\t{\n\t\t\/\/ get current section header\n\t\tpCurrSectionHeader = (IMAGE_SECTION_HEADER *)((BYTE *)&amp;pImageNtHeader->OptionalHeader + pImageNtHeader->FileHeader.SizeOfOptionalHeader + (i * sizeof(IMAGE_SECTION_HEADER)));\n\n\t\t\/\/ ignore executable sections\n\t\tif(pCurrSectionHeader->Characteristics &amp; IMAGE_SCN_MEM_EXECUTE)\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\n\t\t\/\/ scan current section for the target address\n\t\tdwReadOffset = pCurrSectionHeader->VirtualAddress;\n\t\tfor(DWORD ii = 0; ii &lt; pCurrSectionHeader->Misc.VirtualSize \/ sizeof(NATIVE_VALUE); ii++)\n\t\t{\n\t\t\t\/\/ check if the current value contains the target address\n\t\t\tpCurrPtr = pModuleBase + dwReadOffset;\n\t\t\tif(*(NATIVE_VALUE *)pCurrPtr == dwAddr)\n\t\t\t{\n\t\t\t\t\/\/ found target address - check memory protection\n\t\t\t\tmemset((void *)&amp;MemoryBasicInfo, 0, sizeof(MemoryBasicInfo));\n\t\t\t\tif(VirtualQuery(pCurrPtr, &amp;MemoryBasicInfo, sizeof(MemoryBasicInfo)) != 0)\n\t\t\t\t{\n\t\t\t\t\t\/\/ check if the current region is writable\n\t\t\t\t\tif(MemoryBasicInfo.Protect == PAGE_EXECUTE_READWRITE || MemoryBasicInfo.Protect == PAGE_READWRITE)\n\t\t\t\t\t{\n\t\t\t\t\t\t\/\/ ensure the address list is not full\n\t\t\t\t\t\tif(dwGlobal_AddressCount >= MAXIMUM_STORED_ADDRESS_COUNT)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tprintf(\"Error: Address list is full\\n\");\n\t\t\t\t\t\t\treturn 1;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\/\/ store current address in list\n\t\t\t\t\t\tdwGlobal_AddressList&#91;dwGlobal_AddressCount] = (NATIVE_VALUE)pCurrPtr;\n\t\t\t\t\t\tdwGlobal_AddressCount++;\n\n\t\t\t\t\t\t\/\/ calculate stack delta\n\t\t\t\t\t\tdwStackDelta = (DWORD)(dwGlobal_InitialStackPtr - dwStackPtr);\n\n\t\t\t\t\t\tprintf(\"Instruction 0x%p referenced at %s!0x%p (sect: %s, virt_addr: 0x%X, stack delta: 0x%X)\\n\", (void*)dwAddr, pModuleName, (void*)pCurrPtr, pCurrSectionHeader->Name, dwReadOffset, dwStackDelta);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t\/\/ increase read offset\n\t\t\tdwReadOffset += sizeof(NATIVE_VALUE);\n\t\t}\n\t}\n\n\treturn 0;\n}\nDWORD ScanAllModulesForAddress(NATIVE_VALUE dwAddr, NATIVE_VALUE dwStackPtr)\n{\n\tDWORD dwPEB = 0;\n\tPEB *pPEB = NULL;\n\tLDR_DATA_TABLE_ENTRY *pCurrEntry = NULL;\n\tLIST_ENTRY *pCurrListEntry = NULL;\n\tDWORD dwEntryOffset = 0;\n\tchar szModuleName&#91;512];\n\tDWORD dwStringLength = 0;\n\n\t\/\/ get PEB ptr\n#if _WIN64\n\tpPEB = (PEB *)__readgsqword(0x60);\n#else\n\tpPEB = (PEB *)__readfsdword(0x30);\n#endif\n\n\t\/\/ get InMemoryOrderLinks offset in structure\n\tdwEntryOffset = (DWORD)((BYTE *)&amp;pCurrEntry->InLoadOrderLinks - (BYTE *)pCurrEntry);\n\n\t\/\/ get first link\n\tpCurrListEntry = pPEB->Ldr->InLoadOrderModuleList.Flink;\n\n\t\/\/ enumerate all modules\n\tfor(;;)\n\t{\n\t\t\/\/ get ptr to current module entry\n\t\tpCurrEntry = (LDR_DATA_TABLE_ENTRY *)((BYTE *)pCurrListEntry - dwEntryOffset);\n\n\t\t\/\/ check if this is the final entry\n\t\tif(pCurrEntry->DllBase == 0)\n\t\t{\n\t\t\t\/\/ end of module list\n\t\t\tbreak;\n\t\t}\n\n\t\t\/\/ ignore main exe module\n\t\tif(pCurrEntry->DllBase != pGlobal_ExeBase)\n\t\t{\n\t\t\t\/\/ convert module name to ansi\n\t\t\tdwStringLength = pCurrEntry->BaseDllName.Length \/ sizeof(wchar_t);\n\t\t\tif(dwStringLength > sizeof(szModuleName) - 1)\n\t\t\t{\n\t\t\t\tdwStringLength = sizeof(szModuleName) - 1;\n\t\t\t}\n\t\t\tmemset(szModuleName, 0, sizeof(szModuleName));\n\t\t\twcstombs(szModuleName, pCurrEntry->BaseDllName.Buffer, dwStringLength);\n\n\t\t\t\/\/ scan current module\n\t\t\tScanModuleForAddress((BYTE *)pCurrEntry->DllBase, szModuleName, dwAddr, dwStackPtr);\n\t\t}\n\n\t\t\/\/ get next module entry in list\n\t\tpCurrListEntry = pCurrListEntry->Flink;\n\t}\n\n\treturn 0;\n}\nLONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ExceptionInfo)\n{\n\tNATIVE_VALUE dwReturnAddress = 0;\n\n\t\/\/ check exception code\n\tif(ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_SINGLE_STEP)\n\t{\n\t\tif(dwGlobal_TraceStarted == 0)\n\t\t{\n\t\t\t\/\/ trace not started - ensure the current eip is the target function\n\t\t\tif(CURRENT_EXCEPTION_INSTRUCTION_PTR != ExceptionInfo->ContextRecord->Dr0)\n\t\t\t{\n\t\t\t\treturn EXCEPTION_CONTINUE_SEARCH;\n\t\t\t}\n\n\t\t\t\/\/ store original stack pointer\n\t\t\tdwGlobal_InitialStackPtr = CURRENT_EXCEPTION_STACK_PTR;\n\n\t\t\t\/\/ set hardware breakpoint on the original return address\n\t\t\tExceptionInfo->ContextRecord->Dr1 = *(NATIVE_VALUE *)dwGlobal_InitialStackPtr;\n\n\t\t\t\/\/ initial trace started\n\t\t\tdwGlobal_TraceStarted = 1;\n\t\t}\n\n\t\t\/\/ set debug control field\n\t\tExceptionInfo->ContextRecord->Dr7 = DEBUG_REGISTER_EXEC_DR1;\n\n\t\t\/\/ check current instruction pointer\n\t\tif(CURRENT_EXCEPTION_INSTRUCTION_PTR == dwGlobal_Wow64TransitionStub)\n\t\t{\n\t\t\t\/\/ we have hit the wow64 transition stub - don't single step here, set a breakpoint on the current return address instead\n\t\t\tdwReturnAddress = *(NATIVE_VALUE *)CURRENT_EXCEPTION_STACK_PTR;\n\t\t\tExceptionInfo->ContextRecord->Dr0 = dwReturnAddress;\n\t\t\tExceptionInfo->ContextRecord->Dr7 |= DEBUG_REGISTER_EXEC_DR0;\n\t\t}\n\t\telse if(CURRENT_EXCEPTION_INSTRUCTION_PTR == ExceptionInfo->ContextRecord->Dr1)\n\t\t{\n\t\t\t\/\/ we have reached the original return address - remove all breakpoints\n\t\t\tExceptionInfo->ContextRecord->Dr7 = 0;\n\t\t}\n\t\telse\n\t\t{\n\t\t\t\/\/ scan all modules for the current instruction pointer\n\t\t\tScanAllModulesForAddress(CURRENT_EXCEPTION_INSTRUCTION_PTR, CURRENT_EXCEPTION_STACK_PTR);\n\n\t\t\t\/\/ single step\n\t\t\tExceptionInfo->ContextRecord->EFlags |= SINGLE_STEP_FLAG;\n\t\t}\n\n\t\t\/\/ continue execution\n\t\treturn EXCEPTION_CONTINUE_EXECUTION;\n\t}\n\telse if(ExceptionInfo->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION)\n\t{\n\t\t\/\/ access violation - check if the eip matches the expected value\n\t\tif(CURRENT_EXCEPTION_INSTRUCTION_PTR != OVERWRITE_REFERENCE_ADDRESS_VALUE)\n\t\t{\n\t\t\treturn EXCEPTION_CONTINUE_SEARCH;\n\t\t}\n\n\t\t\/\/ caught current hook successfully\n\t\tdwGlobal_CurrHookExecuted = 1;\n\n\t\t\/\/ restore correct instruction pointer\n\t\tCURRENT_EXCEPTION_INSTRUCTION_PTR = dwGlobal_OriginalReferenceValue;\n\n\t\t\/\/ continue execution\n\t\treturn EXCEPTION_CONTINUE_EXECUTION;\n\t}\n\n\treturn EXCEPTION_CONTINUE_SEARCH;\n}\nDWORD InitialiseTracer()\n{\n\tNATIVE_VALUE dwWow64Transition = 0;\n\tPVOID(WINAPI * RtlAddVectoredExceptionHandler)(DWORD dwFirstHandler, void *pExceptionHandler) = NULL;\n\tHMODULE hNtdllBase = NULL;\n\n\t\/\/ store exe base\n\tpGlobal_ExeBase = (BYTE *)GetModuleHandleA(NULL);\n\tif(pGlobal_ExeBase == NULL)\n\t{\n\t\treturn 1;\n\t}\n\n\t\/\/ get ntdll base\n\thNtdllBase = GetModuleHandleA(\"ntdll.dll\");\n\tif(hNtdllBase == NULL)\n\t{\n\t\treturn 1;\n\t}\n\n\t\/\/ get RtlAddVectoredExceptionHandler function ptr\n\tRtlAddVectoredExceptionHandler = (void *(WINAPI*)(unsigned long, void *))GetProcAddress(hNtdllBase, \"RtlAddVectoredExceptionHandler\");\n\tif(RtlAddVectoredExceptionHandler == NULL)\n\t{\n\t\treturn 1;\n\t}\n\n\t\/\/ add exception handler\n\tif(RtlAddVectoredExceptionHandler(1, (void *)ExceptionHandler) == NULL)\n\t{\n\t\treturn 1;\n\t}\n\n\t\/\/ find Wow64Transition export\n\tdwWow64Transition = (NATIVE_VALUE)GetProcAddress(hNtdllBase, \"Wow64Transition\");\n\tif(dwWow64Transition != 0)\n\t{\n\t\t\/\/ get Wow64Transition stub address\n\t\tdwGlobal_Wow64TransitionStub = *(NATIVE_VALUE *)dwWow64Transition;\n\t}\n\n\treturn 0;\n}\nDWORD BeginTrace(BYTE *pTargetFunction)\n{\n\tCONTEXT DebugThreadContext;\n\n\t\/\/ reset values\n\tdwGlobal_TraceStarted = 0;\n\tdwGlobal_SuccessfulHookCount = 0;\n\tdwGlobal_AddressCount = 0;\n\n\t\/\/ set initial debug context - hardware breakpoint on target function\n\tmemset((void *)&amp;DebugThreadContext, 0, sizeof(DebugThreadContext));\n\tDebugThreadContext.ContextFlags = CONTEXT_DEBUG_REGISTERS;\n\tDebugThreadContext.Dr0 = (NATIVE_VALUE)pTargetFunction;\n\tDebugThreadContext.Dr7 = DEBUG_REGISTER_EXEC_DR0;\n\tif(SetThreadContext(GetCurrentThread(), &amp;DebugThreadContext) == 0)\n\t{\n\t\treturn 1;\n\t}\n\n\t\/\/ execute the target function\n\tExecuteTargetFunction();\n\n\treturn 0;\n}\n\nDWORD TestHooks()\n{\n\t\/\/ attempt to hook the target function at all referenced instructions found earlier\n\tfor(DWORD i = 0; i &lt; dwGlobal_AddressCount; i++)\n\t{\n\t\tprintf(\"\\nOverwriting reference: 0x%p...\\n\", (void*)dwGlobal_AddressList&#91;i]);\n\n\t\t\/\/ reset flag\n\t\tdwGlobal_CurrHookExecuted = 0;\n\n\t\t\/\/ store original value\n\t\tdwGlobal_OriginalReferenceValue = *(NATIVE_VALUE *)dwGlobal_AddressList&#91;i];\n\n\t\t\/\/ overwrite referenced value with placeholder value\n\t\t*(NATIVE_VALUE *)dwGlobal_AddressList&#91;i] = OVERWRITE_REFERENCE_ADDRESS_VALUE;\n\n\t\tprintf(\"Calling target function...\\n\");\n\n\t\t\/\/ execute target function\n\t\tExecuteTargetFunction();\n\n\t\t\/\/ restore original value\n\t\t*(NATIVE_VALUE *)dwGlobal_AddressList&#91;i] = dwGlobal_OriginalReferenceValue;\n\n\t\t\/\/ check if the hook was executed\n\t\tif(dwGlobal_CurrHookExecuted == 0)\n\t\t{\n\t\t\t\/\/ hook wasn't executed - ignore\n\t\t\tprintf(\"Failed to catch hook\\n\");\n\t\t}\n\t\telse\n\t\t{\n\t\t\t\/\/ hook was executed - this address can be used to hook the target function\n\t\t\tprintf(\"Hook caught successfully!\\n\");\n\t\t\tdwGlobal_SuccessfulHookCount++;\n\t\t}\n\t}\n\n\treturn 0;\n}\n\nDWORD ExecuteTargetFunction()\n{\n\t\/\/ call the target function\n\tCreateFileA(\"temp_file.txt\", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);\n\n\treturn 0;\n}\n\/\/ www.x86matthew.com\nint main()\n{\n\tprintf(\"StealthHook - x86matthew\\n\");\n\tprintf(\"www.x86matthew.com\\n\\n\");\n\n\t\/\/ initialise tracer\n\tif(InitialiseTracer() != 0)\n\t{\n\t\treturn 1;\n\t}\n\n\tprintf(\"Searching for hooking points...\\n\\n\");\n\n\t\/\/ begin trace\n\tif(BeginTrace((BYTE *)CreateFileA) != 0)\n\t{\n\t\treturn 1;\n\t}\n\n\t\/\/ check if any referenced addresses were found\n\tif(dwGlobal_AddressCount == 0)\n\t{\n\t\t\/\/ none found\n\t\tprintf(\"No potential hooking points found\\n\");\n\t}\n\telse\n\t{\n\t\tprintf(\"\\nFound %u potential hooking points, testing...\\n\", dwGlobal_AddressCount);\n\n\t\t\/\/ test all of the potential hooks\n\t\tif(TestHooks() != 0)\n\t\t{\n\t\t\treturn 1;\n\t\t}\n\t}\n\n\t\/\/ finished\n\tprintf(\"\\nFinished - found %u successful hooking points\\n\\n\", dwGlobal_SuccessfulHookCount);\n\n\treturn 0;\n}\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>\u5e38\u89c1\u7684\u7528\u6237\u6a21\u5f0f\u51fd\u6570\u622a\u83b7\u65b9\u6cd5\u5305\u62ec\u5185\u8054\u4ee3\u7801\u6302\u94a9\u3001IAT \u6302\u94a9\u548c\u786c\u4ef6\u65ad\u70b9\u6302\u94a9\u3002\u8fd9\u4e9b\u65b9\u6cd5\u5f88\u6709\u6548\uff0c\u4f46\u5b83\u4eec\u9700\u8981\u4fee\u6539&#038;nbs [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[45,37],"tags":[],"class_list":["post-955","post","type-post","status-publish","format-standard","hentry","category-x86matthew-com","category-samples"],"views":2886,"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/www.aqwu.net\/wp\/index.php?rest_route=\/wp\/v2\/posts\/955","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aqwu.net\/wp\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aqwu.net\/wp\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aqwu.net\/wp\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aqwu.net\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=955"}],"version-history":[{"count":4,"href":"https:\/\/www.aqwu.net\/wp\/index.php?rest_route=\/wp\/v2\/posts\/955\/revisions"}],"predecessor-version":[{"id":960,"href":"https:\/\/www.aqwu.net\/wp\/index.php?rest_route=\/wp\/v2\/posts\/955\/revisions\/960"}],"wp:attachment":[{"href":"https:\/\/www.aqwu.net\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=955"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aqwu.net\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=955"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aqwu.net\/wp\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=955"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}