吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4208|回复: 51
上一主题 下一主题
收起左侧

[调试逆向] [菜鸟尝试]劫持线程注入

  [复制链接]
跳转到指定楼层
楼主
wolfSpicy 发表于 2024-3-28 19:56 回帖奖励

劫持线程注入以我自己的看法来说,就是和dll注入差不多,在一个程序中运行然后在另一个程序是注入自己想要的dll

它的过程和dll注入有所不同

  1. 要先找到目标线程
  2. 找到目标线程后要进行挂起(大白话就是把线程给暂停了)
  3. 写入shellcode和dll名称到目标线程的内存中
  4. 把目标线程的EIP位置修改到shellcode的位置(在这之前要考虑堆栈平衡)
  5. 恢复线程运行

这就是劫持线程注入的流程,这和普通的dll注入区别就是在于要多出自写shellcode和EIP指向并且还需要考虑堆栈平衡等因素。

找到目标线程

当我们有目标进程的PID的时候如何找到目标线程?

我的思路是把全部进程的线程给遍历,然后每次都看下是该线程的进程PID与目标PID相同


    DWORD threadId = 0;

    DWORD pid = 0;

    HANDLE snapHandle = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, threadId);

THREADENTRY32   processStruct = { 0 };

    processStruct.dwSize = sizeof(processStruct);

    Thread32First(snapHandle, &threadStruct);

    do
    {
        pid = threadStruct.th32OwnerProcessID;//从线程找到目标进程PID
        if (pid == tagrtPid) {
            processHandle = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
            handleTread =OpenThread(THREAD_ALL_ACCESS, false, threadStruct.th32ThreadID);//把目标进程的线程句柄给保存
            if (!handleTread) {
                printf("%d", GetLastError());
            }
            vAlloc =(char*)VirtualAllocEx(processHandle, NULL, 1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);//开辟一段内存 即将用于写入shellcode和dll名称
            break;
        }

    } while (Thread32Next(snapHandle, &threadStruct));

写shellcode

我们的目的是为了能够在另一线程中执行我们想要的dll
所以我们写shellcode是与loadlibrary有关的,并且还要考虑到堆栈等问题

    char shellcode[] = { 
        0x68, 0x00, 0x00, 0x00, 0x00,//push eip存储挂起前EIP的位置
        0x60,//pushad 保存现场
        0x68, 0x00, 0x00, 0x00, 0x00, //push 参数名称
        0xB8,0x00, 0x00, 0x00, 0x00, //mov eax,loadlibrary函数地址
        0xFF, 0xD0, //call eax
        0x61, //popad 恢复现场
        0xC3 //ret 这个指令相当于pop eip 
        };

我在写的时候会在想,loadlibrary地址到时候咋获得,我自己这个程序是怎么知道目标程序的loadlibrary的?

其实这个是一个知识点,你想想一个电脑中有几百个进程都可能需要这个dll函数,如果每个都特地给这个dll函数空间那不是又费时又占空间吗。

那这时候换做你该怎么办呢?是的,就是共享,只要共享了就可以既省空间又省时间,我这个程序中loadlibrary地址是这个,那么另一个程序的loadlibrary地址也应该是这个.这个可以做下实验看看.

写路径到目标内存空间

    if (!WriteProcessMemory(processHandle, vAlloc + sizeof(shellcode), path, strlen(path), NULL)) {
        printf("%d", GetLastError());
        return;

    };//这个是先把dll的路径 名称写入内存空间  位置是写在shellcode的后面

shellcode到目标内存空间

//在这之前要先挂起线程 为的是能够获取EIP的位置才能修改shellcode
    SuspendThread(handleTread);

    //获取shellcode的上下文环境,其中就包括eip
    GetThreadContext(handleTread, &context);

    //为什么要兜一圈变成DWORD 如果直接赋值会因为是char的原因
    //最后只会赋值到一个字节
    *((DWORD*) & shellcode[1]) = context.Eip;

    *((DWORD*)&shellcode[7]) = (int)vAlloc + sizeof(shellcode) ;

    *((DWORD*)&shellcode[13]) =(DWORD)LoadLibraryA;
    if (!WriteProcessMemory(processHandle, vAlloc, shellcode, sizeof(shellcode), NULL)) {
        printf("%d", GetLastError());
        return;

    };

写入前

写入后

正常运行

    context.Eip = (DWORD)vAlloc;//EIP指向shellcode开头位置

    SetThreadContext(handleTread, &context);

    ResumeThread(handleTread);

免费评分

参与人数 9吾爱币 +13 热心值 +7 收起 理由
linxiaoche + 1 + 1 我很赞同!
willJ + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
warobot + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
898522783 + 1 谢谢@Thanks!
杨辣子 + 1 + 1 谢谢@Thanks!
Ehtrs + 1 我很赞同!
qwq23496 + 1 + 1 我很赞同!
bullshit + 1 + 1 谢谢@Thanks!
sjlhao123 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

推荐
DEATHTOUCH 发表于 2024-3-29 11:42
本帖最后由 DEATHTOUCH 于 2024-3-29 11:44 编辑

这是前几天帮助坛友写的,是针对x64的,刚好和楼主针对x86的互补,放出来给大家参考。
不过shellcode没有考虑恢复rax寄存器的内容,不知道会不会有影响(测试是没问题的,就怕测试不全面,如果有问题就保存了rax并利用xchg指令就行)。
[C++] 纯文本查看 复制代码
#include <Windows.h>
#include <iostream>

int main(int argc, char* argv[])
{
        char* ExePath; // exe路径
        char* DllPath; // dll路径
        int dll_mem_len = 0; // dll路径长度(包括结尾'\0')

        LPVOID Remote_DllStringPtr; // 写入被注入进程的dll路径
        LPVOID Remote_ShellCodePtr; // 写入被注入进程的ShellCode

        CONTEXT ctx = {};
        PROCESS_INFORMATION pi = {};
        STARTUPINFOA si = {};

        if (argc < 3) {
                printf("Usage: CreateSuspendInject.exe <exe> <dll>\n");
                return 1;
        }

        ExePath = argv[1];
        DllPath = argv[2];
        dll_mem_len = strlen(DllPath) + 1;

        if (CreateProcessA(ExePath, NULL, NULL, NULL, NULL, CREATE_SUSPENDED, NULL, NULL, &si, &pi) == 0) {
                printf("Can't create process\n");
                return 1;
        }

        Remote_DllStringPtr = VirtualAllocEx(pi.hProcess, NULL, dll_mem_len, MEM_COMMIT, PAGE_READWRITE);
        Remote_ShellCodePtr = VirtualAllocEx(pi.hProcess, NULL, 64, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

        ctx.ContextFlags = CONTEXT_CONTROL;
        GetThreadContext(pi.hThread, &ctx); // 获取线程上下文

        unsigned char ShellCode[] = {
                0x48, 0xb8, 0,0,0,0,0,0,0,0, // mov rax, original_rip
                0x50, // push rax
                0x51, // push rcx
                0x52, // push rdx
                0x41, 0x50, // push r8
                0x41, 0x51, // push r9
                0x41, 0x52, // push r10
                0x41, 0x53, // push r11
                0x48, 0xb9, 0,0,0,0,0,0,0,0, // mov rcx, str
                0x48, 0xb8, 0,0,0,0,0,0,0,0, // mov rax, LoadLibraryA
                0xff, 0xd0, // call rax
                0x41, 0x5b, // pop r11
                0x41, 0x5a, // pop r10
                0x41, 0x59, // pop r9
                0x41, 0x58, // pop r8
                0x5a, // pop rdx
                0x59, // pop rcx
                0xc3, // ret
        };
        *(void**)&ShellCode[2] = (void*)ctx.Rip;
        *(void**)&ShellCode[23] = Remote_DllStringPtr;
        *(void**)&ShellCode[33] = (void*)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA");

        WriteProcessMemory(pi.hProcess, Remote_DllStringPtr, DllPath, dll_mem_len, NULL);
        WriteProcessMemory(pi.hProcess, Remote_ShellCodePtr, ShellCode, sizeof(ShellCode), NULL);

        ctx.Rip = (DWORD64)Remote_ShellCodePtr; // 把Rip指向ShellCode
        ctx.ContextFlags = CONTEXT_CONTROL;
        SetThreadContext(pi.hThread, &ctx); // 设置线程上下文

        ResumeThread(pi.hThread); // 恢复线程,执行ShellCode

        Sleep(1000);

        VirtualFreeEx(pi.hProcess, Remote_DllStringPtr, dll_mem_len, MEM_DECOMMIT);
        VirtualFreeEx(pi.hProcess, Remote_ShellCodePtr, sizeof(ShellCode), MEM_DECOMMIT);

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);

        return 0;
}
推荐
egoistcy 发表于 2024-3-28 23:50
3#
guohuanxian 发表于 2024-3-28 20:09
4#
LittleHedgehog 发表于 2024-3-28 20:38
学习学习
5#
wanzm 发表于 2024-3-28 21:20
学习学习学习
6#
xiaoguips123 发表于 2024-3-28 21:39
值得深入学习
7#
mumulu 发表于 2024-3-28 22:02
学习学习
8#
qwq23496 发表于 2024-3-28 23:36
学习学习线程相关原理与知识
9#
wolaikaoyan 发表于 2024-3-28 23:44
楼主来个实际的案例吧,对照具体的案例学习,更好理解
10#
kilkilo502 发表于 2024-3-29 00:23
这种注入试是最实用的尤其在辅助领悟
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-21 15:38

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表