本帖最后由 爱飞的猫 于 2023-4-10 22:56 编辑
如果只是穿透(不对函数做处理),可以尝试在加载后把导入表指向的地址改了(IAT Hook),或在 DLL 入口的时候动态 patch 函数(VirtualProtect 允许内存区域读写然后直接改);
如果地址距离过大或不方便计算相对距离,就 push / ret:
push ADDR_LO_32 ; 低 32 位
mov dword[rsp+4], ADDR_HI_32 ; 高 32 位
ret
; | 68 78563412 | push 12345678 |
; | C74424 04 22221111 | mov dword [rsp+4] , 11112222 |
; | C3 | ret |
如果地址距离没那么大,直接 jmp 过去;
jmp 0x12345678
如果同时需要调用原来的函数,调整两边函数签名一致,然后调用就好;举个例子:
// 这里只是举个例子,gdi32.dll 不一定能这样劫持加载
typedef HGDIOBJ(WINAPI* tGetStockObject)(_In_ int i);
tGetStockObject g_GetStockObjectOrig;
HANDLE g_replacementSystemFont;
// DLL 入口点初始化
g_GetStockObjectOrig = GetProcAddress(hGDI32, "GetStockObject");
// 导出
HGDIOBJ WINAPI GetStockObject(_In_ int i) {
if (i == SYSTEM_FONT) {
return g_replacementSystemFont; // 返回我自己的字体句柄
}
return g_GetStockObjectOrig(i); // 回退到系统自己的实现
}
|