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);
}

原文地址:https://www.cnblogs.com/ltyandy/p/11107480.html

时间: 2024-10-12 20:02:30

PE基础6_远程线程注入-HOOK(消息-InLine-IAT)的相关文章

远程线程注入方法CreateRemoteThread

最近在整理学习Windows注入方面的知识,这个远程注入前面早写过,现在看看人家博客的理解整理,整理, 需要源码的可以到我的github上下载. 链接是  https://github.com/Arsense/WindowsCode 首先先来说说什么是注入,为什么要注入 0x00 Baise 注入就是把自己的Dll注入到人家的代码中,被注入的DLL拥有目标进程内存的访问权限,所以我们可以通过该 向某个进程注入DLL时的方法主要有以下三种: 创建远程线程(CreateRemoteThread()

奇技淫巧之调试被远程线程注入的DLL

远程线程注入, 这东西大家都懂的, 一般都被大家用来干些小小的坏事情,比如API Hook~~将DLL注入到其它进程并不是难事,问题是这个被注入的DLL不太好调试,调试DLL本来就是个比较头疼的问题,更何况是这种运行在其它进程空间的DLL, 被注入DLL的程序,不崩溃还好,崩溃了,要定位崩溃点,真是够麻烦的. 这几天,无意中发现了一个可以调试这种DLL的方法. 首先,需要准备两样东西: 1.微软的Detours库, 下载地址戳这里: 下载链接 2.打开Detours安装目录下的samples\s

远程线程注入

一丶远程线程注入的讲解 远程线程注入的原理,我会写一个远程线程开发的例子 我们总共需要几步 /*1.查找窗口,获取窗口句柄*/ /*2.根据窗口句柄,获得进程的PID*/ /*3.根据进程的PID,获得进程的句柄*/ /*4.根据进程的句柄,给进程申请额外内存空间*/ /*5.调用WriteProcessMemory,给进程写入DLL的路径*/ /*6.创建远程线程,执行我们的代码*/ /*7.调用退出代码,释放远程线程的dll*/ 每一步单独讲解 我们新建一个MFC 对话框程序,添加一个按钮,

详细解读:远程线程注入DLL到PC版微信

一.远程线程注入的原理 1.其基础是在 Windows 系统中,每个 .exe 文件在双击打开时都会加载 kernel32.dll 这个系统模块,该模块中有一个 LoadLibrary() 函数,可以将DLL文件加载到自身进程中. 2.这样,就可以用 CreateRemoteThread() 函数创建一个远程线程,让目标进程调用LoadLibrary() 来加载我们自己写的DLL .CreateRemoteThread() 有这几个参数比较关键:A:想要注入的进程的句柄,这里可以通过OpenPr

C++进程注入(通过远程线程注入进程)

需要本文代码请直接跳到文章最底部下载 注入进程的方法有很多,本文主要介绍通过远程线程来注入进程的方法: 我们知道,每个进程都有4GB的地址空间,windows可用的大小大概为1.5GB左右,远程线程注入的方法主要是,打开一个线程以后,将要注入的动态库的地址写入这个地址空间,然后调用开启远程线程的函数,来执行LoadLibraryA或者LoadLibraryW(其实不存在LoadLibrary这个函数,他只是一个宏,如果是UNICODE环境的话会调用LoadLibraryW,否则就是LoadLib

【windows核心编程】使用远程线程注入DLL

前言 该技术是指通过在[目标进程]中创建一个[远程线程]来达到注入的目的. 创建的[远程线程]函数为LoadLibrary, 线程函数的参数为DLL名字, 想要做的工作在DLL中编写.  示意图如下:  相关API 1.创建远程线程 //该函数除了第一个参数为目标进程句柄外 //其他参数均和CreateThread一样 HANDLE hThread = CreateRemoteThread( __in HANDLE hProcess, //目标进程句柄 __in_opt LPSECURITY_A

远程线程注入dll

// CommonInject.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <WinUser.h> #include <WinDef.h> #include <iostream> #include <Tlhelp32.h> using namespa

安全之路 —— 无DLL文件实现远程线程注入

简介 在之前的章节中,笔者曾介绍过有关于远程线程注入的知识,将后门.dll文件注入explorer.exe中实现绕过防火墙反弹后门.但一个.exe文件总要在注入时捎上一个.dll文件着实是怪麻烦的,那么有没有什么方法能够不适用.dll文件实现注入呢? 答案是有的,我们可以直接将功能写在线程函数中,然后直接将整个函数注入,这个方法相较之于DLL注入会稍微复杂一些,适用于对一些体积比较小的程序进行注入.但是要注意动态链接库的地址重定位问题,因为正常的文件一般会默认载入kernel32.dll文件,而

安全之路 —— 利用远程线程注入的方法(使用DLL)实现穿墙与隐藏进程

简介 大多数后门或病毒要想初步实现隐藏进程,即不被像任务管理器这样典型的RING3级进程管理器找到过于明显的不明进程,其中比较著名的方法就是通过远程线程注入的方法注入将恶意进程的DLL文件注入系统认可的正常进程,你会发现任务管理器以及找不到独立出现的恶意进程项了.反向连接型后门采用这种技术,注入防火墙认可的进程(例如大部分系统进程,像explorer.exe就很常见)还能够获得一定的穿墙效果. 进程注入虽然已经是将近10年前的技术了,但是今天出现的很多新型黑客技术大多数还是基于这类老技术演变而来