PE基础6_远程线程注入-HOOK(消息-InLine-IAT)

注入

概述

DLL注入的初始动力源自于程序员对其他第三方应用程序进行功能扩展的愿望

注入方式有
  1. 注册表注入

  1. ComRes注入

  1. APC注入

  1. 消息钩子注入

  1. 远程线程注入

  1. 依赖可信进程注入

  2. 劫持进程创建注入

  1. 输入法注入

远程线程注入
//要加载的dll路径
WCHAR szDllPath[] = L"C:\\Users\\42140\\source\\repos\\34windows原理PE \\Debug\\16InjectDll.dll";
​
int main()
{
    //1.要注入,需要dll文件
    //2.找到要注入的进程PID
    DWORD dwPid;
    HWND hwnd = FindWindow(NULL, L"new 1 - Notepad++");
    GetWindowThreadProcessId(hwnd, &dwPid);
    //直接输入也行
    //printf("PID: ");
    //scanf_s("%d", &dwPid);
​
    //2.打开进程
    HANDLE hProcess = OpenProcess(
        PROCESS_ALL_ACCESS, FALSE, dwPid);
​
    //3.目标进程申请空间
    LPVOID pBuff = VirtualAllocEx(
        hProcess,
        NULL,
        sizeof(szdllPath),
        MEM_RESERVE | MEM_COMMIT,
        PAGE_EXECUTE_READWRITE);
​
    //4.向目标进程写入dll路径
    DWORD dwSize;
    WriteProcessMemory(
        hProcess,
        pBuff,                  //需要绝对路径
        szdllPath,
        sizeof(szdllPath),
        &dwSize
    );
​
    //DWORD WINAPI proc(LPVOID lpamam);
    //线程回调函数 参数只有一个
​
    //DWORD WINAPI  LoadLibrary(wchar_t * dllname);
    // 加载模块函数1 参数刚好只有一个
​
​
    //5.创建远程线程
    HANDLE hThread = CreateRemoteThread(
        hProcess,                                   //目标进程句柄
        NULL,                                       //安全属性
        NULL,                                       //默认栈大小
        (LPTHREAD_START_ROUTINE)LoadLibrary,        //回调函数
        pBuff,                                      //回调的参数
        NULL,                                       //创建标志
        NULL                                        //线程TID
    );
​
    //6.等待线程结束
    WaitForSingleObject(hThread, -1);
​
    //7.收尾工作
    CloseHandle(hThread);
    VirtualFreeEx(hProcess, pBuff, sizeof(szdllPath), MEM_FREE);
    CloseHandle(hProcess);
}

 

16InjectDll.dll
#include<Windows.h>
​
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    //添加MessageBox
        MessageBox(0, L"注入成功了", 0, 0);
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

 

 

HOOK

概述

HOOK中文名钩子

HOOK的函数:

系统提供的消息HOOK机制

自定义HOOK编程技巧

消息钩子

系统提供的消息钩子机制是由一系列的API提供的一种服务,这个系列的API可以完成对大多数应用程序关键节 点的Hook操作,为此,Windows为每种Hook类型维护了一个钩子链表,我们可以通过一个系统API来完成对整 个系统中所有符合此机制的关键点的Hook

消息钩子

//模块句柄
HANDLE g_hModule; 
//钩子句柄 
HHOOK  g_hook;
​
//键盘钩子的hook函数
LRESULT CALLBACK KeyboardProc(
    _In_ int    code,
    _In_ WPARAM wParam,
    _In_ LPARAM lParam
)
{
    //code如果小于0,不处理, lparam 键盘按下
    if (code >= 0 && lParam & 0x80000000)
    {
        // wParam 按键码
        char msg[2] = { (char)wParam, 0 };
        OutputDebugStringA(msg);
        OutputDebugStringA("\n");
    }
​
    return CallNextHookEx(g_hook, code,wParam, lParam);
}
​
​
//开启消息钩子 void OnHook() 
{
    //做键盘钩子,hook所有钩子
    //消息钩子的副作用,如果这个程序没有加载当前模块,那么系统会自动将这个dll注入到目标进程中
    //这样也能实现dll注入
    g_hook = SetWindowsHookEx(
        WH_KEYBOARD,                //钩子类型
        KeyboardProc,               //钩子回调函数
        (HINSTANCE)g_hModule,       //当前模块句柄
        0                           //hook的线程,0表示全局
    );
​
}
//卸载消息钩子 void UnHook() 
{
    UnhookWindowsHookEx(g_hook);
}
​

 



头文件
//头文件内容
#include<Windows.h>
​
//消息钩子句柄
extern HHOOK g_hook;
// 当前钩子回调所在模块
extern HMODULE g_hmod;
​
​
//开启消息钩子
extern "C" _declspec(dllexport)void OnHook();
//卸载消息钩子
extern "C" _declspec(dllexport)void UnHook();

 


dllmain
//dllmain
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
     {
    case DLL_PROCESS_ATTACH:
        g_hModule = hModule;
        OnHook();
        break;;
    case DLL_THREAD_ATTACH:
        break;;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        UnHook();
        break;
    }
    return TRUE;
}

 

 

测试
#include "pch.h"
#include <iostream>
#include <Windows.h>
typedef void ( *ONHOOK)();
typedef void (* UNHOOK)();
int main()
{
    //获取钩子函数
    HMODULE hmod = 
        LoadLibrary(L"..\\Debug\\03消息hookdll.dll");
    ONHOOK onhook = 
        (ONHOOK)GetProcAddress(hmod, "OnHook");
    UNHOOK unhook = 
        (UNHOOK)GetProcAddress(hmod, "UnHook");
     //开启hook
    onhook();
     //暂停
    system("pause");
     //关闭hook
    unhook();
}

 

 

自定义HOOK

自定义HOOK大致分为两类:

inline hook iat hook

inline hook 的跳转偏移:

跳转偏移 = 目录地址 - JMP所在地址 - 5

inline hook

cpp内容

#include "inlinehook.h"
//原始字节
char g_oldbyte[5] = {0};
//新跳转字节
char g_newbyte[5] = {0xE9,0};
//目标地址 hook的回调函数
int  WINAPI MyMessageBox(
    _In_opt_ HWND hWnd,
    _In_opt_ LPCWSTR lpText,
    _In_opt_ LPCWSTR lpCaption,
    _In_ UINT uType)
{
    
    UnHook();
    int  ret = MessageBox(0, L"你被hook了", 0, 0);
    OnHook();
    return  ret;
}
​
​
extern "C" _declspec(dllexport) void OnHook()
{
    //1. 获取MessageBox的真正地址
    LPVOID pMessageBox = 
        GetProcAddress(LoadLibrary(L"user32.dll"), "MessageBoxW");
    //2. 计算跳转偏移
    //跳转偏移 = 目标地址 - 指令所在 - 5
    DWORD offset = (DWORD)MyMessageBox - (DWORD)pMessageBox - 5;
    //3. 构建跳转指令   E9  跳转偏移
    *(DWORD*)(g_newbyte + 1) = offset;
    //4 .修改目标页属性
    DWORD  dwProtect;
    VirtualProtectEx(
        GetCurrentProcess(),
        pMessageBox,
        5,
        PAGE_EXECUTE_READWRITE,
        &dwProtect
    );
    //5. 备份原始字节
    memcpy(g_oldbyte, pMessageBox, 5);
    //6. Hook  MessageBox函数
    memcpy(pMessageBox, g_newbyte,5);
    //7 .修改目标页属性
    VirtualProtectEx(
        GetCurrentProcess(),
        pMessageBox,
        5,
        dwProtect,
        &dwProtect
    );
}
​
​
extern "C" _declspec(dllexport) void UnHook()
{
    //1. 获取MessageBox的真正地址
    LPVOID pMessageBox = GetProcAddress(LoadLibrary(L"user32.dll"), "MessageBoxW");
    //2 .修改目标页属性
    DWORD  dwProtect;
    VirtualProtectEx(
        GetCurrentProcess(),
        pMessageBox,
        5,
        PAGE_EXECUTE_READWRITE,
        &dwProtect
    );
    //3. 还原  MessageBox函数
    memcpy(pMessageBox, g_oldbyte, 5);
    //4 .还原目标页属性
    VirtualProtectEx(
        GetCurrentProcess(),
        pMessageBox,
        5,
        dwProtect,
        &dwProtect
    );
}

 

头文件内容
#include<Windows.h>
​
// 跳转偏移 =  目标地址 - 指令所在 - 5
// MessageBox      指令所在
// MyMessageBox    目标地址
​
​
//原始字节
extern char g_oldbyte[5];
​
//新跳转字节
extern char g_newbyte[5];
​
int  WINAPI MyMessageBox(
    _In_opt_ HWND hWnd,
    _In_opt_ LPCWSTR lpText,
    _In_opt_ LPCWSTR lpCaption,
    _In_ UINT uType);
​
extern "C" _declspec(dllexport) void OnHook();
​
extern "C" _declspec(dllexport)void UnHook();

 


dllmain
#include "inlinehook.h"
​
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        OnHook();
        break;
    case DLL_THREAD_ATTACH:break;
    case DLL_THREAD_DETACH:break;
    case DLL_PROCESS_DETACH:
        UnHook();
        break;
    }
    return TRUE;
}

 

测试
#include "pch.h"
#include <iostream>
#include<Windows.h>
int main()
{
    //愉快的奔跑
    MessageBox(0, L"愉快的奔跑", 0, 0);
    //开启hook
    HMODULE hmod = LoadLibrary(L"..\\Debug\\05InlineHookdll.dll");
    MessageBox(0, L"愉快的奔跑", 0, 0);
    //卸载
    FreeLibrary(hmod);
}

 

 

IAT HOOK
cpp
#include"IatHook.h"
​
typedef  int  ( WINAPI* MESSAGEPRO)(
    _In_opt_ HWND hWnd,
    _In_opt_ LPCWSTR lpText,
    _In_opt_ LPCWSTR lpCaption,
    _In_ UINT uType);
// Iat地址指针
DWORD * g_Iat;
//原始函数地址
MESSAGEPRO  g_oldfun;
//初始化函数
void InitHook()
{
    g_Iat = GetIatAddress("user32.dll", "MessageBoxW");
    g_oldfun = (MESSAGEPRO)*g_Iat; 
}
​
//获取IAT地址
DWORD * GetIatAddress(const char * szDllName, const char * szFunName)
{
    //1.获取当前进程加载地址
    char  *pBuff = (char *)GetModuleHandle(0);
    //2. 获取DOS头
    PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)pBuff;
​
    //3. 获取NT头
    PIMAGE_NT_HEADERS pNt = 
        (PIMAGE_NT_HEADERS)(pDos->e_lfanew + (DWORD)pBuff);
​
    //4.数据目标表第1项
    DWORD ImportRva = pNt->OptionalHeader.DataDirectory[1].VirtualAddress;
​
    //5.转换成VA地址
    PIMAGE_IMPORT_DESCRIPTOR pImport =
        (PIMAGE_IMPORT_DESCRIPTOR)(ImportRva + (DWORD)pBuff);
​
​
    //6.遍历导出表
    //找到指定模块的导出地址
    while (pImport->FirstThunk)
    {
        //6.1 比较指定模块名是否符号
        char * pDllName= 
            (char *)(pImport->Name + (DWORD)pBuff);
        //找到的指定模块了
        if (_stricmp(pDllName, szDllName) == 0)
        {
            //6.2 遍历IAT和INT
            PIMAGE_THUNK_DATA  pIAT =
                (PIMAGE_THUNK_DATA ) (pImport->FirstThunk + (DWORD)pBuff);
            PIMAGE_THUNK_DATA  pINT = 
                (PIMAGE_THUNK_DATA )(pImport->OriginalFirstThunk + (DWORD)pBuff);
​
            //6.3 找到指定函数对应的地址
            while (pINT->u1.Ordinal)
            {
                //如果是名称导出的再比较函数名
                if (!(pINT->u1.Ordinal & 0x80000000))
                {
                    //获取函数名
                    PIMAGE_IMPORT_BY_NAME FunName =
                        (PIMAGE_IMPORT_BY_NAME)
                        (pINT->u1.Function + (DWORD)pBuff);
                    if (strcmp(FunName->Name, szFunName) == 0)
                    {
                        //找到函数地址
                        return  (DWORD *)pIAT;
​
                        //0x40001000    MyMessageBox
                        //0x40001004    CreateWindows
                    }
                }
                pINT++;
                pIAT++;
            }
        }
        //移动到下一个导入表
        pImport++;
    }
    return 0;
}
​
​
​
extern "C" _declspec(dllexport) void OnHook()
{
    DWORD dwOldProtect;
    //修改页属性
    VirtualProtect(g_Iat, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect);
    //hook IAT
    *g_Iat = (DWORD)MyMessageBox;
    //恢复页属性
    VirtualProtect(g_Iat, 4, dwOldProtect, &dwOldProtect);
}
​
extern "C" _declspec(dllexport)void UnHook()
{
    DWORD dwOldProtect;
    //修改页属性
VirtualProtect(g_Iat, 4, PAGE_EXECUTE_READWRITE, &dwOldProtect);
//恢复函数
*g_Iat = (DWORD)g_oldfun;
//恢复页属性
VirtualProtect(g_Iat, 4, dwOldProtect, &dwOldProtect);
}
​
//目标地址 hook的回调函数
int  WINAPI MyMessageBox(
_In_opt_ HWND hWnd,
_In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption,
_In_ UINT uType)
{
return g_oldfun(hWnd, L"你被IAT   hook了", L"^-^", NULL);
​
}

 

头文件
#include<windows.h>
void InitHook();
//获取IAT地址
DWORD * GetIatAddress(const char * szDllName, const char * szFunName);
extern "C" _declspec(dllexport) void OnHook();
extern "C" _declspec(dllexport)void UnHook();
//目标地址 hook的回调函数
int  WINAPI MyMessageBox(
    _In_opt_ HWND hWnd,
    _In_opt_ LPCWSTR lpText,
    _In_opt_ LPCWSTR lpCaption,
    _In_ UINT uType);

 

dllmain
#include"IatHook.h"
​
BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        InitHook();
        OnHook();
        break;
        
    case DLL_THREAD_ATTACH:break;
    case DLL_THREAD_DETACH:break;
    case DLL_PROCESS_DETACH:
        UnHook();
        break;
    }
    return TRUE;
}

 

测试
int main()
{
    LoadLibrary(L"..\\Debug\\07IatHookdll.dll");
    MessageBox(0,0,0,0);
}

 

 

上一篇:5 pandas之DataFrame简单实用2


下一篇:PE知识复习之PE的绑定导入表