SCTF2020

刚开始接触,不会的太多了。

Reverse

Signin

题目下载下来很大,一般的exe文件都不会这么大,可以考虑是从py文件打包成的exe文件。

载入ida看一下字符串,有很多py开头的和__main__的。从经验来看,这是pyinstaller打包的。使用python pyinstxtractor.py signin.exe 还原python代码。对其中main文件进行文件头补齐,然后使用uncompyle6 -o main.py main.pyc将.pyc转化为.py文件。

但是由于这是python3.8写的py文件,如果在python3.7下使用uncompyle6会提示文件有损,使用python3.8。去升级了python3.8后。image-20200714101947068

打开py文件,程序启动会释放一个dll文件(这在运行程序的时候可以看到)。整体逻辑还是很简单,首先将一个账户以字典形式存储,然后将我们输入的name与密码传入dll文件的一个加密函数后返回,判断与存储的账户是否相等。

ida载入dll文件的enc加密函数:一个CRC64与异或。image-20200714102629777

如果之前接触过CRC64,那这里就会很简单。但是我第一次遇到,有点恼火。

首先使用python得到异或之前的key:

1
2
3
4
5
6
7
8
import base64

s = list(base64.b64decode(b'PLHCu+fujfZmMOMLGHCyWWOq5H5HDN2R5nHnlV30Q0EA'))
t = "SCTFer"
for i in range(len(s)):
s[i] ^= ord(t[i%len(t)])

print (s)

C语言写CRC64解密:

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
#include <stdio.h>

int main(void)
{
unsigned char s[] = {111, 242, 150, 253, 130, 156, 222, 181, 50, 118, 134, 121, 75, 51, 230, 31, 6, 216, 183, 61, 19, 74, 184, 227, 181, 50, 179, 211, 56, 134, 16, 2, 84};
_int64 *ans = NULL;
int i = 0, j = 0;

for(i = 0; i < 32; i += 8)
{
for(j = 0; j < 64; j++)
{
ans = (_int64 *)(s+i);
if(*ans & 1)
{
if(*ans < 0)
{
*ans ^= 0xB0004B7679FA26B3;
*ans /= 2;
*ans += 0x8000000000000000;
}
else
{
*ans ^= 0xB0004B7679FA26B3;
*ans /= 2;
}
}
else
{
if(*ans < 0)
{
*ans /= 2;
*ans += 0x8000000000000000;
}
else
*ans /= 2;
}
}
}

for(j = 0; j < 32; j++)
printf("%c", s[j]);
return 0;
}

得到flag:image-20200714103110024

总结:1.CRC64加密与解密。2.反编译python文件。

get_up

运行一下,提示输入一个word。载入ida,shift+f12看到该字符串,来到引用的地方:image-20200714150947146

进入sub_401df0:开始只是感觉复杂,但看见输入单词加密后与32位的a-f+0-9的字符串,猜测是md5加密。随便找了一个cmd5网站解密:image-20200714151246530

继续看下面的sub_402B00(“.reioc”)ke:进入可以看到是先获得image_base,然后依次加地址,直到获得.reioc节区的首地址。

最后引用输入的:sycsyc对.reioc节区进行了重写。这里使用idcpython脚本或载入OD动调都可以得到改写后的节区。

载入OD,调试可以发现重写的代码正是接下来要执行的,dump再载入ida:image-20200714152255641

可以看到与之前的类似,但这次是改写.ebata节区,使用同样的方法,OD中dump出载入ida。

进入改写.ebata后的最后一个节区:image-20200714152729970

看加密函数:image-20200714152932947

从OD动调得到表后写C语言爆破:

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
#include <stdio.h>

int od[256] = {0x00000031, 0x00000050, 0x00000052, 0x000000C1, 0x000000CD, 0x000000A7, 0x00000007, 0x00000039, 0x0000003D, 0x00000004,
0x000000FD, 0x000000C4, 0x0000002A, 0x00000072, 0x000000DF, 0x00000060, 0x000000E3, 0x000000BD, 0x000000E2, 0x00000061,
0x000000E4, 0x00000063, 0x000000EA, 0x000000FF, 0x000000FE, 0x00000009, 0x000000F9, 0x000000C3, 0x000000CE, 0x0000009E,
0x00000025, 0x0000006A, 0x0000004C, 0x000000DC, 0x00000013, 0x000000F0, 0x00000083, 0x0000003B, 0x00000024, 0x000000DB,
0x000000DD, 0x0000007F, 0x000000EF, 0x0000008C, 0x0000003E, 0x000000E1, 0x00000026, 0x0000006F, 0x00000092, 0x00000006,
0x000000F7, 0x00000096, 0x000000D0, 0x000000B4, 0x000000E7, 0x000000F8, 0x0000005F, 0x00000078, 0x000000F2, 0x000000AA,
0x00000044, 0x00000032, 0x00000036, 0x0000005A, 0x000000EC, 0x000000A6, 0x0000007B, 0x00000008, 0x000000C0, 0x0000002E,
0x0000009B, 0x00000084, 0x00000055, 0x0000009C, 0x000000AE, 0x00000065, 0x0000000A, 0x00000010, 0x00000053, 0x00000088,
0x00000049, 0x00000046, 0x000000AB, 0x0000000C, 0x0000001F, 0x00000059, 0x0000007E, 0x000000E5, 0x000000B3, 0x000000F6,
0x00000048, 0x0000001A, 0x000000D1, 0x000000A4, 0x00000067, 0x0000006B, 0x000000BA, 0x00000087, 0x00000073, 0x0000004B,
0x000000A2, 0x000000CF, 0x0000001D, 0x00000018, 0x000000D4, 0x000000BB, 0x0000002C, 0x00000070, 0x00000093, 0x000000AC,
0x0000000F, 0x0000007A, 0x00000051, 0x000000B5, 0x00000021, 0x00000085, 0x00000045, 0x00000002, 0x0000001C, 0x0000009F,
0x00000081, 0x0000005C, 0x0000004A, 0x00000095, 0x0000001B, 0x00000016, 0x000000D2, 0x000000C7, 0x000000E0, 0x000000DA,
0x00000058, 0x000000A9, 0x0000001E, 0x000000D7, 0x000000C2, 0x00000069, 0x00000071, 0x000000D6, 0x0000002D, 0x00000075,
0x000000BC, 0x00000066, 0x000000FA, 0x00000030, 0x000000AD, 0x00000099, 0x0000008B, 0x00000077, 0x00000041, 0x00000097,
0x00000022, 0x000000B8, 0x000000B2, 0x000000D3, 0x00000047, 0x000000C6, 0x00000079, 0x00000014, 0x0000000B, 0x000000F4,
0x0000003F, 0x00000011, 0x0000002B, 0x000000DE, 0x000000EE, 0x000000F3, 0x000000F5, 0x000000AF, 0x000000A5, 0x00000086,
0x00000091, 0x000000BE, 0x0000008E, 0x0000008F, 0x000000E8, 0x000000E6, 0x000000B1, 0x0000004E, 0x00000037, 0x000000D5,
0x000000FC, 0x0000004D, 0x0000005E, 0x00000042, 0x000000CA, 0x00000035, 0x000000C8, 0x0000006E, 0x000000A3, 0x00000089,
0x00000015, 0x0000006D, 0x00000003, 0x0000008A, 0x0000008D, 0x000000D8, 0x00000076, 0x000000CB, 0x000000C5, 0x000000F1,
0x0000006C, 0x000000B9, 0x00000017, 0x00000064, 0x00000068, 0x000000E9, 0x00000056, 0x00000029, 0x00000090, 0x000000ED,
0x00000074, 0x0000000D, 0x000000EB, 0x000000B0, 0x000000A1, 0x00000094, 0x00000080, 0x000000C9, 0x0000007C, 0x000000B7,
0x00000028, 0x00000005, 0x0000005B, 0x00000023, 0x0000009D, 0x000000A0, 0x00000027, 0x00000098, 0x00000043, 0x0000007D,
0x000000BF, 0x0000004F, 0x00000012, 0x00000034, 0x000000A8, 0x000000D9, 0x00000057, 0x00000033, 0x0000009A, 0x00000001,
0x00000054, 0x0000002F, 0x0000003C, 0x00000062, 0x00000038, 0x000000FB, 0x00000082, 0x0000000E, 0x0000003A, 0x00000019,
0x0000005D, 0x000000B6, 0x00000040, 0x00000020, 0x000000CC, 0x00000000};

int main(void)
{
int a[] = {0x00000080, 0x00000055, 0x0000007E, 0x0000002D, 0x000000D1, 0x00000009, 0x00000025, 0x000000AB, 0x0000003C, 0x00000056,
0x00000095, 0x000000C4, 0x00000036, 0x00000013, 0x000000ED, 0x00000072, 0x00000024, 0x00000093, 0x000000B2, 0x000000C8,
0x00000045, 0x000000EC, 0x00000016, 0x0000006B, 0x00000067, 0x0000001D, 0x000000F9, 0x000000A3, 0x00000096, 0x000000D9,
0x00000000, 0x00000000};
int v10 = 0, v11 = 0, v6 = 0, i = 0, j = 0, temp = 0;
char flag[100] = {0};

for(i = 0; i < 30; i++)
{
v11 = (v11 + 1) % 256;
v10 = (*(od + v11) + v10) % 256;
*(od + v11) = (*(od + v10) & ~*(od + v11)) | (*(od + v11) & ~*(od + v10));
*(od + v10) = (*(od + v10) & ~*(od + v11)) | (*(od + v11) & ~*(od + v10));
*(od + v11) = (*(od + v10) & ~*(od + v11)) | (*(od + v11) & ~*(od + v10));
v6 = (*(od + v10) + *(od + v11)) % 256;
for(j = 32; j < 127; j++)
{
temp = j;
temp ^= *(od + v6);

if(temp == a[i])
{

flag[i] = j;
break;
}

}
}
puts(flag);

return 0;
}

得到flag:image-20200714153241364

下面使用idcpython脚本执行来得到改写的区段,首先ctrl+s查看区段的首地址:image-20200714161123125

shift+f2输入要执行的脚本,执行:image-20200714161222707

得到改写的数据后,先u让数据未定义,再p转化为函数。image-20200714162237927

总结:多猜测,对数据的敏感性,这道题开始想到是hash简单很多。

MISC

签到题

直接挂VPN进入所给网址:image-20200720211239002

Easymisc

附件下载后是一张图片,图片名字是倒序的且打不开。

拖进010editor发现jpg图片的尾巴格式但是倒序的,结合图片名字可以知道要将图片的信息倒序,这里注意是成对的倒序还是一个一个倒序。image-20200720212540806

复制出数据的十六进制格式,写python脚本倒序写入文件:

1
2
3
4
5
6
7
8
9
import struct
s = '复制的图片的二进制信息‘
s = s[::-1]
with open('flag.jpg', "wb") as f:
for i in range(0, len(s), 2):
n = s[i]+s[i+1]
ans = struct.pack('B', int(n, 16))
f.write(ans)
f.close()

得到逆序后的文件,补齐jpg图片的文件头后打开图片:image-20200720213434806f

发现不对,看看图片属性:image-20200720213644954

最后载入010editor发现更多的信息:image-20200720213808864

最后找在线网站进行rc4解密:image-20200720213948350

doudizhu

直接玩游戏通关,有游戏体验。。哈哈

-------------本文结束感谢您的阅读-------------