CSAPP Bomb Lab

news2025/5/24 23:35:29

CSAPP Bomb Lab

芜湖,完成实验来记录一下啦~

这个lab看的我真是眼皮发麻,框框就是反汇编->c语言形式->优化c语言 最后我才能写出来,整的我睡觉都是 mov… lea…

难道适中,感觉只要耐心一点就没问题,好了现在开始正文…

小技巧

用gdb调试的技巧

gdb --tui bomb #打开类似界面的东东
(gdb) layout asm #汇编界面
(gdb) layout split #分割窗口
(gdb) layout re #寄存器界面

完整后整个界面就是下面的啦

在这里插入图片描述

我经常使用的gdb命令

x/【n】(x)/(d)/(s) 内存地址  #以x/d进制查看n个字节对应的内存  括号里面x代表16进制,d是10进制,s是字符串显示
x/x $rax 查看rax对应内存的值16进制显示
b n  在n处打断点
set $pc = 0x11111  将程序跳转到0x11111处执行
info r 查看寄存器信息,不过有上面的也不用这个了
stepi 单步执行汇编指令
s 单步执行代码(遇到能进去的函数会进去)
n 单步执行代码(不进去)
finish 直接跳出当前函数
#上面用到了界面,可以使用下面的指令切换焦点窗口
focus n 切换到下面的窗口
focus p 切换上面的窗口

我这边用的windows终端,感觉也是很不错,接下来就开始我们的逆向工程了

说实话,下面只是记录一下我的逆向过程,以及大致思路,没写出来的小伙伴不建议查看昂,还是自己一次一次stepi比较好,当然逆向的代码可以对比,看看我的有多少错误。

phase1

第一个锻炼一下看汇编代码的能力,只要进去把某个内存的东西输出一下就ok了

phase2

进入到执行函数会看到 read_six_numbers

在这里插入图片描述

这就直接猜到要输入6个数字了

进去看一下

在这里插入图片描述

哟,居然有一个sscanf,这不太熟(仅限我不熟啊),百度一下

int sscanf(const char *str, const char *format, ...)

昂~,这不就是个类似输入的函数吗

然后使用gdb查看一下参数

哦对,这个参数都是标准的,第一个参数都是%rdi ,然后以此类推, %rsi , % rdx , %rcx … 忘了就记住4个

x/s $rsi
->   "%d %d %d %d %d %d"

哟,果然是6个数字,直接输入6个数字,继续往下

然后你就会发现一个规律,验证一下就能找到咯

phase3

这个继续做他,上手我就是一个stepi

在这里插入图片描述

哟呵,老朋友了,看一看这次要输入几个数

x/s $rsi
-> "%d %d"

这次就俩个数啊

然后往下就是一堆

在这里插入图片描述

诶?怎么这么熟悉呢(翻一番书),我擦这不就是switch吗

我直接就是一手 反c语言, 反c语言中…(其实就是照着对应一条一条套, jmp改goto 寄存器改变量,然后优化)

void phase(string input){
        usigned char  t ; // 0xc
        usigned char  t1 ; //0x8
        string fmt= "%d %d";
        char res = ssacnf(input , fmt , t1 ,t );        //sscanf("123456 ", "%s", buf);
        if(res <= 1){
                explode_bomb();
                return ;
        }
        if(t1 > 7){
                goto L1;
        }
        switch(t1){
                case 0: //  // 0x400f7c
                                res = 0xcf;   //207
                                break;
                case 2: //      // 0x400f83
                                res = 0x2c3; // 707
                                break;
                case 3: //      // 0x400f8a
                                res = 0x100; // 256
                                break;
                case 4: //      // 0x400f91
                                res = 0x185; // 389
                                break;
                case 5: //      // 0x400f98
                                res = 0xce;  // 206
                                break;
                case 6: //      // 0x400f9f
                                res = 0x2aa; // 682
                                break;
                case 7: //      // 0x400fa6
                                res = 0x147; // 327
                                break;
L1:     explode_bomb();
                 case ?: //      // 0x400fb2
                                res = 0x0;
                                break;
                case 1:
                                res = 0x137; // 311
        }

        if(res == t){
                //      success
                return ;
        }
        explode_bomb();
}

我这一看,好家伙,还不止一个正确答案,一堆啊,随便选一个吧

其中有一个地方没搞明白他的结构,只优化成上面这样了。

phase4

继续就是一个stepi

在这里插入图片描述

老朋友又来了这次输入几个数呀

这次是俩个数字(就不贴图了)

看见这次汇编挺短还以为很容易呢,正高兴的看到个func4,好家伙还调函数了

在这里插入图片描述

先把上面的汇编弄成能看的c语言出来,挺短的

这里面有个test %eax,%eax 标准是 eax&eax 其实就是判断 eax是不是0

void phase_4(string input){ // di si dx cx
        // 3 int in the stack
        int t1 , t2;  //   ?   0
        auto res = sscanf(input , "%d %d" , t1 , t2);
        if(res != 2){
                bomb();
        }
        if(t1 > 14){
                bomb();
        }
        int res = func4(t1 , 0 , 14);
        if(res == 0){
                if(t2 == 0){
                        goto L1;
                }
        }
        bomb();
        L1: success
}

然后进去fun4看一看

在这里插入图片描述

这小子还调上自己了,继续一步一步转成能看的c

int fun4(int a , int  b  int c){
        //1 byte in the stack
        //int res = c - b;
        //int d = res >> 31;  // -1 or 0
        //res = (d + res) / 2;
        //d = a + res;
        if(b > c) b += 1;
        int d = a + (c - b) / 2;

        if(d  >  a){
                res = func4(a , b , d - 1);
                return res * 2;
        }
        res = 0;
        if(c < a){
                res = func4(a , c + 1 , c);
                res = res * 2 + 1;
        }
        return res
}

emmm就算转成代码,这求解…用计算机?快算了带入一个0发现可以通过,其他答案看你们啦

phase5

这次看看能不能碰到老朋友啦

在这里插入图片描述

哟换人了,换成 string_length,这不是求字符串长度的吗,看起来这次是要求长度了

看到了一个

cmp $0x6 , %eax

啊这,不是6个字符就给我爆炸啊

确定了数量,看看下面还有啥规则吧

这一写就是好几小时呀…

这个逆向的时候,会发现一系列从其他地放的字符串,譬如

在这里插入图片描述

这个0x40245e就有一个字符串

还有一个

在这里插入图片描述

这里有一串字符串,需要自己辨别一下

最后逆向出来的代码就是下面

char * A[] = "maduiersnfotvbyl" // 0x4024b0
void phase_5(string input){ // rdi
        // 32 byte
        int t1 = %fs:0x28; // rbx |  0x18 + rsp
        int res = string_length(input);
        char * result[6];
        if(res != 6){
                bomb();
        }
        goto L1; // phase_5 + 39
        for(int i = 0; i < 6; i++){
                char rdx = inptu[i];
                int index = input[i] & 15;
                rdx = A[index];
                result[index] = rdx;
        }
        res = strings_not_equal(result , "flyers"); // 9 15 14 5 6 7
        if(res != 0){
                bomb();
        }

        L1:
}

代码挺短,一看哈呀,这个地方还有 & 15 来确定字符呢,嘎嘎绕蒙

昂~,就是根据我输入的字符然后 % 15 来确定下标位置呀,然后根据A[]数组的字符查出来连起来和flyers相同就行,于是拿出我的密码本来吧

在这里插入图片描述

根据顺序,框框就是画,然后每一列的值输入进去都是能通过的。

终于解密了这个了,框框累,其实也可以直接写代码暴力搜索的,不过我还是选择了人工破译,至于为什么 ~

不会写代码破解…

phase6

还是往常看stepi

0X00000000004010f4 <phase_6>:
  0X4010f4:	push   %r14
  0X4010f6:	push   %r13
  0X4010f8:	push   %r12
  0X4010fa:	push   %rbp
  0X4010fb:	push   %rbx
  0X4010fc:	sub    $0x50,%rsp
  0X401100:	mov    %rsp,%r13
  0X401103:	mov    %rsp,%rsi
  0X401106:	callq  0X40145c <read_six_numbers>
  0X40110b:	mov    %rsp,%r14
  0X40110e:	mov    $0x0,%r12d

#第一部分
.L0
  0X401114:	mov    %r13,%rbp
  0X401117:	mov    0x0(%r13),%eax
  0X40111b:	sub    $0x1,%eax
  0X40111e:	cmp    $0x5,%eax
  0X401121:	jbe    .L1
  0X401123:	callq  0X40143a <explode_bomb>
.L1
  0X401128:	add    $0x1,%r12d
  0X40112c:	cmp    $0x6,%r12d
  0X401130:	je     .L4
  0X401132:	mov    %r12d,%ebx
.L2
  0X401135:	movslq %ebx,%rax
  0X401138:	mov    (%rsp,%rax,4),%eax
  0X40113b:	cmp    %eax,0x0(%rbp)
  0X40113e:	jne    .L3
  0X401140:	callq  0X40143a <explode_bomb>
.L3
  0X401145:	add    $0x1,%ebx
  0X401148:	cmp    $0x5,%ebx
  0X40114b:	jle    .L2
  0X40114d:	add    $0x4,%r13
  0X401151:	jmp    .L0

#第二部分

.L4  
  0X401153:	lea    0x18(%rsp),%rsi
  0X401158:	mov    %r14,%rax
  0X40115b:	mov    $0x7,%ecx
.L5
  0X401160:	mov    %ecx,%edx
  0X401162:	sub    (%rax),%edx
  0X401164:	mov    %edx,(%rax)
  0X401166:	add    $0x4,%rax
  0X40116a:	cmp    %rsi,%rax
  0X40116d:	jne    .L5

  0X40116f:	mov    $0x0,%esi
  0X401174:	jmp    .L9

#第三部分
.L6
  0X401176:	mov    0x8(%rdx),%rdx
  0X40117a:	add    $0x1,%eax
  0X40117d:	cmp    %ecx,%eax
  0X40117f:	jne    .L6

  0X401181:	jmp    .L8
.L7  
  0X401183:	mov    $0x6032d0,%edx
.L8
  0X401188:	mov    %rdx,0x20(%rsp,%rsi,2)
  0X40118d:	add    $0x4,%rsi
  0X401191:	cmp    $0x18,%rsi
  0X401195:	je     .L10
.L9
  0X401197:	mov    (%rsp,%rsi,1),%ecx
  0X40119a:	cmp    $0x1,%ecx
  0X40119d:	jle    .L7

  0X40119f:	mov    $0x1,%eax
  0X4011a4:	mov    $0x6032d0,%edx
  0X4011a9:	jmp    .L6

#第四部分
.L10
  0X4011ab:	mov    0x20(%rsp),%rbx
  0X4011b0:	lea    0x28(%rsp),%rax
  0X4011b5:	lea    0x50(%rsp),%rsi
  0X4011ba:	mov    %rbx,%rcx
.L11
  0X4011bd:	mov    (%rax),%rdx
  0X4011c0:	mov    %rdx,0x8(%rcx)
  0X4011c4:	add    $0x8,%rax
  0X4011c8:	cmp    %rsi,%rax
  0X4011cb:	je     .L12
  0X4011cd:	mov    %rdx,%rcx
  0X4011d0:	jmp    .L11

#第五部分
.L12
  0X4011d2:	movq   $0x0,0x8(%rdx)
  0X4011da:	mov    $0x5,%ebp
.L13
  0X4011df:	mov    0x8(%rbx),%rax
  0X4011e3:	mov    (%rax),%eax
  0X4011e5:	cmp    %eax,(%rbx)
  0X4011e7:	jge    .L14
  0X4011e9:	callq  0X40143a <explode_bomb>
.L14
  0X4011ee:	mov    0x8(%rbx),%rbx
  0X4011f2:	sub    $0x1,%ebp
  0X4011f5:	jne    .L13


  0X4011f7:	add    $0x50,%rsp
  0X4011fb:	pop    %rbx
  0X4011fc:	pop    %rbp
  0X4011fd:	pop    %r12
  0X4011ff:	pop    %r13
  0X401201:	pop    %r14
  0X401203:	retq   

我滴妈~,让我冷静一下 一下。这么长~,这真的这个代码耗时我好多天

没办法,还是一步一步写呗

这部分我逆向出来的代码丢了,没保存(真的很痛心)但是不想在逆向了,所以这里就简述一下过程吧

前面2部分还是很好写的,还是判断输入的数量,以及输入类型

void f1(int a[]){
    for(int i = 0; i < 6;i++){
        if( a[i] > 6 ) BOOM();
        for(int j = i + 1; j < 6; j++){
            if( a[i] == a[j]) BOOM();
        }
    }
}

从前面就可以看出,输入的数字不可以超过6个,然后不能超过6,还不能重复

然后第二部分是把每个a[i] = 7 - a[i];

然后下面这部分代码真是框框goto跳,给我整晕乎的

没办法,我就一步一步stepi,stepi,stepi,stepi,stepi,看寄存器的值

最后发现,这玩意居然有个这个东西

在这里插入图片描述

这个是把rbx + 8处的内存放到rax然后这居然又把额,就是*rax 复制给了eax。

这这这,相当于内存中存了个地址,然后猜一下估计是个链表了,然后就是框框用x/x n 查内存,

最后还发现了一个 0x6032d0这直接纯地址,看见就不一般,直接查一下

在这里插入图片描述

撕,gdb直接给出这玩意是个node了,然后看一下他内存里的值,在查一下,发现这不就是个

struct node{
	int v1;
	int v2;
	struct node * next;
}

v2记录的是我们输入的值(好像是)

v1是他自己的值

然后呢?继续stepi,跳了几个小时发现,

phase_6 +130 到 pahse_6 + 181这部分的代码,就是上面的第三部分代码,好像是在排序啊,我擦。赶紧带入数字一看,我丢,这不就是给node里面的东西排序吗这下有眉目了,接着整。

直接看第五部分怎么就爆炸的代码。发现满足序列递减就可以了,然后看node里的值,我们可以推出合法的链表项顺序应为3->4->5->6->1->2,因为第二步操作的存在,每个数x应该取7-x,即4 3 2 1 6 5

secret_phase

芜湖,终于搞完了实验上网看看别人写的代码吧~

开心逛中… 我擦,怎么还有secret_phase这个我咋没有,看看代码

    /* This phase will never be used, since no one will get past the
     * earlier ones.  But just in case, make this one extra hard. */
    input = read_line();
    phase_6(input);
    phase_defused();

    /* Wow, they got it!  But isn't something... missing?  Perhaps
     * something they overlooked?  Mua ha ha ha ha! */

最后一句看起来不像是完成的话呀,翻译一下,嗯?还有秘密的代码,我在找找

最后发现,在最后面的phase_defused()中还有一个秘密入口呢

在这里插入图片描述

这不是老朋友sscanf又来了,但是这次好像没让我们输入啊。看到有个注释,num_input_strings.还看到莫名的地址,看到地址我就想看他一下是啥。

在这里插入图片描述

这怎么意思是输入2个数字一个字符串?,发现还是从0x603870这块获取的值,这块是哪的值啊

看一下他的上下文

x/128s 0x603870

翻着翻着发现

在这里插入图片描述

这不是我之前输入的吗,昂~,懂了,就是之前phase4的输入的东西,这里又获取到了,发现之前输入的后面还应该输入一个字符串,接着stepi看看要输入什么字符串。

在这里插入图片描述

然后在之前的4答案处补上这个字符串继续往下走

发现了一个secret_phase函数进去看看

在这里插入图片描述

代码比较短(相比上一个)

逆向一下吧

你会发现这玩意也有指针,而且还不一一个,优化优化的代码就成下面这样的

void secret_phase(){
        chaar * input = read_line();
        long int res = strcol(input , NULL , 10);
        if(res > 1001){ // 0x3e8 == 1000
                bomb();
        }
        T * rdi = 0x6030f0;
        res = fun7(rdi , res);
        if(res != 2){
                bomb();
        }
        ...
}

fun7(T * node , long int val){
        if(node != NULL){
                return -1;
        }

        if(node->val == val){
                return 0;
        }
        if(node->val > val){
                return fun7(nqode->left , val) * 2;
        }

        return fun7(node->right , val) * 2 + 1;
}

这不就是个二叉树吗,然后看看人家的值计算一下答案就会出来的,结果发现,还是改4层的二分树,这还能难道我这个算法高手?框一下一个答案

24,错了,撕~,发现内存里的值看出了应该是22,最后就对了。(答案不止一个)

至此我的第二个lab就完成啦~

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

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

相关文章

【鸿蒙(HarmonyOS)】List列表、ArkUI资源组数据类型

一、引言 描述&#xff1a;List列表在移动端设备中最为常见。比如&#xff1a;通讯录、短信、聊天软件等都&#xff0c;都拥有他的身影。难度&#xff1a;简单知识点&#xff1a;1、列表组件的使用2、认识ArkUI资源组数据类型 二、列表List 1、发现问题&#xff08;Bug&…

2023-9-14 石子合并

题目链接&#xff1a;石子合并 #include <iostream> #include <algorithm>using namespace std;const int N 310, INF 1e9;int n; // 前缀和 int s[N]; int f[N][N];int main() {cin >> n;for(int i 1; i < n; i ) cin >> s[i];for(int i 1; i …

模式分类与“组件协作模式”

1. GOF-23 模式分类 从目的来看&#xff1a; 创建型&#xff08;Creational&#xff09;模式&#xff1a;将对象的部分创建工作延迟到子类或者其他对象&#xff0c;从而应对需求变化为对象创建时具体类型实现引来的冲击。结构型&#xff08;Structural&#xff09;模式&#…

CS5366 typec转HDMI 4k60拓展坞方案芯片,带PD快充功能

CS5366是一个高性能的USB类型-c/显示端口到HDMI2.0转换器方案芯片&#xff0c;CS5366集成了一个DP1.4兼容的接收器&#xff0c;一个HDMI2.0兼容的发射器。此外&#xff0c;还包括两个CC控 制器&#xff0c;用于CC通信&#xff0c;以实现DP Alt模式和电源传输功能&#xff0c;一…

[设计模式] 浅谈SOLID设计原则

目录 单一职责原则开闭原则里氏替换原则接口隔离原则依赖倒转原则 SOLID是一个缩写词&#xff0c;代表以下五种设计原则 单一职责原则 Single Responsibility Principle, SRP开闭原则 Open-Closed Principle, OCP里氏替换原则 Liskov Substitution Principle, LSP接口隔离原则 …

怎样做一个简易而温馨的原木风居室空间

由 balbek bureau 设计的 Relogged 是一座重新设计的私人住宅&#xff0c;位于乌克兰河岸的绿化区。顾名思义&#xff0c;该项目重新诠释了木屋的概念&#xff0c;并与充满自然气息的环境相呼应&#xff0c;营造出宁静舒适的生活氛围。在探索重新设计的木屋实例时&#xff0c;建…

【rar技巧】安装了WinRAR,右键没有压缩选项,怎么回事?

我们安装了WinRAR之后想要压缩文件&#xff0c;但是右键点击文件之后发现并没有WinRAR压缩选项&#xff0c;这应该如何设置才能出现右键带有压缩选项呢&#xff1f;方法如下&#xff1a; 首先打开WinRAR&#xff0c;在上面功能中点击选项 – 设置 然后我们在设置界面中切换到集…

unity C#客户端与服务器程序

客户端和服务器公共的脚本 OSC.cs // This is version 1.01(2015.05.27) // Tested in Unity 4 // Most of the code is based on a library for the Make Controller Kit1/* using UnityEngine; using System; using System.Collections; using System.Threading; using Syst…

webpack 基础配置

常见配置 文件打包的出口和入口webpack如何开启一台服务webpack 如何打包图片&#xff0c;静态资源等。webpack 配置 loader配置 plugin配置sourceMap配置 babel 语法降级等 接下来 &#xff0c; 我们先从webpack的基本配置 开始吧&#xff01; 在准备 配置之前 , 搭建一个 …

PCL 生成空间三角形面点云

系列文章目录 第一章&#xff1a;PCL生成线段点云 第二章&#xff1a;PCL创建圆柱面点云 文章目录 系列文章目录前言一、三角形面是什么&#xff1f;二、三角形面点云创建步骤1.引入库2.创建三角形面点云 总结 前言 点云库 (PCL) 是一个独立的、大规模的、开放的 2D/3D 图像和…

nginx部署vue后显示500 Internal Server Error解决方案

今天部署vue前端项目一直报错500&#xff0c;无法显示出主页面。 一个以为是自己的dist位置没有访问正确或者nginx.conf的位置写的不对&#xff0c;&#xff0c;最后才发现&#xff01;是权限的问题&#xff01;&#xff01; 我要访问/home/ubuntu/myapp/ruoyi/ruoyi-ui/dist的…

python环境安装(windows)

1. python安装 一、官网下载安装包 打开python的 官网链接 https://www.python.org鼠标点击Downloads按钮 点击downloads后&#xff0c;下拉&#xff0c;找到如下界面&#xff0c;里面就是python的各个历史版本 找到想要下载的版本&#xff0c;点击Download后&#xff0c;下拉…

AI绘画Stable Diffusion原理之扩散模型DDPM

前言 传送门&#xff1a; stable diffusion&#xff1a;Git&#xff5c;论文 stable-diffusion-webui&#xff1a;Git Google Colab Notebook部署stable-diffusion-webui&#xff1a;Git kaggle Notebook部署stable-diffusion-webui&#xff1a;Git AI绘画&#xff0c;输入一段…

热缩膜机效果不好怎么办?

热缩膜机也称热收缩机或收缩包装机&#xff0c;主要是采用加热的原理对物品表面的薄膜进行加热收缩&#xff0c;多用于食品、药品、化妆品、纸箱等产品的外包装&#xff0c;使用过收缩机的用户都知道&#xff0c;热收缩机效果不好是常出现的问题&#xff0c;下面就从3个方面和您…

EndNote+有道

EndNote里面有划线翻译的功能&#xff0c;前提是你的电脑里面安装了有道翻译或者百度翻译的客户端。 我更喜欢有道&#xff0c;所以...... 然后点击“快速安装”。完了之后打开如下&#xff1a; 实现翻译的操作如下&#xff1a; ok。

OJ练习第172题——可以攻击国王的皇后

可以攻击国王的皇后 力扣链接&#xff1a;1222. 可以攻击国王的皇后 题目描述 在一个 8x8 的棋盘上&#xff0c;放置着若干「黑皇后」和一个「白国王」。 给定一个由整数坐标组成的数组 queens &#xff0c;表示黑皇后的位置&#xff1b;以及一对坐标 king &#xff0c;表…

Element UI 表单验证规则动态失效问题

Element 版本&#xff1a;v2.15.3 问题背景 如下代码所示&#xff1a;有一个上传文件的 input 组件&#xff0c;在更新的时候&#xff0c;如果不上传文件表示不更新&#xff0c;如果要更新则点击 「重新上传」按钮将上传组件显示出来 <el-form ref"form" :mode…

计算机网络:三次握手与四次挥手

摘取作者&#xff1a;拓跋阿秀 三次握手 三次握手&#xff08;Three-way Handshake&#xff09;其实就是指建立一个TCP连接时&#xff0c;需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后…

用于人类复杂疾病成药性评估的R包:DREAM包

已获批药物开发新适应症时&#xff0c;需要对所研究的疾病进行彻底的成药性评估。先前成药性主要通过三种不同的方法进行评估&#xff0c;第一种方法基于公共存数据&#xff0c;关注不同治疗条件下药物的作用机制&#xff08;MOA&#xff09;&#xff1b;第二种是基于网络&…

WEB漏洞原理之---【XMLXXE利用检测绕过】

文章目录 1、概述1.1、XML概念1.2、XML与HTML的主要差异1.3、XML代码示例 2、靶场演示2.1、Pikachu靶场--XML数据传输测试玩法-1-读取文件玩法-2-内网探针或攻击内网应用&#xff08;触发漏洞地址&#xff09;玩法-3-RCE引入外部实体DTD无回显-读取文件开启phpstudy--apache日志…