【安全报告】揭秘创建进程时ebx为什么指向peb的答案

本文深入探讨了在Windows系统中创建进程时,为何eax指向新OEP,ebx指向新PEB的原因。通过分析XP和Win7下的CreateProcessInternalW流程,揭示了进程创建和线程上下文初始化的过程,涉及Ring3和Ring0的交互,以及PE文件结构解析。

在这里插入图片描述

一、背景

为了确保被替换后的进程能顺利执行不崩溃,需要获取原进程各种上下文,并修改被替换后的新进程上下文,其中在原进程被挂起还没开始执行的时候,需要将eax指向新oep,而ebx指向新peb,而为什么这样设置的原因却很少有人提及。为此,在经过查阅了一定的资料与简单的分析后,我们可以找到答案。

二、具体分析

先抛出结论,这里的eax与ebx属于线程上下文信息,在一个PE文件开始被运行的过程中,主线程上下文初始化过程是在进程已经创建完成,而主线程还没创建的阶段发生的,下面是具体更详细的分析:

首先我们需要对进程的创建有一个大概的认识,在ring3下创建进程API无非是CreateProcessA/W,但是无论调用哪一个,最终都会将相关参数转化为Unicode字符串,并最终调用CreateProcessInternalW,因此以下将主要分析CreateProcessInternalW,而在xp和win7下,它具体实现又有一些不一样的地方。

2.1 XP下执行流程
在xp下,它大概分为四个部分,分别是ring3下创建进程,ring0下创建进程,ring3下创建线程,ring0下创建线程,以NtCreateProcessEx为分界线,NtCreateProcessEx之前为ring3下创建进程主要流程。

2.1.1 Ring3下创建进程

  1. 判断处理dwCreationFlag各种标志位,包括是否包含不合法标记组合,判断优先级。
    在这里插入图片描述
  2. 判断lpEnvironment是否为空,不为空则调用RtlAnsiStringToUnicodeString将其转为UniCode字符串。
    在这里插入图片描述
  3. 判断lpApplicationName、lpCommandLine是否为空。
    在这里插入图片描述
    如果lpApplicationName不为空直接调用RtlDosPathNameToNtPathName_U函数将DOS路径(C:\WINDOWS\XXX)转换为NT路径(\Device\HarddiskVolume1\WINDOWS\XXX),为空则会解析lpCommandLine,主要按照’”’引号,’ ’空格,’\t’制表符作为分隔符进行解析并获取相应的PE文件,然后将DOS路径转换为NT路径。

在这里插入图片描述

创建函数,`ebx`、`esi` 和 `edi` 寄存器在 x86 架构中通常被用作通用寄存器,但它们也有一些特定的用途和约定。 ### EBX 寄存器 `ebx` 寄存器通常被称为基地址寄存器(Base Register)。在函数创建和执行过程中,`ebx` 可以被用作存储数据的通用寄存器。在某些情况下,特别是在使用全局偏移表(Global Offset Table, GOT)进行位置无关代码(Position Independent Code, PIC)的实现,`ebx` 通常被用来保存 GOT 的地址,以便于访问全局数据。这种用法在共享库的实现中非常常见。 ### ESI 寄存器 `esi` 寄存器是源索引寄存器(Source Index Register),主要用于字符串和内存操作。在函数创建,`esi` 通常用于指向源数据的地址,特别是在需要进行数据复制或处理的情况下。例如,在字符串操作中,`esi` 会指向源字符串的起始位置,而 `edi` 则指向目标位置。这种用法使得 `esi` 和 `edi` 成为处理内存拷贝和填充操作的理想选择。 ### EDI 寄存器 `edi` 寄存器是目的索引寄存器(Destination Index Register),与 `esi` 类似,它也用于字符串和内存操作。在函数创建,`edi` 通常用于指向目标数据的地址。例如,在执行字符串复制操作,`edi` 会指向目标缓冲区的起始位置。`esi` 和 `edi` 经常一起使用,以实现高效的内存操作。 在函数调用和执行过程中,这些寄存器的使用可能会受到调用约定(Calling Convention)的影响。不同的调用约定可能规定了哪些寄存器应该由调用者保存,哪些应该由被调用者保存。例如,在某些调用约定下,`ebx`、`esi` 和 `edi` 被认为是“非易失性”寄存器,这意味着如果函数在执行过程中修改了这些寄存器的值,它必须在返回前恢复它们的原始值[^3]。 下面是一个简单的汇编代码示例,展示了如何在函数中使用 `ebx`、`esi` 和 `edi`: ```asm section .data source db 'Hello, World!', 0 dest db 13 dup(0) ; 假设我们要复制13个字节 section .text global _start _start: ; 设置esi为源字符串的地址 lea esi, [source] ; 设置edi为目标缓冲区的地址 lea edi, [dest] ; 设置ecx为要复制的字节数 mov ecx, 13 ; 使用rep movsb指令复制字符串 rep movsb ; 这里可以添加其他代码来处理dest中的数据 ; 退出程序 mov eax, 1 ; sys_exit xor ebx, ebx ; exit code 0 int 0x80 ``` 在这个例子中,`esi` 被用来指向源字符串 `source`,`edi` 被用来指向目标缓冲区 `dest`,而 `ecx` 被用来设置要复制的字节数。`rep movsb` 指令会将 `ecx` 指定的字节数从 `esi` 指向的位置复制到 `edi` 指向的位置。 ### 相关问题 1. 在不同的调用约定下,`ebx`、`esi` 和 `edi` 寄存器的使用规则有何不同? 2. 如何在位置无关代码中使用 `ebx` 寄存器? 3. `esi` 和 `edi` 寄存器在字符串操作之外还有哪些用途? 4. 在函数调用过程中,如何正确保存和恢复 `ebx`、`esi` 和 `edi` 寄存器的值? 5. `esi` 和 `edi` 寄存器在处理大数据块有哪些优化技巧?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值