反汇编-拆炸弹bomb实验

拆炸弹解题报告


时间原因先写这些,占坑,持久更新。

作者信息:

2016级山东大学计算机基Frankdura

基础知识

掌握好gdb的方法对你很重要

x/s $r3 可以查看寄存器

如果上述命令不行可以使用:

p $r3

此外

b *0x10878设置指定位置断点
c  该命令是设置断点后继续进行
si 是逐步运行

实验

phase1 输入开始字符

【答案】Let’s begin now!

phase2 id后5位阶乘,首位为1

【答案】(id:123456111111)111111
反汇编-拆炸弹bomb实验_第1张图片
下面通过查看寄存器内容来验证我们想法
反汇编-拆炸弹bomb实验_第2张图片

phase3 switch-case操作

【答案】(多种)4 o 228
先比较后面的228 然后再比较中间的 %c;

phase4 递归函数

还是照例先看一下是不是id最后一位是奇数、偶数
如果是奇数那么和8比较
如果是偶数那么和13比较
反汇编-拆炸弹bomb实验_第3张图片
然后看一下fun4;
很显然
注意r0是函数的“返回”值
关键是这里如果 fun4(n) = fun4(n-1) + fun4(n-2);
(其实连分析都不用分析了)
这是一个单调递增的函数(数列);而且范围无非是 0 – 8或者 0 – 12
那么我直接二分即可,二分枚举 得到5即可。
反汇编-拆炸弹bomb实验_第4张图片
如果正规分析:
斐波那契数列:
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, …
13 –》index = 6;
8 -》index = 5;

【答案】(id:123456111111)5

phase5 字符串加密算法

【答案】o`ekma或者opekma
先后四位截取;
反汇编-拆炸弹bomb实验_第5张图片
可以查看一波:
输入 o 对应的ascii码为 103(g)
反汇编-拆炸弹bomb实验_第6张图片

phase6

第一轮第一个数字必须大于0 小于等于6
注意该炸弹有双重计数,一个是r11 – I = r11 - 12这种。
还有一个r11 – k这种, = r11 – 16;
r3 = [r11 - 12] 即为恢复为计数数据 0()
要求第一个数据和第二个数据不相等;其实整个左半部分都是判断后面的五位是不是和第一位相同。更进一步是一个二重循环判断每一位都不相同。右侧是将这六个数看作链表数据的index,要求指定的位置的index必须有序:

1->253 ->node1
2->725 ->node2
3->301 ->node3
4->997 ->node4
5->212 ->node5
6->432 ->node6
最后一段:
有个判断最后一位是奇数还是偶数的
如果是奇数
从大到小
4 2 6 3 1 5
如果是偶数
从小到大
5 1 3 6 2 4

phase_secret
首先右键点击该函数名称
反汇编-拆炸弹bomb实验_第7张图片

然后选择List cross references to …
反汇编-拆炸弹bomb实验_第8张图片
点击ok
进入:
反汇编-拆炸弹bomb实验_第9张图片
他在左下角,在phrase_defuse中,在其中再次使用上述操作:
看到每个阶段结束后会有这个函数,在main函数中:

通过查看phase_defused里面的验证机制,可以知道是在读一个%d的时候还会额外读一个%s。(判断读入的是不是两个)

然后判断第二个字符是不是和austinpowers相同。
所以我们找到了炸弹

Curses, you've found the secret phase!
But finding it and solving it are quite different...

下面开始拆弹:
直接右键看一下谁调用了fun7
发现一个位置然后查看数据:
这里r3是我们的转换后的“数字”
反汇编-拆炸弹bomb实验_第10张图片
关键是1001代表啥呢?
是func7 的读入参数:
为 r1的内容,就是我们转换后的数字
r0为第二个参数 也就是数据内存地址(反复出现:618872 618848)
我们强行查看内容:

每次func7调用完后会乘2加1;
这里写图片描述
最后的结束标准是 7 所以
我们看如何得到7?
换言之经过了多少次递归后得到了7?
还需要的注意的是 当调用Loc_10F10的时候返回为0;没有其他的数字的返回值所以 7 –> 3 -> 1->0;
也就是说深入到“最深”处你返回值应该是 0;
如何返回零?
注意到当 r2(数据) 比r3(你输入的数字)大或者相等的时候才调用Loc_10F10,返回为0。而我们需要前三次都继续递归,最后一次才大于等于,所以我们每次查看一下r2 r3并调节我们的数值。即可。

【答案样例】

【第一组】
123456111111
Let’s begin now!
1 1 1 1 1 1
4 o 228
5 austinpowers
opekma
4 2 6 3 1 5
【第二组】
123456111112
Let’s begin now!
1 2 2 2 2 2
4 o 114
5 austinpowers
opekma
5 1 3 6 2 4

【附录】
求解ascii码后四位的and操作:

#include 
#include 
#include 
using namespace std;
int main(void)
   {
    int ch[16]={0};  //存放二进制数01
    int i,j;
    int variable,index;
    printf ("Please enter a value(0~32767):\n");
    printf (" (Enter any letter to quit.)\n");
    string str;
    while (cin >> str) 
    {
      variable = str[0];
      for (index=0;index<15;index++)
      {
        i=variable%2;  //2的余数
        j=variable/2;  //取被2整除的数
        variable=j;    
        ch[index]=i;                //将余数存放在数组中
      }
      for(index=15;index>=0;index--)
      {                             
       printf ("%d",ch[index]);     
        if (index%4 == 0)           
       {                            
        printf (" ");               
           //每输出4个元素,输出一个空格
       }
      }
      printf ("-->");
      for(index=15;index>=0;index--)
      {                             
       printf ("%d",ch[index]&1);     
        if (index%4 == 0)           
       {                            
        printf (" ");               
           //每输出4个元素,输出一个空格
       }
      } 
            printf ("\n");
    }
   system ("pause");
   return 0;
   }

求解16位长数组array.7503

#include 
#include 
using namespace std;
int main(int argc, char const *argv[])
{
    int a; 
    while(cin>> a)
    {
        printf("%c\n", a);
    }

    return 0;
}

你可能感兴趣的:(计算机组成,汇编)