Assembly jmpq和lea,以及rdi寄存器如何在二进制文件中工作
因此,我在每个指令旁边注释了我认为它的含义,并在每个指令旁边放置了一个Assembly jmpq和lea,以及rdi寄存器如何在二进制文件中工作,assembly,x86,reverse-engineering,att,Assembly,X86,Reverse Engineering,Att,因此,我在每个指令旁边注释了我认为它的含义,并在每个指令旁边放置了一个(?),我不确定/不太确定它是否起作用。我不确定的可能比我标记的要多得多,但它们大多是相同类型的指令 0x0000000000401251 <+0>: sub $0x8,%rsp 0x0000000000401255 <+4>: cmp $0x1,%rdi #compare num of inputs (?) 0x0
(?)
,我不确定/不太确定它是否起作用。我不确定的可能比我标记的要多得多,但它们大多是相同类型的指令
0x0000000000401251 <+0>: sub $0x8,%rsp
0x0000000000401255 <+4>: cmp $0x1,%rdi #compare num of inputs (?)
0x0000000000401259 <+8>: jg 0x40126c <phase_3+27> #blow up if not >1
0x000000000040125b <+10>: callq 0x401c01 <bomb_ignition>
0x0000000000401260 <+15>: mov $0xffffffffffffffff,%rax
0x0000000000401267 <+22>: jmpq 0x40136c <phase_3+283>
0x000000000040126c <+27>: lea 0x16(%rdi),%rax #rax = rdi[22] (?)
0x0000000000401270 <+31>: sub $0x4b,%rsi #rsi -= 75
0x0000000000401274 <+35>: cmp $0x2b,%rsi #rsi == 43
0x0000000000401278 <+39>: ja 0x40133a <phase_3+233> bomb_ignition #rsi>43 -> blow up (?)
0x000000000040127e <+45>: jmpq *0x4027b0(,%rsi,8) # (?)
0x0000000000401285 <+52>: mov %rdi,%rax #rax = rdi
0x0000000000401288 <+55>: neg %rax #rax = -rax (flip bits)
0x000000000040128b <+58>: sub $0x7,%rax #rax -= 7
0x000000000040128f <+62>: lea 0x14(%rax,%rax,2),%rdi #rdi = rax*3+20
0x0000000000401294 <+67>: jmpq 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x0000000000401299 <+72>: sar %rax #rax /= 2
0x000000000040129c <+75>: mov %rax,%rdi #rdi = rax
0x000000000040129f <+78>: jmpq 0x401351 <phase_3+256 #goto <256>/ compare rdi == 120
0x00000000004012a4 <+83>: lea 0x0(,%rax,8),%rdi #rdi = rax+8
0x00000000004012ac <+91>: jmpq 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x00000000004012b1 <+96>: sar $0x2,%rax #rax /= 4
0x00000000004012b5 <+100>: mov %rax,%rdi #rdi = rax
0x00000000004012b8 <+103>: jmpq 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x00000000004012bd <+108>: callq 0x401c01 <bomb_ignition> #bomb_ignition
0x00000000004012c2 <+113>: mov $0xfffffffffffffffe,%rax
0x00000000004012c9 <+120>: jmpq 0x40136c <phase_3+283> #exit (2 bomb explosions in a row?)
0x00000000004012ce <+125>: callq 0x401c01 <bomb_ignition> #bomb_ignition
0x00000000004012d3 <+130>: mov $0xfffffffffffffffd,%rax
0x00000000004012da <+137>: jmpq 0x40136c <phase_3+283> #exit
0x00000000004012df <+142>: lea (%rax,%rax,1),%rdi #rdi = rax*2
0x00000000004012e3 <+146>: jmp 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x00000000004012e5 <+148>: lea 0x0(,%rax,4),%rdi #rdi = rax*4
0x00000000004012ed <+156>: jmp 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x00000000004012ef <+158>: lea (%rax,%rax,8),%rdi #rdi = rax*9
0x00000000004012f3 <+162>: jmp 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x00000000004012f5 <+164>: lea 0xb(,%rax,4),%rax #rax = rax*4+11
0x00000000004012fd <+172>: sub $0xb,%rax #rax -= 11
0x0000000000401301 <+176>: add $0x15,%rax #rax += 21
0x0000000000401305 <+180>: lea 0x14(%rax,%rax,4),%rdi #rdi = rax*5
0x000000000040130a <+185>: jmp 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x000000000040130c <+187>: lea 0xb(%rax,%rax,1),%rdi #rdi = rax*2+11
0x0000000000401311 <+192>: jmp 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x0000000000401313 <+194>: lea 0x13(,%rax,8),%rdi #rdi = rax*8+19
0x000000000040131b <+202>: jmp 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x000000000040131d <+204>: lea (%rax,%rax,4),%rdi #rdi = rax*5
0x0000000000401321 <+208>: jmp 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x0000000000401323 <+210>: add $0x24,%rdi #rdi += 36
0x0000000000401327 <+214>: jmp 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x0000000000401329 <+216>: mov $0x11,%edi #edi = 17
0x000000000040132e <+221>: sub %rax,%rdi #rdi -= rax
0x0000000000401331 <+224>: jmp 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x0000000000401333 <+226>: lea 0x15(%rax,%rax,8),%rdi #rdi = rax*9+21
0x0000000000401338 <+231>: jmp 0x401351 <phase_3+256> #goto <256> / compare rdi == 120
0x000000000040133a <+233>: callq 0x401c01 <bomb_ignition> #bomb
0x000000000040133f <+238>: mov $0xffffffffffffffff,%rax
0x0000000000401346 <+245>: jmp 0x40136c <phase_3+283> #exit
0x0000000000401348 <+247>: lea (%rax,%rax,2),%rax #rax = rax*3
0x000000000040134c <+251>: lea 0x8(%rax,%rax,4),%rdi #rdi = rax*5+8
0x0000000000401351 <+256>: cmp $0x78,%rdi #rdi == 120
0x0000000000401355 <+260>: sete %al
0x0000000000401358 <+263>: movzbl %al,%eax
0x000000000040135b <+266>: cmp %rdx,%rdi #rdi == rdx
0x000000000040135e <+269>: je 0x40136c <phase_3+283> #exit if rdi == rdx
0x0000000000401360 <+271>: callq 0x401c01 <bomb_ignition>
0x0000000000401365 <+276>: mov $0xffffffffffffffff,%rax
0x000000000040136c <+283>: add $0x8,%rsp
0x0000000000401370 <+287>: retq
所以第八个是
。那么,这只是跳到那个位置吗?然后跳过它之间的一切?我希望并假设是这样,因为如果你不这样做,会有很多计算发生。我在gdb
中看过正确的东西了吗?如果是,则转到
,将rdi
更改为rax*2
。这就是lea
所做的吗?我是否正确地假设了该指令在做什么?然后它立即跳转到
,将rdi
与120进行比较。然后,rdx
也应该是相同的
因此,使用backwords,rdx=rdi=120
。然后,rdi=rax*2,所以rax=60。但是,rax=rdi[22]
,再次假设这就是lea
所做的。但是如果rdi是输入的数量,它怎么能有22个字符呢?那么假设它不是输入数,第22个字符怎么可能是2位数字呢
基于上一阶段(如果愿意,您可以查看我的历史记录),我认为%rdi
包含输入的数量。不过我可能错了。这是在bomb.c
k = sscanf(input, "%d %d", &a, &b);
status = phase_3(k, a, b);
phase_defused(status);
基于此,我假设
&a
和&b
是输入,分别是寄存器%rsi
和%rdx
。我试过118120
但它爆炸了 第一个lea
就是rax=rdi+22
。C等价物是rax=&rdi[22]
。您缺少&
。LEA是一种移位和加法指令,使用寻址模式语法和机器编码。是的,jmpq*0x4027b0(,%rsi,8)
是地址表的间接跳转。我不知道gdb有一种/a
格式,可以将符号标签放在地址上;这很酷:P(通常我有源代码,不是逆向工程)。看起来你用对了。一旦CPU计算出跳转目标地址,它的工作方式与普通的直接跳转完全相同。下一条要执行的指令是该目标地址处的指令,并从该地址继续执行。您可能希望尝试在反汇编中标记跳转目标。例如,在0x4012bd
之前添加一个空行,并在其上放置jumptable\u 0:
。Agner Fog可以为你添加分支目标,但我认为你只能在直接跳跃时获得。(尽管如此,可以很容易地找到循环的顶部。)不久前,我用它做了一个有趣的二进制炸弹,结果很好。顺便问一下,你有没有尝试过单步在GDB中跟随你的猜测执行?还是说这太容易了,被认为是作弊?请参阅本文底部的GDB提示。您可以查看寄存器中的值,以确认rdi
作为scanf返回值是正确的。(不过,我相信这是正确的。)我并没有试图研究整个代码,只是回答了一些您特别询问的问题。希望这能让你摆脱困境。第一个lea
就是rax=rdi+22
。C等价物是rax=&rdi[22]
。您缺少&
。LEA是一种移位和加法指令,使用寻址模式语法和机器编码。是的,jmpq*0x4027b0(,%rsi,8)
是地址表的间接跳转。我不知道gdb有一种/a
格式,可以将符号标签放在地址上;这很酷:P(通常我有源代码,不是逆向工程)。看起来你用对了。一旦CPU计算出跳转目标地址,它的工作方式与普通的直接跳转完全相同。下一条要执行的指令是该目标地址处的指令,并从该地址继续执行。您可能希望尝试在反汇编中标记跳转目标。例如,在0x4012bd
之前添加一个空行,并在其上放置jumptable\u 0:
。Agner Fog可以为你添加分支目标,但我认为你只能在直接跳跃时获得。(尽管如此,可以很容易地找到循环的顶部。)不久前,我用它做了一个有趣的二进制炸弹,结果很好。顺便问一下,你有没有尝试过单步在GDB中跟随你的猜测执行?还是说这太容易了,被认为是作弊?请参阅本文底部的GDB提示。您可以查看寄存器中的值,以确认rdi
作为scanf返回值是正确的。(不过,我相信这是正确的。)我并没有试图研究整个代码,只是回答了一些您特别询问的问题。希望这能让你摆脱困境。
k = sscanf(input, "%d %d", &a, &b);
status = phase_3(k, a, b);
phase_defused(status);