从ws2_32绕道连接时出现奇怪的错误行为?

时间:2018-01-29 18:33:04

标签: c++ windows assembly hook

所以目前我有以下代码,它只是一个简单的trampoline类型挂钩,ws2_32挂钩connect,以便最终为应用程序添加代理。有问题的区域在int __stdcall connect_FUNC(SOCKET s, const struct sockaddr* name, int namelen)内。虽然我不需要 来理解或调用任何之后的'connect_ORI(s,name,namelen)`代理时(所有工作都在之前完成调用原始函数);理解以下不正确/奇怪的行为会很好:

printf正常工作并且连接成功之前调用MessageBoxstd::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"

0 个答案:

没有答案