小菜鸟一枚 发表于 2022-6-10 19:38

学破解第196天,《攻防世界reverse练习区hackme》学习

前言:

  坛友们,年轻就是资本,和我一起逆天改命吧,我的学习过程全部记录及学习资源:(https://www.52pojie.cn/thread-1582287-1-1.html)

**立帖为证!--------记录学习的点点滴滴**

## 0x1 正向分析
  1.将程序拖进IDA,没有看到main函数,打开字符串窗口,看到关键字符串

!(https://s1.ax1x.com/2022/06/09/Xy8tuq.png)

  2.查看引用地址所在的函数,F5伪代码查看,可以看到关键在v26必须为true,再看看v26会赋值0,必须过掉v21的那个循环判断,v21可以看到是直接从数据段取地址。

!(https://s1.ax1x.com/2022/06/09/XyYHM9.png)

  3. 去看看byte_6B4270这个数组,可以看到数组长度24,一共22个数据。

!(https://s1.ax1x.com/2022/06/09/Xyd4gS.png)

  4.再往上看,可以知道我输入的密码必须是22位,v26才会被赋值true。
```
sub_407470((unsigned int)"Give me the password: ", a2, a3, a4, a5, a6, a2);
sub_4075A0((unsigned int)"%s", (unsigned int)v16, v6, v7, v8, v9, v14);
for ( i = 0; v16; ++i )
    ;
v26 = i == 22;
v25 = 10;
```

  5.再看看这个循环,就是处理的关键点,sub_406D90这个函数执行的返回值可以看到是int,猜测是随机数对22取余,然后v21就是从数组中对应下标取值,v20就是从我输入的密码字符串下标取值,然后v24那个循环有点看不明白。
```
do
{
    v10 = (int)sub_406D90() % 22;
    v22 = v10;
    v24 = 0;
    v21 = byte_6B4270;
    v20 = v16;
    v19 = v10 + 1;
    v23 = 0;
    while ( v23 < v19 )
    {
      ++v23;
      v24 = 1828812941 * v24 + 12345;
    }
    v18 = v24 ^ v20;
    if ( v21 != ((unsigned __int8)v24 ^ v20) )
      v26 = 0;
    --v25;
}
```

&emsp;&emsp;6.到这里静态已经看不出什么了,程序的流程已经理清楚了,接下来的关键是弄清楚循环中v24的由来和sub_406D90是不是符合我前面的猜想。

## 0x2 逆向解密
&emsp;&emsp;1.本来想用IDA动态调试看看,验证我的猜想,一直失败,不知道啥原因。

&emsp;&emsp;2.不能完全搞清楚也不要紧,按照前面的逻辑,涉及到运算的,代码反转即可,但是这里那个循环没弄明白,可不好反转,将ida中代码重命名一下,再看看。
```
do
{
    j = (int)sub_406D90() % 22;
    v22 = j;
    sum = 0;
    pwd_ch = password;
    input_ch = intput;
    k = j + 1;
    m = 0;
    while ( m < k )
    {
      ++m;
      sum = 1828812941 * sum + 12345;
    }
    v18 = sum ^ input_ch;
    if ( pwd_ch != ((unsigned __int8)sum ^ input_ch) )
      v26 = 0;
    --v25;
}
while ( v25 );
if ( v26 )
    v17 = sub_407470((unsigned int)"Congras\n", (unsigned int)intput, sum, j, v11, v12, v15);
```

&emsp;&emsp;3.现在我们看,就是从input和password中取值比较,最后的比较是异或,sum的计算只与k有关,和两个数组本身无关,异或的特性我们知道,可以直接颠倒运算,那么我可以把password作为输入,计算出input。
```
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int password[]={0x5F,0xF2,0x5E,0X8B,0X4E,0XE,0XA3,0XAA,0XC7,0X93,0X81,
    0X3D,0X5F,0X74,0XA3,9,0X91,0X2B,0X49,0X28,0X93,0X67,0x0};

    char input;

    int v25 = 22; //结束外层循环
    int i = 0;//下标,遍历每一个元素

    do
    {
      int sum = 0;
      int j = i + 1;
      int m = 0;
      while ( m < j )
      {
      ++m;
      sum = 1828812941 * sum + 12345;
      }
      
      input = (unsigned __int8)sum ^ password;

      i++;
      --v25;
    }while(v25);

    printf("%s\n",input);
    system("pause");

    return 1;
}

```

&emsp;&emsp;4.运行上面这段代码得到flag:
```
flag{d826e6926098ef46}
请按任意键继续. . .
```

## 0x3 总结
&emsp;&emsp;1.在分析遇到困难,不能理解代码含义的时候,可以靠猜想和保持逻辑不变去计算flag。

&emsp;&emsp;2.编写flag计算时,可以将IDA中的伪代码重命名,方面理解,还可以直接搬运使用。

马西瓜 发表于 2022-6-10 23:04

我爱你我爱你我爱你

马西瓜 发表于 2022-6-10 23:13

可以的兄弟

马西瓜 发表于 2022-6-10 23:17

真的厉害兄弟

马西瓜 发表于 2022-6-10 23:24

太刻意了兄弟比

q935849597 发表于 2022-6-10 23:39

厉害了,加油哦

bigbeer321 发表于 2022-6-10 23:44

厉害了,兄弟

qqxiazhitmac 发表于 2022-6-11 00:02

好厉害坚持下去了

bj9ye666 发表于 2022-6-11 00:04

白嫖是中华民族传统美德

0mengzi0 发表于 2022-6-11 00:10

这个好,支持一波{:1_919:}
页: [1] 2 3 4
查看完整版本: 学破解第196天,《攻防世界reverse练习区hackme》学习