C &引用;“lea”;炸弹实验室第四阶段指挥部
这是我进行组装的第一个月,我的任务是解决臭名昭著的炸弹实验室。今天我取得了一些重大进展,但就我的一生而言,我无法确切地了解第四阶段到底发生了什么。我可以看出它需要两个整数的输入(我相信第二个应该是35?),但我无法理解它调用的递归函数的某些部分。我已经尽我所能评论了每一行 以下是第四阶段的大会:C &引用;“lea”;炸弹实验室第四阶段指挥部,c,assembly,x86-64,C,Assembly,X86 64,这是我进行组装的第一个月,我的任务是解决臭名昭著的炸弹实验室。今天我取得了一些重大进展,但就我的一生而言,我无法确切地了解第四阶段到底发生了什么。我可以看出它需要两个整数的输入(我相信第二个应该是35?),但我无法理解它调用的递归函数的某些部分。我已经尽我所能评论了每一行 以下是第四阶段的大会: 000000000040103f <phase_4>: 40103f: 48 83 ec 18 sub $0x18,%rsp
000000000040103f <phase_4>:
40103f: 48 83 ec 18 sub $0x18,%rsp //INPUT 2 INTEGERS //ANSWER =
401043: 48 8d 4c 24 08 lea 0x8(%rsp),%rcx
401048: 48 8d 54 24 0c lea 0xc(%rsp),%rdx
40104d: be 0d 28 40 00 mov $0x40280d,%esi //This is our numbers, they get put into %esi
401052: b8 00 00 00 00 mov $0x0,%eax //%eax = 0
401057: e8 d4 fb ff ff callq 400c30 <__isoc99_sscanf@plt> //scan in the input
40105c: 83 f8 02 cmp $0x2,%eax //make sure there are two integers
40105f: 75 07 jne 401068 <phase_4+0x29> //if there are not 2 integers, jump to bomb
401061: 83 7c 24 0c 0e cmpl $0xe,0xc(%rsp) // 0xc(%rsp) == 12? (x/s $rsp gives "h\342\377\377\377\177")
401066: 76 05 jbe 40106d <phase_4+0x2e> //jump past the detonation
401068: e8 17 05 00 00 callq 401584 <explode_bomb> //BOOM
40106d: ba 0e 00 00 00 mov $0xe,%edx //%edx = 0xe (14)
401072: be 00 00 00 00 mov $0x0,%esi //%esi = 0
401077: 8b 7c 24 0c mov 0xc(%rsp),%edi //%edi = 0xc(%rsp)
40107b: e8 8c ff ff ff callq 40100c <func4> //call fun4
401080: 83 f8 23 cmp $0x23,%eax //%eax == 35?
401083: 75 07 jne 40108c <phase_4+0x4d> //if %eax != 35, jump to detonation
401085: 83 7c 24 08 23 cmpl $0x23,0x8(%rsp) //0x8(%rsp) == 35?
40108a: 74 05 je 401091 <phase_4+0x52> //if so, jump past the detonation
40108c: e8 f3 04 00 00 callq 401584 <explode_bomb> //BOOM
401091: 48 83 c4 18 add $0x18,%rsp //%rsp = 18
401095: c3 retq //phase 4 disarmed
0000000000 40103F:
40103f:48 83 ec 18 sub$0x18,%rsp//输入2个整数//答案=
401043:48 8d 4c 24 08 lea 0x8(%rsp),%rcx
401048:48 8d 54 24 0c lea 0xc(%rsp),%rdx
40104d:be 0d 28 40 00 mov$0x40280d,%esi//这是我们的数字,它们被放入%esi
401052:b8 00 mov$0x0,%eax//%eax=0
401057:e8 d4 fb ff ff callq 400c30//在输入中扫描
40105c:83 f8 02 cmp$0x2,%eax//确保有两个整数
40105f:75 07 jne 401068//如果没有2个整数,跳到bomb
401061:83 7c 24 0c 0e cmpl$0xe,0xc(%rsp)//0xc(%rsp)==12?(x/s$rsp给出“h\342\377\377\377\177”)
401066:76 05 jbe 40106d//跳过爆炸
401068:e8 17 05 00 00 callq 401584//动臂
40106d:ba 0e 00 mov$0xe,%edx//%edx=0xe(14)
401072:be 00 mov$0x0,%esi//%esi=0
401077:8b 7c 24 0c mov 0xc(%rsp),%edi//%edi=0xc(%rsp)
40107b:e8 8c ff ff ff callq 40100c//呼叫功能4
401080:83 f8 23 cmp$0x23,%eax//%eax==35?
401083:75 07 jne 40108c//if%eax!=35,跳到爆炸点
401085:83 7c 24 08 23 cmpl$0x23,0x8(%rsp)//0x8(%rsp)==35?
40108a:74 05 je 401091//如果是,跳过爆炸
40108c:e8 f3 04 00 00 callq 401584//动臂
401091:48 83 c4 18添加$0x18,%rsp//%rsp=18
401095:c3 retq//第4阶段解除防护
这是func4的汇编,递归数学函数,它做了一些恶作剧:
000000000040100c <func4>:
40100c: 53 push %rbx
40100d: 89 d0 mov %edx,%eax //%eax = %edx
40100f: 29 f0 sub %esi,%eax //%eax -= %esi
401011: 89 c3 mov %eax,%ebx //%ebx = eax
401013: c1 eb 1f shr $0x1f,%ebx //shift %ebx right by 0x1f (31)
401016: 01 d8 add %ebx,%eax //%eax += %ebx
401018: d1 f8 sar %eax //shift %eax right by 1
40101a: 8d 1c 30 lea (%rax,%rsi,1),%ebx //???
40101d: 39 fb cmp %edi,%ebx //compare %edi and %ebx
40101f: 7e 0c jle 40102d <func4+0x21> //if %edi < %ebx, jump to 40102d
401021: 8d 53 ff lea -0x1(%rbx),%edx //???
401024: e8 e3 ff ff ff callq 40100c <func4> //RECURSE
401029: 01 d8 add %ebx,%eax //%eax += %ebx
40102b: eb 10 jmp 40103d <func4+0x31> //jump to 40103d (done)
40102d: 89 d8 mov %ebx,%eax //%eax = %ebx
40102f: 39 fb cmp %edi,%ebx //compare %edi and %ebx
401031: 7d 0a jge 40103d <func4+0x31> //if %edi > %ebx, jump to 40103d (done)
401033: 8d 73 01 lea 0x1(%rbx),%esi //???
401036: e8 d1 ff ff ff callq 40100c <func4> //RECURSE
40103b: 01 d8 add %ebx,%eax //%eax += %ebx
40103d: 5b pop %rbx //done.
40103e: c3 retq
0000000000 40100C:
40100c:53%rbx推送
40100d:89 d0 mov%edx,%eax//%eax=%edx
40100f:29 f0子%esi,%eax//%eax-=%esi
401011:89 c3 mov%eax,%ebx//%ebx=eax
401013:c1 eb 1f shr$0x1f,%ebx//shift%ebx向右移动0x1f(31)
401016:01 d8添加%ebx,%eax//%eax+=%ebx
401018:d1 f8 sar%eax//将%eax向右移动1
40101a:8d 1c 30 lea(%rax,%rsi,1),%ebx/???
40101d:39 fb cmp%edi,%ebx//比较%edi和%ebx
40101f:7e 0c jle 40102d//如果%edi<%ebx,则跳至40102d
401021:8d 53 ff lea-0x1(%rbx),%edx/???
401024:e8 e3 ff ff ff callq 40100c//递归
401029:01 d8添加%ebx,%eax//%eax+=%ebx
40102b:eb 10 jmp 40103d//跳转到40103d(完成)
40102d:89 d8 mov%ebx,%eax//%eax=%ebx
40102f:39 fb cmp%edi,%ebx//比较%edi和%ebx
401031:7d 0a jge 40103d//如果%edi>%ebx,则跳至40103d(完成)
401033:8d 73 01 lea 0x1(%rbx),%esi/???
401036:e8 d1 ff ff ff callq 40100c//递归
40103b:01 d8添加%ebx,%eax//%eax+=%ebx
40103d:5b弹出%rbx//完成。
40103e:c3 retq
我看到了这里发生的事情的要点(递归函数中的一系列数学运算),但我真的不明白lea命令(例如lea(%rax,%rsi,1),%ebx)在这个实例中做了什么。我知道它被称为“加载有效地址”,以及它通常的功能,但不是它在这里的功能。在这一点上,您似乎已经为这个程序的功能编写了伪代码。你的下一步是走完这个程序。一旦你知道最终结果应该是什么,你应该能够向后走,并对你的输入进行反向工程。确保您知道哪些命令使用哪些地址,并且您应该很好
在进行此操作时,使用gdb中的“ir”和“layout reg”等命令检查寄存器和变量的值。祝你好运 它使用基数、索引和比例计算,并将其置于EBX中。所以它是EBX=RAX+RSI*1。基本上,将RAX添加到RSI并将其存储到EBX。LEA仅仅意味着加载有效地址。LEA不访问内存,它只是为了帮助计算内存地址而设计的,但本质上它可以为任何目的执行简单的数学类型操作。通过查看一个很酷的例子,您可以了解指令的作用。所以0x1(%rbx),%esi将意味着%esi=1*%rbx,那么?
lea0x1(%rbx),%esi
将是esi=1+rbx。它是位移(基准、指数、刻度)。计算方法为位移+基底+指数*比例)。