【计算机系统基础bomb lab】CSAPP实验:Bomb Lab

news2024/9/20 17:30:54

CSAPP 实验:Bomb Lab

实验内容简述

  • 作为实验目标的二进制炸弹 “Bomb Lab” Linux可执行程序包含了多个阶段(或关卡),在每个阶段程序要求输入一-个特定字符串,如果输入满足程序代码所定义的要求,该阶段的炸弹就被拆除了,否则程序输出 “炸弹爆炸BOOM!!!” 的提示并转到下一阶段再次等待对应的输入-实验的目标是设法得出解除尽可能多阶段的字符串。
  • 为完成二进制炸弹拆除任务,需要通过反汇编并分析可执行炸弹文件程序的机器代码或使用 gdb 调试器跟踪机器代码的执行,从中理解关键机器指令的行为和作用,进而设法推断拆除炸弹所需的目标字符串。

实验环境

64 位 linux 操作系统

实验过程:phase 1

  • 将可执行文件bomb 反汇编

    objdump -d bomb > bomb.asm
    
  • 查看源代码

    image-20220727104850796

    可以了解到 phase_1 是调用函数名

  • bomb.asm 里搜索 phase_1,阅读源码含义

    image-20220727105926060

phase 1 调试过程

  • 使用 gdb 调试,将断点设置在 phase_1 ,即 0x400ee0。运行后随便输入后查看 0x402400 的内容

    (gdb) b *0x400ee0
    Breakpoint 1 at 0x400ee0
    (gdb) r
    Starting program: /mnt/d/OneDrive/csapp/bomb/bomb 
    Welcome to my fiendish little bomb. You have 6 phases with
    which to blow yourself up. Have a nice day!
    dsasd 
    
    Breakpoint 1, 0x0000000000400ee0 in phase_1 ()
    (gdb) i r rip
    rip            0x400ee0            0x400ee0 <phase_1>
    (gdb) si
    0x0000000000400ee4 in phase_1 ()
    (gdb) si
    0x0000000000400ee9 in phase_1 ()
    (gdb) x/s 0x402400
    0x402400:       "Border relations with Canada have never been better."
    

    image-20220727111507095

  • 可以从上面了解到字符串的答案就是: Border relations with Canada have never been better.

实验过程:phase 2

  • 查看 phase 2 汇编代码

    0000000000400efc <phase_2>:
      400efc:	55                   	push   %rbp
      400efd:	53                   	push   %rbx
      400efe:	48 83 ec 28          	sub    $0x28,%rsp
      400f02:	48 89 e6             	mov    %rsp,%rsi
      ----------------------分割线----------------------------------------;上面是函数的初始化
      400f05:	e8 52 05 00 00       	callq  40145c <read_six_numbers>;读取六个数字
      400f0a:	83 3c 24 01          	cmpl   $0x1,(%rsp);拿第一个数字与 1 进行比较
      400f0e:	74 20                	je     400f30 <phase_2+0x34>;如果相等就跳转到 400f30
      400f10:	e8 25 05 00 00       	callq  40143a <explode_bomb>;否则,爆炸
      400f15:	eb 19                	jmp    400f30 <phase_2+0x34>
      400f17:	8b 43 fc             	mov    -0x4(%rbx),%eax ;将第一个数字赋给 eax
      400f1a:	01 c0                	add    %eax,%eax;将第一个数字*2
      400f1c:	39 03                	cmp    %eax,(%rbx);将当前数字(eax) 与后一个数字 (rbx) 比较
      400f1e:	74 05                	je     400f25 <phase_2+0x29>;如果相等,就跳转到400f25
      400f20:	e8 15 05 00 00       	callq  40143a <explode_bomb>;否则爆炸
      400f25:	48 83 c3 04          	add    $0x4,%rbx;循环迭代条件
      400f29:	48 39 eb             	cmp    %rbp,%rbx;rbp 是栈底,也就是数组最后一个元素,作为循环判断的最后一个条件
      400f2c:	75 e9                	jne    400f17 <phase_2+0x1b>;如果没遍历到最后一个数字,就跳转到循环内400f17
      400f2e:	eb 0c                	jmp    400f3c <phase_2+0x40>;循环结束,跳转到最后函数结束后的处理400f3c
      400f30:	48 8d 5c 24 04       	lea    0x4(%rsp),%rbx ;将第二个数赋值给 rbx
      400f35:	48 8d 6c 24 18       	lea    0x18(%rsp),%rbp ;设置栈底,就是最后一个数字(0x18 == 24,输入的是6个数,所以是最后一个数)
      400f3a:	eb db                	jmp    400f17 <phase_2+0x1b>;跳到 400f17 进入循环开始的地方
      ----------------------分割线----------------------------------------;之后都是函数结束后的处理
      400f3c:	48 83 c4 28          	add    $0x28,%rsp
      400f40:	5b                   	pop    %rbx
      400f41:	5d                   	pop    %rbp
      400f42:	c3                   	retq  
    

phase 2 调试过程

  • 设置断点

    (gdb) b phase_2
    Breakpoint 1 at 0x400efc
    
  • 运行并输入phase 1 的答案与 phase 2 推测出的答案

    image-20220730105854670

  • 一直单步汇编运行,执行到 400f0a: cmpl $0x1,(%rsp); 此步说明第一个数字必须为1

    image-20220730111649035

  • 比较第一个数字是否为 1

    (gdb) x/wd $rsp
    0x7ffffffedd70: 1
    

    可以看到,rsp 的值为1 ,就是我们输入的第一个值:1

    由此,通过 je 400f30 可知,两数相等,故跳转到 400f30

    image-20220730111959643

  • 通过单步汇编调试,查看rsp 的值

    (gdb) si
    0x0000000000400f30 in phase_2 ()
    (gdb) si
    0x0000000000400f35 in phase_2 ()
    

    image-20220730112217810

    由此可以得出,rbx 此时存放的是第二个数字 2rbp 作为栈底,是最后一个数字的结尾,存放的是 4199473 这个数字。

  • 继续单步汇编调试,进入循环400f17

    image-20220730112624184

    此时执行完 400f17:mov -0x4(%rbx),%eax eax` 的值为 1。如下图

    image-20220730113150925

    继续单步调试,执行到 add %eax,%eax ,对 eax进行 乘 2 的操作。 此时 eax 为2 ,与我们输入的第二个数( rbx 存放) 相等

    image-20220730113939792

    image-20220730114119156

  • 继续单步汇编调试,跳转到 400f25:add $0x4,%rbx

    image-20220730114459317

    image-20220730114515282

    执行完 add $0x4,%rbx ,则选择了数组的下一个数字,判断循环是否是否结束。

  • 之后一直执行到结束。

    image-20220730135934202

  • 所以答案为:1 2 4 8 16 32

实验过程:phase 3

  • 查看 phase_3 汇编代码:
0000000000400f43 <phase_3>:
  400f43:	48 83 ec 18          	sub    $0x18,%rsp
  400f47:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx ;第二个参数
  400f4c:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx ;第一个参数
  400f51:	be cf 25 40 00       	mov    $0x4025cf,%esi ;系统自带字符串"%d %d",2个参数
  400f56:	b8 00 00 00 00       	mov    $0x0,%eax
  ;----------------------------------------------------------------
  400f5b:	e8 90 fc ff ff       	callq  400bf0 <__isoc99_sscanf@plt>
  400f60:	83 f8 01             	cmp    $0x1,%eax ;eax 与 1 比较。返回的是输入的参数个数
  400f63:	7f 05                	jg     400f6a <phase_3+0x27> ;如果大于 1,跳转400f6a
  400f65:	e8 d0 04 00 00       	callq  40143a <explode_bomb>
  400f6a:	83 7c 24 08 07       	cmpl   $0x7,0x8(%rsp) ;比较 7 与 第一个参数大小
  400f6f:	77 3c                	ja     400fad <phase_3+0x6a> ;如果第一个参数大于7,爆炸
  400f71:	8b 44 24 08          	mov    0x8(%rsp),%eax ;把第一个参数赋给 eax
  400f75:	ff 24 c5 70 24 40 00 	jmpq   *0x402470(,%rax,8) ;跳转到 rax*8 + *0x402470
  400f7c:	b8 cf 00 00 00       	mov    $0xcf,%eax
  400f81:	eb 3b                	jmp    400fbe <phase_3+0x7b>
  400f83:	b8 c3 02 00 00       	mov    $0x2c3,%eax
  400f88:	eb 34                	jmp    400fbe <phase_3+0x7b>
  400f8a:	b8 00 01 00 00       	mov    $0x100,%eax
  400f8f:	eb 2d                	jmp    400fbe <phase_3+0x7b>
  400f91:	b8 85 01 00 00       	mov    $0x185,%eax
  400f96:	eb 26                	jmp    400fbe <phase_3+0x7b>
  400f98:	b8 ce 00 00 00       	mov    $0xce,%eax
  400f9d:	eb 1f                	jmp    400fbe <phase_3+0x7b>
  400f9f:	b8 aa 02 00 00       	mov    $0x2aa,%eax
  400fa4:	eb 18                	jmp    400fbe <phase_3+0x7b>
  400fa6:	b8 47 01 00 00       	mov    $0x147,%eax
  400fab:	eb 11                	jmp    400fbe <phase_3+0x7b>
  400fad:	e8 88 04 00 00       	callq  40143a <explode_bomb>
  400fb2:	b8 00 00 00 00       	mov    $0x0,%eax
  400fb7:	eb 05                	jmp    400fbe <phase_3+0x7b>
  400fb9:	b8 37 01 00 00       	mov    $0x137,%eax ;eax 为311(十进制)
  400fbe:	3b 44 24 0c          	cmp    0xc(%rsp),%eax ;比较第二个参数与 eax
  400fc2:	74 05                	je     400fc9 <phase_3+0x86>;如果成功,拆弹成功
  400fc4:	e8 71 04 00 00       	callq  40143a <explode_bomb>
  ;----------------------------------------------------------------
  400fc9:	48 83 c4 18          	add    $0x18,%rsp
  400fcd:	c3                   	retq   

分析:

我这个都是自己调试出来看到参数的,最开始第一个参数与第二个参数理解有误。结果最开始输入的竟然是第二个参数

首先看到了调用函数是 __isoc99_sscanf 可以从中得知,返回的 eax 为输入格式的个数,而最开始 0x4025cf 的字符串就是 %d %d,可以了解到参数个数为 2 。

之后让第一个参数与 7 比较,可以猜到第一个参数是一个选择做一个选择,选择是下面7个跳转(类似于 switch)。

最后可以在 400f75:jmpq *0x402470(,%rax,8) 观测,程序的跳转地址情况。

phase 3 调试过程

  • 设置断点并运行

    此时的 ans.txt如下:

    Border relations with Canada have never been better.
    1 2 4 8 16 32
    1 311
    
    

    image-20220730172753721

  • 单步汇编调试,直到执行完 400f5b:callq 400bf0 <__isoc99_sscanf@plt>

    image-20220730203508519

  • 单步汇编调试,执行到 400f75:jmpq *0x402470(,%rax,8),观察对应 0x402470 开始的 8 个单元对应的值。

    image-20220731104055183

    rax 保存的是第一个参数的值,我们输入的是 1,所以计算机结果是 0x402470 + 1 * 80x402478 单元对应的值 0x400fb9

  • 单步汇编调试,验证进入的单元。

    image-20220731104919753

  • 要使第一个第二个参数与 0x137相等,即十进制 311,最后拆除炸弹。

    image-20220731105331630

实验过程:phase 4

0000000000400fce <func4>:
  400fce:	48 83 ec 08          	sub    $0x8,%rsp
  400fd2:	89 d0                	mov    %edx,%eax ;eax = 14 (phase_4 输入的第三个参数)
  400fd4:	29 f0                	sub    %esi,%eax ;eax = 14 - 0 = 14 (第二个参数减去第三个参数)
  400fd6:	89 c1                	mov    %eax,%ecx ;ecx = 14
  400fd8:	c1 e9 1f             	shr    $0x1f,%ecx;逻辑右移31 位,ecx 为0
  400fdb:	01 c8                	add    %ecx,%eax ;eax = 14
  400fdd:	d1 f8                	sar    %eax ;算术右移1位,即÷2  eax = 7
  400fdf:	8d 0c 30             	lea    (%rax,%rsi,1),%ecx ;ecx = 7
  400fe2:	39 f9                	cmp    %edi,%ecx ;比较第一传入参数与 ecx = 7
  400fe4:	7e 0c                	jle    400ff2 <func4+0x24> ;如果小于等于7,跳转400ff2
  400fe6:	8d 51 ff             	lea    -0x1(%rcx),%edx ;
  400fe9:	e8 e0 ff ff ff       	callq  400fce <func4>
  400fee:	01 c0                	add    %eax,%eax
  400ff0:	eb 15                	jmp    401007 <func4+0x39>
  400ff2:	b8 00 00 00 00       	mov    $0x0,%eax ;eax = 0
  400ff7:	39 f9                	cmp    %edi,%ecx ;比较 7 与第一个传入参数的大小
  400ff9:	7d 0c                	jge    401007 <func4+0x39>;如果第一个传入参数的大小大于等于7就正常返回
  400ffb:	8d 71 01             	lea    0x1(%rcx),%esi
  400ffe:	e8 cb ff ff ff       	callq  400fce <func4>
  401003:	8d 44 00 01          	lea    0x1(%rax,%rax,1),%eax
  401007:	48 83 c4 08          	add    $0x8,%rsp
  40100b:	c3                   	retq    
  
000000000040100c <phase_4>:
  40100c:	48 83 ec 18          	sub    $0x18,%rsp
  401010:	48 8d 4c 24 0c       	lea    0xc(%rsp),%rcx;第二个参数
  401015:	48 8d 54 24 08       	lea    0x8(%rsp),%rdx;第一个参数
  40101a:	be cf 25 40 00       	mov    $0x4025cf,%esi;"%d %d"
  40101f:	b8 00 00 00 00       	mov    $0x0,%eax
  ;------------------------------------------------------------------------------------------
  401024:	e8 c7 fb ff ff       	callq  400bf0 <__isoc99_sscanf@plt>
  401029:	83 f8 02             	cmp    $0x2,%eax;输入的参数个数是不是两个
  40102c:	75 07                	jne    401035 <phase_4+0x29>;不是,爆炸
  40102e:	83 7c 24 08 0e       	cmpl   $0xe,0x8(%rsp);将第一个参数和 0xe 比较
  401033:	76 05                	jbe    40103a <phase_4+0x2e>;如果小于等于,就继续
  401035:	e8 00 04 00 00       	callq  40143a <explode_bomb>;否则爆炸
  40103a:	ba 0e 00 00 00       	mov    $0xe,%edx;调用函数第三个传入的实参,14
  40103f:	be 00 00 00 00       	mov    $0x0,%esi;调用函数第二个传入实参,0
  401044:	8b 7c 24 08          	mov    0x8(%rsp),%edi;调用函数第一个传入实参,也是输入的第一个参数
  401048:	e8 81 ff ff ff       	callq  400fce <func4>
  40104d:	85 c0                	test   %eax,%eax ;递归返回值为0
  40104f:	75 07                	jne    401058 <phase_4+0x4c>;否则爆炸
  401051:	83 7c 24 0c 00       	cmpl   $0x0,0xc(%rsp) ;经过func4 递归后,输入的第二个参数应为0 
  401056:	74 05                	je     40105d <phase_4+0x51>;第二个参数不为0就爆炸
  401058:	e8 dd 03 00 00       	callq  40143a <explode_bomb>
  ;------------------------------------------------------------------------------------------
  40105d:	48 83 c4 18          	add    $0x18,%rsp
  401061:	c3                   	retq   

分析:

首先从callq 400bf0 <__isoc99_sscanf@plt> 可以知道又是调用sscanf,上面的内容就是输入的参数。 401010:lea 0xc(%rsp),%rcx401015:lea 0x8(%rsp),%rdx 可以得知,这是传入的第二个和第一个参数,传入的是两个参数。

之后从 40103a:mov $0xe,%edx 可以得知,接下来这三行都是传递实参,为调用 func4 做准备。 func4 被调用的过程可以分析出第一个数字小于等于7,之后完成以后回到 phase_4401051:cmpl $0x0,0xc(%rsp) 可以得知第二个参数为 0。故测试以下 7 0

phase 4 调试过程

  • 设置断点,并运行至 phase_4

    此时的 ans.txt如下:

    Border relations with Canada have never been better.
    1 2 4 8 16 32
    1 311
    7 0
    
    

    image-20220802151932815

  • 执行到调用 func4 的位置,中间确认输入参数

    image-20220803145124535

  • 重点是 func4 的实现,这个过程需要的确定各个寄存器的值是否符合预期

    image-20220803150218152

  • 最后拆弹成功

    image-20220803150307235

实验过程:phase 5

0000000000401062 <phase_5>:
  401062:	53                   	push   %rbx
  401063:	48 83 ec 20          	sub    $0x20,%rsp
  401067:	48 89 fb             	mov    %rdi,%rbx ;第一个参数 -> rbx
  40106a:	64 48 8b 04 25 28 00 	mov    %fs:0x28,%rax ;接下来4行汇编是栈哨兵的检查(栈的保护机制,在编译时加上 -fno-stack-protector 就会被取消)
  401071:	00 00 
  401073:	48 89 44 24 18       	mov    %rax,0x18(%rsp) ;将哨兵的值赋值到栈里
  401078:	31 c0                	xor    %eax,%eax ;如果 eax 不为0,则说明栈被破坏
  ;---------------------------------------------------------------------------------
  40107a:	e8 9c 02 00 00       	callq  40131b <string_length> ;判断字符串长度
  40107f:	83 f8 06             	cmp    $0x6,%eax ;字符串长度必须为6
  401082:	74 4e                	je     4010d2 <phase_5+0x70>
  401084:	e8 b1 03 00 00       	callq  40143a <explode_bomb>
  401089:	eb 47                	jmp    4010d2 <phase_5+0x70>
  40108b:	0f b6 0c 03          	movzbl (%rbx,%rax,1),%ecx ;ecx = Mem[rbx + rax(0) * 1] 此时ecx 指向字符串第一个字符a
  40108f:	88 0c 24             	mov    %cl,(%rsp) ;取字符串的低8位值入栈
  
  401092:	48 8b 14 24          	mov    (%rsp),%rdx ;输入字符串作为值(具体的ascii),之后在一长串字符串将输入字符串的值作为偏移量
  401096:	83 e2 0f             	and    $0xf,%edx ;与1111 取与运算后作为偏移量,也就是取低4位
  401099:	0f b6 92 b0 24 40 00 	movzbl 0x4024b0(%rdx),%edx ;edx = 'a' 0x4024b0 = "maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?"
  ;分别取第10位 f(I:74->0100 1001), 第 16 位 l(O:79->0100 1111), 第 15 位 y(N:78->0100 1110),第 6 位 e(E:69->0100 0101),第 7 位 r(F:70->0100 0110),第 8 位 s(G:71->0100 0111)
  4010a0:	88 54 04 10          	mov    %dl,0x10(%rsp,%rax,1) ;rax = 0
  4010a4:	48 83 c0 01          	add    $0x1,%rax ;rax = 1
  4010a8:	48 83 f8 06          	cmp    $0x6,%rax ;循环终止的判断条件
  4010ac:	75 dd                	jne    40108b <phase_5+0x29>
  4010ae:	c6 44 24 16 00       	movb   $0x0,0x16(%rsp)
  4010b3:	be 5e 24 40 00       	mov    $0x40245e,%esi ;第二个传入参数 0x40245e = "flyers"
  4010b8:	48 8d 7c 24 10       	lea    0x10(%rsp),%rdi ;第一个传入参数,rdi 0x10(%rsp)是保存的我们输入的地址,上面的操作就是将每个字符串赋值到0x10(%rsp)起始的地址单元里面
  4010bd:	e8 76 02 00 00       	callq  401338 <strings_not_equal> ;要使得二者相等
  4010c2:	85 c0                	test   %eax,%eax
  4010c4:	74 13                	je     4010d9 <phase_5+0x77> ;相等就结束
  4010c6:	e8 6f 03 00 00       	callq  40143a <explode_bomb>
  4010cb:	0f 1f 44 00 00       	nopl   0x0(%rax,%rax,1)
  4010d0:	eb 07                	jmp    4010d9 <phase_5+0x77>
  4010d2:	b8 00 00 00 00       	mov    $0x0,%eax ;初始化 eax 为0 
  4010d7:	eb b2                	jmp    40108b <phase_5+0x29>
  ;---------------------------------------------------------------------------------
  4010d9:	48 8b 44 24 18       	mov    0x18(%rsp),%rax
  4010de:	64 48 33 04 25 28 00 	xor    %fs:0x28,%rax
  4010e5:	00 00 
  4010e7:	74 05                	je     4010ee <phase_5+0x8c>
  4010e9:	e8 42 fa ff ff       	callq  400b30 <__stack_chk_fail@plt>
  4010ee:	48 83 c4 20          	add    $0x20,%rsp
  4010f2:	5b                   	pop    %rbx
  4010f3:	c3                   	retq   

分析:

首先能够判断是要输入 6 个字符串,然后随便输入6个字符进行调试,建议使用规律不同的字符串,这样能够知道传递的参数位置。我使用的是 abcdef

接着当代码运行到 40108b:movzbl (%rbx,%rax,1),%ecx 以后,表示程序进入到循环体内,最后退出的条件是 rax == 6 ,而 rax 的初始值为 0, 这个意思就是遍历完我们输入的字符串,循环体内的意思是取我们输入字符的值的低四位的值,我们输入的是字符,也就是该字符对应 ascii 码的低四位。然后利用这个值作为一个索引,去 0x4024b0 这个长的字符串中寻找 flyers 对应的下标,注意我注释里面添加说明的是第几位,但是具体下标要-1操作。

当代码运行到 4010b3:mov $0x40245e,%esi 的时候,可以看到这个就是在传递参数了,作为第二个实参,是系统赋予的,要将这个字符串flyers0x10(%rsp) 的值(也就是上面提及到的低四位ascii码作为索引取出来的字符)进行比较,必须要二者相等。

综上,得出更新的ans.txt

Border relations with Canada have never been better.
1 2 4 8 16 32
1 311
7 0
IONEFG

phase 5 调试过程

  • 设置断点在 phase_5 并运行

    image-20220804164357374

  • 运行到进入循环体 40108b:movzbl (%rbx,%rax,1),%ecx

    image-20220804165103007

    可以看到movzbl (%rbx,%rax,1),%ecx,注意 rbx 最开始就用存储输入的字符串,此时rax作为循环体初始变量 为 0。

  • 执行到 401096 以后,完成了取第一个值的低四位的目的,此时再查看取到值是否为 I 的低四位 ascii 码的值 9

    image-20220804165345097

    可以看到值为 9,证明计算没错,之后可以直接运行 n,直到结束。

  • 运行 n,直接验证是否正确

    image-20220804165447748

实验过程:phase 6

实在是太长了,暂时放弃😞

00000000004010f4 <phase_6>:
  4010f4:	41 56                	push   %r14
  4010f6:	41 55                	push   %r13
  4010f8:	41 54                	push   %r12
  4010fa:	55                   	push   %rbp
  4010fb:	53                   	push   %rbx
  4010fc:	48 83 ec 50          	sub    $0x50,%rsp
  401100:	49 89 e5             	mov    %rsp,%r13
  401103:	48 89 e6             	mov    %rsp,%rsi
  401106:	e8 51 03 00 00       	callq  40145c <read_six_numbers>;读取六个数
  ;------------------------------------------------------------------------------------
  40110b:	49 89 e6             	mov    %rsp,%r14 ;r14 最后一个数地址
  40110e:	41 bc 00 00 00 00    	mov    $0x0,%r12d 
  401114:	4c 89 ed             	mov    %r13,%rbp
  401117:	41 8b 45 00          	mov    0x0(%r13),%eax ;第一个数字
  40111b:	83 e8 01             	sub    $0x1,%eax ; eax是返回的值的大小
  40111e:	83 f8 05             	cmp    $0x5,%eax ; 第一个数字小于等于5就继续
  401121:	76 05                	jbe    401128 <phase_6+0x34> 
  401123:	e8 12 03 00 00       	callq  40143a <explode_bomb> 
  401128:	41 83 c4 01          	add    $0x1,%r12d ; 循环迭代器 i
  40112c:	41 83 fc 06          	cmp    $0x6,%r12d ; 循环体,条件为6
  401130:	74 21                	je     401153 <phase_6+0x5f> 
  401132:	44 89 e3             	mov    %r12d,%ebx
  401135:	48 63 c3             	movslq %ebx,%rax
  401138:	8b 04 84             	mov    (%rsp,%rax,4),%eax
  40113b:	39 45 00             	cmp    %eax,0x0(%rbp)
  40113e:	75 05                	jne    401145 <phase_6+0x51>
  401140:	e8 f5 02 00 00       	callq  40143a <explode_bomb>
  401145:	83 c3 01             	add    $0x1,%ebx
  401148:	83 fb 05             	cmp    $0x5,%ebx
  40114b:	7e e8                	jle    401135 <phase_6+0x41>
  40114d:	49 83 c5 04          	add    $0x4,%r13
  401151:	eb c1                	jmp    401114 <phase_6+0x20>
  ; ---------------------------------------------------------------------
  ; 循环分析比较麻烦,401151会跳转到401114这个是最外层,完成了%r13 + 0x4。即arr++
  ; %13初始的时候是数组首地址。
  ;  按照思路逻辑如下
  ;  for( i=0;i<6;i++ ){
  ;      if(arr[i] - 1 > 5) bomb()
  ;      for(j=i+1;j<=5;j++){
  ;          if(arr[j] == arr[i]) bomb()
  ;      }
  ;  }
  401153:	48 8d 74 24 18       	lea    0x18(%rsp),%rsi 
  401158:	4c 89 f0             	mov    %r14,%rax
  40115b:	b9 07 00 00 00       	mov    $0x7,%ecx
  401160:	89 ca                	mov    %ecx,%edx
  401162:	2b 10                	sub    (%rax),%edx
  401164:	89 10                	mov    %edx,(%rax)
  401166:	48 83 c0 04          	add    $0x4,%rax
  40116a:	48 39 f0             	cmp    %rsi,%rax
  40116d:	75 f1                	jne    401160 <phase_6+0x6c>
; -----------------------------------------------------------------
; rsi的值为rsp+0x18 = rsp+0x4*6即数组的结束位置。
; %rax = %r14往前看,是输入的数组首地址。
; 
; for(int i=0;i<6;i++){
;     arr[i] = 7 - arr[i];
; }
  40116f:	be 00 00 00 00       	mov    $0x0,%esi
  401174:	eb 21                	jmp    401197 <phase_6+0xa3>
  401176:	48 8b 52 08          	mov    0x8(%rdx),%rdx
  40117a:	83 c0 01             	add    $0x1,%eax
  40117d:	39 c8                	cmp    %ecx,%eax
  40117f:	75 f5                	jne    401176 <phase_6+0x82>
  401181:	eb 05                	jmp    401188 <phase_6+0x94>

  401183:	ba d0 32 60 00       	mov    $0x6032d0,%edx

  401188:	48 89 54 74 20       	mov    %rdx,0x20(%rsp,%rsi,2)
  40118d:	48 83 c6 04          	add    $0x4,%rsi
  401191:	48 83 fe 18          	cmp    $0x18,%rsi
  401195:	74 14                	je     4011ab <phase_6+0xb7>

  401197:	8b 0c 34             	mov    (%rsp,%rsi,1),%ecx
  40119a:	83 f9 01             	cmp    $0x1,%ecx
  40119d:	7e e4                	jle    401183 <phase_6+0x8f>
  40119f:	b8 01 00 00 00       	mov    $0x1,%eax
  4011a4:	ba d0 32 60 00       	mov    $0x6032d0,%edx
  4011a9:	eb cb                	jmp    401176 <phase_6+0x82>
  ; --------------------------------------------------------------------------
  ; 借助流程图分析我们得到如下逻辑伪代码
  ; for(int i=0;i<6;i++){
  ;     int cnt = arr[i];
  ;     int add = 0x6032d0;
  ;     for(int j=1;j<arr[i];j++){
  ;         add = *(add+8);
  ;     *(rsp + 2*i + 0x20) = add;  // 8 字节 
  ; }
  ; 查看下*(add+8)中的数据
  ; (gdb) x 0x6032d0+0x8
  ; 0x6032d8 <node1+8>:   0x006032e0
  ; (gdb) x 0x6032e0+0x8 
  ; 0x6032e8 <node2+8>:   0x006032f0
  ; (gdb) x 0x6032f0+0x8
  ; 0x6032f8 <node3+8>:   0x00603300
  ; (gdb) x 0x603300+0x8
  ; 0x603308 <node4+8>:   0x00603310
  ; (gdb) x 0x603310+0x8
  ; 0x603318 <node5+8>:   0x00603320
  4011ab:	48 8b 5c 24 20       	mov    0x20(%rsp),%rbx
  4011b0:	48 8d 44 24 28       	lea    0x28(%rsp),%rax
  4011b5:	48 8d 74 24 50       	lea    0x50(%rsp),%rsi
  4011ba:	48 89 d9             	mov    %rbx,%rcx
  4011bd:	48 8b 10             	mov    (%rax),%rdx
  4011c0:	48 89 51 08          	mov    %rdx,0x8(%rcx)
  4011c4:	48 83 c0 08          	add    $0x8,%rax
  4011c8:	48 39 f0             	cmp    %rsi,%rax
  4011cb:	74 05                	je     4011d2 <phase_6+0xde>
  4011cd:	48 89 d1             	mov    %rdx,%rcx
  4011d0:	eb eb                	jmp    4011bd <phase_6+0xc9>
  ;   --------------------------------------------------------------- 
  ; narr 数组存放数据范围上面分析为 0x6032d0 - 0x603320 
  ; int *narr = {};
  ; for(int i=1;i<6;i++){
  ;     *(narr[i-1]+0x8) = narr[i]
  ; }
  ; 将narr[i-1]+0x8内存地址数据存放为narr[i]
  4011d2:	48 c7 42 08 00 00 00 	movq   $0x0,0x8(%rdx)
  4011d9:	00 
  4011da:	bd 05 00 00 00       	mov    $0x5,%ebp
  4011df:	48 8b 43 08          	mov    0x8(%rbx),%rax
  4011e3:	8b 00                	mov    (%rax),%eax
  4011e5:	39 03                	cmp    %eax,(%rbx)
  4011e7:	7d 05                	jge    4011ee <phase_6+0xfa>
  4011e9:	e8 4c 02 00 00       	callq  40143a <explode_bomb> 
  4011ee:	48 8b 5b 08          	mov    0x8(%rbx),%rbx 
  4011f2:	83 ed 01             	sub    $0x1,%ebp
  4011f5:	75 e8                	jne    4011df <phase_6+0xeb>
  ;----------------------------------------------------------------------------------------
; eax    :  *(narr[0]+0x8) => narr[1] => *(narr[1])
; (%rbx) :  *(narr[0])
; for(int i=1;i<=5;i++){
;     if( *(narr[i-1]) < *(narr[i]) ) bomb()        
; }
  4011f7:	48 83 c4 50          	add    $0x50,%rsp
  4011fb:	5b                   	pop    %rbx
  4011fc:	5d                   	pop    %rbp
  4011fd:	41 5c                	pop    %r12
  4011ff:	41 5d                	pop    %r13
  401201:	41 5e                	pop    %r14
  401203:	c3                   	retq   

一些其他收获

  • 下载一些 cmucode

    wget -r -np -nH --cut-dirs=3 -R index.html 网站地址
    

    e.g.

    wget -r -np -nH --cut-dirs=3 -R index.html https://www.cs.cmu.edu/~213/code/06-machine-control/
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/548138.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Zynq的雷达10Gbps高速PCIE数据采集卡方案(二)硬件设计

3.1 引言 采集卡的硬件设计是实现采集功能的基础&#xff0c;良好的硬件设计可以使采集功能更容 易实现&#xff0c;方便软件开发。本章基于第二章的硬件设计方案来详细介绍采集卡硬件设计。 包括载卡和子卡的芯片的选型、配置和具体电路的设计。载卡和子卡的硬件设计总体 …

美联储内部分歧不断加大 妥协方案:6月“跳过”,7月再加

在周五举行的托马斯劳巴赫研究会议上&#xff0c;美联储主席鲍威尔、前主席伯南克一同出席&#xff0c;并对当前的热点政策问题发表了看法。货币政策&#xff0c;自然是备受关注的议题。 凭借研究“银行和金融危机”荣获2022年诺贝尔经济学奖的伯南克表示&#xff0c;银行业危机…

Linux文件与目录管理笔记1

鸟哥私房菜笔记 这里写目录标题 常用文件命令cd,pwd,mkdir,rmdir 执行文件的路径的变量:$PATHls,cp,rm,mv 文件内容查看指令(cat,tac,nl)可翻页查看(more,less)More(一页一页翻动)less 数据截取&#xff08;head,tail&#xff09;非纯文本文件&#xff1a;od 常用文件命令 cd…

lwIP:宏 LWIP_TCPIP_CORE_LOCKING(内核锁定)

从 lwIP-2.0.0 开始&#xff0c;在 opt.h 中多了一个宏开关 LWIP_TCPIP_CORE_LOCKING&#xff0c;默认使能。这个宏是启用内核锁定功能的。 本文探索这个宏的前世今生。 2007 年 5 月 24 日&#xff0c;Simon Goldschmid &#xff08;以下简称 西蒙 &#xff09;提交了一个任务…

DriveAct:用于自动驾驶汽车细粒度驾驶员行为识别的多模态数据集

Drive&Act&#xff1a;A Multi-modal Dataset for Fine-grained Driver Behavior Recognition in Autonomous Vehicles 摘要1. 简介2. 其它驾驶员动作数据集3. Drive&Act数据集3.1 数据采集3.2 记录的数据流传感器设置和视频流3D Body Pose3D Head PoseInterior ModelA…

接口优化技巧汇总

1.批处理 批量思想&#xff1a;批量操作数据库&#xff0c;这个很好理解&#xff0c;我们在循环插入场景的接口中&#xff0c;可以在批处理执行完成后一次性插入或更新数据库&#xff0c;避免多次IO。 //批量入库 batchInsert();2.异步处理 异步思想&#xff1a;针对耗时比较…

短视频去水印接口 支持各短视频平台去水印 快速稳定

短视频去水印接口 支持各短视频平台去水印&#xff0c;抖音、快手、微视、西瓜等。 快速稳定 不限次 免费测试 接口开发文档 返回格式&#xff1a; JSON 请求方式&#xff1a; GET/POST 请求示例&#xff1a; 请求参数说明&#xff1a; 字段必填类型说明url是String短视…

听说你想成为一名6的飞起的黑客,这些资料怎么能少

重点提醒&#xff1a;本项目工具来源于互联网&#xff0c;是否含带木马及后门请自行甄别&#xff01;&#xff01;Hvv来即&#xff0c;请大家提高警惕&#xff01;&#xff01;&#xff01; 受限于篇幅原因&#xff0c;无法全部展示&#xff0c;如果你需要的话&#xff0c;可以…

【正点原子STM32连载】 第十章 STM32CubeMX简介 摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十章…

教你精通Java语法之第十四章、枚举

目录 一、背景及定义 二、使用 2.1switch语句 2.2常用方法 三、枚举优点缺点 四、枚举和反射 4.1枚举是否可以通过反射&#xff0c;拿到实例对象呢&#xff1f; 五、总结 六、面试问题 一、背景及定义 枚举是在JDK1.5以后引入的。主要用途是&#xff1a;将一组常量组织…

触发器章节小结

触发器&#xff08;Flip Flop&#xff09; 4.1 SR锁存器&#xff08;Set-Reset Latch&#xff09; 4.1.1 或非门构成的SR锁存器 SD称为置位端或置1输入端&#xff1b; RD称为复位端或置0输入端。 当SD 1、RD 0时,Q1、Q’0。在SD 1信号消失以后&#xff08;即SD 回到0)&#…

AI绘画-Midjourney基础1-突破想象的界限:掌握文本引导的图像生成技巧

Midjourney是一款 AI 绘画工具&#xff0c;可以根据你的提示&#xff08;本文中称为 prompt&#xff09;创作出各种图像。你只需要在Discord上和一个机器人聊天&#xff0c;就可以用简单的命令来控制它。目前已不支持免费试用&#xff0c;可以选择付费计划来获得更多功能和优势…

viet构建项目及<script setup>的用法

vite构建项目 官方文档&#xff1a;https://v3.cn.vuejs.org/guide/installation.html#vite vite 官网&#xff1a;https://vitejs.cn 什么是 vite&#xff1f;—— 新一代前端构建工具。 优势如下&#xff1a; 开发环境中&#xff0c;无需打包操作&#xff0c;可快速的冷启动。…

操作系统易错题

操作系统易错题 假设某硬盘由5个盘片构成&#xff08;共有8个记录面&#xff09;&#xff0c;盘面有效记录区域的外直径为30cm&#xff0c;内直径为10cm&#xff0c;记录位密度为250位/mm&#xff0c;磁道密度为16道/mm&#xff0c;每磁道分16个扇区&#xff0c;每扇区512字节&…

【图像分割】卫星遥感影像道路分割:D-LinkNet算法解读

前言 因为毕设中的部分内容涉及到卫星遥感影像道路分割&#xff0c;因此去对相关算法做了一些调研。 本文所使用数据集为DeepGlobe&#xff0c;来自于CVPR2018年的一个挑战赛&#xff1a;DeepGlobe Road Extraction Challenge。 D-LinkNet为该挑战赛的冠军算法。 考虑到D-Lin…

时间序列预测 | Matlab基于遗传算法优化BP神经网络(GA-BP)的时间序列预测,matlab代码

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 时间序列预测 | Matlab基于遗传算法优化BP神经网络(GA-BP)的时间序列预测,matlab代码 评价指标包括:R2、MAE、MSE、RMSE等,代码质量极高,方便学习和替换数据。 部分源码 %% 清空环境变量 warning off …

Flink学习——处理函数ProcessFunction及多流转换

处理函数 在DataStream的更底层&#xff0c;我们可以不定义任何具体的算子&#xff08;如map()&#xff0c;filter()等&#xff09;二只提炼出一个统一的“处理”&#xff08;process&#xff09;操作 。它是所有转换算子的概括性的表达。可以自定义处理逻辑。 所以这一层接口就…

Springcloud1--->Eureka注册中心

目录 Eureka原理Eureka入门案例编写EurekaServer将user-service注册到Eureka消费者从Eureka获取服务 Eureka详解基础架构高可用的Eureka Server失效剔除和自我保护 Eureka原理 Eureka&#xff1a;就是服务注册中心&#xff08;可以是一个集群&#xff09;&#xff0c;对外暴露自…

开心档之MySQL 数据类型

目录 MySQL 数据类型 数值类型 日期和时间类型 字符串类型 MySQL 中定义数据字段的类型对你数据库的优化是非常重要的。 MySQL 支持多种类型&#xff0c;大致可以分为三类&#xff1a;数值、日期/时间和字符串(字符)类型。 数值类型 MySQL 支持所有标准 SQL 数值数据类型…

矢量图形处理控件CAD .NET介绍以及安装

CAD .NET一款在CAD领域被广泛应用的控件&#xff0c;可以快速准确的阅读DWG和DXF文件&#xff0c;并且通过Windows GDI方法绘制件&#xff0c;支持多种文件格式&#xff0c;包括DWG、DXF、Gerber、光栅图像等&#xff0c;并支持部分编辑功能。 CAD.NET最新下载https://www.evg…