单步调试:

(gdb) bt
#1 0x0000000000401347 in strings_not_equal ()
#2 0x0000000000400eee in phase_1 ()
#3 0x0000000000400e3f in main (argc=<optimized out>, argv=<optimized out>) at bomb.c:74

这里的执行流程为:

    /* Hmm...  Six phases must be more secure than one phase! */
input = read_line(); /* Get input */
phase_1(input); /* Run the phase */
phase_defused(); /* Drat! They figured it out!
* Let me know how they did it. */
printf("Phase 1 defused. How about the next one?\n");

可以发现只有phase_1正常返回的时候,才会执行下面的phase_defused()函数将阶段1的炸弹拆除。现在就想让phase_1正常执行完,那就需要让此函数中所有不正常的跳转都不执行。

首先查看phase_1函数的汇编代码:

(gdb) disassemble phase_1
Dump of assembler code for function phase_1:
0x0000000000400ee0 <+0>: sub $0x8,%rsp
0x0000000000400ee4 <+4>: mov $0x402400,%esi #0x402400 --> %esi
0x0000000000400ee9 <+9>: call 0x401338 <strings_not_equal> #调用strings_not_equal函数
0x0000000000400eee <+14>: test %eax,%eax
0x0000000000400ef0 <+16>: je 0x400ef7 <phase_1+23> #如果%eax值为0,则正常返回
0x0000000000400ef2 <+18>: call 0x40143a <explode_bomb> #如果%eax值不为0,则触发炸弹
0x0000000000400ef7 <+23>: add $0x8,%rsp
0x0000000000400efb <+27>: ret

test 指令将 %eax 寄存器的值与自身进行逻辑与操作,并设置标志位,但不修改 %eax 的值。如果 %eax 的值为零,则标志位会被置为零;如果 %eax 的值不为零,则标志位会被置为非零。

如果想让程序正常执行,那么就需要让获得%esi寄存器值的函数strings_not_equal返回值为0。

下面查看函数strings_not_equal的代码,并且分析下主要的控制代码,看看如何让返回值为0:

(gdb) disassemble strings_not_equal
Dump of assembler code for function strings_not_equal:
0x0000000000401338 <+0>: push %r12
0x000000000040133a <+2>: push %rbp
0x000000000040133b <+3>: push %rbx
0x000000000040133c <+4>: mov %rdi,%rbx
0x000000000040133f <+7>: mov %rsi,%rbp
0x0000000000401342 <+10>: call 0x40131b <string_length> # 将%rbx和 %rbp传入函数string_length
0x0000000000401347 <+15>: mov %eax,%r12d # 第一次返回值%eax赋给 %r12d
0x000000000040134a <+18>: mov %rbp,%rdi # %rbp —> %rdi
0x000000000040134d <+21>: call 0x40131b <string_length> # %rdi的值作为入参
0x0000000000401352 <+26>: mov $0x1,%edx
0x0000000000401357 <+31>: cmp %eax,%r12d # 对比两次函数长度调用的结果
0x000000000040135a <+34>: jne 0x40139b <strings_not_equal+99> # 若长度不同,返回1 # 以上代码均为判断两个字符串的长度是否相同,现在的%r12d、%eax分别保存了第一次和第二次的函数调用结果,即两个字符串的长度
# 寄存器rbx 和 rbp 分别保存着函数的两个参数 # 35c-41:若函数第一个参数低8位为0,则返回0
0x000000000040135c <+36>: movzbl (%rbx),%eax # 参数1的低1位字节赋值给eax
0x000000000040135f <+39>: test %al,%al # %al & %al
0x0000000000401361 <+41>: je 0x401388 <strings_not_equal+80> # Jump condition:ZF---(Equal / zero)
# 35c-37f:对比参数1和参数2的每个字节,均相同的话遍
0x0000000000401363 <+43>: cmp 0x0(%rbp),%al # 参数2的低1位字节与数1的低1位字节对比
0x0000000000401366 <+46>: je 0x401372 <strings_not_equal+58> # 如果相等,则对比更高1位的字节
0x0000000000401368 <+48>: jmp 0x40138f <strings_not_equal+87> # 不相等,返回错误1
0x000000000040136a <+50>: cmp 0x0(%rbp),%al
0x000000000040136d <+53>: nopl (%rax)
0x0000000000401370 <+56>: jne 0x401396 <strings_not_equal+94> #若参数1、2的第2个字节不同,则返回错误1
0x0000000000401372 <+58>: add $0x1,%rbx
0x0000000000401376 <+62>: add $0x1,%rbp
0x000000000040137a <+66>: movzbl (%rbx),%eax
0x000000000040137d <+69>: test %al,%al
0x000000000040137f <+71>: jne 0x40136a <strings_not_equal+50> 0x0000000000401381 <+73>: mov $0x0,%edx
0x0000000000401386 <+78>: jmp 0x40139b <strings_not_equal+99>
0x0000000000401388 <+80>: mov $0x0,%edx
0x000000000040138d <+85>: jmp 0x40139b <strings_not_equal+99>
0x000000000040138f <+87>: mov $0x1,%edx
0x0000000000401394 <+92>: jmp 0x40139b <strings_not_equal+99>
0x0000000000401396 <+94>: mov $0x1,%edx
0x000000000040139b <+99>: mov %edx,%eax
0x000000000040139d <+101>: pop %rbx
0x000000000040139e <+102>: pop %rbp
0x000000000040139f <+103>: pop %r12
0x00000000004013a1 <+105>: ret
End of assembler dump.

这里的几个比较重要的跳转代码:

0x40139b <strings_not_equal+99>:函数将以%edx作为返回值返回。

0x401388 <strings_not_equal+80>:返回0。

0x40136a <strings_not_equal+50>:比较 %al 寄存器中的值与 %rbp 寄存器偏移 0 的内存地址处的值,如果不相等,则跳转到地址 0x401396 处执行相应的代码(函数会返回1),否则继续执行后续指令。

重点理解的指令有:

  • test S1, S2:相当于S1&S2,若结果为0,则设置ZF为1
  • jmp的所有指令。重点有je,jump condition为ZF = 1
  • movzbl:0拓展数据。Move zero-extended byte to double word(movz S,R: R ← ZeroExtend(S))

综上,可以得知如果想拆除阶段1的炸弹,则需要输入合理的字符串,而这个字符串可以通过以下分析得出:

  1. 查看phase_1函数的汇编代码,发现入参%rdi需要跟另一个参数0x402400 --> %rsi进入函数strings_not_equal 进行计算,若结果为0,则可以拆除炸弹,否则爆炸。
  2. 查看strings_not_equal 函数的汇编代码,可以分析出此函数是将入参寄存器(%rdi%rsi)所指地址处的字符串进行比对,如果长度相同并且每个字都相同(按照字节对比),则返回0

通过上面两个函数的分析,就可以得知我们所输入的字符串,需要跟地址为0x402400处的字符串进行比对,比对成功则炸弹拆除。

那这样,通过gdb的命令x/30s 0x402400,以 ASCII 格式打印出从地址 0x402400 开始的 10 个字节的数据(假设这些数据是以 0 结尾的字符串),并且找出第一个字符串即可,这里打印的值为:

(gdb) x/30s 0x402400
0x402400: "Border relations with Canada have never been better."
#translation:边境与加拿大的关系从未如此良好。

boom lab分析的更多相关文章

  1. XML第一次简单入门(Lab分析)

    In this tutorial you will create a well-formed and verified XML file. Consider the XML document belo ...

  2. Visual Lab Online —— 事后分析

    项目 内容 班级:北航2020春软件工程 博客园班级博客 作业:事后分析 事后分析 设想和目标 我们的软件要解决什么问题?是否定义得很清楚?是否对典型用户和典型场景有清晰的描述? 我们的软件使得编写简 ...

  3. CSAPP buffer lab记录——IA32版本

    CSAPP buffer lab为深入理解计算机系统(原书第二版)的配套的缓冲区溢出实验,该实验要求利用缓冲区溢出的原理解决5个难度递增的问题,分别为smoke(level 0).fizz(level ...

  4. 超像素经典算法SLIC的代码的深度优化和分析。

    现在这个社会发展的太快,到处都充斥着各种各样的资源,各种开源的平台,如github,codeproject,pudn等等,加上一些大型的官方的开源软件,基本上能找到各个类型的代码.很多初创业的老板可能 ...

  5. MIT 6.828 JOS学习笔记17. Lab 3.1 Part A User Environments

    Introduction 在这个实验中,我们将实现操作系统的一些基本功能,来实现用户环境下的进程的正常运行.你将会加强JOS内核的功能,为它增添一些重要的数据结构,用来记录用户进程环境的一些信息:创建 ...

  6. MIT 6.828 JOS学习笔记15. Lab 2.1

    Lab 2: Memory Management lab2中多出来的几个文件: inc/memlayout.h kern/pmap.c kern/pmap.h kern/kclock.h kern/k ...

  7. MIT 6.828 JOS学习笔记10. Lab 1 Part 3: The kernel

    Lab 1 Part 3: The kernel 现在我们将开始具体讨论一下JOS内核了.就像boot loader一样,内核开始的时候也是一些汇编语句,用于设置一些东西,来保证C语言的程序能够正确的 ...

  8. MIT 6.828 JOS学习笔记7. Lab 1 Part 2.2: The Boot Loader

    Lab 1 Part 2 The Boot Loader Loading the Kernel 我们现在可以进一步的讨论一下boot loader中的C语言的部分,即boot/main.c.但是在我们 ...

  9. Tomcat源码分析

    前言: 本文是我阅读了TOMCAT源码后的一些心得. 主要是讲解TOMCAT的系统框架, 以及启动流程.若有错漏之处,敬请批评指教! 建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, ...

  10. GJM : 【技术干货】给The Lab Renderer for Unity中地形添加阴影

    感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...

随机推荐

  1. Python简单程序设计(Unicode编码与字符间转换篇)

    如题: (误以为本题存在两者之间互相转换,后附上逆过程代码) 解题方式如下: 逆过程:

  2. uniapp中引入Leaflet

    1. 引言 uniapp中自带有map组件,并且自带的map组件有常见的显示地图.绘制点线面的功能 但是,它存在以下问题: 收费,自带的map组件使用的是高德.腾讯的地图,无论使用什么样的功能,即使只 ...

  3. 「AntV」路网数据获取与L7可视化

    1. 引言 L7 地理空间数据可视分析引擎是一种基于 WebGL 技术的地理空间数据可视化引擎,可以用于实现各种地理空间数据可视化应用.L7 引擎支持多种数据源和数据格式,包括 GeoJSON.CSV ...

  4. vue项目本地开发完成后部署到服务器后报404是什么原因呢?

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.如何部署 前后端分离开发模式下,前后端是独立布署的,前端只需要将最后的构建物上传至目标服务器的web容器指定的静态目录下即可 我们知道 ...

  5. 记录-JS 基础知识大全

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 1.通过javascript向文档中输出文本 document是javascript的内置对象,代表浏览器的文档部分 document.w ...

  6. kali局域网断网攻击

    首先我们打开我们熟悉的kali linux操作系统,利用指令: ifconfig 来确认本机的ip地址 确认了本机的ip地址之后,利用一下的指令查看局域网下所有ip: fping -g 本机IP地址/ ...

  7. 《.NET内存管理宝典 》(Pro .NET Memory Management) 阅读指南 - 第3章

    本章勘误: 暂无,等待细心的你告诉我哦. 本章注解: 暂无 本章释疑: 暂无,等待你的提问 致谢: MVP 林德熙 MVP 吕毅 sPhinX 相关链接 试读记录

  8. Kingbase Create Type 语句使用

    Kingbase create type类型创建语句 说明: KingbaseES 数据库中,可以通过CREATE TYPE语句定义一种新的数据类型. 有八种形式的CREATE TYPE.它们分别创建 ...

  9. P9966 [THUPC 2024 初赛] 机器人 题解

    细节大模拟. 题意 一堆机器人在一起,每个人有左右手和一些指令,依次执行并输出结果. 做法 首先这种指令的执行还算是比较简单的大模拟,一个个实现即可,在此给出我的定义. struct Robot{ i ...

  10. BeautifulSoup 库 和 re 库 解析腾讯视频电影

    1 import requests 2 import json 3 from bs4 import BeautifulSoup #网页解析获取数据 4 import sys 5 import re 6 ...