在x86程序集中实现反射(在运行时编辑程序)

时间:2014-07-10 12:47:07

标签: assembly

我想编写一个汇编程序,一旦加载到内存中,就会自行编写新指令,但我并不是100%肯定如何继续操作,因为我对指令指针和其他汇编概念有些怀疑。我的假设方法:

_func:

    push rip    ; Not allowed to push RIP, how can I read from RIP?
    jmp stage1

    stage2:

    mov eax, 0
    ret

    stage1:

    pop rbx

    ; How many times should I increment rbx to point to ‘mov eax, 0’?
    ; Assuming this is done:

    ;Move opcodes for ‘mov eax, 1’ into memory where ‘mov eax, 0’ located

    mov [rbx], 0xB8
    mov [rbx+1], 0x01
    mov [rbx+2], 0x00
    mov [rbx+3], 0x00
    mov [rbx+4], 0x00

    jmp stage2

当它跳到第2阶段而不是'mov eax,0'时,它将遇到操作码'B8 01 00 00 00'并解释'mov eax,1'。我的一般方法是否正确,有人可以在代码中填补这个空白吗?


其他混淆/问题

RBX指向指令行的第一个字节,还是“整行”?上述方法是正确的,还是我应该写的:

mov [rbx], B801000000h

操作系统:Mac OS X 10.9 汇编程序: NASM

2 个答案:

答案 0 :(得分:1)

在16位"实模式"这样做很简单。当我开始汇编编程时,我使用反射实现了一个循环。

但是在16位或32位"保护模式下"或长期模式" (64位)这更棘手:

在这些模式下,可以保护存储器不被覆盖。自从" Pentium Pro"处理器也可以保护内存不被执行。

Windows和Linux都使用这些功能,因此默认情况下可以修改的内存不能包含可执行代码,并且不能覆盖包含可执行代码的内存。

您必须分配可写和可执行的内存(或更改现有内存的内存访问权限)。参见" VirtualAlloc"和#34; VirtualProtect" Windows中的函数或" mmap"和" mprotect"在Linux中。然后你必须将代码移动到那段内存中。

顺便说一句:以下命令错误:

jmp stage1

一定是"打电话"而不是" jmp"因为" jmp"没有"推"堆栈上的返回地址。

答案 1 :(得分:1)

在16位“实模式”中:

mov bx, stage2      ; NASM get offset address

mov cs:[bx], 0xB8
mov cs:[bx+1], 0x01
mov cs:[bx+2], 0x00
mov cs:[bx+3], 0x00
mov cs:[bx+4], 0x00