所以目前我有以下代码,它只是一个简单的trampoline类型挂钩,ws2_32
挂钩connect,以便最终为应用程序添加代理。有问题的区域在int __stdcall connect_FUNC(SOCKET s, const struct sockaddr* name, int namelen)
内。虽然我不需要 来理解或调用任何之后的'connect_ORI(s,name,namelen)`代理时(所有工作都在之前完成调用原始函数);理解以下不正确/奇怪的行为会很好:
在printf
正常工作并且连接成功之前调用MessageBox
,std::cout
,甚至connect_ORI(s, name, namelen)
等函数,但是,移动相同的调用({{1}在printf
导致绕行函数返回不同(不正确)的结果(-1)之后。在两个测试用例中添加注入的进程不崩溃可能很重要。
我知道不能成为connect_ORI(s, name, namelen)
/ Patch
个函数,我尝试MinHook并且它有相同的奇怪行为。另外,在RemovePatch
内修补其他功能也很好。在user32.dll
中是否有一些特殊情况或优化需要注意?我认为存在某种堆栈或帧指针/寄存器损坏但不确定是否是这种情况并且不确定如何修复它。我包含了所有代码的完整性。任何人都可以使用代码专门解释这种行为吗?
我正在使用MinGW-w64 x86_64-720-posix-sjlj-rt_v5-rev1。 32Bit DLL注入32位进程。使用-Os优化。
提前致谢。
ws2_32.dll
两个测试用例中的差异(connect_FUNC)
在调用原始函数之前printf(正常工作):
typedef int (__stdcall *connect_DEF)(SOCKET, const struct sockaddr*, int);
connect_DEF connect_ORI = NULL;
void* jmpOffset = NULL;
std::uint8_t* Patch(std::uint8_t* OrigFunc, std::uint8_t* HookFunc)
{
DWORD dwProtect = 0;
const static std::uint8_t jmp[] = {0xB8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE0};
const static std::int8_t jmp_size = sizeof(jmp) / sizeof(std::uint8_t);
static std::uint8_t HookJump[jmp_size + 1] = {jmp_size};
VirtualProtect(OrigFunc, jmp_size, PAGE_EXECUTE_READWRITE, &dwProtect);
memcpy(&HookJump[1], OrigFunc, jmp_size);
memcpy(OrigFunc, jmp, jmp_size);
memcpy(OrigFunc + 1, &HookFunc, sizeof(void*));
VirtualProtect(OrigFunc, jmp_size, dwProtect, &dwProtect);
return HookJump;
}
void RemovePatch(std::uint8_t* OrigFunc, std::uint8_t* HookJump)
{
DWORD dwProtect = 0;
VirtualProtect(OrigFunc, HookJump[0], PAGE_EXECUTE_READWRITE, &dwProtect);
memcpy(OrigFunc, &HookJump[1], HookJump[0]);
VirtualProtect(OrigFunc, HookJump[0], dwProtect, &dwProtect);
}
int __stdcall connect_FUNC(SOCKET s, const struct sockaddr* name, int namelen)
{
int Result = -1;
printf("HERE\n"); // printf works here, connect func works with printf here.
if (jmpOffset)
{
RemovePatch((uint8_t*)connect_ORI, (uint8_t*)jmpOffset);
jmpOffset = NULL;
Result = connect_ORI(s, name, namelen);
jmpOffset = (void*)Patch((uint8_t *)connect_ORI, (uint8_t*)connect_FUNC);
}
//printf("HERE\n"); // stack gets corrupted or something happens when printf is here. connect returns -1.
return Result;
}
BOOL __stdcall DllMain(HMODULE DLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
HMODULE WS2_32DLL = GetModuleHandle("ws2_32.dll");
if (WS2_32DLL)
{
connect_ORI = (connect_DEF)GetProcAddress(WS2_32DLL, "connect");
if (connect_ORI)
jmpOffset = (void*)Patch((uint8_t*)connect_ORI, (uint8_t*)connect_FUNC);
}
}
break;
case DLL_PROCESS_DETACH:
{
if (jmpOffset)
{
RemovePatch((uint8_t*)connect_ORI, (uint8_t*)jmpOffset);
}
}
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
调用原始函数后printf(无法正常工作):
LC0:
.ascii "HERE\12\0"
.text
.globl __Z12connect_FUNCjPK8sockaddri@12
.def __Z12connect_FUNCjPK8sockaddri@12; .scl 2; .type 32; .endef
__Z12connect_FUNCjPK8sockaddri@12:
pushl %ebp
movl %esp, %ebp
pushl %ebx
orl $-1, %ebx
subl $20, %esp
movl $LC0, (%esp)
call __Z6printfPKcz
movl _jmpOffset, %eax
testl %eax, %eax
je L7
movl %eax, 4(%esp)
movl _connect_ORI, %eax
movl %eax, (%esp)
call __Z11RemovePatchPhS_
movl 16(%ebp), %eax
movl $0, _jmpOffset
movl %eax, 8(%esp)
movl 12(%ebp), %eax
movl %eax, 4(%esp)
movl 8(%ebp), %eax
movl %eax, (%esp)
call *_connect_ORI
movl %eax, %ebx
movl _connect_ORI, %eax
subl $12, %esp
movl $__Z12connect_FUNCjPK8sockaddri@12, 4(%esp)
movl %eax, (%esp)
call __Z5PatchPhS_
movl %eax, _jmpOffset
L7:
movl %ebx, %eax
movl -4(%ebp), %ebx
leave
ret $12
.section .rdata,"dr"