需要准备的工具
- Microsoft Visual Studio开发工具。
- IDA pro动态调试工具。
- Process Hacker 2进程监控工具。
- 被远程注入的exe程序。(以crackme.exe为例)
远程注入dll进行虚表hook
一、IDA pro反编译找到函数逻辑地址
- 使用IDA pro打开crackme.exe,开启动态调试。
- 找到需要hook的地方,一般是系统库里的函数,以jmp cs:EnterCriticalSection为例。(其中EnterCriticalSection可以是其他系统函数)
- 双击函数名,找到其真实地址为0x7ff6472bd0c8。
- 找到程序的起始地址为0x7ff6472a0000。
- 可以计算得出EnterCriticalSection函数相对程序入口的逻辑地址为0x7ff6472bd0c8-0x7ff6472a0000=0x1d0c8。
二、VS编写虚表hook动态链接库
- 打开Visual Studio,创建一个DLL项目。
- 将dllmain.cpp修改为以下代码,其中其中0x1d0c8修改为第一步中函数逻辑地址,Hooked_VtableFunc函数中写自己想要执行的代码。
#include "pch.h"
#include
#include
#include
typedef void(__fastcall* VtableFunc_t)();
VtableFunc_t VtableFunc = nullptr;
void __fastcall Hooked_VtableFunc() {
printf("正确\n");
system("pause");
return VtableFunc();
}
void HookVtableTest() {
uintptr_t VtableAddress = (uintptr_t)GetModuleHandleA(0) + 0x1d0c8;
DWORD old_protect = 0;
VirtualProtect((LPVOID)VtableAddress, 0x8, PAGE_EXECUTE_READWRITE, &old_protect);
*(uintptr_t*)(VtableAddress) = (uintptr_t)Hooked_VtableFunc;
VirtualProtect((LPVOID)VtableAddress, 0x8, old_protect, &old_protect);
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
HookVtableTest(); break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 生成解决方案后,可以得到虚表hook的dll文件。dll文件一般在“项目路径/x64/Debug/”。
三、VS编写远程注入代码
- 打开Visual Studio,创建一个控制台应用。
- 将以下代码复制到cpp源文件中,其中main函数的第一行wStr变量修改为第二步中生成的dll的路径(windows路径下的\需要用\转译),第二行修改为进程名(可以打开任务管理器查看)。
#include
#include
#include
#include
#include
using namespace std;
bool Inject(DWORD dwId, WCHAR* szPath)
{
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwId);
LPVOID pRemoteAddress = VirtualAllocEx(
hProcess,
NULL,
wcslen(szPath) * 2,
MEM_COMMIT,
PAGE_READWRITE
);
DWORD dwWriteSize = 0;
BOOL bRet = WriteProcessMemory(hProcess, pRemoteAddress, szPath, wcslen(szPath) * 2, NULL);
HMODULE hModule = GetModuleHandle(L"kernel32.dll");
if (!hModule)
{
printf("GetModuleHandle Error !\n");
GetLastError();
CloseHandle(hProcess);
return FALSE;
}
LPTHREAD_START_ROUTINE dwLoadAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "LoadLibraryW");
if (!dwLoadAddr)
{
printf("GetProcAddress Error !\n");
CloseHandle(hProcess);
CloseHandle(hModule);
return FALSE;
}
HANDLE hThread = CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START_ROUTINE)dwLoadAddr,
pRemoteAddress,
NULL,
NULL
);
return 0;
}
DWORD GetPid(WCHAR* szName)
{
HANDLE hprocessSnap = NULL;
PROCESSENTRY32 pe32 = { 0 };
hprocessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pe32.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hprocessSnap, &pe32))
{
do {
if (!wcscmp(szName, pe32.szExeFile))
return (int)pe32.th32ProcessID;
} while (Process32Next(hprocessSnap, &pe32));
}
else
CloseHandle(hprocessSnap);
return 0;
}
int main()
{
wchar_t wStr[] = L"C:\\Users\\zhang\\source\\repos\\crackme_dll\\x64\\Release\\crackme_dll.dll";
WCHAR S[] = L"crackme.exe";
DWORD SS = GetPid(S);
printf("目标窗口的进程PID为:%d\n", SS);
Inject(SS, wStr);
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 生成解决方案后,可以得到远程注入的exe文件。exe文件一般在“项目路径/x64/Debug/”。
四、远程注入dll并使用Process Hack 2观察注入结果
- 管理员运行crackme.exe,管理员运行Process Hacker 2,搜索crackme,并查看Modules,可以看到没有我们注入的dll。
- 管理员运行第三步中exe程序,再次打开Process Hacker 2,可以看到crackme_dll.dll已经注入成功。
- 可以看到第二步代码中Hooked_VtableFunc函数成功执行
如果帮到你了,麻烦点个赞。如果暂时用不到,不妨也收藏以下,可能以后会有用。教程中有错误的地方也麻烦留言或私信指正,尽量及时修正。