吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 460|回复: 0
收起左侧

[求助] VMP下HOOK遇到的问题

[复制链接]
BC2023 发表于 2023-12-23 11:20
关注了大神[@你与明日 ,ID:251657]的作品《DLL巧妙的绕过被VMP壳HOOK的ZwProtectVirtualMemory》一文,刚好在写一款从EXE导出数据的小工具,实际操作中碰到了闪退的问题,需要请大神们给予指志。
[C++] 纯文本查看 复制代码
PBYTE CHook::LoadFileContext(CString filename, CString apifun) 
{
    HANDLE hFile; 
    PBYTE hDllContext = NULL; 
    HMODULE ntdllAddr = NULL; 
    CString libname = filename; 
    UINT pos = filename.ReverseFind('\\'); 
    hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL);
    if (hFile == INVALID_HANDLE_VALUE) {
        MessageBox(0, ("CreateFileError"), ("error"), MB_OK);
        return NULL;
    }

    if(pos != -1) {
        libname = filename.Right(filename.GetLength()-pos-1); 
    }
    ntdllAddr = LoadLibrary(libname);
    PBYTE apiAddr = (PBYTE)GetProcAddress(ntdllAddr, apifun);
    if (apiAddr == NULL || ntdllAddr == NULL) {
        MessageBox(0, ("LoadLibrary|GetProcAddress,Error"), ("error"), MB_OK);
        CloseHandle(hFile);
        return NULL;
    }

    //把Ntdll读入进内存
    DWORD dwHighSize = 0;
    DWORD dwLowSize = GetFileSize(hFile, &dwHighSize);
    BYTE* pBuff = new BYTE[dwLowSize + dwHighSize]();
    DWORD  dwFileSize = 0;
    ReadFile(hFile, pBuff, dwLowSize + dwHighSize, &dwFileSize, NULL);

    //寻找所在区段
    PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBuff;
    PIMAGE_NT_HEADERS32 pNtHeader = (PIMAGE_NT_HEADERS32)(pDosHeader->e_lfanew + ((SIZE_T)pDosHeader));
    PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(((SIZE_T)(pNtHeader)) + sizeof(IMAGE_NT_HEADERS32));
    DWORD Deviation = 0;
    //ZwProtectVirtualMemory 地址 - ntdll地址 = RVA
    SIZE_T Rva = (DWORD)apiAddr - (DWORD)ntdllAddr;

    // 先通过RVA找到所在区段,再用RVA-当前区段RVA+当前区段文件偏移 = F0A
    // 最后用F0A找到相对的opcode,复制到新内存执行再跳转
    for (WORD i = 0; i < pNtHeader->FileHeader.NumberOfSections; ++i) {
        // 通过RVA找到所在区段,再用RVA-当前区段RVA+文件偏移 = F0A
        if (Rva >= pSectionHeader[i].VirtualAddress && Rva < pSectionHeader[i].VirtualAddress + pSectionHeader[i].SizeOfRawData) { 
            Deviation = Rva - pSectionHeader[i].VirtualAddress + pSectionHeader[i].PointerToRawData;
            break;
        }
    }

    if (Deviation == 0) {
        MessageBoxA(0, "计算段内偏移错误", "error", MB_OK);
        delete[] pBuff;
        CloseHandle(hFile);
        return NULL;
    }

    // 最后用段内偏移找到相对的opcode
    // 申请一段堆空间执行被修改的汇编代码
    hDllContext = (PBYTE)VirtualAlloc(0, 0x10, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if (hDllContext == NULL) {
        MessageBoxA(0, "VirtualAlloc Error", "error", MB_OK);
        delete[] pBuff;
        CloseHandle(hFile);
        return NULL;
    }

    WriteLogger("%s <%s> file vs vmp Context: \n", libname, apifun); 
    for(int c=0; c<1; c++) { 
        WriteLogger("===%d===\r\nSRC:", c); 
        for(int i=0; i<16; i++) {
            WriteLogger("%02X ", pBuff[Deviation + i + c*16]); 
        }
        WriteLogger("\r\nVMP:"); 

        for(int i=0; i<16; i++) {
            WriteLogger("%02X ", apiAddr[i + c*16]); 
        }
        WriteLogger("\r\n"); 
    }
    memcpy(hDllContext, pBuff + Deviation, 5);//x32下VMP修改了前5字节,把文件内的原5字节拷贝过去
    apiAddr += 5;
#if 0 
    hDllContext[5] = 0x68;//push
    memcpy(hDllContext + 6, &apiAddr, 4);//push的地址是ZwProtectVirtualMemory+5的地方
    hDllContext[10] = 0xc3;//使用retn过去
#else 
    // jmp ZwProtectVirtualMemory
    hDllContext[5] = 0xE9; 
    *((DWORD*)(hDllContext+6)) = (DWORD)apiAddr; 
#endif 
    /*[CODE]****************************************
    0:  b8 50 00 00 00          mov    eax,0x50
    5:  e9 a5 30 52 77          jmp    0x775230af
    ************************************************/
    delete[] pBuff;
    CloseHandle(hFile);

    WriteLogger("\n\n%08x, RESULT: \n", apiAddr); 
    for(int i=0; i<16; i++) {
        WriteLogger("%02X ", hDllContext[i]); 
    }
    WriteLogger("\r\n\r\n"); 

    return hDllContext; 
}

SIZE_T CHook::ZwProtectVirtualMemory(
    HANDLE ProcessHandle,          // 进程句柄
    PVOID* BaseAddress,            // 地址的指针
    SIZE_T* NumberOfBytesToProtect,// 修改的大小,函数调用后会改成成功修改的大小
    ULONG NewAccessProtection,     // 新的内存属性
    PULONG OldAccessProtection)    // 旧的内存属性
{
    // ZwProtectVirtualMemory
    /*[SRC]*****************************************
    0:  b8 50 00 00 00          mov    eax,0x50
    5:  ba 40 8a 30 4b          mov    edx,0x4b308a40
    a:  ff d2                   call   edx
    c:  c2 14 00                ret    0x14
    f:  90                      nop
    /*[VMP]*****************************************
    0:  e9 6a cf b4 8c          jmp    0x8cb4cf6f
    5:  ba 40 8a 53 77          mov    edx,0x77538a40
    a:  ff d2                   call   edx
    c:  c2 14 00                ret    0x14
    f:  90                      nop
    ************************************************/
    if(hProtectVirtualMemory == NULL) { 
        hProtectVirtualMemory = (fZwProtectVirtualMemory)LoadFileContext("C:\\Windows\\System32\\ntdll.dll", "ZwProtectVirtualMemory"); 
        if (hProtectVirtualMemory == NULL) {
            MessageBox(0, ("LoadFileContext|ntdll.dll,Error"), ("error"), MB_OK);
            return 0;
        }
    } 

    return hProtectVirtualMemory(
        ProcessHandle, 
        BaseAddress, 
        NumberOfBytesToProtect, 
        NewAccessProtection, 
        OldAccessProtection
    );
}BOOL CHook::ReadProcessMemory( 
    HANDLE hProcess, 
    LPCVOID lpBaseAddress, 
    LPVOID lpBuffer, 
    SIZE_T nSize, 
    SIZE_T *lpNumberOfBytesRead )
{ 
    // ReadProcessMemory
    /*[SRC]*****************************************
    0:  8b ff                   mov    edi,edi
    2:  55                      push   ebp
    3:  8b ec                   mov    ebp,esp
    5:  5d                      pop    ebp
    6:  ff 25 58 13 88 6b       jmp    DWORD PTR ds:0x6b881358
    /*[VMP]*****************************************
    0:  8b ff                   mov    edi,edi
    2:  55                      push   ebp
    3:  8b ec                   mov    ebp,esp
    5:  5d                      pop    ebp
    6:  ff 25 58 13 72 75       jmp    DWORD PTR ds:0x75721358
    ************************************************/
    // if(hReadProcessMemory == NULL) {
    //     hReadProcessMemory = (fReadProcessMemory)LoadFileContext("C:\\Windows\\System32\\Kernel32.dll", "ReadProcessMemory"); 
    //     if (hReadProcessMemory == NULL) {
    //         MessageBox(0, ("LoadFileContext|Kernel32.dll,Error"), ("error"), MB_OK);
    //         return 0;
    //     }
    // }

    return ::ReadProcessMemory(hProcess, lpBaseAddress, lpBuffer, nSize, lpNumberOfBytesRead); 
} 


BOOL CHook::VMP_ReadData(DWORD address, DWORD* dwNews, UINT len)
{
    BOOL ret = FALSE; 
    DWORD dwOldProtect = 0; //旧保护属性 

    // MyMessageBox(); 

    // 去内存保护 
    WriteLogger("%s:%d modify memory.\n", __FUNCTION__, __LINE__); 
    this->ZwProtectVirtualMemory(INVALID_HANDLE_VALUE, (PVOID*)&address, (SIZE_T*)&len, PAGE_READWRITE, &dwOldProtect); //修改属性

    // Hook 读指定长度的内存 
    WriteLogger("%s:%d ReadProcessMemory.\n", __FUNCTION__, __LINE__); 
    // if (ReadProcessMemory(INVALID_HANDLE_VALUE, (LPCVOID)address, dwNews, len, NULL) == 0) { 
    ret = this->ReadProcessMemory(INVALID_HANDLE_VALUE, (LPCVOID)address, dwNews, len, NULL);

    // 写内存保护 
    WriteLogger("%s:%d restore memory.\n", __FUNCTION__, __LINE__); 
    this->ZwProtectVirtualMemory(INVALID_HANDLE_VALUE, (PVOID*)&address, (SIZE_T*)&len, dwOldProtect, &dwOldProtect);

    if(ret) {
        WriteLogger("VMP_ReadData Good, Result:%02X.\n", (BYTE)*dwNews); 
    } else {
        WriteLogger("VMP_ReadData Faild, Cause:%s.\n", CTools::GetLastErrorString()); 
    }
    return ret; 
}


注入VMP程序并执行后,VMP程序便闪退了。

代码执行后生成的记录为:
[Asm] 纯文本查看 复制代码
CHook::VMP_ReadData:381 modify memory.
ntdll.dll <ZwProtectVirtualMemory> file vs vmp Context:
===0===
SRC:B8 50 00 00 00 BA 40 8A 30 4B FF D2 C2 14 00 90
VMP:E9 6A CF B6 8A BA 40 8A 53 77 FF D2 C2 14 00 90


775230a5, RESULT:
B8 50 00 00 00 E9 A5 30 52 77 00 00 00 00 00 00
B8 50 00 00 00 BA 40 8A 30 4B FF D2 C2 14 00 90 

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 14:23

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表