• 《逆向工程核心原理》学习笔记(四):API钩取


    前言

    继续学习《逆向工程核心原理》,本篇笔记是第四部分:API钩取,主要介绍了调试钩取、DLL注入实现IAT钩取、API代码修改钩取和全局API钩取等内容

    一、API钩取简介

    1、基础概念

    钩取(Hook):截取信息、更改程序执行流向、添加新功能的技术

    • 使用反汇编/调试器把握程序结构与原理
    • 开发Hook代码,以修改bug、改善程序功能
    • 灵活操作可执行文件和进程内存,设置Hook代码

    API(Application Programming Interface):可以认为是调用资源的路径,notepad.exe为例如下图所示

    在这里插入图片描述
    其API调用如下:
    在这里插入图片描述
    API钩取:对Win32 API的钩取,一个例子如下图所示

    在这里插入图片描述

    2、技术图表

    在这里插入图片描述
    (下划线的是常用且好用的方法)

    二、调试钩取技术

    通过调试钩取技术,来钩取kernel32!WriteFile() API

    1、调试器

    调试器(Debbuger):能逐一执行被调试者的指令,拥有对寄存器和内存的所有访问权限,工作原理如下图所示

    在这里插入图片描述
    调试事件共9种,见微软官方调试事件
    其中,与调试相关的是EXCEPTION_DEBUG_EVENT,与其相关的异常列表如下:

    在这里插入图片描述
    其中,调试器必须处理的是EXCEPTION_BREAKPOINT(断点),对应汇编指令是INT3,IA-32指令是0xCC
    要设置断点时,只需将代码在内存中的起始地址的1个字节设置为0xCC即可,想继续调试就把它恢复

    2、调试流程

    基本思路:被调试者的API起始部份修改为0xCC,控制权转移到调试器后执行指定操作,最后使被调试者重新进入运行状态

    • 对目标进程进行附加操作,使之成为被调试者
    • Hook:API起始地址的第1个字节修改为0xCC
    • 调用相应API,控制权转移到调试器
    • 执行操作:操作参数、返回值等
    • 脱钩:0xCC恢复原值
    • 运行相应API(正常状态)
    • Hook:再次修改为0xCC(继续钩取)
    • 控制权返还被调试者

    3、示例:记事本 WriteFile() API钩取

    目标是将notepad.exe中所有小写字母都变成大写字母

    WriteFile() 定义如下:

    BOOL WriteFile(
    	HANDLE  hFile, //文件句柄
    	LPCVOID lpBuffer, //数据缓存区指针
    	DWORD   nNumberOfBytesToWrite, //要写的字节数
    	LPDWORD lpNumberOfBytesWritten, //用于保存实际写入字节数的存储区域的指针
    	LPOVERLAPPED lpOverlapped //OVERLAPPED结构体指针
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (1)hookdbg.exe

    源码如下:

    // hookdbg.exe
    
    #include "windows.h"
    #include "stdio.h"
    
    LPVOID g_pfWriteFile = NULL;
    CREATE_PROCESS_DEBUG_INFO g_cpdi;
    BYTE g_chINT3 = 0xCC, g_chOrgByte = 0;
    
    BOOL OnCreateProcessDebugEvent(LPDEBUG_EVENT pde)
    {
        // 获取 WriteFile() API 地址(注意是调试进程的内存地址,不是被调试进程)
        g_pfWriteFile = GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteFile");
    
        // API Hook - WriteFile()
        //   更改第一个字节为 0xCC (INT 3) 
        //   (orginal byte 是g_chOrgByte备份)
        memcpy(&g_cpdi, &pde->u.CreateProcessInfo, sizeof(CREATE_PROCESS_DEBUG_INFO));
        ReadProcessMemory(g_cpdi.hProcess, g_pfWriteFile, 
                          &g_chOrgByte, sizeof(BYTE), NULL);
        WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile, 
                           &g_chINT3, sizeof(BYTE), NULL);
    
        return TRUE;
    }
    
    BOOL OnExceptionDebugEvent(LPDEBUG_EVENT pde)
    {
        CONTEXT ctx;
        PBYTE lpBuffer = NULL;
        DWORD dwNumOfBytesToWrite, dwAddrOfBuffer, i;
        PEXCEPTION_RECORD per = &pde->u.Exception.ExceptionRecord;
    
        // 断点异常 (INT 3) 
        if( EXCEPTION_BREAKPOINT == per->ExceptionCode )
        {
            // 断点地址为 WriteFile() API 地址
            if( g_pfWriteFile == per->ExceptionAddress )
            {
                // #1. Unhook
                //   0xCC 恢复为 original byte
                WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile, 
                                   &g_chOrgByte, sizeof(BYTE), NULL);
    
                // #2. 获取线程上下文
                ctx.ContextFlags = CONTEXT_CONTROL;
                GetThreadContext(g_cpdi.hThread, &ctx);
    
                // #3. 获取 WriteFile() 的 param 2, 3 值
                //   函数参数存在于相应进程的栈
                //   param 2 : ESP + 0x8 缓冲区地址
                //   param 3 : ESP + 0xC 缓冲区大小
                ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.Esp + 0x8), 
                                  &dwAddrOfBuffer, sizeof(DWORD), NULL);
                ReadProcessMemory(g_cpdi.hProcess, (LPVOID)(ctx.Esp + 0xC), 
                                  &dwNumOfBytesToWrite, sizeof(DWORD), NULL);
    
                // #4. 分配临时缓冲区
                lpBuffer = (PBYTE)malloc(dwNumOfBytesToWrite+1);
                memset(lpBuffer, 0, dwNumOfBytesToWrite+1);
    
                // #5. 复制 WriteFile() 缓冲区到临时缓冲区
                ReadProcessMemory(g_cpdi.hProcess, (LPVOID)dwAddrOfBuffer, 
                                  lpBuffer, dwNumOfBytesToWrite, NULL);
                printf("\n### original string ###\n%s\n", lpBuffer);
    
                // #6. 小写字母 -> 大写字母
                for( i = 0; i < dwNumOfBytesToWrite; i++ )
                {
                    if( 0x61 <= lpBuffer[i] && lpBuffer[i] <= 0x7A )
                        lpBuffer[i] -= 0x20;
                }
    
                printf("\n### converted string ###\n%s\n", lpBuffer);
    
                // #7. 变换后的缓冲区复制到 WriteFile() 缓冲区
                WriteProcessMemory(g_cpdi.hProcess, (LPVOID)dwAddrOfBuffer, 
                                   lpBuffer, dwNumOfBytesToWrite, NULL);
                
                // #8. 释放临时缓冲区
                free(lpBuffer);
    
                // #9. 线程上下文的 EIP 改为 WriteFile() 首地址
                //   (当前为 WriteFile() + 1 位置,INT3命令后)
                ctx.Eip = (DWORD)g_pfWriteFile;
                SetThreadContext(g_cpdi.hThread, &ctx);
    
                // #10. 运行被调试者
                ContinueDebugEvent(pde->dwProcessId, pde->dwThreadId, DBG_CONTINUE);
                Sleep(0);
    
                // #11. API Hook
                WriteProcessMemory(g_cpdi.hProcess, g_pfWriteFile, 
                                   &g_chINT3, sizeof(BYTE), NULL);
    
                return TRUE;
            }
        }
    
        return FALSE;
    }
    
    void DebugLoop()
    {
        DEBUG_EVENT de;
        DWORD dwContinueStatus;
    
        // 等待被调试者发生事件
        while( WaitForDebugEvent(&de, INFINITE) )
        {
            dwContinueStatus = DBG_CONTINUE; //dwContinueStatus值为DBG_CONTINUE(处理正常)或DBG_EXCEPTION_NOT_HANDLED(无法处理或在SEH中处理)
    
            // 被调试者生成或附加事件
            if( CREATE_PROCESS_DEBUG_EVENT == de.dwDebugEventCode )
            {
                OnCreateProcessDebugEvent(&de); //OnCreateProcessDebugEvent是CREATE_PROCESS_DEBUG_EVENT事件句柄
            }
            // 异常事件
            else if( EXCEPTION_DEBUG_EVENT == de.dwDebugEventCode )
            {
                if( OnExceptionDebugEvent(&de) ) //OnExceptionDebugEvent是EXCEPTION_DEBUG_EVENT事件句柄,处理被调试者的INT3指令
                    continue;
            }
            // 被调试者终止事件
            else if( EXIT_PROCESS_DEBUG_EVENT == de.dwDebugEventCode )
            {
                // 被调试者终止 -> debugger 终止
                break;
            }
    
            // 再次运行被调试者
            ContinueDebugEvent(de.dwProcessId, de.dwThreadId, dwContinueStatus);
        }
    }
    
    int main(int argc, char* argv[])
    {
        DWORD dwPID;
    
        if( argc != 2 )
        {
            printf("\nUSAGE : hookdbg.exe <pid>\n");
            return 1;
        }
    
        // Attach Process
        dwPID = atoi(argv[1]); //以程序运行参数的形式接收进程PID
        if( !DebugActiveProcess(dwPID) ) //将调试器附加到进程上
        {
            printf("DebugActiveProcess(%d) failed!!!\n"
                   "Error Code = %d\n", dwPID, GetLastError());
            return 1;
        }
    
        // 调试器循环
        DebugLoop();
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160

    (2)试验

    先运行notepad.exe,并获取notepad的PID是32220,然后运行hookdbg.exe,如下
    在这里插入图片描述
    输入一串字符串,保存
    再次打开的时候会发现都变成大写字母了

    在这里插入图片描述

    三、DLL注入实现IAT钩取技术

    本节向计算器calc.exe插入用户的DLL文件,钩取IAT的user32.SetWindowTextW() API地址,使得计算器显示中文数字

    1、选定目标API

    PEView打开calc.exe,在IAT中寻找API,如下两个负责显示文本
    在这里插入图片描述
    其中,SetDigitemTextW()又调用了SetWindowTextW()
    SetWindowTextW() API定义如下:

    BOOL SetWindowText(
    	HWND hwnd, //窗口句柄
    	LPCTSTR lpString //字符串指针(钩取的目标)
    );
    
    • 1
    • 2
    • 3
    • 4

    在OD里验证下
    右键-search for-all intermodular calls,在SetWindowTextW()设置断点

    在这里插入图片描述
    运行,然后可以看到第一个断点处lpString的值是0,就是计算器显示的初始值

    在这里插入图片描述
    在计算器中输入7,继续运行,发现lpString的值变为7(注意此时地址不同)

    在这里插入图片描述
    尝试修改为中文“七”,Unicode码4e03,记住是小端序故要逆序
    然后就会在计算器上显示“七”
    验证完毕

    2、IAT钩取工作原理

    关于IAT,可以见《逆向工程核心原理》学习笔记(二):PE文件

    原理如下图所示:

    • 首先注入hookiat.dll文件,文件中提供了 MySetWindowTextW() 函数
    • 然后修改IAT中的CALL的值为 MySetWindowTextW() 函数起始地址
    • 一系列处理后,再CALL到user32.SetWindowTextW()函数起始地址
    • user32.SetWindowTextW()执行完后返回到hookiat.dll执行下一条指令
    • 最后返回到01002628

    在这里插入图片描述

    3、示例:计算器显示中文数字

    (1)hookiat.dll

    // hookiat.dll
    
    #include "stdio.h"
    #include "wchar.h"
    #include "windows.h"
    
    
    // typedef
    typedef BOOL (WINAPI *PFSETWINDOWTEXTW)(HWND hWnd, LPWSTR lpString);
    
    
    // globals
    FARPROC g_pOrgFunc = NULL;
    
    
    BOOL WINAPI MySetWindowTextW(HWND hWnd, LPWSTR lpString)
    {
        wchar_t* pNum = L"零一二三四五六七八九";
        wchar_t temp[2] = {0,};
        int i = 0, nLen = 0, nIndex = 0;
    
        nLen = wcslen(lpString);
        for(i = 0; i < nLen; i++)
        {
            // 阿拉伯数字转换为中文数字
            //   lpString 是 wide-character (2 byte) 字符串
            if( L'0' <= lpString[i] && lpString[i] <= L'9' )
            {
                temp[0] = lpString[i];
                nIndex = _wtoi(temp);
                lpString[i] = pNum[nIndex];
            }
        }
    
        // 调用 user32!SetWindowTextW() API 
        //   (修改 lpString 缓冲区中内容)
        return ((PFSETWINDOWTEXTW)g_pOrgFunc)(hWnd, lpString);
    }
    
    
    // hook_iat
    //   负责钩取 IAT 
    BOOL hook_iat(LPCSTR szDllName, PROC pfnOrg, PROC pfnNew)
    {
    	HMODULE hMod;
    	LPCSTR szLibName;
    	PIMAGE_IMPORT_DESCRIPTOR pImportDesc; 
    	PIMAGE_THUNK_DATA pThunk;
    	DWORD dwOldProtect, dwRVA;
    	PBYTE pAddr;
    
        //查找 IAT 位置
        // hMod, pAddr = ImageBase of calc.exe
        //             = VA to MZ signature (IMAGE_DOS_HEADER)
    	hMod = GetModuleHandle(NULL);
    	pAddr = (PBYTE)hMod;
    
        // pAddr = VA to PE signature (IMAGE_NT_HEADERS)
    	pAddr += *((DWORD*)&pAddr[0x3C]);
    
        // dwRVA = RVA to IMAGE_IMPORT_DESCRIPTOR Table
    	dwRVA = *((DWORD*)&pAddr[0x80]);
    
        // pImportDesc = VA to IMAGE_IMPORT_DESCRIPTOR Table
    	pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)hMod+dwRVA);
    
        // for循环找到user32.dll
    	for( ; pImportDesc->Name; pImportDesc++ )
    	{
            // szLibName = VA to IMAGE_IMPORT_DESCRIPTOR.Name
    		szLibName = (LPCSTR)((DWORD)hMod + pImportDesc->Name);
    		if( !_stricmp(szLibName, szDllName) )
    		{
                // pThunk = IMAGE_IMPORT_DESCRIPTOR.FirstThunk
                //        = VA to IAT(Import Address Table)
    			pThunk = (PIMAGE_THUNK_DATA)((DWORD)hMod + 
                                             pImportDesc->FirstThunk);
                // for循环找到SetWindowTextW的IAT地址
                // pThunk->u1.Function = VA to API
    			for( ; pThunk->u1.Function; pThunk++ )
    			{
    				if( pThunk->u1.Function == (DWORD)pfnOrg )
    				{
                        // 更改内存属性为 E/R/W
    					VirtualProtect((LPVOID)&pThunk->u1.Function, 
                                       4, 
                                       PAGE_EXECUTE_READWRITE, 
                                       &dwOldProtect);
    
                        // 修改 IAT 值(钩取)
                        pThunk->u1.Function = (DWORD)pfnNew;
    					
                        // 恢复内存属性
                        VirtualProtect((LPVOID)&pThunk->u1.Function, 
                                       4, 
                                       dwOldProtect, 
                                       &dwOldProtect);						
    
    					return TRUE;
    				}
    			}
    		}
    	}
    
    	return FALSE;
    }
    
    
    
    BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
    {
    	switch( fdwReason )
    	{
    		case DLL_PROCESS_ATTACH : 
                // 保存原始 API 地址
               	g_pOrgFunc = GetProcAddress(GetModuleHandle(L"user32.dll"), 
                                            "SetWindowTextW");
    
                // # hook
                //   用 hookiat.MySetWindowText() 钩取 user32.SetWindowTextW() 
    			hook_iat("user32.dll", g_pOrgFunc, (PROC)MySetWindowTextW);
    			break;
    
    		case DLL_PROCESS_DETACH :
                // # unhook
                //   将 calc.exe 的 IAT 恢复原值
                hook_iat("user32.dll", (PROC)MySetWindowTextW, g_pOrgFunc);
    			break;
    	}
    
    	return TRUE;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132

    (2)InjectDll.exe

    类似于《逆向工程核心原理》学习笔记(三):DLL注入

    // InjectDll.exe
    
    #include "stdio.h"
    #include "windows.h"
    #include "tlhelp32.h"
    #include "winbase.h"
    #include "tchar.h"
    
    
    void usage()
    {
    	printf("\nInjectDll.exe by ReverseCore\n"
               "- blog  : http://www.reversecore.com\n"
               "- email : reversecore@gmail.com\n\n"
               "- USAGE : InjectDll.exe <i|e> <PID> <dll_path>\n\n");
    }
    
    
    BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName)
    {
    	HANDLE hProcess, hThread;
    	LPVOID pRemoteBuf;
        DWORD dwBufSize = (DWORD)(_tcslen(szDllName) + 1) * sizeof(TCHAR);
    	LPTHREAD_START_ROUTINE pThreadProc;
    
    	if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
        {
            DWORD dwErr = GetLastError();
    		return FALSE;
        }
    
    	pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);
    
    	WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, dwBufSize, NULL);
    
    	pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
    	hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
    	WaitForSingleObject(hThread, INFINITE);	
    
    	CloseHandle(hThread);
    	CloseHandle(hProcess);
    
    	return TRUE;
    } 
    
    
    BOOL EjectDll(DWORD dwPID, LPCTSTR szDllName)
    {
    	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, szDllName) || !_tcsicmp(me.szExePath, szDllName) )
    		{
    			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;
    }
    
    
    DWORD _EnableNTPrivilege(LPCTSTR szPrivilege, DWORD dwState)
    {
    	DWORD dwRtn = 0;
    	HANDLE hToken;
    	if (OpenProcessToken(GetCurrentProcess(),
    		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    	{
    		LUID luid;
    		if (LookupPrivilegeValue(NULL, szPrivilege, &luid))
    		{
    			BYTE t1[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)];
    			BYTE t2[sizeof(TOKEN_PRIVILEGES) + sizeof(LUID_AND_ATTRIBUTES)];
    			DWORD cbTP = sizeof(TOKEN_PRIVILEGES) + sizeof (LUID_AND_ATTRIBUTES);
    
    			PTOKEN_PRIVILEGES pTP = (PTOKEN_PRIVILEGES)t1;
    			PTOKEN_PRIVILEGES pPrevTP = (PTOKEN_PRIVILEGES)t2;
    
    			pTP->PrivilegeCount = 1;
    			pTP->Privileges[0].Luid = luid;
    			pTP->Privileges[0].Attributes = dwState;
    
    			if (AdjustTokenPrivileges(hToken, FALSE, pTP, cbTP, pPrevTP, &cbTP))
    				dwRtn = pPrevTP->Privileges[0].Attributes;
    		}
    
    	    CloseHandle(hToken);
    	}
    
    	return dwRtn;
    }
    
    
    int _tmain(int argc, TCHAR* argv[])
    {
        if( argc != 4 )
        {
            usage();
            return 1;
        }
    
    	// adjust privilege
    	_EnableNTPrivilege(SE_DEBUG_NAME, SE_PRIVILEGE_ENABLED);
    
        // InjectDll.exe <i|e> <PID> <dll_path>
        if( !_tcsicmp(argv[1], L"i") )
            InjectDll((DWORD)_tstoi(argv[2]), argv[3]);
        else if(!_tcsicmp(argv[1], L"e") )
            EjectDll((DWORD)_tstoi(argv[2]), argv[3]);
    
    	return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142

    四、API代码修改技术

    API代码修改技术:库文件被加载到进程内存后,在目录映像中直接修改要钩取的API代码本身(相较于上一节的IAT钩取,本技术可以钩取更多的不在IAT的API)

    本节将用API代码修改技术实现隐藏进程

    1、API代码修改原理

    原始状态如下:
    在这里插入图片描述

    钩取原理如下图所示:

    • 注入stealth.dll,钩取ntdll.ZwQuerySystemInformation() API
    • ntdll.ZwQuerySystemInformation() API起始地址的5个字节代码改为stealth.MyZwQuerySystemInformation() 的地址JMP 10001120
    • 于是 ntdll.ZwQuerySystemInformation()被调用的时候,会跳转到stealth.MyZwQuerySystemInformation()
    • 1000116A的指令将 ntdll.ZwQuerySystemInformation() API起始地址的5个字节代码恢复原值
    • 1000119B的指令调用正常的 ntdll.ZwQuerySystemInformation()
    • ntdll.ZwQuerySystemInformation()执行完后,返回stealth.dll
    • 然后10001212再次钩取ntdll.ZwQuerySystemInformation()(即第二步)
    • stealth.MyZwQuerySystemInformation() 执行完后,返回进程

    在这里插入图片描述

    2、示例:隐藏进程

    (1)相关API

    一般获取进程快照,用的是CreateToolHelp32Snapshot() API
    枚举进程则用的是EnumProcesses() API

    而这两个API底层都调用的是 ntdll.ZwQuerySystemInformation() API
    ntdll.ZwQuerySystemInformation() API可以获取运行中的所有进程信息,形成链表

    NTSTATUS WINAPI ZwQuerySystemInformation(
    	_In_      SYSTEM_INFORMATION_CLASS SystemInformationClass,
      	_Inout_   PVOID                    SystemInformation,
      	_In_      ULONG                    SystemInformationLength,
      	_Out_opt_ PULONG                   ReturnLength
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    隐藏进程时,需要钩取所有进程的ZwQuerySystemInformation() API,即全局钩取

    (2)源码

    HideProc.exe,可以认为是InjectDll.exe的加强版

    // HideProc.exe
    
    #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;
    		
    		if( dwPID < 100 ) //PID小于100的系统进程不注入
    			continue;
    
            if( nMode == INJECTION_MODE )
    		    InjectDll(dwPID, szDllPath); //dll注入
            else
                EjectDll(dwPID, szDllPath); //卸载dll
    	} 
    	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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208

    stealth.dll

    // stealth.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 variable
    BYTE g_pOrgBytes[5] = {0,};
    
    //此函数用来将api前5个字节改为jmp xxxx,以实现钩取
    //szDllName:dll名称,szFuncName:api名称,pfnNew:勾取函数地址,pOrgBytes:存储原来5个字节的缓冲区
    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;
    
        // 若已被勾取,则返回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);
    
        // Hook - 修改 5 byte  (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;
    
        // 若已脱钩,则返回False
        if( pByte[0] != 0xE9 )
            return FALSE;
    
        // 向内存添加“写”的属性,为恢复原代码做准备
        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_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes);
    
        // 调用原始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 是单向链表的头
            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勾取操作,为下次调用准备
        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 __cplusplus
    extern "C" {
    #endif
    __declspec(dllexport) void SetProcName(LPCTSTR szProcName)
    {
        _tcscpy_s(g_szProcName, szProcName);
    }
    #ifdef __cplusplus
    }
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230

    五、全局API钩取

    全局 API 钩取针对所有进程,包括正在运行和将要运行的进程
    用全局API钩取对上一节内容进行加强

    1、相关API

    (1)Kernel32.CreateProcess()

    Kernel32.CreateProcess() API 是用来创建新进程的,钩取时要注意:

    • 要同时钩取Kernel32.CreateProcessA()Kernel32.CreateProcessW()
    • 上两个API分别调用了CreateProcessInternalA()CreateProcessInternalW(),故这两个API也要钩取
    BOOL CreateProcess(
    	LPCTSTR lpApplicationName,
    	LPTSTR lpCommandLine,
    	LPSECURITY_ATTRIBUTES lpProcessAttributes,
    	LPSECURITY_ATTRIBUTES lpThreadAttributes,
    	BOOL bInheritHandles,
    	DWORD dwCreationFlags,
    	LPVOID lpEnvironment,
    	LPCTSTR lpCurrentDirectory,
    	LPSTARTUPINFO lpStartupInfo,
    	LPPROCESS_INFORMATION lpProcessInformation
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    可参考CreateProcess函数详解

    (2)Ntdll.ZwResumeThread()

    Ntdll.ZwResumeThread()在进程创建后,主线程运行前在Kernel32.CreateProcess() 内被调用执行,不过这个API似乎并未公开,故有不确定性

    ZwResumeThread(
    	IN	HANDLE	ThreadHandle,
    	OUT	PULONG	SuspendCount OPTIONAL
    )
    
    • 1
    • 2
    • 3
    • 4

    2、源码

    (1)HideProc2.exe

    HideProc2.exe与HideProc.exe相似

    // HideProc2.exe
    
    #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;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194

    (2)stealth2.dll

    使用时先将stealth2.dll复制到%SYSTEM%文件夹

    #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
                                  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;
    }
    
    // 这个InjectDll2值得注意下
    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;
    }
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380

    结语

    本章对API钩取做了学习
    书中还提点了下工具的使用标准

  • 相关阅读:
    Ubuntu 安装 Docker 的详细步骤
    CORS跨域资源共享+CORS的一系列响应头
    心情碎片~
    【信号处理】基于Matlab实现男女音变声系统
    ESP32系列--第九篇 ADC的使用
    02Java线程模型
    【图解HTTP】HTTP首部
    Golang学习——基于vscode安装go环境
    内置单片机的433无线模块高速连传典型运用
    小程序变更主体公证怎么做?
  • 原文地址:https://blog.csdn.net/weixin_44604541/article/details/124838854