R3修改线程上下文EIP实现的无模块注入

本文介绍了一种使用Shellcode注入技术来挂起并恢复目标进程的方法。通过编写特定的Shellcode,该代码能够弹出消息框,并在执行前后保存和恢复进程的执行上下文,实现了对目标进程的精确控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include "stdafx.h"
#include <windows.h>
#include <iostream>
using std::cin;

DWORD dwOldEip = 0;
DWORD funRemote = 0;

BYTE shellCode[25] = {
        0x68, 0x78, 0x56, 0x34, 0x12,                                //push        12345678h
        0x9C,                                                                                //pushfd
        0x60,                                                                                //pushad
        0x6A, 0x00,                                                                        //push        0
        0x6A, 0x00,                                                                        //push        0
        0x6A, 0x00,                                                                        //push        0
        0x6A, 0x00,                                                                        //push        0
        0xB8, 0x78, 0x56, 0x34, 0x12,                                //mov         eax, 12345678h
        0xFF, 0xD0,                                                                        //call        eax
        0x61,                                                                                //popad
        0x9D,                                                                                //popfd
        0xC3,                                                                                //ret
};


BOOL ThreadContextTest(DWORD dwProcessId, DWORD dwMemSize)
{
        HWND hwnd = FindWindow(NULL, L"Dependency Walker");
        if (!hwnd)
                return FALSE;
        printf("hwnd:%p\n", hwnd);

        // 打开进程
        HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
        if (!hProcess)
                return FALSE;

        // 获取主线程ID
        DWORD dwThreadId = GetWindowThreadProcessId(hwnd, NULL);
        printf("dwThreadId:%d\n", dwThreadId);

        HANDLE hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, dwThreadId);
        // 暂停主线程
        DWORD dwSuspendCount = SuspendThread(hThread);
        printf("暂停线程,任意键恢复线程,dwSuspendCount:%d\n", dwSuspendCount);
        CONTEXT stcContext = { CONTEXT_FULL };
        if (!GetThreadContext(hThread, &stcContext))
                return FALSE;

        HMODULE hModule = LoadLibrary(L"User32.dll");
        funRemote = (DWORD)GetProcAddress(hModule, "MessageBoxA");
        // 获取原始EIP
        dwOldEip = stcContext.Eip;
        printf("stcContext.Eip:%p\n", stcContext.Eip);

        // 申请内存
        LPVOID lpAddr = VirtualAllocEx(hProcess, NULL, dwMemSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (!lpAddr)
                return FALSE;

        printf("lpAddr:%p\n", lpAddr);

        // 构造shellCode
        memcpy(&shellCode[16], &funRemote, 4);
        memcpy(&shellCode[1], &dwOldEip, 4);

        // 写入内存
        BOOL bRet = WriteProcessMemory(hProcess, lpAddr, shellCode, dwMemSize, NULL);
        if (!bRet)
                return FALSE;

        
        // 设置EIP
        stcContext.Eip = (DWORD)lpAddr;
        SetThreadContext(hThread, &stcContext);


        //system("pause");

        DWORD dwResumeCount = ResumeThread(hThread);
        printf("恢复线程,dwResumeCount:%d\n", dwResumeCount);

        return TRUE;
}

int _tmain(int argc, _TCHAR* argv[])
{
        DWORD dwLen = sizeof(shellCode);
        DWORD dwProcessId = 0;
        cin >> dwProcessId;

        ThreadContextTest(dwProcessId, dwLen);

        system("pause");
        return 0;
}

我把执行的代码写成了ShellCode,就是弹一个 MessageBox,但是前面一句和最后一句是重点,第一句是把当前EIP 压栈,最后的RET就是

返回到正确EIP  这个是必须有的,在这里RET指令的内部操作是:栈顶字单元出栈,其值赋给IP寄存器。即实现了一个程序的转移,将栈顶字单元保存

的偏移地址作为下一条指令的偏移地址。

        当然也可以把你自己的执行代码写成函数,遇到的问题就是计算函数的大小,一般方法就是搜索特征码Ret(高老湿说滴),然后特征码地址减

去,函数地址,就是大小~~

由于EIP必须在运行的时候才能得到,所以我把获得的EIP直接MEMCOPY到相应shellCode位置。

运行结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值