二进制炸弹bomblab-第六关解析-附还原的C语言代码

本文详细解析了一关游戏中的汇编代码,重点探讨了控制结构的循环和嵌套,以及数据结构的使用。通过实例分析,逐步揭示了代码逻辑,帮助理解如何在实际编程中处理类似问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

观前提示:本文并非速通指南,偏向于如何一步步思考与解题,也许会分析得有些拖沓。且本文为系列文章,每一篇会分析一关的破解思路,前文提到的知识点后面不会赘述,分析过的类似的汇编代码段也不会再分析,除非是没见过的结构,所以越往后分析得越少

本文共九百余字(汇编代码占大部分,实际没有多少字)。

前言

​ 如果这些解析对你有帮助,那么我会非常荣幸和开心!

​ 如果我的解析存在错误,非常抱歉误导了你!请在评论区提出!我也是一个正在不断学习的学生。

​ 谢谢你!

正式破解

概览全局

这一关并没有什么新东西,就是条件跳转构成的循环。所以我不打算一句句分析了。这关只是看着代码很长而已,难点可能是分清循环的并列关系和嵌套关系和数据结构判断。

关于控制结构

只分析一个片段:

感觉好多都是读到最后才知道是循环体的范围。

关于数据结构

跟踪堆栈内存:

在这里插入图片描述

分析汇编代码时划分出的循环体

#第一块(有嵌套)
   0x08048d82 <+39>:	mov    0xc(%esp,%esi,4),%eax
   0x08048d86 <+43>:	sub    $0x1,%eax
   0x08048d89 <+46>:	cmp    $0x5,%eax
   0x08048d8c <+49>:	jbe    0x8048d93 <phase_6+56>
   0x08048d8e <+51>:	call   0x804907d <explode_bomb>
   0x08048d93 <+56>:	add    $0x1,%esi
   0x08048d96 <+59>:	cmp    $0x6,%esi
   0x08048d99 <+62>:	je     0x8048dce <phase_6+115>
   0x08048d9b <+64>:	mov    %esi,%ebx

   0x08048d9d <+66>:	mov    0xc(%esp,%ebx,4),%eax
   0x08048da1 <+70>:	cmp    %eax,0x8(%esp,%esi,4)
   0x08048da5 <+74>:	jne    0x8048dac <phase_6+81>
   0x08048da7 <+76>:	call   0x804907d <explode_bomb>
   0x08048dac <+81>:	add    $0x1,%ebx
   0x08048daf <+84>:	cmp    $0x5,%ebx
   0x08048db2 <+87>:	jle    0x8048d9d <phase_6+66>

   0x08048db4 <+89>:	jmp    0x8048d82 <phase_6+39>
   
   
#第二块(有嵌套)
   0x08048db6 <+91>:	mov    0x8(%edx),%edx
   0x08048db9 <+94>:	add    $0x1,%eax
   0x08048dbc <+97>:	cmp    %ecx,%eax
   0x08048dbe <+99>:	jne    0x8048db6 <phase_6+91>

   0x08048dc0 <+101>:	mov    %edx,0x24(%esp,%esi,4)
   0x08048dc4 <+105>:	add    $0x1,%ebx
   0x08048dc7 <+108>:	cmp    $0x6,%ebx
   0x08048dca <+111>:	jne    0x8048dd3 <phase_6+120>

   0x08048dcc <+113>:	jmp    0x8048dea <phase_6+143>

   0x08048dce <+115>:	mov    $0x0,%ebx

   0x08048dd3 <+120>:	mov    %ebx,%esi
   0x08048dd5 <+122>:	mov    0xc(%esp,%ebx,4),%ecx
   0x08048dd9 <+126>:	mov    $0x1,%eax
   0x08048dde <+131>:	mov    $0x804c13c,%edx
   0x08048de3 <+136>:	cmp    $0x1,%ecx
   0x08048de6 <+139>:	jg     0x8048db6 <phase_6+91>

   0x08048de8 <+141>:	jmp    0x8048dc0 <phase_6+101>


#第三块(无嵌套)
   0x08048dea <+143>:	mov    0x24(%esp),%ebx
   0x08048dee <+147>:	lea    0x24(%esp),%eax
   0x08048df2 <+151>:	lea    0x38(%esp),%esi
   0x08048df6 <+155>:	mov    %ebx,%ecx

   0x08048df8 <+157>:	mov    0x4(%eax),%edx
   0x08048dfb <+160>:	mov    %edx,0x8(%ecx)
   0x08048dfe <+163>:	add    $0x4,%eax
   0x08048e01 <+166>:	mov    %edx,%ecx
   0x08048e03 <+168>:	cmp    %esi,%eax
   0x08048e05 <+170>:	jne    0x8048df8 <phase_6+157>


#第四块(无嵌套)
   0x08048e07 <+172>:	movl   $0x0,0x8(%edx)
   0x08048e0e <+179>:	mov    $0x5,%esi

   0x08048e13 <+184>:	mov    0x8(%ebx),%eax
   0x08048e16 <+187>:	mov    (%eax),%eax
   0x08048e18 <+189>:	cmp    %eax,(%ebx)
   0x08048e1a <+191>:	jge    0x8048e21 <phase_6+198>
   0x08048e1c <+193>:	call   0x804907d <explode_bomb>
   0x08048e21 <+198>:	mov    0x8(%ebx),%ebx
   0x08048e24 <+201>:	sub    $0x1,%esi
   0x08048e27 <+204>:	jne    0x8048e13 <phase_6+184>

还原成C代码

里面的注释是对注释上面的代码作用说明。

typedef struct NODE{
    int val;
    int num;
    struct NODE *next;
}node;

void phase_6(char* input , node *head){
    int numbers[6]; //开辟空间
    read_six_numbers(input,numbers);
    
    int i=0;
    node * sorted[7];
    while(1){
        unsigned int number = numbers[i];
        number--;
        //巧妙利用无符号负数比正数大的方法排除负数,如果是0,减去1变成负数,能排除零
        
        if(number>5){	
			explode_bomb();
        }
        //限制输入的范围在1~5 为了下面的数组遍历操作
        
        i++;
        if(i == 6){break;}
        
        for(int j=i;j<=5;j++){
            if(numbers[j] == numbers[j-1]){
                explode_bomb();
            }
        }
        //确保输入的6个数字不重复
       
    }

    for(int j=0; j!=6 ;j++){
        int number = numbers[j];
        int k=1;
        node *p = head->next;
        if(number > 1){
            do{
                p=p->next;
                k++;
            }while(number != k);
        }
        sorted[number] = p;
    }
    //按我们的输入把对应位置的链表节点重新排序 存放在数组里
    
    head->next = NULL;
    node *q=sorted;
    node *p = head;
    node *temp;
    do{
        temp = ++q;
        p->next = temp;
        p = temp;
    }while(p->next != NULL);
    //按数组构建新链表
    
    i=5;
    q=head->next;
    p=q->next;
    while(i--){
        if(p->val >= q->val){
            q=p;
            p=p->next;
        }else{
            explode_bomb();
        }
    }
    //遍历链表 如果链表节点不是递增的 会爆炸
    
}

后记

感谢你看到这里!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值