前言:
坛友们,年轻就是资本,和我一起逆天改命吧,我的学习过程全部记录及学习资源:https://www.52pojie.cn/thread-1582287-1-1.html
立帖为证!--------记录学习的点点滴滴
0x1 正向分析
1.将程序拖进IDA,没有看到main函数,打开字符串窗口,看到关键字符串
2.查看引用地址所在的函数,F5伪代码查看,可以看到关键在v26必须为true,再看看v26会赋值0,必须过掉v21的那个循环判断,v21可以看到是直接从数据段取地址。
3. 去看看byte_6B4270这个数组,可以看到数组长度24,一共22个数据。
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]; ++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[v10];
v20 = v16[v10];
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;
}
6.到这里静态已经看不出什么了,程序的流程已经理清楚了,接下来的关键是弄清楚循环中v24的由来和sub_406D90是不是符合我前面的猜想。
0x2 逆向解密
1.本来想用IDA动态调试看看,验证我的猜想,一直失败,不知道啥原因。
2.不能完全搞清楚也不要紧,按照前面的逻辑,涉及到运算的,代码反转即可,但是这里那个循环没弄明白,可不好反转,将ida中代码重命名一下,再看看。
do
{
j = (int)sub_406D90() % 22;
v22 = j;
sum = 0;
pwd_ch = password[j];
input_ch = intput[j];
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);
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[23];
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[i] = (unsigned __int8)sum ^ password[i];
i++;
--v25;
}while(v25);
printf("%s\n",input);
system("pause");
return 1;
}
4.运行上面这段代码得到flag:
flag{d826e6926098ef46}
请按任意键继续. . .
0x3 总结
1.在分析遇到困难,不能理解代码含义的时候,可以靠猜想和保持逻辑不变去计算flag。
2.编写flag计算时,可以将IDA中的伪代码重命名,方面理解,还可以直接搬运使用。