Hk_Mayfly's Blog

攻防世界--hackme

字数统计: 561阅读时长: 2 min
2020/01/18 Share

测试链接:https://adworld.xctf.org.cn/media/task/attachments/33009710e3f44f04b5a4cdbaaa46f00a

准备

获取信息

  • 64位文件

IDA打开

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
__int64 __fastcall sub_400F8E(__int64 a1, __int64 a2)
{
char v3[136]; // [rsp+10h] [rbp-B0h]
int v4; // [rsp+98h] [rbp-28h]
char v5; // [rsp+9Fh] [rbp-21h]
int v6; // [rsp+A0h] [rbp-20h]
unsigned __int8 v7; // [rsp+A6h] [rbp-1Ah]
char v8; // [rsp+A7h] [rbp-19h]
int v9; // [rsp+A8h] [rbp-18h]
int v10; // [rsp+ACh] [rbp-14h]
int v11; // [rsp+B0h] [rbp-10h]
int v12; // [rsp+B4h] [rbp-Ch]
_BOOL4 v13; // [rsp+B8h] [rbp-8h]
int i; // [rsp+BCh] [rbp-4h]

sub_407470((__int64)"Give me the password: ", a2);
sub_4075A0((__int64)"%s", v3);
for ( i = 0; v3[i]; ++i )
;
v13 = i == 22;
v12 = 10;
do
{
v9 = (signed int)sub_406D90("%s", v3) % 22;
v11 = 0;
v8 = byte_6B4270[v9];
v7 = v3[v9];
v6 = v9 + 1;
v10 = 0;
while ( v10 < v6 )
{
++v10;
v11 = 1828812941 * v11 + 12345;
}
v5 = v11 ^ v7;
if ( v8 != ((unsigned __int8)v11 ^ v7) )
v13 = 0;
--v12;
}
while ( v12 );
if ( v13 )
v4 = sub_407470((__int64)"Congras\n");
else
v4 = sub_407470((__int64)"Oh no!\n");
return 0LL;
}

代码分析

这道题主要是sub_406D90函数,对于第33行代码,我们能够知道v9是0~21的整数,在这道题中,v9的在循环当中值的顺序不会影响判断,因为v9用到的地方就两个,一个在已知数组byte_6B4270和输入字符串v3的取值中,另一个在v11的循环中,因为v11最终影响的是v11^v7!=v8,又因为v7和v3[v9]有关,v8和byte_6B4270[v9]有关,因此v11,byte_6B4270[v9]和v3[v9]都应该是固定的对应关系。
我们只需要让v9的值小于22即可,通过观察byte_6B4270,我们知道byte_6B4270数组实际长度应该就是22,又通过观察第36行代码,我们能够知道这道题实际就是取10位输入的字符,异或后,与byte_6B4270比较是否相同。
我们只需要逆向操作就行。

脚本解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
index = [0x5F,0xF2,0x5E,0x8B,0x4E,0x0E,0xA3,0xAA,0xC7,0x93,0x81,0x3D,0x5F,0x74,0xA3,0x09,
0x91,0x2B,0x49,0x28,0x93,0x67]

flag = ''

for i in range(22):
v6 = i + 1
v10 = 0
v11 = 0
while v10 < v6:
v10 = v10 + 1
v11 = 1828812941 * v11 + 12345
flag += chr((index[i]^v11)&0xff)
print (flag)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>

#pragma warning(disable:4996)
using namespace std;

int main()
{
int index[] = { 0x5F,0xF2,0x5E,0x8B,0x4E,0x0E,0xA3,0xAA,0xC7,0x93,0x81,0x3D,0x5F,0x74,0xA3,0x09,
0x91,0x2B,0x49,0x28,0x93,0x67 };

for (int i = 0; i < 22; ++i) {
int v6 = i + 1;
int v10 = 0;
int v11 = 0;
while (v10 < v6) {
v10++;
v11 = 1828812941 * v11 + 12345;
}
printf("%c", index[i] ^ v11);
}

system("PAUSE");
return 0;
}

get flag!

flag{d826e6926098ef46}

CATALOG
  1. 1. 准备
  2. 2. IDA打开
  3. 3. 代码分析
  4. 4. 脚本解密
  5. 5. get flag!