edi是argc,rsi是argv
0x0000000000400535 <+8>: mov %edi,-0x4(%rbp)
0x0000000000400538 <+11>: mov %rsi,-0x10(%rbp)
这里我得到了argv指针
(gdb) x/8x $rbp-0x10
0x7ffdb7cac380: 0xb7cac478 0x00007ffd 0x00000000 0x00000003
0x7ffdb7cac390: 0x00000000 0x00000000 0x1f130b45 0x00007ff3
指针0x7ffdb7cac478
所以我的argv [2]就在这里:
(gdb) x/8x 0x7ffdb7cac478+16
0x7ffdb7cac488: 0xb7cacd8a 0x00007ffd 0x00000000 0x00000000
地址0x7ffdb7cacd8a
我需要获取argv [2]的地址,所以我想写这个汇编代码:
伪代码:
x - 从地址$ rbp-0x10 //(指向argv的指针)
加载8个字节y - 从x值加载8个字节+ 16 //(指向argv [2]的指针)
我稍后需要jmp到y。
如何用汇编程序x64编写?我可以使用哪个寄存器用于x和y?
我希望这是可以理解的。我是初学者。
我问这里,因为我不知道从哪里开始做研究。
更新
试过这个:
bits 64
ldr r8, rbp, #0x10
ldr r9, r8, #0x10
jmp r9
但它甚至没有编译....我正在使用nasm。
我猜以上是针对ARM arch,因为下面的amd64(x64)应该这样做。这是对的吗?
更新2:
bits 64
lea r8, [rbp-0x10]
lea r9, [r8+0x10]
jmp r9
更新3:
也不起作用......
bits 64
lea r8, [rbp-0x10]
mov r9, [r8]
mov r10, [r9+0x10]
jmp r10
答案 0 :(得分:1)
您在撰写main()
或_start
吗?
如果您正在编写main
,那么它是rdi
,rsi
中的args的正常函数,遵循正常的调用约定。有关x86的链接,请参见wiki代码to the x86-64 ABI。
如果您正在编写_start
,那么数据就在堆栈中,如ABI的流程启动部分所述:[rsp] = argc
,以及指针数组char *arg[]
之上从rsp+8
开始。它是堆栈上的实际数组,而不是指向类似main
的数组的指针。
rbp
除非您初始化它,否则毫无意义。它有来电者留下的任何东西。
您的代码片段也很愚蠢:您永远不会初始化rbp。您应该假设它在进程输入时保留垃圾。只有rsp
才有用。
lea
只是一个转变&amp;添加使用有效地址语法/编码的指令。 mov
是加载/存储的助记符。
;; your code with comments, also assuming that RBP was initialized
bits 64
lea r8, [rbp-0x10] ; r8 = rbp-0x10
mov r9, [r8] ; should have just done mov r9, [rbp-0x10]
mov r10, [r9+0x10]
jmp r10 ; jump to argv[2]???
您是否将机器代码字节放在argv[2]
中?跳转到字符串通常不是很有用。
当然,由于rbp
未初始化,因此实际上并未访问argv[2]
。
在调试器中单步执行此操作。
; get argc and argv from the stack, for x86-64 SysV ABI
global _start
_start:
mov ecx, [rsp] ; load argc (assuming it's smaller than 2^32)
cmp ecx, 3
jb .argc_below_3
; argv[0] is at rsp+8
mov rsi, [rsp+8 + 8*2] ; argv[2] (the 3rd element)
movzx eax, byte [rsi] ; first char of argv[2]
; if you stop here in a debugger, you can see the character from the second arg.
; fall through and exit
.argc_below_3:
xor edi, edi
mov eax, 231 ; exit_group(0)
syscall