[TOC]

easy_pyc

很简单的py逆向题,用uncompyle6反编译出源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# uncompyle6 version 3.9.0
# Python bytecode version base 2.7 (62211)
# Decompiled from: Python 3.9.11 (tags/v3.9.11:2de452f, Mar 16 2022, 14:33:45) [MSC v.1929 64 bit (AMD64)]
# Embedded file name: enpyc.py
# Compiled at: 2023-03-29 18:30:23
print 'Welcome to CTFshow Re!'
print 'your flag is here!'
flag = ''
l = len(flag)
for i in range(l):
num = ((flag[i] + i) % 114514 + 114514) % 114514
code += chr(num)

code = map(ord, code)
for i in range(l - 4 + 1):
code[i] = code[i] ^ code[i + 1]

print code
code = ['\x16', '\x1d', '\x1e', '\x1a', '\x18', '\t', b'\xff', b'\xd0', ',', '\x03',
'\x02', '\x14', '8', 'm', '\x01', 'C', 'D', b'\xbd', b'\xf7', '*', '\r',
b'\xda', b'\xf9', '\x1c', '&', '5', "'", b'\xda', b'\xd4', b'\xd1', '\x0b',
b'\xc7', b'\xc7', '\x1a', b'\x90', 'D', b'\xa1']

flag逐位加上其位置模114514然后与后一位异或得code,code已知。该说不说,模数真臭
需要注意的是有几位不用异或
##exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
code = ['0x16', '0x1d', '0x1e', '0x1a', '0x18', '0x09', '0xff', '0xd0', '0x2c', '0x03', 
'0x02', '0x14', '0x38', '0x6d', '0x01', '0x43', '0x44', '0xbd', '0xf7', '0x2a', '0x0d',
'0xda', '0xf9', '0x1c', '0x26', '0x35', '0x27', '0xda', '0xd4', '0xd1', '0x0b',
'0xc7', '0xc7', '0x1a', '0x90', '0x44', '0xa1']

code_int = [int(x, 16) for x in code]
print(code_int)

for i in range(len(code_int)-4,0,-1):
code_int[i] ^= code_int[i+1]
code_int[0] ^= code_int[1]
print(code_int)
flag=''
for i in range(len(code_int)):
code_int[i] = (code_int[i] - i) % 114514
flag += chr(code_int[i])
print (flag)

flagctfshow{Just_F00l's_D@y_R3_Ch3ck-in!}

easy_cc

一开始想复杂了
查壳是32位无壳,直接 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
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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // esi
FILE *v4; // eax
size_t v5; // eax
unsigned int v6; // ecx
unsigned int v7; // kr00_4
unsigned int v8; // kr04_4
unsigned int v9; // esi
unsigned int v10; // kr08_4
char *v11; // ebx
unsigned int v12; // esi
int v13; // eax
int v15; // [esp-4h] [ebp-20Ch]
char v16[204]; // [esp+0h] [ebp-208h] BYREF
char v17[204]; // [esp+CCh] [ebp-13Ch] BYREF
char Buffer[100]; // [esp+198h] [ebp-70h] BYREF
char v19[8]; // [esp+1FCh] [ebp-Ch] BYREF

strcpy(v19, "key123");
sub_401010("请输入您的flag: ", v16[0]);
v4 = _acrt_iob_func(0);
fgets(Buffer, 100, v4);
v5 = strcspn(Buffer, "\n");
if ( v5 >= 0x64 )
goto LABEL_16;
v15 = v3;
Buffer[v5] = 0;
v6 = 0;
v7 = strlen(Buffer);
if ( v7 )
{
v8 = strlen(v19);
do
{
v17[v6] = Buffer[v6] ^ v19[v6 % v8];
++v6;
}
while ( v6 < v7 );
if ( v6 >= 0xC9 )
goto LABEL_16;
}
v17[v6] = 0;
v9 = 0;
v10 = strlen(v17);
if ( v10 )
{
v11 = v16;
do
{
sub_401040(v11, "%02x", v17[v9++]);
v11 += 2;
}
while ( v9 < v10 );
}
v12 = 2 * v9;
if ( v12 >= 0xC9 )
{
LABEL_16:
__report_rangecheckfailure(v15);
__debugbreak();
}
v16[v12] = 0;
sub_401010("\n", v15);
v13 = strcmp(v16, "08111f425a5c1c1e1a526d410e3a1e5e5d573402165e561216");
if ( v13 )
v13 = v13 < 0 ? -1 : 1;
if ( v13 )
sub_401010("flag is false: ", v16[0]);
else
sub_401010("flag is true: ", v16[0]);
system("pause");
return 0;
}

大致加密逻辑就是flag逐位异或v19,v19就是异或值为key123
然后把异或的结果转换成16进制,最终得到08111f425a5c1c1e1a526d410e3a1e5e5d573402165e561216

exp

1
2
3
4
5
6
7
hexstring = '08111f425a5c1c1e1a526d410e3a1e5e5d573402165e561216'
hexlist = [int (hexstring[i:i+2], 16) for i in range (0,len(hexstring), 2)]
key = 'key123'
flag = ''
for i in range(len(hexlist)):
flag += chr(hexlist[i] ^ ord(key[i % len(key)]))
print(flag)

flagctfshow{cc_re_good_good!}

easy_re

32位无壳,拖进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
int __cdecl main(int argc, const char **argv, const char **envp)
{
int v3; // ebx
int v4; // ecx
unsigned int v5; // edi
unsigned int v6; // kr00_4
int v8; // [esp-4h] [ebp-414h]
int v9; // [esp+10h] [ebp-400h]
int v10; // [esp+18h] [ebp-3F8h] BYREF
int v11; // [esp+1Ch] [ebp-3F4h] BYREF
char v12[1004]; // [esp+20h] [ebp-3F0h] BYREF

sub_401460();
sub_401700(v12);
sub_401460();
std::istream::operator>>(std::cin, &v10);
std::istream::operator>>(std::cin, &v11);
v3 = v10 % 299;
v4 = v11 % 299;
v5 = 0;
v9 = v11 % 299;
v6 = strlen(v12);
if ( v6 )
{
do
{
v8 = dword_403AA0[300 * v3 + v4] ^ v12[v5];
v3 = (v8 + v3) % 299;
v9 = (v8 + v9) % 300;
std::ostream::operator<<(std::cout, v8);
sub_401460();
v4 = v9;
++v5;
}
while ( v5 < v6 );
}
sub_401460();
return 0;
}

只看得出来是个300*300的一个数组
记住403AA0地址是从28A0到5A6E3
尝试用x32dbg看看
img
也就是说用两个300以内数字去加密一段话
可以得到后面一大串的数字,尝试直接枚举出这两个key
利用flag的base64值是’ZmxhZ’来判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from base64 import *
from pwn import u32

def decrypt(k1,k2,cipher):
tk1,tk2 = k1,k2
m = []
for v8 in cipher[::-1]:
k1 = (k1-v8)%299
k2 = (k2-v8)%300
m.append(d_3aa0[300*k1+k2] ^ v8)
base64_text = bytes(m[::-1])
if base64_text[:5]==b'ZmxhZ':
flag=b64decode(base64_text).decode('utf-8')
print(base64_text,tk1,tk2,'\n',flag)

flag=''
data = open('re1.exe', 'rb').read()[0x28a0: 0x5a6e0]
d_3aa0 = [u32(data[i:i+4]) for i in range(0, len(data), 4)]
a = [90,171,198,235,229,43,246,92,198,203,233,228,6,128,215,68,201,4,220,214,169,245,208,199,112,170,119,251,244,58,237,4,70,231,200,45,186,137,247,225,243,13,145,139,190,146,194,242,253,56,239,5,41,225,105,51,247,79,170,231,88,64,224,138,222,220,229,88,43,117,236,189,228,205,150,65,26,205,232,141,116,149,185,89,212,251,16,215,205,17,238,22,245,77,220,198,224,248,223,209,205,167,223,210,165,247,190,3,5,246,243,228,181,33,42,207,174,138,244,118,192,22,219,60,80,229,144,219,133,211,221,229,190,58,151,240,183,207,221,60,77,217,220,74,105,220,221,165,85,174,43,183,188,190,252,255,130,137,189,201,239,181,150,143,214,203,26,211,103,222,105,87,214,179,83,185,104,206,229,172,221,117,163,57,106,200,46,165,193,135,243,166,168,209,144,52,210,12,58,10,103,5,211,55,172,76,88,250,136,245,167,139,241,26,92,97,139,241,137,27,53,211,251,191,240,173,14,231,241,242,255,122,144,97,234,36,175,155,253,35,156,229,19,166,191,140,195,218,130,35,200,178,245,41,162,243,214,222,87,83,195,144,55,159,208,241,193,233,204,228,196,105,84,58,220,226,1,47,248,138,177,124,236,53,210,79,250,106,27,244,251,203,210,103,213,218,183,4,40,28,12,175,52,224,203,89,176,174,175,233,43,20,103,152,201,4,148,76,241,103,135,139,136,246,80,184,255,194,149,239,206,207,246,166,20,63,202,199,177,214,60,99,74,211,219,94,247,193,40,212,197,175,30,244,41,24,113,27,249,213,225,55,188,193,165,220,174,252,105,154,74,126,174,255,110,169,103,44,246,255,98,251,211,87,171,62,67,250,69,149,18,77,159,137,168,231,187,97,174,115,243,44,128,151,90,246,83,11,138,67,184,22,53,228,230,252,76,112,20,136,131,90,233,248,67,207,61,212,113,62,239,203,201,66,83,179,16,209,253,63,206,208,101,150,196,145,101,220,22,79,241,69,237,219,97,87,20,22,240,244,218,7,237,42,14,8,38,115,141,102,206,191,142,55,196,200,142,98,16,129,53,52,50,197,53,219,2,66,152,192,245,243,69,26,132,240,164,90,246,200,53,89,221,119,139,76,47,132,53,47,249,26,53,141,113,69,76,152,121,193,53,176,97,135,205,206,237,108,251,38,216,108,12,220,209,194,26,243,217,231,36,117,235,106,205,43,254,75,209,141,239,200,5,183,219,166,113,9,16,154,116,144,238,208,245,136,173,16,103,107,114,17,208,181,196,98,212,133,211,252]

for k1 in range(299):
for k2 in range(300):
decrypt(k1,k2,a)

运行结果
img
提示研究一下加密矩阵,尝试把d_3aa0中的元素输出来发现很像RGB值,尝试转化成图片。最后输出
img
flagctfshow{d244daeb-7182-4c98-bec6-0c99329ab71f}

exp

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
from base64 import *
from pwn import u32

def decrypt(k1,k2, cipher):
tk1,tk2 = k1,k2
m = []
for v8 in cipher[::-1]:
k1 = (k1-v8)%299
k2 = (k2-v8)%300
m.append(d_3aa0[300*k1+k2] ^ v8)
base64_text = bytes(m[::-1])
if base64_text[:5]==b'ZmxhZ':
flag=b64decode(base64_text).decode('utf-8')
print(base64_text,tk1,tk2,'\n',flag)

flag=''
data = open('re1.exe', 'rb').read()[0x28a0: 0x5a6e0]
d_3aa0 = [u32(data[i:i+4]) for i in range(0, len(data), 4)]
a = [90,171,198,235,229,43,246,92,198,203,233,228,6,128,215,68,201,4,220,214,169,245,208,199,112,170,119,251,244,58,237,4,70,231,200,45,186,137,247,225,243,13,145,139,190,146,194,242,253,56,239,5,41,225,105,51,247,79,170,231,88,64,224,138,222,220,229,88,43,117,236,189,228,205,150,65,26,205,232,141,116,149,185,89,212,251,16,215,205,17,238,22,245,77,220,198,224,248,223,209,205,167,223,210,165,247,190,3,5,246,243,228,181,33,42,207,174,138,244,118,192,22,219,60,80,229,144,219,133,211,221,229,190,58,151,240,183,207,221,60,77,217,220,74,105,220,221,165,85,174,43,183,188,190,252,255,130,137,189,201,239,181,150,143,214,203,26,211,103,222,105,87,214,179,83,185,104,206,229,172,221,117,163,57,106,200,46,165,193,135,243,166,168,209,144,52,210,12,58,10,103,5,211,55,172,76,88,250,136,245,167,139,241,26,92,97,139,241,137,27,53,211,251,191,240,173,14,231,241,242,255,122,144,97,234,36,175,155,253,35,156,229,19,166,191,140,195,218,130,35,200,178,245,41,162,243,214,222,87,83,195,144,55,159,208,241,193,233,204,228,196,105,84,58,220,226,1,47,248,138,177,124,236,53,210,79,250,106,27,244,251,203,210,103,213,218,183,4,40,28,12,175,52,224,203,89,176,174,175,233,43,20,103,152,201,4,148,76,241,103,135,139,136,246,80,184,255,194,149,239,206,207,246,166,20,63,202,199,177,214,60,99,74,211,219,94,247,193,40,212,197,175,30,244,41,24,113,27,249,213,225,55,188,193,165,220,174,252,105,154,74,126,174,255,110,169,103,44,246,255,98,251,211,87,171,62,67,250,69,149,18,77,159,137,168,231,187,97,174,115,243,44,128,151,90,246,83,11,138,67,184,22,53,228,230,252,76,112,20,136,131,90,233,248,67,207,61,212,113,62,239,203,201,66,83,179,16,209,253,63,206,208,101,150,196,145,101,220,22,79,241,69,237,219,97,87,20,22,240,244,218,7,237,42,14,8,38,115,141,102,206,191,142,55,196,200,142,98,16,129,53,52,50,197,53,219,2,66,152,192,245,243,69,26,132,240,164,90,246,200,53,89,221,119,139,76,47,132,53,47,249,26,53,141,113,69,76,152,121,193,53,176,97,135,205,206,237,108,251,38,216,108,12,220,209,194,26,243,217,231,36,117,235,106,205,43,254,75,209,141,239,200,5,183,219,166,113,9,16,154,116,144,238,208,245,136,173,16,103,107,114,17,208,181,196,98,212,133,211,252]

for k1 in range(299):
for k2 in range(300):
decrypt(k1,k2,a)

from PIL import Image

img = Image.new('RGB', (300, 300))
pixels = img.load()

for i in range(299):
for j in range(300):
pixels[i, j] = d_3aa0[i * 300 + j]
img = img.transpose(Image.FLIP_LEFT_RIGHT).rotate(90)
img.save('a.png')
img.show()

参考