发布于 

Bbbbbbbbbabyre

摸鱼文重写了。

一、无法反汇编怎么办

本题的主函数在不经过处理的情况下没有办法反汇编,解决途径有二:

1. 将函数体选中,直接转化为函数

2. 在函数体最后sp堆栈不平衡的位置把多余的代码行去掉

这种情况基本是函数内部的函数调用有问题, 某个函数的函数声明有问题. 此时选项->general->disassembly->Display disassembly line parts->stack pointer前的勾打上, 就可以看到IDA view窗口前面多出000, 004, -004之类的. 这就是堆栈变化数字, 选中某一行, 按alt+k就可以调整堆栈变化. 去找有问题的函数, 或者粗暴地把末尾的正数改成负数, 按F5就行了. 不过详细分析的时候应该找找哪个函数的声明弄错了, 然后按Y改下就行了 ## 二、题目重点

  1. 每轮一个操作数,存入三个数据进行操作

  2. 注意操作数有两个%64,对这个数据对应位置查看可以发现,其实是从0到41均操作了两遍,但如果没有意识到的话,会发现这个数据是没有规律的(即,注意使用传入的数据分析,而非原始数据自身)

  3. 分析操作数(按先后顺序)p1,p2,可以发现是将p1是三元组的第一个数,p2的(b是对应的byte)b0,b2为同一个三元组的第二个数,b1为同一个三元组的第三个数

  4. 对每一步switch进行分析,发现:

    case 0:更新p2的b0为b0指向的字符 case 1:更新p2的b0与b1为其对应指向的字符 case 2:将b1与b0进行异或 case 3: 将b1与b0进行求与赋给d,以及时钟判断debug case 4:将b1乘2,b3=b1 case 5:将d赋值b0 case 6:case5,寄存更新b2(b1)位置对应的字符 case 7:切换下一轮 case 8:(异常)退出 case 9: (正经)退出

  5. 分析switch的生成逻辑知,如果p1为999直接终极退出(见上);否则,如果有b3,每次取p1的下一个lowbit位,为下一个操作数;如果到6且b3不为零就返回2;否则,如果b3为0,就到7。

  6. 再分析每次的三元组,通过动态调试发现,第一个三元组负责提供操作数据,第二个负责赋值,所以取出这些数,进行逆向操作。

三、逆向代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include<cstdio>
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
unsigned char ans[43]=
{
31, 24, 15, 250, 184, 99, 100, 137, 24, 104,
124, 25, 20, 45, 125, 88, 0, 30, 84, 106, 65,
60, 54, 62, 86, 19,
4, 59, 46, 75, 121, 67, 122, 34, 69, 110,
58, 117, 38, 200, 192, 142
};

unsigned char xo[84]=
{
9, 2, 7, 8, 6, 9, 11, 10, 4, 11, 12, 4, 7, 7,
10, 4, 3, 9, 4, 6, 3, 12,
11, 13, 4, 10, 7, 7, 2, 6, 6, 12, 9, 14, 7, 8
, 11, 13, 14, 12, 4, 7, 13, 8, 12, 10, 3, 9,
5, 12, 13, 11, 12, 7, 6, 10, 8, 9, 13
, 8, 5, 10, 7, 13, 4, 13, 2, 12, 10, 12, 9, 7
, 14, 5, 11, 7, 13, 7, 13, 11, 5, 14, 6, 10
};
int main()
{
int flag=0;
for(int i=83;i+1;i--)
{
flag=0;
// ans[i%42]^=ans[(i+1)%42];
for(int j=1;j<255;j++)
{

unsigned char b0=j,
b1=xo[i],b3=1,d=j;
while(1)
{
d=b1^b0;
b1&=b0;
b1*=2;
b3=b1;
b0=d;
if(b3==0)break;
}
d=b0^ans[(i+1)%42];
if(d==ans[i%42])
{
ans[i%42]=j;
flag=1;
break;
}


}
if(flag==0)printf("%2d:wrong\n",i);
}
cout<<ans;
return 0;
}

备注:注意有求与求或的无法逆向,只能暴力破拆,而且要逆向运算,但是在re里,输入的都是可见字符,所以范围可以小一点。

Enter text in Markdown. Use the toolbar above, or click the ? button for formatting help.


本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本站由 [@Zuni](http://example.com/) 创建,使用 Stellar 作为主题。