我想编写一个汇编程序,一旦加载到内存中,就会自行编写新指令,但我并不是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
答案 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