windows ring3 注入及hook

需求背景

动态修改程序的函数oldsub()执行我们的newsub()

此时则需要注入并hook

注入

简单的远程线程注入分三步
//获取进程句柄
//提升权限
//注入dll

#include <windows.h>

//获取进程句柄
HANDLE GetThePidOfTargetProcess(HWND hwnd)
{
    DWORD pid;
    GetWindowThreadProcessId(hwnd, &pid);
    HANDLE hProcee = ::OpenProcess(PROCESS_ALL_ACCESS | PROCESS_CREATE_THREAD, 0, pid);
    return hProcee;
}
//提升权限
void Up()
{
    HANDLE hToken;
    LUID luid;
    TOKEN_PRIVILEGES tp;
    OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
    LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid);
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    tp.Privileges[0].Luid = luid;
    AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL);
}
 
//进程注入
 
BOOL DoInjection(char *DllPath, HANDLE hProcess)
{
    DWORD BufSize = strlen(DllPath)+1;
    LPVOID AllocAddr = VirtualAllocEx(hProcess, NULL, BufSize, MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(hProcess, AllocAddr, DllPath, BufSize, NULL);
    PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("Kernel32")), "LoadLibraryA");
 
    HANDLE hRemoteThread;
    hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartAddr, AllocAddr, 0, NULL);
    if (hRemoteThread)
    {
        MessageBox(NULL, TEXT("注入成功"), TEXT("提示"), MB_OK);
        return true;
    }
    else
    {
        MessageBox(NULL, TEXT("注入失败"), TEXT("提示"), MB_OK);
        return false;
    }
}
 
 
int main()
{
    //这里填写窗口标题
    HWND hwnd=FindWindowExA(NULL, NULL, NULL, "任务管理器");
    Up();
    HANDLE hP = GetThePidOfTargetProcess(hwnd);
    //开始注入
    //这里填写Dll路径
    DoInjection("E:\\studio\\VS2017\\F2H1.MessageBox\\x64\\Release\\F2H1.MessageBox.dll", hP);
}

参考:
https://github.com/suvllian/process-inject
https://github.com/suvllian/process-inject

hook

方式1:通过注入dll到目标进程进行,可以替换kernelbase.dll里面的OpenProcess的前面5个字节为jmp跳转到我们自己的地址,也可以修改目标进程的IAT.
方式2:通过WriteProcessMemory写入代码,修改目标进程的OpenProcess跳转到我们的代码

// 设置hook  https://bbs.pediy.com/thread-250631.htm
void* setReturn1(int toAddr, int fromAddr) {
 
    int isize = 5 + 5 + 5;
    char *p1 = (char*)VirtualAlloc(0, isize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memset(p1, 0, isize);
    char *p = (char*)&return1;
    // 改用汇编,不然Release编译时会出错
    // memcpy(p1, p, isize);
    __asm {
        pushad;
        mov esi, p;
        mov edi, p1;
        mov ecx, isize;
        rep movsb;
        popad;
    }
 
    // 目标地址 - (当前地址 + 指令长度)
    int fix1 = toAddr - ((int)p1 + 5);
    int fix2 = (fromAddr + 5) - ((int)p1 + 0xA + 5); // ret addr
    int fix3 = (int)p1 - (fromAddr + 5);
    *(int*)((int)p1 + 1) = fix1;
    *(int*)((int)p1 + 0xB) = fix2;
 
    // hook
    DWORD flOldProtect;
    VirtualProtect((LPVOID)fromAddr, 5, PAGE_EXECUTE_READWRITE, &flOldProtect);
    *(BYTE*)fromAddr = 0xE9; // JMP x
    *(int*)(fromAddr + 1) = fix3; // JMP x
    VirtualProtect((LPVOID)fromAddr, 5, flOldProtect, &flOldProtect);
 
    return p1;
}
hook库对比:

nthookengine //支持x64 开源
mhook //支持x64 开源 https://github.com/martona/mhook
Detour//x64收费 https://github.com/microsoft/Detours

https://blog.csdn.net/zhuhuibeishadiao/article/details/51170608

寻址

通过LoadLibrary加载kernelbase.dll模块基地址.
通过GetProcAddress获取OpenProcess的地址.
方式2:编程直接引用OpenProcess的地址,因为在Windows下3大模块user32.dll,kernelbase.dll,ntdll.dll的加载基地址在每个应用程序中都是一样的.
方式3:通过寻找目标的IAT找到OpenProcess

内存中特征码匹配参考:
https://bbs.pediy.com/thread-121198.htm
https://blog.csdn.net/HoneyCat/article/details/3950939

参考:
hook原理:https://bbs.pediy.com/thread-228669.htm

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值