【问题标题】:Null bytes in shellcodeshellcode 中的空字节
【发布时间】:2013-05-14 18:36:06
【问题描述】:

通过维基百科上的shellcode文章,它给出了一个示例如下:

B8 01000000    MOV EAX,1          // Set the register EAX to 0x000000001

为了使上述指令为空,他们将其重写如下:

33C0           XOR EAX,EAX        // Set the register EAX to 0x000000000
40             INC EAX            // Increase EAX to 0x00000001

第一条指令中的空字节在哪里?转换后的指令怎么没有空字节?

【问题讨论】:

    标签: shellcode


    【解决方案1】:

    空字节在第一条指令的B8 01 之后。 第二条指令使用xor 操作将eax(任何x xor x = 0)归零,然后将其加一以在没有00空字节)的情况下达到相同的结果em>。

    【讨论】:

    • 所以在这里,0x00 是被视为 1 字节还是 00000000?
    • 0x00 是 1 字节 == 8 位。 0x00000000 是 4 字节/32 位,这是 32 位(原文如此)机器上的寄存器长度。
    【解决方案2】:

    第一条指令中的空字节在哪里?

    B8 01000000    MOV EAX,1          // Set the register EAX to 0x000000001
         ^^^^^^
         1 2 3
    

    实际上有 3 个空字节

    转换后的指令怎么没有空字节? 因为

    1. XOR 和 INC 的操作码不包含空字节 (http://ref.x86asm.net/coder32-abc.html)
    2. 这里只使用寄存器作为参数

    对于MOV EAX, 1 指令,汇编器必须编写操作码 (B8) 和 2 个参数,其中一个是 32 位整数。由于 1 是一个很小的数字,所以剩余的位用零填充,从而产生一个空字节。

    XORINC 指令在您的代码中不采用整数,也不必插入零。

    更新

    我没有注意到 MOV r32, imm32 的操作码中的 +r。

    寄存器在 x86 中使用 3 位编码,eax 为 000B8 是二进制的 0b10111000,最后是 3 个空闲位。

    0b10111000 + 0x000 = 0b10111000 = 0xB8
    

    所以B8 编码为MOV EAX, imm32

    剩下的是0x01000000,1 是小端序。

    【讨论】:

    • 那么,既然 B8 是 mov 的操作码,01000000 包含两个参数?那么如果 01 是 1 个参数,其余 000000 用于填充目的,那么第一个参数在哪里? 1不应该写成00000001而不是01000000吗?
    • 01000000 对两个参数进行编码,但我不知道如何,x86 指令编码非常复杂。我认为它看起来是因为字节序而颠倒的。
    • @Lennart 实际上 0x01000000 只对第二个参数进行编码。 0xb8move immediate 32-bit value into EAX 的操作码。但你是对的 - 0x01000000 是 32 位值 1 的小端编码。
    • @Lennart 好的。我理解B8部分。操作码中的 +r 是什么?尽管我几年前做过 x86 编程,但我现在对字节顺序有点困惑。
    • @user85030 +r 表示添加到值的寄存器代码,从 0 到 7。 (ref.x86asm.net/#column_po); Endiannes: (en.wikipedia.org/wiki/Endianness#Little-endian) 基本上字节是颠倒的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多