首页
论坛
课程
招聘
[原创]获取被挂起进程基址小技巧(傀儡进程)
2019-7-29 15:13 4614

[原创]获取被挂起进程基址小技巧(傀儡进程)

2019-7-29 15:13
4614

创建傀儡进程时,一般以挂起模式创建一个系统进程,如:svchost.exe

然后调用未导出NT函数NtQueryInformationProcess来获取目标进程的PEB地址,拿到PEB地址后,再通过ReadProcessMemory获取目标进程的PEB数据,
最后NtUnMapViewOfSection,传入PEB结构中的ImageBaseAddress来卸载目标进程的内存。

其实可以直接通过GetThreadContext这个函数来直接获取PEB地址,在Ebx寄存器中保存的就是PEB地址。

typedef struct __PEB {
    BYTE InheritedAddressSpace;
    BYTE ReadImageFileExecOptions;
    BYTE BeingDebugged;
    BYTE SpareBool;
    void* Mutant;
    void* ImageBaseAddress;  // offset 0x08
    _PEB_LDR_DATA* Ldr;
    /*....*/
}MYPEB, *PMYPEB;

得知PEB结构偏移0x8的位置就是进程加载基址,在获取线程上下文后,直接用ebx的内容+8,再通过ReadProcessMemory读取4个字节,就可以得到被挂起进程的基址了。


   // 获取线程上下文
    CONTEXT ctx = { 0 };
    ctx.ContextFlags = CONTEXT_ALL;
    if (!GetThreadContext(pi.hThread, &ctx))
    {
        printf("GetThreadContext failed (%d).\n", GetLastError());
    }

    // 拿到目标进程主线程上下文后,在Ebx寄存器中保存的就是PEB的地址,
    // 而PEB结构偏移0x8的位置是AddressOfImageBase字段,
    // 所以直接来读取ctx.Ebx+0x8,就可以获取到目标进程的加载基址
    DWORD dwImageBase =  0;
    DWORD lpNumberOfBytesRead = 0;
    if (!ReadProcessMemory(pi.hProcess, (LPCVOID)(ctx.Ebx + 0x8), &dwImageBase, sizeof(DWORD), &lpNumberOfBytesRead))
    {
        printf("ReadProcessMemory failed (%d).\n", GetLastError());
        return;
    }




第五届安全开发者峰会(SDC 2021)议题征集正式开启!

收藏
点赞1
打赏
分享
最新回复 (4)
雪    币: 1509
活跃值: 活跃值 (641)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
SAO 活跃值 2021-5-4 18:51
2
0
能解释一下这个技巧的原理吗?为什么GetThreadContext可以直接获取PEB,这是规律吗?看有的傀儡进程demo还会直接在获取寄存器数据后使用eax=oep,能解释一下吗?
雪    币: 2080
活跃值: 活跃值 (1341)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Mr.hack 活跃值 2021-7-14 11:18
3
0
SAO 能解释一下这个技巧的原理吗?为什么GetThreadContext可以直接获取PEB,这是规律吗?看有的傀儡进程demo还会直接在获取寄存器数据后使用eax=oep,能解释一下吗?
以挂起的方式创建进程,其线程上下文context的ebx存放的就是peb的地址,这是通过逆向分析进程创建3环部分得到的结论
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_cigdritw 活跃值 4天前
4
0

看来这个编程技巧挺深奥的,先收藏下来,慢慢学习一下。

雪    币: 16
活跃值: 活跃值 (159)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
如此美丽。 活跃值 4天前
5
1
Mr.hack 以挂起的方式创建进程,其线程上下文context的ebx存放的就是peb的地址,这是通过逆向分析进程创建3环部分得到的结论
仅限于32位程序下  ebx只是刚好是不易丢失寄存器 本身在r3的进入程序"主线程"的时候 param1是oep param2是peb 而eax=param1  ebx=param2 所以出现的ebx=peb 未被丢失 而64位程序则不会出现这种情况
游客
登录 | 注册 方可回帖
返回