【Binary Bomb Lab】二进制拆弹的解说
这听说是一个著名的反汇编实验,我其实不是很熟悉反汇编,所以通过这个来稍微熟悉一下关于反汇编的原理
这个实验总共有6道题,题目难度会循序渐进
工具和事前准备
使用的工具:
??我们在CMU官网上下载的实验会有一个已经编译好的可执行文件bomb,我这边是先直接使用了objdump将其反汇编了一下,存在了文件中以方便查看,也比较方便进行语句注释什么的
objdump反汇编命令
objdump -d bomb > bomb.asm
拆弹过程
Phase_1
第一关的汇编代码是这样的
08048b20 <phase_1>:
8048b20: 55 push %ebp
8048b21: 89 e5 mov %esp,%ebp
8048b23: 83 ec 08 sub $0x8,%esp
8048b26: 8b 45 08 mov 0x8(%ebp),%eax ; eax = ebp - 8 = address of input
8048b29: 83 c4 f8 add $0xfffffff8,%esp ; esp -8
8048b2c: 68 c0 97 04 08 push $0x80497c0
8048b31: 50 push %eax
8048b32: e8 f9 04 00 00 call 8049030 <strings_not_equal>
; equal to C language: strings_not_equal(eax,0x80497c0)
8048b37: 83 c4 10 add $0x10,%esp
8048b3a: 85 c0 test %eax,%eax ;eax = 0
8048b3c: 74 05 je 8048b43 <phase_1+0x23> ;if equal -> success
8048b3e: e8 b9 09 00 00 call 80494fc <explode_bomb>
8048b43: 89 ec mov %ebp,%esp
8048b45: 5d pop %ebp
8048b46: c3 ret
8048b47: 90 nop
是一个比较清晰的过程,分析的部分我都写在注释中了,主要是输入的字符串和内存中的字符串的比较
接下来查看内存的字符串,也就是这个0x80497c0的地址
使用gdb命令
gdb bomb
x/s 0x80497c0
效果如下 可以知道输入的payload是
Public speaking is very easy.
Phase_2
第二关的汇编代码如下:
08048b48 <phase_2>:
8048b48: 55 push %ebp
8048b49: 89 e5 mov %esp,%ebp
8048b4b: 83 ec 20 sub $0x20,%esp
8048b4e: 56 push %esi
8048b4f: 53 push %ebx
8048b50: 8b 55 08 mov 0x8(%ebp),%edx ; edx = input
8048b53: 83 c4 f8 add $0xfffffff8,%esp ; esp-8
8048b56: 8d 45 e8 lea -0x18(%ebp),%eax ; eax = ebp - 18
8048b59: 50 push %eax
8048b5a: 52 push %edx
; equal in C language: read_six_numbers(input,ebp - 18)
; 估计这是一个将6个数字压入栈的函数 第一个数字的地址是ebp-18
8048b5b: e8 78 04 00 00 call 8048fd8 <read_six_numbers>
8048b60: 83 c4 10 add $0x10,%esp
; if 1 == input[0] 如果不是就失败
8048b63: 83 7d e8 01 cmpl $0x1,-0x18(%ebp)
8048b67: 74 05 je 8048b6e <phase_2+0x26>
8048b69: e8 8e 09 00 00 call 80494fc <explode_bomb>
; 如果是
8048b6e: bb 01 00 00 00 mov $0x1,%ebx ; ebx =1
8048b73: 8d 75 e8 lea -0x18(%ebp),%esi ; esi = address of input[0]
8048b76: 8d 43 01 lea 0x1(%ebx),%eax ; eax = ebx + 1
; eax = eax * (esi + 4*ebx) eax = eax*(第(ebx-1)个数字)
8048b79: 0f af 44 9e fc imul -0x4(%esi,%ebx,4),%eax
; if eax == esi + 4 * ebx
8048b7e: 39 04 9e cmp %eax,(%esi,%ebx,4)
8048b81: 74 05 je 8048b88 <phase_2+0x40>
8048b83: e8 74 09 00 00 call 80494fc <explode_bomb>
8048b88: 43 inc %ebx ;ebx++
8048b89: 83 fb 05 cmp $0x5,%ebx ;if ebx <= 5
8048b8c: 7e e8 jle 8048b76 <phase_2+0x2e>
8048b8e: 8d 65 d8 lea -0x28(%ebp),%esp
8048b91: 5b pop %ebx
8048b92: 5e pop %esi
8048b93: 89 ec mov %ebp,%esp
8048b95: 5d pop %ebp
8048b96: c3 ret
8048b97: 90 nop
乍一看感觉是非常的难以理解,虽然我已经注释过了但是还是很难,我们主要挑出重要的代码: 1) 这里是这关的第一个点:输入的第一个数字必须要是1
; if 1 == input[0] 如果不是就失败
8048b63: 83 7d e8 01 cmpl $0x1,-0x18(%ebp)
8048b67: 74 05 je 8048b6e <phase_2+0x26>
8048b69: e8 8e 09 00 00 call 80494fc <explode_bomb>
2) 有一个循环
8048b76: 8d 43 01 lea 0x1(%ebx),%eax ; eax = ebx + 1
; eax = eax * (esi + 4*ebx) eax = eax*(第(ebx-1)个数字)
8048b79: 0f af 44 9e fc imul -0x4(%esi,%ebx,4),%eax
; if eax == esi + 4 * ebx
8048b7e: 39 04 9e cmp %eax,(%esi,%ebx,4)
8048b81: 74 05 je 8048b88 <phase_2+0x40>
8048b83: e8 74 09 00 00 call 80494fc <explode_bomb>
8048b88: 43 inc %ebx ;ebx++
8048b89: 83 fb 05 cmp $0x5,%ebx ;if ebx <= 5
8048b8c: 7e e8 jle 8048b76 <phase_2+0x2e>
这个循环主要是以ebx开始,ebx由1到5
如果按照C语言的方式,这个循环的逻辑是:
void testNumber (int *nums) {
if (nums[0] != 1)
explode();
for (int i = 1; i <= 5; i++) {
temp = (i + 1) * nums[i - 1];
if (nums[i] != temp)
explode();
}
}
我们可以知道这是一个公式:
Func(n) = ( n+1 ) * Func( n - 1 ) Func( 0 ) = 1
也就是说,Func(1)= 2 * 1 = 2、Func( 2 )= 3 * 2 = 6
由此递推,这一关的payload是
1 2 6 24 120 720
Phase_3
这一关的汇编代码:
08048b98 <phase_3>:
8048b98: 55 push %ebp
8048b99: 89 e5 mov %esp,%ebp
8048b9b: 83 ec 14 sub $0x14,%esp
8048b9e: 53 push %ebx
8048b9f: 8b 55 08 mov 0x8(%ebp),%edx ; edx = ebp - 8 = input
8048ba2: 83 c4 f4 add $0xfffffff4,%esp
8048ba5: 8d 45 fc lea -0x4(%ebp),%eax ; eax = ebp - 4
8048ba8: 50 push %eax
8048ba9: 8d 45 fb lea -0x5(%ebp),%eax ; eax = ebp - 5
8048bac: 50 push %eax
8048bad: 8d 45 f4 lea -0xc(%ebp),%eax ; eax = ebp - 12
8048bb0: 50 push %eax
8048bb1: 68 de 97 04 08 push $0x80497de
8048bb6: 52 push %edx
8048bb7: e8 a4 fc ff ff call 8048860 <sscanf@plt>
8048bbc: 83 c4 20 add $0x20,%esp
8048bbf: 83 f8 02 cmp $0x2,%eax
8048bc2: 7f 05 jg 8048bc9 <phase_3+0x31>
8048bc4: e8 33 09 00 00 call 80494fc <explode_bomb>
8048bc9: 83 7d f4 07 cmpl $0x7,-0xc(%ebp)
8048bcd: 0f 87 b5 00 00 00 ja 8048c88 <phase_3+0xf0>
8048bd3: 8b 45 f4 mov -0xc(%ebp),%eax
8048bd6: ff 24 85 e8 97 04 08 jmp *0x80497e8(,%eax,4)
8048bdd: 8d 76 00 lea 0x0(%esi),%esi
8048be0: b3 71 mov $0x71,%bl
8048be2: 81 7d fc 09 03 00 00 cmpl $0x309,-0x4(%ebp)
8048be9: 0f 84 a0 00 00 00 je 8048c8f <phase_3+0xf7>
8048bef: e8 08 09 00 00 call 80494fc <explode_bomb>
8048bf4: e9 96 00 00 00 jmp 8048c8f <phase_3+0xf7>
8048bf9: 8d b4 26 00 00 00 00 lea 0x0(%esi,%eiz,1),%esi
8048c00: b3 62 mov $0x62,%bl
8048c02: 81 7d fc d6 00 00 00 cmpl $0xd6,-0x4(%ebp)
8048c09: 0f 84 80 00 00 00 je 8048c8f <phase_3+0xf7>
8048c0f: e8 e8 08 00 00 call 80494fc <explode_bomb>
8048c14: eb 79 jmp 8048c8f <phase_3+0xf7>
8048c16: b3 62 mov $0x62,%bl
8048c18: 81 7d fc f3 02 00 00 cmpl $0x2f3,-0x4(%ebp)
8048c1f: 74 6e je 8048c8f <phase_3+0xf7>
8048c21: e8 d6 08 00 00 call 80494fc <explode_bomb>
8048c26: eb 67 jmp 8048c8f <phase_3+0xf7>
8048c28: b3 6b mov $0x6b,%bl
8048c2a: 81 7d fc fb 00 00 00 cmpl $0xfb,-0x4(%ebp)
8048c31: 74 5c je 8048c8f <phase_3+0xf7>
8048c33: e8 c4 08 00 00 call 80494fc <explode_bomb>
8048c38: eb 55 jmp 8048c8f <phase_3+0xf7>
8048c3a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
8048c40: b3 6f mov $0x6f,%bl
8048c42: 81 7d fc a0 00 00 00 cmpl $0xa0,-0x4(%ebp)
8048c49: 74 44 je 8048c8f <phase_3+0xf7>
8048c4b: e8 ac 08 00 00 call 80494fc <explode_bomb>
8048c50: eb 3d jmp 8048c8f <phase_3+0xf7>
8048c52: b3 74 mov $0x74,%bl
8048c54: 81 7d fc ca 01 00 00 cmpl $0x1ca,-0x4(%ebp)
8048c5b: 74 32 je 8048c8f <phase_3+0xf7>
8048c5d: e8 9a 08 00 00 call 80494fc <explode_bomb>
8048c62: eb 2b jmp 8048c8f <phase_3+0xf7>
8048c64: b3 76 mov $0x76,%bl
8048c66: 81 7d fc 0c 03 00 00 cmpl $0x30c,-0x4(%ebp)
8048c6d: 74 20 je 8048c8f <phase_3+0xf7>
8048c6f: e8 88 08 00 00 call 80494fc <explode_bomb>
8048c74: eb 19 jmp 8048c8f <phase_3+0xf7>
8048c76: b3 62 mov $0x62,%bl
8048c78: 81 7d fc 0c 02 00 00 cmpl $0x20c,-0x4(%ebp)
8048c7f: 74 0e je 8048c8f <phase_3+0xf7>
8048c81: e8 76 08 00 00 call 80494fc <explode_bomb>
8048c86: eb 07 jmp 8048c8f <phase_3+0xf7>
8048c88: b3 78 mov $0x78,%bl ; bl是78
8048c8a: e8 6d 08 00 00 call 80494fc <explode_bomb>
8048c8f: 3a 5d fb cmp -0x5(%ebp),%bl ; 比较ebp-5地址的数和bl大小
8048c92: 74 05 je 8048c99 <phase_3+0x101> ; 相等跳转
8048c94: e8 63 08 00 00 call 80494fc <explode_bomb>
8048c99: 8b 5d e8 mov -0x18(%ebp),%ebx ; 将ebp下方第6个单位的值给ebx
8048c9c: 89 ec mov %ebp,%esp
8048c9e: 5d pop %ebp
8048c9f: c3 ret
这一关开始的代码真的是越来越长,到这开始其实我们已经可以使用ida pro来看看了,但主要是想要学学汇编代码的练习,所以这两关我们还是使用gdb来看看
我们一步一步看看:
1)输入数字的范围
8048bbc: 83 c4 20 add $0x20,%esp
8048bbf: 83 f8 02 cmp $0x2,%eax ; if eax >2
8048bc2: 7f 05 jg 8048bc9 <phase_3+0x31>
8048bc4: e8 33 09 00 00 call 80494fc <explode_bomb>
8048bc9: 83 7d f4 07 cmpl $0x7,-0xc(%ebp) ; if [ebp-12] <7
8048bcd: 0f 87 b5 00 00 00 ja 8048c88 <phase_3+0xf0>
可以知道输入的第一个数字是3到6,否则炸弹会爆炸
2)我们发现一段代码
8048bb1: 68 de 97 04 08 push $0x80497de
8048bb6: 52 push %edx
8048bb7: e8 a4 fc ff ff call 8048860 <sscanf@plt>
我们知道edx中存储的是input的字符串的地址
那么我们的重点就是关注一下这个0x80497de的地址了
同样,我们试试使用gdb的命令
x/s 0x80497de
得到输出 这是关于sscanf函数的用法,不懂的同学可以百度搜索一下“C语言 sscanf函数”
函数大概的格式是 sscanf( [原字符串], [需要的格式], [被赋值的变量]); (上一关的 read_six_number() 中也有这个函数,只是没有细说而已)
所以我们知道这一关的输入是两个数字和一个字符
3) 我们往下又观察到了一段代码
8048bd3: 8b 45 f4 mov -0xc(%ebp),%eax
8048bd6: ff 24 85 e8 97 04 08 jmp *0x80497e8(,%eax,4)
这个0x80497e8引起了我们的注意,这行代码的意思是跳转到一个地址,这个地址储存在(0x80497e8 + 4*eax)里面
并且,eax现在存储的是我们第一个输入的参数
我们查看0x80497e8地址中存储的是什么
发现从0x80497e8开始的地址,存储的都是一些其他的地址,再加上刚刚的汇编代码。
我们可以判断,从这个地址开始做偏移量,我们可以跳转回我们的phase_3的汇编代码中,再进行后面的字符的匹配
这样我们可以思考出一条路出来:
如果我第一个数字是3(第一个数字在3到6)—> 计算跳转的偏移是(0x80497e8 + 4*3)—> 其中的值是 8048c28 我们跳转到0x8048c28
8048c28: b3 6b mov $0x6b,%bl
8048c2a: 81 7d fc fb 00 00 00 cmpl $0xfb,-0x4(%ebp)
8048c31: 74 5c je 8048c8f <phase_3+0xf7>
我们知道:-0x4(%ebp)我们输入的最后一个参数 这个参数是0xfb(十进制的251)
再次跳转到8048c8f :
8048c8f: 3a 5d fb cmp -0x5(%ebp),%bl ; 比较ebp-5地址的数和bl大小
8048c92: 74 05 je 8048c99 <phase_3+0x101> ; 相等跳转
8048c94: e8 63 08 00 00 call 80494fc <explode_bomb>
8048c99: 8b 5d e8 mov -0x18(%ebp),%ebx ; 将ebp下方第6个单位的值给ebx
我们知道此时bl中是0x6b,也就是107,经过ascii码,这个是字符‘g’ 所以我们的payload是
3 k 251
Phase_4
第四关的汇编代码是
08048ce0 <phase_4>:
8048ce0: 55 push %ebp
8048ce1: 89 e5 mov %esp,%ebp
8048ce3: 83 ec 18 sub $0x18,%esp
8048ce6: 8b 55 08 mov 0x8(%ebp),%edx ; edx = [ebp +8] = input
8048ce9: 83 c4 fc add $0xfffffffc,%esp
8048cec: 8d 45 fc lea -0x4(%ebp),%eax ; eax = ebp - 4
8048cef: 50 push %eax
8048cf0: 68 08 98 04 08 push $0x8049808
8048cf5: 52 push %edx
8048cf6: e8 65 fb ff ff call 8048860 <sscanf@plt>
8048cfb: 83 c4 10 add $0x10,%esp
8048cfe: 83 f8 01 cmp $0x1,%eax
8048d01: 75 06 jne 8048d09 <phase_4+0x29>
8048d03: 83 7d fc 00 cmpl $0x0,-0x4(%ebp)
8048d07: 7f 05 jg 8048d0e <phase_4+0x2e>
8048d09: e8 ee 07 00 00 call 80494fc <explode_bomb>
8048d0e: 83 c4 f4 add $0xfffffff4,%esp
8048d11: 8b 45 fc mov -0x4(%ebp),%eax
8048d14: 50 push %eax
8048d15: e8 86 ff ff ff call 8048ca0 <func4>
8048d1a: 83 c4 10 add $0x10,%esp
8048d1d: 83 f8 37 cmp $0x37,%eax
8048d20: 74 05 je 8048d27 <phase_4+0x47>
8048d22: e8 d5 07 00 00 call 80494fc <explode_bomb>
8048d27: 89 ec mov %ebp,%esp
8048d29: 5d pop %ebp
8048d2a: c3 ret
8048d2b: 90 nop
1)第一部分
8048cef: 50 push %eax
8048cf0: 68 08 98 04 08 push $0x8049808
8048cf5: 52 push %edx
8048cf6: e8 65 fb ff ff call 8048860 <sscanf@plt>
8048cfb: 83 c4 10 add $0x10,%esp
有调用了sscanf函数,我们去看看这个地址,发现是个数字 也就是说我们需要输入一个数字,保存在ebp-4的地址
2)接下来看这个部分
8048d11: 8b 45 fc mov -0x4(%ebp),%eax
8048d14: 50 push %eax
8048d15: e8 86 ff ff ff call 8048ca0 <func4>
8048d1a: 83 c4 10 add $0x10,%esp
8048d1d: 83 f8 37 cmp $0x37,%eax
8048d20: 74 05 je 8048d27 <phase_4+0x47>
8048d22: e8 d5 07 00 00 call 80494fc <explode_bomb>
相当于C语言中的
if (0x37 == func4 ( input ))
success;
else
bomb;
0x37是十进制中的55;也就是返回值必须要是55
我们观察func4 的汇编代码
08048ca0 <func4>:
8048ca0: 55 push %ebp
8048ca1: 89 e5 mov %esp,%ebp
8048ca3: 83 ec 10 sub $0x10,%esp
8048ca6: 56 push %esi
8048ca7: 53 push %ebx
; if input_number<=1, <func4> return 1
8048ca8: 8b 5d 08 mov 0x8(%ebp),%ebx
8048cab: 83 fb 01 cmp $0x1,%ebx
8048cae: 7e 20 jle 8048cd0 <func4+0x30>
8048cb0: 83 c4 f4 add $0xfffffff4,%esp
; esi == func4( input_number-1 )
8048cb3: 8d 43 ff lea -0x1(%ebx),%eax
8048cb6: 50 push %eax
8048cb7: e8 e4 ff ff ff call 8048ca0 <func4>
8048cbc: 89 c6 mov %eax,%esi
8048cbe: 83 c4 f4 add $0xfffffff4,%esp
;; esi += func4( input_number-2 )
8048cc1: 8d 43 fe lea -0x2(%ebx),%eax
8048cc4: 50 push %eax
8048cc5: e8 d6 ff ff ff call 8048ca0 <func4>
8048cca: 01 f0 add %esi,%eax
8048ccc: eb 07 jmp 8048cd5 <func4+0x35>
8048cce: 89 f6 mov %esi,%esi
8048cd0: b8 01 00 00 00 mov $0x1,%eax
8048cd5: 8d 65 e8 lea -0x18(%ebp),%esp
8048cd8: 5b pop %ebx
8048cd9: 5e pop %esi
8048cda: 89 ec mov %ebp,%esp
8048cdc: 5d pop %ebp
8048cdd: c3 ret
8048cde: 89 f6 mov %esi,%esi
如同我的注释所写,总共三个注意点:
- 如果input是1,返回1
- 如果input是其他的话,返回 func(n-1)+ func(n-2)
是不是很熟悉,DNA都动了,我嗅到了递归的味道
所以这个func4函数就是一个递归函数
我们要求func4(x)=55,解得x = 9
所以payload是
9
Phase_5
我们到这里就已经可以了,汇编的知识复习得挺好了,我们还是改用ida pro 来解决剩下的题目吧
(实在是太累了,脑子要绕晕了)
我们使用ida打开这个可执行文件
按住F5对其进行伪代码查看
可以大概理解这个函数:
- 输入的字符长度必须为6
- 通过对我们的输入字符串的每一个字符进行与0xF,来得到另一个字符
- 最后的字符结果要和“giants”一样
我们发现这里有个array_123,查看一下这个数组
那我们就根据ascii码来一个个使吧,思路如下
比如说第一个字符必须是‘g’—>相与结果必须是0b1111(array_123的最后一个)----> 按照ascii码表,我们选‘o’
一步步来 我们选取的payload就是
opekmq
( ida 果然轻松多了)
Phase_6
最后一关,老样子,汇编代码如下
08048d98 <phase_6>:
;; part 1
8048d98: 55 push %ebp
8048d99: 89 e5 mov %esp,%ebp
8048d9b: 83 ec 4c sub $0x4c,%esp
8048d9e: 57 push %edi
8048d9f: 56 push %esi
8048da0: 53 push %ebx
8048da1: 8b 55 08 mov 0x8(%ebp),%edx ;edx = [ebp + 8]
8048da4: c7 45 cc 6c b2 04 08 movl $0x804b26c,-0x34(%ebp) ;[ebp - 0x34] = 0x804b26c
8048dab: 83 c4 f8 add $0xfffffff8,%esp ;esp -8
8048dae: 8d 45 e8 lea -0x18(%ebp),%eax ;eax = ebp - 0x18
8048db1: 50 push %eax
8048db2: 52 push %edx
8048db3: e8 20 02 00 00 call 8048fd8 <read_six_numbers>
8048db8: 31 ff xor %edi,%edi ;edi 0~5
8048dba: 83 c4 10 add $0x10,%esp
8048dbd: 8d 76 00 lea 0x0(%esi),%esi
;for (edi =0; edi<=5;edi++)
8048dc0: 8d 45 e8 lea -0x18(%ebp),%eax
8048dc3: 8b 04 b8 mov (%eax,%edi,4),%eax ;eax = (ebp -18) + edi*4
8048dc6: 48 dec %eax ;[input[edi]]-1
;if [input[edi]]-1 <= 5
8048dc7: 83 f8 05 cmp $0x5,%eax
8048dca: 76 05 jbe 8048dd1 <phase_6+0x39>
8048dcc: e8 2b 07 00 00 call 80494fc <explode_bomb>
8048dd1: 8d 5f 01 lea 0x1(%edi),%ebx ;ebx = edi+1
;if ebx <=5
; ...
8048dd4: 83 fb 05 cmp $0x5,%ebx
8048dd7: 7f 23 jg 8048dfc <phase_6+0x64>
8048dd9: 8d 04 bd 00 00 00 00 lea 0x0(,%edi,4),%eax ;eax = edi * 4
8048de0: 89 45 c8 mov %eax,-0x38(%ebp)
8048de3: 8d 75 e8 lea -0x18(%ebp),%esi ;esi = ebp -18 = the beginning address of the six numbers
;for (ebx =edi+1; edi<=5;ebx++)
8048de6: 8b 55 c8 mov -0x38(%ebp),%edx ;edx = [ebp -38] = edi * 4
8048de9: 8b 04 32 mov (%edx,%esi,1),%eax
8048dec: 3b 04 9e cmp (%esi,%ebx,4),%eax ; if [esi + 4*ebx] != [edi * 4 + esi] //ebx = edi+1
8048def: 75 05 jne 8048df6 <phase_6+0x5e>
8048df1: e8 06 07 00 00 call 80494fc <explode_bomb>
8048df6: 43 inc %ebx
8048df7: 83 fb 05 cmp $0x5,%ebx
8048dfa: 7e ea jle 8048de6 <phase_6+0x4e>
;endfor
;else
;edi++
8048dfc: 47 inc %edi ;edi ++
8048dfd: 83 ff 05 cmp $0x5,%edi ;if edi <= 5
8048e00: 7e be jle 8048dc0 <phase_6+0x28>
;endfor
8048e02: 31 ff xor %edi,%edi
8048e04: 8d 4d e8 lea -0x18(%ebp),%ecx ;ecx = ebp -18
8048e07: 8d 45 d0 lea -0x30(%ebp),%eax ;eax = ebp -30
8048e0a: 89 45 c4 mov %eax,-0x3c(%ebp)
8048e0d: 8d 76 00 lea 0x0(%esi),%esi
8048e10: 8b 75 cc mov -0x34(%ebp),%esi
8048e13: bb 01 00 00 00 mov $0x1,%ebx
8048e18: 8d 04 bd 00 00 00 00 lea 0x0(,%edi,4),%eax
8048e1f: 89 c2 mov %eax,%edx
8048e21: 3b 1c 08 cmp (%eax,%ecx,1),%ebx
8048e24: 7d 12 jge 8048e38 <phase_6+0xa0>
8048e26: 8b 04 0a mov (%edx,%ecx,1),%eax
8048e29: 8d b4 26 00 00 00 00 lea 0x0(%esi,%eiz,1),%esi
8048e30: 8b 76 08 mov 0x8(%esi),%esi
8048e33: 43 inc %ebx
8048e34: 39 c3 cmp %eax,%ebx
8048e36: 7c f8 jl 8048e30 <phase_6+0x98>
8048e38: 8b 55 c4 mov -0x3c(%ebp),%edx
8048e3b: 89 34 ba mov %esi,(%edx,%edi,4)
8048e3e: 47 inc %edi
8048e3f: 83 ff 05 cmp $0x5,%edi
8048e42: 7e cc jle 8048e10 <phase_6+0x78>
8048e44: 8b 75 d0 mov -0x30(%ebp),%esi
8048e47: 89 75 cc mov %esi,-0x34(%ebp)
8048e4a: bf 01 00 00 00 mov $0x1,%edi
8048e4f: 8d 55 d0 lea -0x30(%ebp),%edx
8048e52: 8b 04 ba mov (%edx,%edi,4),%eax
8048e55: 89 46 08 mov %eax,0x8(%esi)
8048e58: 89 c6 mov %eax,%esi
8048e5a: 47 inc %edi
8048e5b: 83 ff 05 cmp $0x5,%edi
8048e5e: 7e f2 jle 8048e52 <phase_6+0xba>
8048e60: c7 46 08 00 00 00 00 movl $0x0,0x8(%esi)
8048e67: 8b 75 cc mov -0x34(%ebp),%esi
8048e6a: 31 ff xor %edi,%edi
8048e6c: 8d 74 26 00 lea 0x0(%esi,%eiz,1),%esi
8048e70: 8b 56 08 mov 0x8(%esi),%edx
8048e73: 8b 06 mov (%esi),%eax
8048e75: 3b 02 cmp (%edx),%eax
8048e77: 7d 05 jge 8048e7e <phase_6+0xe6>
8048e79: e8 7e 06 00 00 call 80494fc <explode_bomb>
8048e7e: 8b 76 08 mov 0x8(%esi),%esi
8048e81: 47 inc %edi
8048e82: 83 ff 04 cmp $0x4,%edi
8048e85: 7e e9 jle 8048e70 <phase_6+0xd8>
8048e87: 8d 65 a8 lea -0x58(%ebp),%esp
8048e8a: 5b pop %ebx
8048e8b: 5e pop %esi
8048e8c: 5f pop %edi
8048e8d: 89 ec mov %ebp,%esp
8048e8f: 5d pop %ebp
8048e90: c3 ret
8048e91: 8d 76 00 lea 0x0(%esi),%esi
可以看出来代码真的好多
我们再从ida看看
1)首先可以看出函数:
2)我们再查看这个node链表 发现:
- node[0] 是这个链表节点存储的值
- node[1] 是序号
- node[2] 是下一个节点的地址
3)我们再看这个函数,这个函数有点难以归纳,简单来说:
我的输入的6个数字是:3 1 2 4 5 6 那么这个v14就是选择这个第3个节点、第1个节点、第2个节点。。。。。。组成一个新指针数组
4)接下来这里 这个函数是把我们的指针数组变成了一个链表,也就是线性表变成了链表。
5)最后 如果这个节点的数小于下一个节点,这个数就会爆炸,也就是我们这个指针数组是不能单调递增的,只能单调递减或不变
由此,我们选取的payload是
4 2 6 3 1 5
至此,这整个实验完成!!!!!!!
结果展示
|