ida打开,main函数是sub_5B4270,没加混淆,但是main函数调用的其他计算函数都加了混淆(大概看了下,与Archaia战队在前几次比赛中用的差不多,难搞)
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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/
/
bad sp value at call has been detected, the output may be wrong!
int
__cdecl main(
int
argc, const char
*
*
argv, const char
*
*
envp)
{
/
/
[COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL
-
"+"
TO EXPAND]
memset(v70,
0
,
0x1C2u
);
memset(v69,
0
, sizeof(v69));
qmemcpy(v116,
"abcdefgh"
, sizeof(v116));
memset(name,
0
,
0x32u
);
*
(_DWORD
*
)
Buffer
=
0
;
v406
=
0
;
v207
=
0
;
v208
=
0
;
v209
=
0
;
v210
=
0
;
v326
=
0
;
v327
=
0
;
v328
=
0
;
printf(&
Format
);
/
/
"请输入用户名:\n"
gets((
int
)name);
v390
=
name;
v293
=
&name[
1
];
v390
+
=
strlen(v390);
v289
=
+
+
v390
-
&name[
1
];
Value
=
sub_5AE2D3(name, v390
-
&name[
1
]);
itoa(Value,
Buffer
,
16
);
sub_5AD9F9(v116,
Buffer
, &v207, &v326);
*
(_DWORD
*
)v70
=
v207;
*
(_DWORD
*
)&v70[
4
]
=
v208;
*
(_DWORD
*
)v69
=
v326;
*
(_DWORD
*
)&v69[
4
]
=
v327;
qmemcpy(v115,
"ijklmnop"
, sizeof(v115));
v231
=
0
;
v232
=
0
;
v233
=
0
;
v234
=
0
;
v323
=
0
;
v324
=
0
;
v325
=
0
;
...
sub_593D03(v126,
Buffer
, v77, v277);
qmemcpy(v127,
"abcdefgh"
, sizeof(v127));
memset(v76,
0
, sizeof(v76));
v275[
0
]
=
0
;
v275[
1
]
=
0
;
v276
=
0
;
sub_5937B3(v127,
Buffer
, v76, v275);
memset(v365,
0
, sizeof(v365));
v366
=
0
;
v3
=
sub_5AE2D3(v69,
192
);
sprintf(v365,
"%08x"
, v3);
/
/
v365
v401[
0
]
=
0
;
v401[
1
]
=
0
;
v402
=
0
;
v403
=
0
;
v404
=
0
;
v391[
0
]
=
0
;
v391[
1
]
=
0
;
v392
=
0
;
v393
=
0
;
v394
=
0
;
sub_592CB9(v70, v365, v401);
v368
=
malloc(
8u
);
v4
=
v368;
v5
=
v403;
*
v368
=
v402;
v4[
1
]
=
v5;
sub_592CB9(&v70[
9
], v401, v391);
...
v44
=
malloc(
8u
);
v387
=
v44;
v45
=
v403;
*
v44
=
v402;
v44[
1
]
=
v45;
sub_592CB9(&v70[
189
], v401, v391);
/
/
here, v391
is
the correct serial
v44
=
malloc(
8u
);
v387
=
v44;
v45
=
v403;
*
v44
=
v402;
v44[
1
]
=
v45;
sub_592CB9(&v70[
189
], v401, v391);
memset(serial,
0
, sizeof(serial));
v288
=
0
;
memset(v399,
0
, sizeof(v399));
v400
=
0
;
memset(v395,
0
, sizeof(v395));
v396
=
0
;
v397
=
0
;
v398
=
0
;
printf(&byte_5D0848);
/
/
"请输入序列号:\n"
gets((
int
)serial);
v389
=
serial;
v291
=
&serial[
1
];
v389
+
=
strlen(v389);
v292
=
+
+
v389
-
&serial[
1
];
if
( v389
-
&serial[
1
]
=
=
16
)
{
sub_592C10(&v70[
189
], v399, serial);
v47
=
v387[
1
];
*
(_DWORD
*
)&v399[
8
]
=
*
v387;
*
(_DWORD
*
)&v399[
12
]
=
v47;
...
sub_592C10(&v70[
9
], v399, v395);
v67
=
v368[
1
];
*
(_DWORD
*
)&v399[
8
]
=
*
v368;
*
(_DWORD
*
)&v399[
12
]
=
v67;
sub_592C10(v70, v395, v399);
for
( i
=
0
; i <
8
;
+
+
i )
{
if
( v395[i] !
=
v365[i] )
{
printf(&fail_1);
/
/
"登录失败!\n"
system(aPause_0);
return
0
;
}
}
printf(&success);
/
/
"登录成功!\n"
system(aPause_1);
return
0
;
}
else
{
printf(&fail_2);
/
/
"登录失败!\n"
system(Command);
return
0
;
}
}
修正函数签名后,交叉引用的查找也会变得更准。“登录成功”的条件是v395和v365相等,对v365查找交叉引用可以定位到上面的sprintf,是从name计算出来的一个值;v395则是从serial计算出来的一个值。
观察代码,发现v70变量贯穿了大部分代码。
在输入serial之前以v365为初始值正向遍历v70进行了22次迭代计算得到v391;在输入serial之后以serial为初始值反向遍历v70进行了22次迭代计算得到v395。
这两块计算给人感觉很像互逆的。输入公开的name,尝试在0x5B6364下断点查看正向迭代22次后的v391,发现此处的v391正好就是公开的serial。