W4ntY0u每日训练

First Post:

Last Update:

5.3

xctf:流浪者

一道mfc的逆向,ida打开,利用字符串定位关键函数

image-20230503202224316

定位到sub_4017F0函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __cdecl sub_4017F0(int a1)
{
char Str1[28]; // [esp+D8h] [ebp-24h] BYREF
int v3; // [esp+F4h] [ebp-8h]
int v4; // [esp+F8h] [ebp-4h]

v4 = 0;
v3 = 0;
while ( *(a1 + 4 * v4) <= 0x3Du )
{
Str1[v4] = aAbcdefghiabcde[*(a1 + 4 * v4)];
++v4;
}
Str1[v4] = 0;
if ( !strcmp(Str1, "KanXueCTF2019JustForhappy") )
return sub_401770();
else
return sub_4017B0();
}

主要逻辑就是一个置换加密,再交叉引用查看谁调用了他

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
int __thiscall sub_401890(CWnd *this)
{
CWnd *DlgItem; // eax
int v2; // eax
struct CString *v4; // [esp-4h] [ebp-C4h]
int v5[26]; // [esp+4Ch] [ebp-74h] BYREF
int i; // [esp+B4h] [ebp-Ch]
char *Str; // [esp+B8h] [ebp-8h]
CWnd *v8; // [esp+BCh] [ebp-4h]

v8 = this;
v4 = (this + 100);
DlgItem = CWnd::GetDlgItem(this, 1002);
CWnd::GetWindowTextA(DlgItem, v4);
v2 = sub_401A30(v8 + 100);
Str = CString::GetBuffer((v8 + 100), v2);
if ( !strlen(Str) )
return CWnd::MessageBoxA(v8, &byte_4035DC, 0, 0);
for ( i = 0; Str[i]; ++i )
{
if ( Str[i] > '9' || Str[i] < '0' )
{
if ( Str[i] > 'z' || Str[i] < 'a' )
{
if ( Str[i] > 'Z' || Str[i] < 'A' )
sub_4017B0();
else
v5[i] = Str[i] - '\x1D';
}
else
{
v5[i] = Str[i] - 'W';
}
}
else
{
v5[i] = Str[i] - '0';
}
}
return sub_4017F0(v5);
}

可以看到对输入的字符进行了三次判断,如果不在该判断范围内,直接错误

那么逆向脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
KanXue = "KanXueCTF2019JustForhappy"
abcdef = "abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ"
SomeDwordArray = []
Key = ""

for i in range(len(KanXue)):
SomeDwordArray.append(abcdef.find(KanXue[i]))

print("SomeDwordArray =", SomeDwordArray)

for dw in SomeDwordArray:
if dw <= 9 and dw >= 0:
Key += chr(dw + ord('0'))
elif dw + ord('W') >= ord('a') and dw + ord('W') <= ord('z'):
Key += chr(dw + ord('W'))
else:
Key += chr(dw + 0x1D)

print(Key)
#j0rXI4bTeustBiIGHeCF70DDM

re2-cpp-is-awesome

main函数:

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
__int64 __fastcall main(int a1, char **a2, char **a3)
{
char *v3; // rbx
__int64 v4; // rax
__int64 v5; // rdx
__int64 v6; // rax
__int64 v7; // rdx
_BYTE *v8; // rax
__int64 v10[2]; // [rsp+10h] [rbp-60h] BYREF
char v11[47]; // [rsp+20h] [rbp-50h] BYREF
char v12; // [rsp+4Fh] [rbp-21h] BYREF
__int64 v13; // [rsp+50h] [rbp-20h] BYREF
int v14; // [rsp+5Ch] [rbp-14h]

if ( a1 != 2 )
{
v3 = *a2;
v4 = std::operator<<<std::char_traits<char>>(&std::cout, "Usage: ", a3);
v6 = std::operator<<<std::char_traits<char>>(v4, v3, v5);
std::operator<<<std::char_traits<char>>(v6, " flag\n", v7);
exit(0);
}
std::allocator<char>::allocator(&v12, a2, a3);
std::string::basic_string(v11, a2[1], &v12);
std::allocator<char>::~allocator(&v12);
v14 = 0;
v10[0] = std::string::begin(v11);
while ( 1 )
{
v13 = std::string::end(v11);
if ( !sub_400D3D(v10, &v13) )
break;
v8 = sub_400D9A(v10);
if ( *v8 != off_6020A0[dword_6020C0[v14]] )
sub_400B56();
++v14;
sub_400D7A(v10);
}
sub_400B73();
std::string::~string(v11);
return 0LL;
}

前面的逻辑还算不少,但是关键是最后的比较,直接用了明文,所以前面就都不用管了,直接逆向最后的比较

先idc爬数据:

1
2
3
4
5
6
7
auto addr = 0x00006020C0;
auto i = 0;
for(i; addr+i < 0x060213C; i = i+4)
{
Message("%d,",Byte(addr+i));
//PatchByte(addr+i,Byte());
}

脚本:

1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
int main()
{
char a[] = "L3t_ME_T3ll_Y0u_S0m3th1ng_1mp0rtant_A_{FL4G}_W0nt_b3_3X4ctly_th4t_345y_t0_c4ptur3_H0wev3r_1T_w1ll_b3_C00l_1F_Y0u_g0t_1t";
int b[] = { 36,0,5,54,101,7,39,38,45,1,3,0,13,86,1,3,101,3,45,22,2,21,3,101,0,41,68,68,1,68,43, };
for (int i = 0; i < 31; ++i)
{
printf("%c", a[b[i]]);
}
return 0;
}

5.4

whats-the-hell-500

题目直接给了源码了,vs打开:(真抽象)

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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "somelib.hxx"
#include <iostream>
#include <cstdlib>

void error()
{
std::cout << "Wrong password" << std::endl;
std::exit(-1);
}

int pow(int x, int n)
{
int ret(1);
for (int i = 1; i <= n; ++i)
ret *= x;
return ret;
}

void check_password(std::string& p)
{
if (p.size() != 13)
{
std::cout << "Password must be 13 characters" << std::endl;
std::exit(-1);
}

if (p[0]+p[1] != pow(I-----I,2) * pow(I-----------I,2) + (I---I)) error();

if (p[1]+p[2] != pow(I-------I,2) * pow(I-----I,4) - (I---I)) error();

if (p[0]*p[2] != (pow(pow(I-------I,2) * pow(I-----I,3) - (I---I),2) - (I-----I)*(I-------I))) error();

if (p[3]+p[5] != pow((o-------o
| !
! !
! !
o-------o).A,2) * (I-----I)+(I---I)) error();

if (p[3]+p[4] != pow((o-----------o
| !
! !
! !
o-----------o).A,2)+(I---I)) error();

if (p[4]*p[5] != (pow((o-------------o
| !
! !
! !
o-------------o).A,2)-(I---I))*(I-----I)*pow(I-------I,2)) error();

if (p[7]+p[8] != (o-----------o
|L \
| L \
| L \
| o-----------o|!
o | !
L | !
L | !
L| !
o-----------o).V*pow(I-----I,2) - pow((o-------o
| !
! !
o-------o).A,2) + (I---I)) error();

if (p[6]+p[8] != (o-----------o
|L \
| L \
| L \
| L \
| L \
| o-----------o
| ! !
o | !
L | !
L | !
L | !
L | !
L| !
o-----------o).V - (I-----I)) error();

if (p[6]*p[7] != (o---------------------o
|L \
| L \
| L \
| L \
| L \
| L \
| L \
| L \
| o---------------------o
| ! !
! ! !
o | !
L | !
L | !
L | !
L | !
L | !
L | !
L | !
L| !
o---------------------o).V*(pow(I-------I,2) + (I-----I)) + pow(I-----I,6)) error();

if (p[9]+p[10]*p[11] != (o---------o
|L \
| L \
| L \
| L \
| o---------o
| ! !
! ! !
o | !
L | !
L | !
L | !
L| !
o---------o).V*(I-------I)*pow(I-----I,4)-(I---I)) error();

if (p[10]+p[9]*p[11] != (o-----------o
|L \
| L \
| L \
| L \
| L \
| o-----------o
| ! !
o | !
L | !
L | !
L | !
L | !
L| !
o-----------o).V*pow(I-------I,3) - (I-----------I)*((I-----I)*(I-----------I)+(I---I))) error();

if (p[9]+p[10] != (o-------------o
|L \
| L \
| L \
| L \
| L \
| o-------------o
| ! !
o | !
L | !
L | !
L | !
L | !
L| !
o-------------o).V-(I-----------I)) error();

if (p[12] != 'w') error();
}

int main()
{
std::cout << "Guess passwd" << std::endl;
std::string password;
std::cin >> password;
check_password(password);
std::cout << "Correct password! It's your flag, bruh" << std::endl;
}

这个是调用了一个cxx的库,稍微google一下,可以大概了解到那一坨抽象的东西是等于一个数的,要么继续学怎么计算,这个时候gpt-4就挺好用的了(3.5是傻子),得到12个的结果,然后直接爆破:

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
#0-2
flag = ''
for i in range(0x20, 0x7f):
for j in range(0x20, 0x7f):
for k in range(0x20, 0x7f):
if i+j == 101 and j+k==143 and i*k==5035:
flag += chr(i)+chr(j)+chr(k)
print('['+chr(i)+chr(j)+chr(k) + ']')
#50_
#3-5
for i in range(0x20, 0x7f):
for j in range(0x20, 0x7f):
for k in range(0x20, 0x7f):
if i+j == 226 and i+k==163 and j*k==5814:
flag += chr(i)+chr(j)+chr(k)
print('['+chr(i)+chr(j)+chr(k) + ']')
#pr3
for i in range(0x20, 0x7f):
for j in range(0x20, 0x7f):
for k in range(0x20, 0x7f):
if j+k == 205 and i+k==173 and i*j==9744:
flag += chr(i)+chr(j)+chr(k)
print('['+chr(i)+chr(j)+chr(k) + ']')
#Tty
for i in range(0x20, 0x7f):
for j in range(0x20, 0x7f):
for k in range(0x20, 0x7f):
if i+j*k == 5375 and j+i*k==4670 and i+j==205:
flag += chr(i)+chr(j)+chr(k)
print('['+chr(i)+chr(j)+chr(k) + ']')
#_n0
flag +='w'
print(flag)


easyRE

main函数:

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
__int64 sub_4009C6()
{
__int64 result; // rax
int i; // [rsp+Ch] [rbp-114h]
__int64 v2; // [rsp+10h] [rbp-110h]
__int64 v3; // [rsp+18h] [rbp-108h]
__int64 v4; // [rsp+20h] [rbp-100h]
__int64 v5; // [rsp+28h] [rbp-F8h]
__int64 v6; // [rsp+30h] [rbp-F0h]
__int64 v7; // [rsp+38h] [rbp-E8h]
__int64 v8; // [rsp+40h] [rbp-E0h]
__int64 v9; // [rsp+48h] [rbp-D8h]
__int64 v10; // [rsp+50h] [rbp-D0h]
__int64 v11; // [rsp+58h] [rbp-C8h]
char v12[13]; // [rsp+60h] [rbp-C0h] BYREF
char v13[4]; // [rsp+6Dh] [rbp-B3h] BYREF
char v14[19]; // [rsp+71h] [rbp-AFh] BYREF
char v15[32]; // [rsp+90h] [rbp-90h] BYREF
int v16; // [rsp+B0h] [rbp-70h]
char v17; // [rsp+B4h] [rbp-6Ch]
char v18[72]; // [rsp+C0h] [rbp-60h] BYREF
unsigned __int64 v19; // [rsp+108h] [rbp-18h]

v19 = __readfsqword(0x28u);
qmemcpy(v12, "Iodl>Qnb(ocy", 12);
v12[12] = 127;
qmemcpy(v13, "y.i", 3);
v13[3] = 127;
qmemcpy(v14, "d`3w}wek9{iy=~yL@EC", sizeof(v14));
memset(v15, 0, sizeof(v15));
v16 = 0;
v17 = 0;
sub_4406E0(0, v15, 37LL);
v17 = 0;
if ( (sub_424BA0)(v15) == 36 )
{
for ( i = 0; i < (sub_424BA0)(v15); ++i )
{
if ( (v15[i] ^ i) != v12[i] )
{
result = 4294967294LL;
goto LABEL_13;
}
}
sub_410CC0("continue!");
memset(v18, 0, 65);
sub_4406E0(0, v18, 64LL);
v18[39] = 0;
if ( (sub_424BA0)(v18) == 39 )
{
v2 = sub_400E44(v18);
v3 = sub_400E44(v2);
v4 = sub_400E44(v3);
v5 = sub_400E44(v4);
v6 = sub_400E44(v5);
v7 = sub_400E44(v6);
v8 = sub_400E44(v7);
v9 = sub_400E44(v8);
v10 = sub_400E44(v9);
v11 = sub_400E44(v10);
if ( !sub_400360(v11, off_6CC090) )
{
sub_410CC0("You found me!!!");
sub_410CC0("bye bye~");
}
result = 0LL;
}
else
{
result = 4294967293LL;
}
}
else
{
result = 0xFFFFFFFFLL;
}
LABEL_13:
if ( __readfsqword(0x28u) != v19 )
sub_444020();
return result;
}

v15存输入的内容,第一段就是将输入异或下标后与已知的v12数组比较(ida分析错了,v12,v13,v14应该是一个数组,地址连在一起的)

脚本解密:

1
2
3
4
5
6
7
8
9
10
arr = [73,111,100,108,62,81,110,98,40,111,99,121,127,121,46,105,127,100,96,51,119,125,
119,101,107,57,123,105,121,61,126,121,76,64,69,67]

dec = ''
for i in range(36):
dec += chr(arr[i]^i)

print(dec)

#Info:The first four chars are flag``

第二次输入,进行了10次base64加密,解密即可:

1
2
3
4
5
enc = "Vm0wd2VHUXhTWGhpUm1SWVYwZDRWVll3Wkc5WFJsbDNXa1pPVlUxV2NIcFhhMk0xVmpKS1NHVkdXbFpOYmtKVVZtcEtTMUl5VGtsaVJtUk9ZV3hhZVZadGVHdFRNVTVYVW01T2FGSnRVbGhhVjNoaFZWWmtWMXBFVWxSTmJFcElWbTAxVDJGV1NuTlhia0pXWWxob1dGUnJXbXRXTVZaeVdrWm9hVlpyV1hwV1IzaGhXVmRHVjFOdVVsWmlhMHBZV1ZSR1lWZEdVbFZTYlhSWFRWWndNRlZ0TVc5VWJGcFZWbXR3VjJKSFVYZFdha1pXWlZaT2NtRkhhRk5pVjJoWVYxZDBhMVV3TlhOalJscFlZbGhTY1ZsclduZGxiR1J5VmxSR1ZXSlZjRWhaTUZKaFZqSktWVkZZYUZkV1JWcFlWV3BHYTFkWFRrZFRiV3hvVFVoQ1dsWXhaRFJpTWtsM1RVaG9hbEpYYUhOVmJUVkRZekZhY1ZKcmRGTk5Wa3A2VjJ0U1ExWlhTbFpqUldoYVRVWndkbFpxUmtwbGJVWklZVVprYUdFeGNHOVhXSEJIWkRGS2RGSnJhR2hTYXpWdlZGVm9RMlJzV25STldHUlZUVlpXTlZadE5VOVdiVXBJVld4c1dtSllUWGhXTUZwell6RmFkRkpzVWxOaVNFSktWa1phVTFFeFduUlRhMlJxVWxad1YxWnRlRXRXTVZaSFVsUnNVVlZVTURrPQ=="

for i in range(10):
enc = enc.decode('base64')
print (enc)

接下来又是两段异或,第一段可以通过已知的flag反向解出v5,第二段异或根据已知数组和v5异或解出flag

1
2
3
4
5
6
7
8
9
10
11
12
13
key = ''
enc1 = 'flag'
dec = ''
enc = [0x40,0x35,0x20,0x56,0x5D,0x18,0x22,0x45,0x17,0x2F,0x24,0x6E,0x62,0x3C,0x27,0x54,0x48,0x6C,0x24,0x6E,0x72,0x3C,0x32,0x45,0x5B]
for i in range(4):
key += chr(enc[i] ^ ord(enc1[i]))
print (key)

for i in range(len(enc)):
dec += chr(enc[i] ^ ord(key[i%4]))
print(dec)

#flag{Act1ve_Defen5e_Test}

5.5

[CISCN 2022 东北]easycpp

今年的全国大学生信息安全竞赛快开了,做做往年的题

这个应该是一个签到

主程序逻辑非常简单,直接上脚本:

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>
using namespace std;

unsigned char miwen[] =
{
0x0A, 0x0B, 0x7D, 0x2F, 0x7F, 0x67, 0x65, 0x30, 0x63, 0x60,
0x37, 0x3F, 0x3C, 0x3F, 0x33, 0x3A, 0x3C, 0x3B, 0x35, 0x3C,
0x3E, 0x6C, 0x64, 0x31, 0x64, 0x6C, 0x3B, 0x68, 0x61, 0x62,
0x65, 0x36, 0x33, 0x60, 0x62, 0x36, 0x1C, 0x7D
};
int main()
{
for (int i = 37; i >=3; i--)
{
miwen[i-1] ^= miwen[i];
miwen[i-2] ^= miwen[i-1];
miwen[i-3] ^= miwen[i-2];
}
for (int i = 0; i < 38; i++)
{
printf("%c", miwen[i]);
}
return 0;
}

AnCTFxD^3CTF:d3sky

还是没看汇编的习惯,人家悄悄把密钥变了都没发现

首先是一个tls反调试,修改标志位跳过,接着就不能看f5的伪代码了,看汇编:

image-20230505192948632

可以看到有try,except的代码,说明程序通过异常来控制执行流程,其中就有一个除零异常,但是按理来说动调时候应该是会触发的,但是没有(这里我还没有完全看明白,大概猜测还是与在调试的状态有关),那么先假设他触发了除零异常了,接下来就会跳转到loc_6310EF那里继续执行,在密钥后面又加上了一个字符串(这才是真正的密钥)。利用这个密钥初始化了s盒,解密opcode最后一部分,长度为74

接下来是一个虚拟机:

​ 进入虚拟机,每次解密3个opcode,然后执行opcode,最后再加密回去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
enc = [36, 11, 109, 15, 3, 50, 66, 29, 43, 67, 120, 67, 115, 48, 43, 78, 99, 72, 119, 46, 50, 57, 26, 18, 113, 122, 66, 23, 69, 114, 86, 12, 92, 74, 98, 83, 51]
dec = [0] * 37
dec[-1] = 126

for i in range(32, -1, -4):
dec[i] = enc[i] ^ enc[i+1] ^ dec[i+4]

dec[33] = enc[33] ^ enc[34] ^ dec[0]

for i in range(29, 0, -4):
dec[i] = enc[i] ^ enc[i+1] ^ dec[i+4]

dec[2] = enc[-1] ^ dec[0] ^ dec[1] ^ dec[-1]

for i in range(3, 37):
dec[i] = enc[i-3] ^ dec[i-1] ^ dec[i-2] ^ dec[i-3]

print(bytes(dec))

5.6

Reverse

主要逻辑:

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
 sub_401AD0();
strcpy(v5, "1A2F943C4D8C5B6EA3C9BCAD7E");
v0 = 0;
v5[27] = 0;
v6 = 0;
do
{
*(_DWORD *)&v7[v0] = 0;
v0 += 4;
}
while ( v0 < 0x20 );
puts("input your key:");
scanf("%s", v7);
v1 = strlen(v7);
if ( v1 <= 19 )
{
printf("too short!");
return -1;
}
else if ( v1 > 30 )
{
printf("too long!");
return -1;
}
else
{
if ( sub_4014A0(v7, v5, v1) )
printf("congratulations, your input is the flag ^_^");
else
printf("try agian");
cnt = iob[0]._cnt - 1;
iob[0]._cnt = cnt;
if ( cnt < 0 )
{
filbuf((FILE *)iob[0]._ptr);
cnt = iob[0]._cnt;
}
else
{
++iob[0]._ptr;
}
v3 = cnt - 1;
iob[0]._cnt = v3;
if ( v3 < 0 )
filbuf((FILE *)iob[0]._ptr);
else
++iob[0]._ptr;
return 0;
}
}

关键函数sub_4014A0(v7, v5, v1),跟进:

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
 v3 = 0;
v11 = 0;
do
{
*(_DWORD *)&v10[v3] = 0;
v3 += 4;
}
while ( v3 < ((v9 - v10 + 30) & 0xFFFFFFFC) );
v9[0] = 15;
v9[1] = -121;
v10[0] = 98;
v10[1] = 20;
v10[2] = 1;
v10[3] = -58;
v10[4] = -16;
v10[5] = 33;
v10[6] = 48;
v10[7] = 17;
v10[8] = 80;
v10[9] = -48;
v10[10] = -126;
v10[11] = 35;
v10[12] = -82;
v10[13] = 35;
v10[14] = -18;
v10[15] = -87;
v10[16] = -76;
v10[17] = 82;
v10[18] = 120;
v10[19] = 87;
v10[20] = 12;
v10[21] = -122;
v10[22] = -117;
if ( a3 == 25 )
{
for ( i = 0; i != 25; ++i )
v12[i] = __ROL1__(*(_BYTE *)(a1 + i), 2);
for ( j = 0; j != 25; ++j )
v12[j] ^= sub_401460(a2, j);
v7 = 15;
for ( k = 0; v12[k] == v7; v7 = v9[k] )
{
if ( ++k == 25 )
return 1;
}
}
return 0;
}

其中sub_401460没有flag参与,直接仿写就行

抄的exp:

1
2
3
4
5
6
7
8
9
10
key = '1A2F943C4D8C5B6EA3C9BCAD7E'
c = [0x0F, 0x87, 0x62, 0x14, 0x01, 0xC6, 0xF0, 0x21, 0x30, 0x11, 0x50, 0xD0, 0x82, 0x23, 0xAE, 0x23, 0xEE, 0xA9, 0xB4, 0x52, 0x78, 0x57, 0x0C, 0x86, 0x8B]
flag = ''

for i in range(25):
x = c[i] ^ int(key[i : i + 2], 16)
x = ((x << 6) & 0xff) | ((x >> 2) & 0xff)
flag += chr(x)

print(flag)

bad_python

是一个被修改的的pyc文件, 根据文件名得到编译环境为python3.6,所以先百度正确的文件头是 33 0d 0d 0a 0c 63 4a 63 61 02 00 e3 00 00 00 。修改好后就可以正常反编译了

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
# uncompyle6 version 3.8.0
# Python bytecode 3.6 (3379)
# Decompiled from: Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)]
# Embedded file name: pyre.py
# Compiled at: 2022-10-15 15:36:44
# Size of source mod 2**32: 609 bytes
from ctypes import *
from Crypto.Util.number import bytes_to_long
from Crypto.Util.number import long_to_bytes

def encrypt(v, k):
v0 = c_uint32(v[0])
v1 = c_uint32(v[1])
sum1 = c_uint32(0)
delta = 195935983
for i in range(32):
v0.value += (v1.value << 4 ^ v1.value >> 7) + v1.value ^ sum1.value + k[(sum1.value & 3)]
sum1.value += delta
v1.value += (v0.value << 4 ^ v0.value >> 7) + v0.value ^ sum1.value + k[(sum1.value >> 9 & 3)]

return (
v0.value, v1.value)


if __name__ == '__main__':
flag = input('please input your flag:')
k = [255, 187, 51, 68]
if len(flag) != 32:
print('wrong!')
exit(-1)
a = []
for i in range(0, 32, 8):
v1 = bytes_to_long(bytes(flag[i:i + 4], 'ascii'))
v2 = bytes_to_long(bytes(flag[i + 4:i + 8], 'ascii'))
a += encrypt([v1, v2], k)

enc = [
4006073346, 2582197823, 2235293281, 558171287, 2425328816, 1715140098, 986348143, 1948615354]
for i in range(8):
if enc[i] != a[i]:
print('wrong!')
exit(-1)

print('flag is flag{%s}' % flag)
# okay decompiling d:\pyre.cpython-36.pyc

简单的tea,逆写:

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
#include<stdio.h>
#define u_int unsigned int
int main()
{
u_int enc[] = { 4006073346, 2582197823, 2235293281, 558171287,
2425328816, 1715140098, 986348143, 1948615354 };
u_int k[] = { 255, 187, 51, 68 };
for (int i = 0; i < 8; i += 2)
{
u_int delta = 195935983;
u_int s1 = delta * 32;
for (int j = 0; j < 32; j++)
{
enc[i + 1] -= (enc[i] << 4 ^ enc[i] >> 7) + enc[i] ^ s1 + k[s1 >> 9 & 3];
s1 -= delta;
enc[i] -= (enc[i + 1] << 4 ^ enc[i + 1] >> 7) + enc[i + 1] ^ s1 + k[s1 & 3];
}
}
char flag[32] = { 0 };
for (int i = 0; i < 8; i++)
{
flag[4 * i] = enc[i] >> 24;
flag[4 * i + 1] = (enc[i] >> 16) ^ 0xFF000000;
flag[4 * i + 2] = (enc[i] >> 8) ^ 0xFF000000;
flag[4 * i + 3] = enc[i] ^ 0xFF000000;
}
for (int i = 0; i < 32; i++)
{
printf("%c", flag[i]);
}
}

5.7

TEA

魔改的xtea加密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for ( i = 0; i <= 8; ++i )
{
v5 = 0;
v6 = 256256256 * i;
v3 = i + 1;
do
{
++v5;
*(a1 + 4i64 * i) += v6 ^ (*(a1 + 4i64 * v3) + ((*(a1 + 4i64 * v3) >> 5) ^ (16 * *(a1 + 4i64 * v3)))) ^ (v6 + *(a2 + 4i64 * (v6 & 3)));
*(a1 + 4i64 * v3) += (v6 + *(a2 + 4i64 * ((v6 >> 11) & 3))) ^ (*(a1 + 4i64 * i)
+ ((*(a1 + 4i64 * i) >> 5) ^ (16 * *(a1 + 4i64 * i))));
v6 += 256256256;
}
while ( v5 <= 0x20 );
result = (i + 1);
}

其中do{}内的是tea加密的算法,外层套了个for()循环,因为原文有10个整数

解密脚本:

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
int main()
{
for (int i = 8; i >= 0; --i)//从后往前遍历
{
int v5 = 0;
unsigned int v6 = 256256256 * (i+33);//detal 因为v6也就是detal在加密过程中一直加256256256,加了32次,所以逆的时候先求出最后的结果,并且要注意使用unsigned int

do//这个部分就完全逆过来,一共三步嘛,去原文那里对照着看一下,+=变-=,后面的内容不需要变,直接抄
{
++v5;
v6 -= 256256256;
a1[i + 1] -= (v6 + a2[(v6 >> 11) & 3]) ^ (a1[i] + ((a1[i] >> 5) ^ (16 * a1[i])));
a1[i] -= v6 ^ (a1[i + 1] + ((a1[i + 1] >> 5) ^ (16 * a1[i + 1]))) ^ (v6 + a2[v6 & 3]);

} while (v5 <= 32);

}
for (int i = 0; i < 10; i++)//这里是原程序这样写的
{
for (int j = 3; j >= 0; j--)
{
printf("%c", (a1[i] >> (j * 8)) & 0xFF);
}
}
return 0;
}

xxxorrr

main函数:

1
2
3
4
5
6
7
8
9
10
11
12
__int64 __fastcall main(int a1, char **a2, char **a3)
{
int i; // [rsp+Ch] [rbp-34h]
char s[40]; // [rsp+10h] [rbp-30h] BYREF
unsigned __int64 v6; // [rsp+38h] [rbp-8h]

v6 = __readfsqword(0x28u);
sub_A90(sub_916);
fgets(s, 35, stdin);
for ( i = 0; i <= 33; ++i )
s1[i] ^= s[i];
return 0LL

输入的s1与s1的元素进行异或,点击sub_916函数找s1

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
unsigned __int64 sub_916()
{
unsigned __int64 v1; // [rsp+8h] [rbp-8h]

v1 = __readfsqword(0x28u);
if ( !strcmp(s1, s2) )
puts("Congratulations!");
else
puts("Wrong!");
return __readfsqword(0x28u) ^ v1;
}
#.data:0000000000201060 s2 db 'VNWXQQ',9,'F' ; DATA XREF: sub_916+17↑o
.data:0000000000201068 db 17h
.data:0000000000201069 db 46h ; F
.data:000000000020106A db 54h ; T
.data:000000000020106B db 5Ah ; Z
.data:000000000020106C db 59h ; Y
.data:000000000020106D db 59h ; Y
.data:000000000020106E db 1Fh
.data:000000000020106F db 48h ; H
.data:0000000000201070 db 32h ; 2
.data:0000000000201071 db 5Bh ; [
.data:0000000000201072 db 6Bh ; k
.data:0000000000201073 db 7Ch ; |
.data:0000000000201074 db 75h ; u
.data:0000000000201075 db 6Eh ; n
.data:0000000000201076 db 7Eh ; ~
.data:0000000000201077 db 6Eh ; n
.data:0000000000201078 db 2Fh ; /
.data:0000000000201079 db 77h ; w
.data:000000000020107A db 4Fh ; O
.data:000000000020107B db 7Ah ; z
.data:000000000020107C db 71h ; q
.data:000000000020107D db 43h ; C
.data:000000000020107E db 2Bh ; +
.data:000000000020107F db 26h ; &
.data:0000000000201080 db 89h

exp:

1
2
3
4
5
6
7
8
9
10
s2=[ 0x56, 0x4E, 0x57, 0x58, 0x51, 0x51, 0x09, 0x46, 0x17, 0x46, 
0x54, 0x5A, 0x59, 0x59, 0x1F, 0x48, 0x32, 0x5B, 0x6B, 0x7C,
0x75, 0x6E, 0x7E, 0x6E, 0x2F, 0x77, 0x4F, 0x7A, 0x71, 0x43,
0x2B, 0x26, 0x89, 0xFE, 0x00]
s1 = 'qasxcytgsasxcvrefghnrfghnjedfgbhn'
flag=''
for i in range(33):
flag+=chr(ord(s1[i])^ (2 * i + 65)^s2[i])
print(flag)
# flag{c0n5truct0r5_functi0n_in_41f}

5.8

ISCC Convert

今天做了两道ISCC的题目,这个比赛还没结束,不可以写wp捏。贴张截图

image-20230508215723510

testre

主要逻辑:

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
__int64 __fastcall sub_400700(void *a1, _QWORD *a2, __int64 a3, size_t a4)
{
unsigned __int8 *v4; // rcx
__int64 v6; // [rsp+0h] [rbp-C0h]
int c; // [rsp+8h] [rbp-B8h]
char v8; // [rsp+Fh] [rbp-B1h]
int v9; // [rsp+10h] [rbp-B0h]
bool v10; // [rsp+17h] [rbp-A9h]
unsigned __int8 *v11; // [rsp+18h] [rbp-A8h]
char v12; // [rsp+27h] [rbp-99h]
int v13; // [rsp+28h] [rbp-98h]
int v14; // [rsp+2Ch] [rbp-94h]
unsigned __int64 i; // [rsp+30h] [rbp-90h]
size_t n; // [rsp+38h] [rbp-88h]
size_t v17; // [rsp+40h] [rbp-80h]
size_t v18; // [rsp+48h] [rbp-78h]
size_t j; // [rsp+50h] [rbp-70h]
size_t v20; // [rsp+58h] [rbp-68h]
int v21; // [rsp+64h] [rbp-5Ch]
unsigned __int64 v22; // [rsp+68h] [rbp-58h]
int v23; // [rsp+74h] [rbp-4Ch]
__int64 *v24; // [rsp+78h] [rbp-48h]
__int64 v25; // [rsp+80h] [rbp-40h]
void *v26; // [rsp+88h] [rbp-38h]
int v27; // [rsp+94h] [rbp-2Ch]
size_t v28; // [rsp+98h] [rbp-28h]
__int64 v29; // [rsp+A0h] [rbp-20h]
_QWORD *v30; // [rsp+A8h] [rbp-18h]
void *s; // [rsp+B0h] [rbp-10h]
char v32; // [rsp+BFh] [rbp-1h]

s = a1;
v30 = a2;
v29 = a3;
v28 = a4;
v27 = -559038737;
v26 = malloc(0x100uLL);
v25 = v29;
v24 = &v6;
v22 = 0LL;
v17 = 0LL;
for ( i = 0LL; i < v28; ++i )
{
v13 = *(unsigned __int8 *)(v25 + i);
*((_BYTE *)v26 + i) = byte_400E90[i % 0x1D] ^ v13;
*((_BYTE *)v26 + i) += *(_BYTE *)(v25 + i);
}
while ( 1 )
{
v12 = 0;
if ( v17 < v28 )
v12 = ~(*(_BYTE *)(v25 + v17) != 0);
if ( !(v12 & 1) )
break;
++v17;
}
n = ((unsigned __int64)(0x28F5C28F5C28F5C3LL * (unsigned __int128)(138 * (v28 - v17) >> 2) >> 64) >> 2) + 1;
v23 = ((unsigned __int64)(0xAAAAAAAAAAAAAAABLL * (unsigned __int128)((v17 + v28) << 6) >> 64) >> 5) - 1;
v11 = (unsigned __int8 *)&v6
- ((((unsigned __int64)(0x28F5C28F5C28F5C3LL * (unsigned __int128)(138 * (v28 - v17) >> 2) >> 64) >> 2) + 16) & 0xFFFFFFFFFFFFFFF0LL);
memset(v11, 0, n);
v20 = v17;
v18 = n - 1;
while ( v20 < v28 )
{
v21 = *(unsigned __int8 *)(v25 + v20);
for ( j = n - 1; ; --j )
{
v10 = 1;
if ( j <= v18 )
v10 = v21 != 0;
if ( !v10 )
break;
v22 = v11[j] << 6;
v21 += v11[j] << 8;
v9 = 64;
v11[j] = v21 % 58;
*((_BYTE *)v26 + j) = v22 & 0x3F;
v22 >>= 6;
v21 /= 58;
v27 /= v9;
if ( !j )
break;
}
++v20;
v18 = j;
}
for ( j = 0LL; ; ++j )
{
v8 = 0;
if ( j < n )
v8 = ~(v11[j] != 0);
if ( !(v8 & 1) )
break;
}
if ( *v30 > n + v17 - j )
{
if ( v17 )
{
c = 61;
memset(s, 49, v17);
memset(v26, c, v17);
}
v20 = v17;
while ( j < n )
{
v4 = v11;
*((_BYTE *)s + v20) = byte_400EB0[v11[j]];
*((_BYTE *)v26 + v20++) = byte_400EF0[v4[j++]];
}
*((_BYTE *)s + v20) = 0;
*v30 = v20 + 1;
if ( !strncmp((const char *)s, "D9", 2uLL)
&& !strncmp((const char *)s + 20, "Mp", 2uLL)
&& !strncmp((const char *)s + 18, "MR", 2uLL)
&& !strncmp((const char *)s + 2, "cS9N", 4uLL)
&& !strncmp((const char *)s + 6, "9iHjM", 5uLL)
&& !strncmp((const char *)s + 11, "LTdA8YS", 7uLL) )
{
HIDWORD(v6) = puts("correct!");
}
v32 = 1;
v14 = 1;
}
else
{
*v30 = n + v17 - j + 1;
v32 = 0;
v14 = 1;
}
return v32 & 1;
}

可以看到最后是s跟D9cS9N9iHjMLTdA8YSMRMp作比较
而s来自于v11

分析一下可能得到是base58编码,解码即可:base58_is_boring

5.9

ISCC Pull the Wool Over People’s Eyes

比赛还是没结束捏,不能写wp

[CISCN 2022 东北]hana

upx壳,使用工具脱掉,幸好我有两个脱壳工具,只有一个能用,动调断在输入处,可以看到加密只有一个异或,比较处也可以找到密文,key反查一下,抄的exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
cip = [0x56,0xEC,0xA0,0xDC,0x57,0x06,0xFE,0xA3,0xEB,0x72,0xEA,0x97,0xE2,0x87,0x03,0xAA,0x18,0x6A,0xF3,0xBE,0xBD,0xDA,0x79,0x0A,0x98,0x36,0x12,0x5C,0xE0,0x94,0x61,0x5A, 0x42,0xBC,0x4B,0x01,0x49,0x7B,0x5F]

flag = 'flag{12345678876543211234567887654321}'

cip2 = [0x56,0xEC,0xA0,0xDC,0x57,0x07,0xF4,0xA3,0xE9,0x77,0xBF,0x93,0xBC,0x86,0x52,0xA5,0x14,0x6A,0xA5,0xBD,0xB5,0xD2,0x7F,0x0B,0x9B,0x67,0x1D,0x08,0xEF,0xC9,0x32,0x5D,0x43,0xED,0x1E,0x01,0x4B,0x7B,0x01]

flag2 = ''

key = []

for i in range(len(flag)):

key.append(ord(flag[i])^cip[i])

print key

for i in range(len(key)):

flag2 += chr(key[i]^cip2[i])

print flag2

5.10

[HNCTF 2022 WEEK2]e@sy_flower

简单的花指令,找到冒红的地方,先u重定义,再将第一个字节改为nop,回到上面main函数那按p重建函数,f5即可反编译

直接逆写即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enc = list('c~scvdzKCEoDEZ[^roDICUMC')
flag = []

# 与 0x30异或
for i in range(len(enc)):
flag.append(chr(ord(enc[i]) ^ 0x30))

#
for i in range(int(len(flag) / 2)):
tmp = flag[2 * i]
flag[2 * i] = flag[2 * i + 1]
flag[2 * i + 1] = tmp

for i in flag:
print(i, end='')

#NSSCTF{Just_junk_Bytess}

luck_guy

1
2
3
4
5
6
7
8
9
10
11
12
13
b = a.to_bytes(8, byteorder='little')
print(b)
c = list(b)
print(c)
flag = ''
flag0 = 'GXY{do_not_'
for i in range(8):
if i % 2 == 1:
flag += chr((c[i]) - 2)
else:
flag += chr((c[i]) - 1)
print(flag0 + flag)

5.11

hackme

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;
}

解密:

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)

SignIn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import libnum
from Crypto.Util.number import long_to_bytes

q = 282164587459512124844245113950593348271
p = 366669102002966856876605669837014229419
e = 65537
c = 0xad939ff59f6e70bcbfad406f2494993757eee98b91bc244184a377520d06fc35
n = 103461035900816914121390101299049044413950405173712170434161686539878160984549

d = libnum.invmod(e, (p - 1) * (q - 1)) #invmod(a, n) - 求a对于n的模逆,这里逆向加密过程中计算ψ(n)=(p-1)(q-1),对ψ(n)保密,也就是对应根据e*d=1modψ(n),求出d
m = pow(c, d, n) # 这里的m是十进制形式,pow(x, y[, z])--函数是计算 x 的 y 次方,如果 z 在存在,则再对结果进行取模,其结果等效于 pow(x,y) %z,对应前面解密算法中M=D(C)=(C^d)mod n
string = long_to_bytes(m) # 获取m明文
print(string)

5.12

[强网杯 2022]GameMaster

c#逆向 dnspy打开,可以看到main函数一开始就打开了gamemessage文件,这个文件也是题目给出的

1
2
3
4
5
FileStream fileStream = File.OpenRead("gamemessage");
int num = (int)fileStream.Length;
Program.memory = new byte[num];
fileStream.Position = 0L;
fileStream.Read(Program.memory, 0, num);

将该文件传给了memory,在goldfunc函数里异或了34

1
2
3
4
5
6
for (int i = 0; i < Program.memory.Length; i++)
{
byte[] array = Program.memory;
int num = i;
array[num] ^= 34;
}

将memory 用AES,ECB 解密生成ExploitClass.dll

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
byte[] key = new byte[]
{
66,
114,
97,
105,
110,
115,
116,
111,
114,
109,
105,
110,
103,
33,
33,
33
};
ICryptoTransform cryptoTransform = new RijndaelManaged
{
Key = key,
Mode = CipherMode.ECB,
Padding = PaddingMode.Zeros
}.CreateDecryptor();
Program.m = cryptoTransform.TransformFinalBlock(Program.memory, 0, Program.memory.Length);

所以,解密:

1
2
3
4
5
6
7
8
9
10
11
12
data = open('gamemessage', 'rb').read()
data = bytes([v^0x22 for v in data])

from Crypto.Cipher import AES

key = bytes([0x42, 0x72, 0x61, 0x69, 110, 0x73, 0x74, 0x6f, 0x72, 0x6d, 0x69, 110, 0x67, 0x21, 0x21, 0x21])
aes = AES.new(key,AES.MODE_ECB)
m = aes.decrypt(data)

pos = 0x13eb
m = m[pos:]+m[:pos]
open('temp.dll', 'wb').write(m)

查看PE,发现了MZ文件头,把前面的删掉,还是一个c#程序,继续拖入dnspy

先看看key是啥,仿写即可:

1
2
3
4
5
6
7
8
9
10
11
private static void ParseKey(ulong[] L, byte[] Key)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
Key[i * 4 + j] = (byte)((L[i] >> j * 8) & 255UL);
}
}
}

check函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static void Check1(ulong x, ulong y, ulong z, byte[] KeyStream)
{
int num = -1;
for (int i = 0; i < 320; i++)
{
x = (((x >> 29) ^ (x >> 28) ^ (x >> 25) ^ (x >> 23)) & 1UL) | (x << 1);
y = (((y >> 30) ^ (y >> 27)) & 1UL) | (y << 1);
z = (((z >> 31) ^ (z >> 30) ^ (z >> 29) ^ (z >> 28) ^ (z >> 26) ^ (z >> 24)) & 1UL) | (z << 1);
bool flag = i % 8 == 0;
if (flag)
{
num++;
}
KeyStream[num] = (byte)((long)((long)KeyStream[num] << 1) | (long)((ulong)((uint)(((z >> 32) & 1UL & ((x >> 30) & 1UL)) ^ ((((z >> 32) & 1UL) ^ 1UL) & ((y >> 31) & 1UL))))));
}
}

z3解方程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import z3
first=[101,5,80,213,163,26,59,38,19,6,173,189,198,166,140,183,42,247,223,24,106,20,145,37,24,7,22,191
print(len(first))
tmp=len(first)*[0]
num = -1
x = z3.BitVec("v1", 64) #64位的v1
y = z3.BitVec("v2", 64)
z = z3.BitVec("v3", 64)
for i in range(0,320):
x = (((x >> 29 ^ x >> 28 ^ x >> 25 ^ x >> 23) & 1) | x << 1)
y = (((y >> 30 ^ y >> 27) & 1) | y << 1)
z = (((z >> 31 ^ z >> 30 ^ z >> 29 ^ z >> 28 ^ z >> 26 ^ z >> 24) & 1) | z << 1)
if i%8==0:
num+=1
tmp[num] = tmp[num] << 1 | (z >> 32 & 1 & (x >> 30 & 1)) ^ (((z >> 32 & 1) ^ 1) & (y >> 31 & 1)
solver = z3.Solver()
for i in range(len(first)):
solver.add(first[i] == tmp[i])
solver.check()
print(solver.model())
# [v3 = 3131229747, v1 = 156324965, v2 = 868387187

exp:

1
2
3
4
5
6
7
8
9
10
l=[156324965, 868387187, 3131229747]
arr=[0]*12
for i in range(3):
for j in range(4):
arr[i*4+j]=(l[i]>>j*8)&0xff
enc=[60, 100, 36, 86, 51, 251, 167, 108, 116, 245,
207, 223, 40, 103, 34, 62, 22, 251, 227]
for i in range(len(enc)):
print(chr(enc[i]^arr[i%len(arr)]),end='')

xctf babymips

main函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int __fastcall main(int a1, char **a2, char **a3)
{
int result; // $v0
int i; // [sp+18h] [+18h] BYREF
char v5[36]; // [sp+1Ch] [+1Ch] BYREF

setbuf((FILE *)stdout, 0);
setbuf((FILE *)stdin, 0);
printf("Give me your flag:");
scanf("%32s", v5);
for ( i = 0; i < 32; ++i )
*((_BYTE *)&i + i + 4) ^= 32 - (_BYTE)i;
if ( !strncmp(v5, fdata, 5u) )
result = sub_4007F0(v5);
else
result = puts("Wrong");
return result;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int __fastcall sub_4007F0(const char *a1)
{
char v1; // $v1
int result; // $v0
size_t i; // [sp+18h] [+18h]

for ( i = 5; i < strlen(a1); ++i )
{
if ( (i & 1) != 0 )
v1 = (a1[i] >> 2) | (a1[i] << 6); //把低二位和高六位进行交换
else
v1 = (4 * a1[i]) | (a1[i] >> 6);
a1[i] = v1;
}
if ( !strncmp(a1 + 5, (const char *)off_410D04, 0x1Bu) )
result = puts("Right!");
else
result = puts("Wrong!");
return result;
}

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
part1=b'Q|j{g'
part2='52 fd 16 a4 89 bd 92 80 13 41 54 a0 8d 45 18 81 de fc 95 f0 16 79 1a 15 5b 75 1f'
part2=list(bytes.fromhex(part2))
for i in range(5,len(part2)+5):
t = part2[i-5]
if i&1==0: #偶数时&1 为0
part2[i-5]=(t&0x3)<<6|(t&0xfc)>>2 #低2位左移6位,高6位右移2位 相当于循环右移2位
else:
part2[i-5]=(t&0x3f)<<2|(t&0xc0)>>6 #低6位左移2位,高2位右移6位 相当于循环左移2位

temp=list(part1)+part2
flag=''
for i in range(len(temp)):
flag+=chr(temp[i]^0x20 -i)
print(flag)

5.13

litctf 逆向wp | shimmer’s blog (shimmer123456.github.io)

5.14

春秋杯 Poisoned_tea_CHELL(壳是真难脱啊,还好我脱掉了)

春秋杯 sum

比赛还没结束捏,不能写wp,(目前为止逆向ak,嘿嘿)贴个图算了:

image-20230514204252391

5.15

[SWPUCTF 2021 新生赛]fakebase

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
flag = 'xxxxxxxxxxxxxxxxxxx'

s_box = 'qwertyuiopasdfghjkzxcvb123456#$'
tmp = ''
for i in flag:
tmp += str(bin(ord(i)))[2:].zfill(8)
b1 = int(tmp,2)
s = ''
while b1//31 != 0:
s += s_box[b1%31]
b1 = b1//31

print(s)

# s = u#k4ggia61egegzjuqz12jhfspfkay

其中s的值都是s_box中取的,因此[b1%31]是可以得知的。也就是

1
2
3
4
s_box = 'qwertyuiopasdfghjkzxcvb123456#$'
s = 'u#k4ggia61egegzjuqz12jhfspfkay'
for i in s:
b1 = k*31+s_box.index(i)

我们是从0开始爆破,因为b1是从大每次整除31,依次减小的,因此我们s选好 是需要逆序。因此:

1
2
3
4
5
6
s_box = 'qwertyuiopasdfghjkzxcvb123456#$'
s = 'u#k4ggia61egegzjuqz12jhfspfkay'
for k in range(5):
b1=k
for i in s[::-1]:
b1 = b1*31+s_box.index(i)

最后直接将整数转换为字符串即可:

1
2
3
4
5
6
7
8
import libnum
s_box = 'qwertyuiopasdfghjkzxcvb123456#$'
s = 'u#k4ggia61egegzjuqz12jhfspfkay'
for k in range(5):
b1=k
for i in s[::-1]:
b1 = b1*31+s_box.index(i)
print(libnum.n2s(int(b1)))

[SWPUCTF 2021 新生赛]fakerandom

逆着逻辑好了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

import random
random.seed(1)
l = []
flag=“”
for i in range(4):
l.append(random.getrandbits(8))
result = [201, 8, 198, 68, 131, 152, 186, 136, 13, 130, 190, 112, 251, 93, 212, 1, 31, 214, 116, 244]

for i in range(len(l)):
random.seed(l[i])
for n in range(5):
flag+=chr(result[i*5+n]^random.getrandbits(8))
print(flag)
#NSSCTF{FakeE_random}

5.16

[HGAME 2022 week1]easyasm

附件是16位的MS-DOS程序,用IDA分析start函数,代码不多,大意是将flag的每个字符前四位和后四位进行置换,然后与0x17异或,再与密文逐位比较。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <windows.h>

int main()
{
unsigned char cipher[] =
{
0x91, 0x61, 0x01, 0xC1, 0x41, 0xA0, 0x60, 0x41, 0xD1, 0x21,
0x14, 0xC1, 0x41, 0xE2, 0x50, 0xE1, 0xE2, 0x54, 0x20, 0xC1,
0xE2, 0x60, 0x14, 0x30, 0xD1, 0x51, 0xC0, 0x17
};

for(int i=0; i<28; i++)
{
unsigned char tmp = cipher[i]^0x17;
printf("%c", (tmp<<4)+(tmp>>4));
}
}

[WUSTCTF 2020]level3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 __int64 O_OLookAtYou()
{
__int64 result; // rax
char v1; // [rsp+1h] [rbp-5h]
int i; // [rsp+2h] [rbp-4h]

for ( i = 0; i <= 9; ++i )
{
v1 = base64_table[i];
base64_table[i] = base64_table[19 - i];
result = 19 - i;
base64_table[result] = v1;
}
return result;
}
//数据交换
v1=base64_table[0:9]
base64_table[0:9]=base64_table[19:10]
base64_table[19:10]=base64_table[0:9]


ABCDEFGHIJ KLMNOPQRST UVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
TSRQPONMLK JIHGFEDCBA UVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
1
2
3
4
5
6
7
8
9
10
11
12
import base64
import string

string = "d2G0ZjLwHjS7DmOzZAY0X2lzX3CoZV9zdNOydO9vZl9yZXZlcnGlfD=="
tableBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
tableNew = "TSRQPONMLKJIHGFEDCBAUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"


maketrans = str.maketrans(tableNew, tableBase64)
translate = string.translate(maketrans)
flag = base64.b64decode(translate)
print (flag)

5.17

[BJDCTF 2020]Easy AmtuOrRF

IDA pro 动调

1.先在 0x00401723 断点 方便查看flag

2.在0x0401773断点 运行到此

3.然后修改EIP 为 0x0401520

4.继续运行看cmd窗口得到flag

HACKIT4FUN

[HNCTF 2022 Week1]X0r

1
2
3
4
5
6
7
8
9
10

flag = ''
f2 = [0x3FE, 0x3EB,0x3EB, 0x3FB, 0x3E4, 0x3F6, 0x3D3, 0x3D0, 0x388, 0x3CA, 0x3EF, 0x389, 0x3CB, 0x3EF, 0x3CB, 0x388, 0x3EF, 0x3D5, 0x3D9, 0x3CB, 0x3D1, 0x3CD]

for i in range(0,22):
flag+=chr((f2[i]-900)^0x34)

print(flag)


5.19

[2023春秋杯 sum]

main函数:

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
char *v3; // rbp
int v4; // r14d
unsigned int v5; // r12d
__int64 i; // rbx
char v7; // al
int v8; // eax
const char *v9; // rax

v3 = (char *)&matrix;
v4 = 1;
v5 = 0;
puts("Welcome to Solver!");
do
{
for ( i = 0LL; i != 9; ++i )
{
if ( !v3[i] )
{
v7 = getchar();
if ( (unsigned __int8)(v7 - 49) > 8u )
v4 = 0;
else
v3[i] = v7 - 48;
}
v8 = v3[i];
v5 += v8;
}
v3 += 9;
}
while ( v3 != (char *)&matrix + 81 );
if ( v4 && (unsigned int)verify("Welcome to Solver!", argv) )
{
puts("You Win!");
__snprintf_chk(buf, 32LL, 1LL, 32LL, "%d", v5);
v9 = (const char *)str2md5(buf, strlen(buf));
__printf_chk(1LL, "flag is: flag{%s}\n\n", v9);
exit(0);
}
puts("Again~");
return 0;
}

首先是一个do while嵌套for的一个81次的循环,循环时当v3[i]的值等于0,会让用户输入一个字符,并且该输入必须在0-9之间

那么接下来进入verify函数:

不仔细看的话中等复杂,但他肯定是一段验证程序,因为它在if条件里嘛,满足条件就是win了。分析的话要么动调,要么为了省事直接问gpt(这个题效果还不错,有时候小心他会胡说八道):

solve:

知道是数独,提取出81个数据,找个在线网站解一下数独,再运行程序填进去flag就输出了

[GDOUCTF 2023]doublegame

直接运行程序是一个贪吃蛇游戏,撞壁游戏就结束了。

拖入ida,因为没有main函数,所以通过字符串来定位关键逻辑,看到挺多0,跟进去,来到了这么一个函数:

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
136
137
138
void __noreturn sub_140012CF0()
{
char *v0; // rdi
__int64 i; // rcx
char v2; // [rsp+20h] [rbp+0h] BYREF
char Buffer[22]; // [rsp+30h] [rbp+10h] BYREF
char v4[44]; // [rsp+46h] [rbp+26h] BYREF
char v5[44]; // [rsp+72h] [rbp+52h] BYREF
char v6[44]; // [rsp+9Eh] [rbp+7Eh] BYREF
char v7[44]; // [rsp+CAh] [rbp+AAh] BYREF
char v8[44]; // [rsp+F6h] [rbp+D6h] BYREF
char v9[44]; // [rsp+122h] [rbp+102h] BYREF
char v10[44]; // [rsp+14Eh] [rbp+12Eh] BYREF
char v11[44]; // [rsp+17Ah] [rbp+15Ah] BYREF
char v12[44]; // [rsp+1A6h] [rbp+186h] BYREF
char v13[66]; // [rsp+1D2h] [rbp+1B2h] BYREF
int j; // [rsp+214h] [rbp+1F4h]
int v15; // [rsp+234h] [rbp+214h]
int v16; // [rsp+254h] [rbp+234h]
int v17; // [rsp+274h] [rbp+254h]
int v18; // [rsp+294h] [rbp+274h]
_DWORD v19[25]; // [rsp+2C0h] [rbp+2A0h] BYREF
char v20[100]; // [rsp+324h] [rbp+304h] BYREF
char v21[828]; // [rsp+388h] [rbp+368h] BYREF
char v22; // [rsp+6C4h] [rbp+6A4h]
int v23; // [rsp+6E4h] [rbp+6C4h]
int v24; // [rsp+704h] [rbp+6E4h]

v0 = &v2;
for ( i = 448i64; i; --i )
{
*(_DWORD *)v0 = -858993460;
v0 += 4;
}
sub_14001141A(&unk_1400290A6);
strcpy(Buffer, "000000000000000000000");
strcpy(v4, "0 0 0 0 0 0 0");
strcpy(&v4[22], "0 0 0 00000 00000 0 0");
strcpy(v5, "0 0 0 0");
strcpy(&v5[22], "0 000 000 0 000 0 0 0");
strcpy(v6, "0 0 0 0 0 0 0 0");
strcpy(&v6[22], "0 0 0 00000 000 000 0");
strcpy(v7, "0 0 0 0 0 0 ");
strcpy(&v7[22], "0 000 0 0 000 0 0 0 0");
strcpy(v8, "0 0 0 0 0 0 0 0 0");
strcpy(&v8[22], "0 00000 000 000 0 0 0");
strcpy(v9, "0 0 0 0 0");
strcpy(&v9[22], "000 0 0 0 000 0 0 0 0");
strcpy(v10, "0 0 0 0 0 0 * 0 0 0 0");
strcpy(&v10[22], "0 0000000 0 000 00000");
strcpy(v11, "@ 0 0 0");
strcpy(&v11[22], "0 0 0 0 0 00000000000");
strcpy(v12, "0 0 0 0 0");
strcpy(&v12[22], "000 0 00000 0 000 000");
strcpy(v13, "0 0 0 0 0");
strcpy(&v13[22], "000000000000000000000");
v11[4] = 48;
strcpy((char *)v19, "Please to save the cat!");
memset(&v19[6], 0, 0x4Cui64);
strcpy(v20, "the score is saving cat's key!\n");
memset(&v20[32], 0, 0x44ui64);
qmemcpy(v21, &unk_14001D340, 0x47ui64);
memset(&v21[71], 0, 729);
sub_1400111F9("path\n");
v23 = 0;
v24 = 0;
v15 = 15;
v16 = 0;
v17 = 7;
v18 = 20;
for ( j = 0; j <= 20; ++j )
puts(&Buffer[22 * j]);
sub_1400111F9("Please to save the cat!\n");
while ( v15 != v17 || v16 != v18 )
{
v22 = getchar();
switch ( v22 )
{
case 's':
if ( Buffer[22 * v15 + 22 + v16] != 48 )
{
Buffer[22 * v15++ + v16] = 32;
Buffer[22 * v15 + v16] = 64;
}
break;
case 'w':
if ( Buffer[22 * v15 - 22 + v16] != 48 )
{
Buffer[22 * v15-- + v16] = 32;
Buffer[22 * v15 + v16] = 64;
}
break;
case 'a':
if ( Buffer[22 * v15 - 1 + v16] != 48 )
{
if ( Buffer[22 * v15 - 1 + v16] == 42 )
v7[20] = 48;
Buffer[22 * v15 + v16--] = 32;
Buffer[22 * v15 + v16] = 64;
}
break;
default:
if ( v22 == 100 && Buffer[22 * v15 + 1 + v16] != 48 )
{
Buffer[22 * v15 + v16++] = 32;
Buffer[22 * v15 + v16] = 64;
}
break;
}
system("cls");
for ( j = 0; j <= 20; ++j )
puts(&Buffer[22 * j]);
puts((const char *)&v19[25 * v23]);
if ( v7[20] == 48 )
{
v24 = sub_140011433(0i64);
if ( v24 == 13376013 )
{
v23 = 1;
v7[20] = 32;
Buffer[22 * v15 + v16] = 32;
v15 = 15;
v16 = 0;
v11[0] = 64;
++v23;
}
else
{
sub_1400111F9("error");
}
}
}
system("cls");
Sleep(0x1F4u);
Sleep(0xBB8u);
sub_140011492();
exit(0);
}

很明显是一个迷宫,但刚才的贪吃蛇哪去了(因为是double game啦),那么就再交叉引用看看谁调用了这个迷宫的函数,一直可以追到贪吃蛇游戏里

这个dword_140022CD0就是当前得分了,当它>13371337时就会跳转到迷宫游戏

逻辑清楚了,那么在判断分数前下个断点,贪吃蛇游戏结束之后断下来,修改两次标志位(sf)跳转到迷宫游戏

接下来通过wsad控制上下左右走迷宫,先把小猫救出来后,程序会让输入key(其实就是贪吃蛇分数13371337),也可以通过判断key的逻辑再把key逆出来:

输入key之后,又回到原点了,再走一下迷宫,flag就是{key+md5(最短路径)}

5.20

[LitCTF 2023]enbase64

变表base64,下断点dump出变表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#python
def basechange(source):
destination = list(source)
v3 = [
16, 34, 56, 7, 46, 2, 10, 44, 20, 41, 59, 31, 51, 60, 61, 26, 5, 40, 21, 38, 4, 54, 52, 47, 3, 11, 58, 48, 32, 15, 49, 14, 37, 0, 55, 53, 24, 35, 18, 25, 33, 43, 50, 39, 12, 19, 13, 42, 9, 17, 28, 30, 23, 36, 1, 22, 57, 63, 8, 27, 6, 62, 45, 29
]
for i in range(48):
for j in range(64):
source[j] = destination[v3[j]]
destination = source[:]
return ''.join(destination)
if __name__ == '__main__':
s =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx
yz0123456789+/"
result = basechange(list(s))
print(result)

5.21

[GXYCTF 2019]luck_guy

1
2
3
4
5
6
7
8
9
10
flag = ''
f2 = [0x7F, 0x66, 0x6F, 0x60, 0x67, 0x75, 0x63, 0x69][::-1]
s = ''
for i in range(8):
if i % 2 == 1:
flag += chr((f2[i]) - 2)
else:
flag += chr((f2[i]) - 1)
# flag += s
print(flag)

5.22

[NISACTF 2022]ezpython

使用pyinstxtractor解包exe

使用010修复src.pyc的文件头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#line 50:
flag = 'IAMrG1EOPkM5NRI1cChQDxEcGDZMURptPzgHJHUiN0ASDgUYUB4LGQMUGAtLCQcJJywcFmddNno/PBtQbiMWNxsGLiFuLwpiFlkyP084Ng0lKj8GUBMXcwEXPTJrRDMdNwMiHVkCBFklHgIAWQwgCz8YQhp6E1xUHgUELxMtSh0xXzxBEisbUyYGOx1DBBZWPg1CXFkvJEcxO0ADeBwzChIOQkdwXQRpQCJHCQsaFE4CIjMDcwswTBw4BS9mLVMLLDs8HVgeQkscGBEBFSpQFQQgPTVRAUpvHyAiV1oPE0kyADpDbF8AbyErBjNkPh9PHiY7O1ZaGBADMB0PEVwdCxI+MCcXARZiPhwfH1IfKitGOF42FV8FTxwqPzBPAVUUOAEKAHEEP2QZGjQVV1oIS0QBJgBDLx1jEAsWKGk5Nw03MVgmWSE4Qy5LEghoHDY+OQ9dXE44Th0='
key = 'this is key'
try:
result = input('please input key: ')
if result == decrypt2('AAAAAAAAAAAfFwwRSAIWWQ==', key):
print(decrypt1(base64.b64decode(decrypt2(flag, result))))
else:
if result == key:
print('flag{0e26d898-b454-43de-9c87-eb3d122186bc}')
else:
print('key is error.')
except Exception as e:
pass
1
2
3
4
5
#line 50:
flag = 'IAMrG1EOPkM5NRI1cChQDxEcGDZMURptPzgHJHUiN0ASDgUYUB4LGQMUGAtLCQcJJywcFmddNno/PBtQbiMWNxsGLiFuLwpiFlkyP084Ng0lKj8GUBMXcwEXPTJrRDMdNwMiHVkCBFklHgIAWQwgCz8YQhp6E1xUHgUELxMtSh0xXzxBEisbUyYGOx1DBBZWPg1CXFkvJEcxO0ADeBwzChIOQkdwXQRpQCJHCQsaFE4CIjMDcwswTBw4BS9mLVMLLDs8HVgeQkscGBEBFSpQFQQgPTVRAUpvHyAiV1oPE0kyADpDbF8AbyErBjNkPh9PHiY7O1ZaGBADMB0PEVwdCxI+MCcXARZiPhwfH1IfKitGOF42FV8FTxwqPzBPAVUUOAEKAHEEP2QZGjQVV1oIS0QBJgBDLx1jEAsWKGk5Nw03MVgmWSE4Qy5LEghoHDY+OQ9dXE44Th0='
key = 'this is key'

print(decrypt1(base64.b64decode(decrypt2(flag, decrypt2('AAAAAAAAAAAfFwwRSAIWWQ==', key)))))

5.23

[HNCTF 2022 WEEK2]来解个方程?

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
from z3 import *
v2=[Int('v2%s' %i) for i in range(22)]
s=Solver()

s.add(245 * v2[4] + 395 * v2[3] + 3541 * v2[2] + 2051 * v2[1] + 3201 * v2[0] + 1345 * v2[5] == 855009)
s.add(3270 * v2[4] + 3759 * v2[3] + 3900 * v2[2] + 3963 * v2[1] + 1546 * v2[0] + 3082 * v2[5] == 1515490)
s.add(526 * v2[4] + 2283 * v2[3] + 3349 * v2[2] + 2458 * v2[1] + 2012 * v2[0] + 268 * v2[5] == 854822)
s.add(3208 * v2[4] + 2021 * v2[3] + 3146 * v2[2] + 1571 * v2[1] + 2569 * v2[0] + 1395 * v2[5] == 1094422)
s.add(3136 * v2[4] + 3553 * v2[3] + 2997 * v2[2] + 1824 * v2[1] + 1575 * v2[0] + 1599 * v2[5] == 1136398)
s.add(2300 * v2[4] + 1349 * v2[3] + 86 * v2[2] + 3672 * v2[1] + 2908 * v2[0] + 1681 * v2[5] == 939991)
s.add( 212 * v2[20]
+ 153 * v2[19]
+ 342 * v2[18]
+ 490 * v2[10]
+ 325 * v2[9]
+ 485 * v2[8]
+ 56 * v2[7]
+ 202 * v2[6]
+ 191 * v2[21] == 245940)




s.add(348 * v2[20]
+ 185 * v2[19]
+ 134 * v2[18]
+ 153 * v2[10]
+ 460 * v2[7]
+ 207 * v2[6]
+ 22 * v2[8]
+ 24 * v2[9]
+ 22 * v2[21] == 146392)
s.add(177 * v2[20]
+ 231 * v2[19]
+ 489 * v2[18]
+ 339 * v2[10]
+ 433 * v2[9]
+ 311 * v2[8]
+ 164 * v2[7]
+ 154 * v2[6]
+ 100 * v2[21] == 239438)

s.add(68 * v2[18]
+ 466 * v2[10]
+ 470 * v2[9]
+ 22 * v2[8]
+ 270 * v2[7]
+ 360 * v2[6]
+ 337 * v2[19]
+ 257 * v2[20]
+ 82 * v2[21] == 233887)

s.add(246 * v2[20]
+ 235 * v2[19]
+ 468 * v2[18]
+ 91 * v2[10]
+ 151 * v2[9]
+ 197 * v2[6]
+ 92 * v2[7]
+ 73 * v2[8]
+ 54 * v2[21] == 152663)
s.add(241 * v2[20]
+ 377 * v2[19]
+ 131 * v2[18]
+ 243 * v2[10]
+ 233 * v2[9]
+ 55 * v2[8]
+ 376 * v2[7]
+ 242 * v2[6]
+ 343 * v2[21] == 228375)
s.add(356 * v2[20]
+ 200 * v2[19]
+ 136 * v2[9]
+ 301 * v2[8]
+ 284 * v2[7]
+ 364 * v2[6]
+ 458 * v2[10]
+ 5 * v2[18]
+ 61 * v2[21] == 211183)
s.add(154 * v2[20]
+ 55 * v2[19]
+ 406 * v2[18]
+ 107 * v2[10]
+ 80 * v2[8]
+ 66 * v2[6]
+ 71 * v2[7]
+ 17 * v2[9]
+ 71 * v2[21] == 96788)
s.add( 335 * v2[20]
+ 201 * v2[19]
+ 197 * v2[9]
+ 280 * v2[8]
+ 409 * v2[7]
+ 56 * v2[6]
+ 494 * v2[10]
+ 63 * v2[18]
+ 99 * v2[21] == 204625)
s.add(428 * v2[16] + 1266 * v2[15] + 1326 * v2[14] + 1967 * v2[13] + 3001 * v2[12] + 81 * v2[11] + 2439 * v2[17] == 1109296)
s.add(2585 * v2[16] + 4027 * v2[15] + 141 * v2[14] + 2539 * v2[13] + 3073 * v2[12] + 164 * v2[11] + 1556 * v2[17] == 1368547)
s.add(2080 * v2[16] + 358 * v2[15] + 1317 * v2[14] + 1341 * v2[13] + 3681 * v2[12] + 2197 * v2[11] + 1205 * v2[17] == 1320274)



s.add(840 * v2[16] + 1494 * v2[15] + 2353 * v2[14] + 235 * v2[13] + 3843 * v2[12] + 1496 * v2[11] + 1302 * v2[17] == 1206735)
s.add(101 * v2[16] + 2025 * v2[15] + 2842 * v2[14] + 1559 * v2[13] + 2143 * v2[12] + 3008 * v2[11] + 981 * v2[17] == 1306983)
s.add(1290 * v2[16] + 3822 * v2[15] + 1733 * v2[14] + 292 * v2[13] + 816 * v2[12] + 1017 * v2[11] + 3199 * v2[17] == 1160573)
s.add(186 * v2[16]
+ 2712 * v2[15]
+ 2136 * v2[14]
+ 98 * v2[11]
+ 138 * v2[12]
+ 3584 * v2[13]
+ 1173 * v2[17]==1005746)

print(s.check())


m=s.model()
res=''
for i in range(0,22):
res+=(chr(m[v2[i]].as_long()))

print(res)

5.24

[GDOUCTF 2023]L!s!

考察了bindiff插件的使用

比较两个文件的不同之处,一般用来比较原文件和dump之后的文件

先用ida随便打开一个文件,再关闭,生成集成的那个文件(i64),再用ida打开另一个文件,打开插件bindiff,选择Diff Database 打开刚刚的i64文件,就可以查看这两个文件的不同之处了

密文提取出来:

1
int aa[] = { 0x04,0x16,0x0f,0x18,0x0a,0x37,0x2e,0x7d,0x22,0x28,0x25,0x2a,0x13,0x7d,0x3f,0x13,0x2d,0x13,0x39,0x3f,0x7f,0x2a,0x39,0x20,0x13,0x38,0x7c,0x7c,0x20,0x31};

加密就仅仅只有一个异或v7,从0-256爆破遍,去结果里找flag

image-20230420120722978

还算好找

5.26

EasyDotnet

月赛的一道题。c#逆向,加了confuserex的壳。

用工具可以脱掉壳,但是会破坏程序,虽然源码能看到但程序不能动调,而这个题的源码里有字符串加密,要看字符串就必须动调看,所以这条路不行

那么就考虑手动脱壳:

仔细阅读代码可以发现,程序中 .static constructor() 是没有被加密的。阅读它调用的 第一个函数,可以发现其中调用了 Marshal.GetHINSTANCE() 和 kernel32.VirtualProtect() ,可 以猜测该函数是用于解密代码的。于是,在 .static constructor() 的第二行下断点,待 运行到该点之后,将程序的内存映像 dump 下来,完成脱壳

注意这里的dump必须要在dnspy下边的那个模块那里保存,不能去左上角文件那里保存模块,这样保存的是整个文件,会报错

dump之后再用dnspy打开,这个时候就可以看到main函数内有源码了,但是还有一些没回复,使用de4dot继续脱一下,就完整的脱掉了

再看源码,有两处反调试nop掉,再逆逻辑就行了,是一个base32加密

如何逆就不说了,主要是手动脱壳

5.27 5.28

这两天国赛,不太想写了

5.29

ciscn 2023 babyRE

进入题目开头给的网站,可视化编程,真是baby re了,导入xml文件,可以看到对输入的处理就是逐位与前一位异或,密文也给出,不过顺序有点不好搞,那么就插入一个for循环,让程序自己打印出密文

5.30

春秋杯 re wp | shimmer’s blog (shimmer123456.github.io)

5.31

春秋杯 re wp | shimmer’s blog (shimmer123456.github.io)

6.1

ciscn 逆向wp | shimmer’s blog (shimmer123456.github.io)

6.2

ciscn 逆向wp | shimmer’s blog (shimmer123456.github.io)

6.3

[MoeCTF 2022]chicken_soup

1
2
3
4
5
6
7
8
9
10
enc = [0xcd,0x4d,0x8c,0x7d,0xad,0x1e,0xbe,0x4a,0x8a,0x7d,0xbc,0x7c,0xfc,0x2e,0x2a,0x79,0x9d,0x6a,0x1a,0xcc,0x3d,0x4a,0xf8,0x3c,0x79,0x69,0x39,0xd9,0xdd,0x9d,0xa9,0x69,0x4c,0x8c,0xdd,0x59,0xe9,0xd7]

for i in range(len(enc)):
enc[i] = ((enc[i]//16 | enc[i]<<4)) & 0xff
print((enc[i]))

for i in range(len(enc)-1, 0, -1):
enc[i-1] -= enc[i]

print(bytes(enc))

6.4

hsctf dasctf

6.5

陕西省赛 逆向wp | shimmer’s blog (shimmer123456.github.io)

6.6

陕西省赛 逆向wp | shimmer’s blog (shimmer123456.github.io)

6.7

[SWPUCTF 2021 新生赛]PYRE

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
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.9

import base64
import hashlib


def init(x, y):
a = 0
y = hashlib.md5(y.encode()).hexdigest()
b = []
for i in range(256):
x.append(i)
b.append(y[i % len(y)])
for i in range(256):
a = (a + x[i] + ord(b[i])) % 256
x[i], x[a] = x[a], x[i]


def Encrypt(x1, y1):
a1 = a2 = 0
c1 = ''
for j in y1:
a1 = (a1 + 1) % 256
a2 = (a2 + x1[a1]) % 256
x1[a1], x1[a2] = x1[a2], x1[a1]
z1 = (x1[a1] + x1[a2]) % 256
z2 = chr(ord(j) ^ x1[(x1[a1] + x1[a2]) % 256])
print(x1[(x1[a1] + x1[a2]) % 256], end=',')
c1 += z2
# c1 = base64.b64encode(c1.encode())
# print(c1)
return c1


# input_str = input('input flag pls:')
s = []
init(s, 'bJLVFYw3WI5ncGez')
# if Encrypt(s, input_str).decode() == 'w4s1PUYsJ8OYwpRXVjvDkVPCgzIEJ27Dt2I=':
# print('good!')
# else:
# print('nonono!')

ci = 'w4s1PUYsJ8OYwpRXVjvDkVPCgzIEJ27Dt2I='
ci = base64.b64decode(ci.encode()).decode()
print(ci)
Encrypt(s, ci)
key = [133, 102, 110, 5, 120, 97, 163, 249, 56, 36, 94, 142, 34, 244, 67, 91, 75, 1, 155, 31]
for i in range(len(ci)):
a = key[i] ^ ord(ci[i])
print(chr(a), end="")

6.8

[MoeCTF 2021]Realezpy

直接爆破:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
c = [119, 121, 111, 109, 100, 112, 123, 74, 105, 100, 114, 48, 120, 95, 49, 99, 95, 99, 121, 48, 121, 48, 121, 48, 121, 48, 95, 111, 107, 99, 105, 125]

def encrypt(a):
result = []
for i in range(len(a)):
if ord('a') <= ord(a[i]) <= ord('z'):
result.append((ord(a[i]) + 114 - ord('a')) % 26 + ord('a'))
elif ord('A') <= ord(a[i]) <= ord('Z'):
result.append((ord(a[i]) + 514 - ord('A')) % 26 + ord('A'))
else:
result.append(ord(a[i]))
else:
return result


for i in range(0,len(c)):
for k in range(37,127):
if c[i]==encrypt(chr(k))[0]:
print(chr(k),end="")
break

6.9

[MTCTF 2021]wow

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
from ctypes import *
import binascii
from Crypto.Util.number import *


def MX(z, y, total, key, p, e):
temp1 = (z.value >> 5 ^ y.value << 2) + (y.value >> 3 ^ z.value << 4)
temp2 = (total.value ^ y.value) + (key[(p & 3) ^ e.value] ^ z.value)

return c_uint32(temp1 ^ temp2)


def encrypt(n, v, key):
delta = 0x9e3779b9
rounds = 6 + 52 // n

total = c_uint32(0)
z = c_uint32(v[n - 1])
e = c_uint32(0)

while rounds > 0:
total.value += delta
e.value = (total.value >> 2) & 3
for p in range(n - 1):
y = c_uint32(v[p + 1])
v[p] = c_uint32(v[p] + MX(z, y, total, key, p, e).value).value
z.value = v[p]
y = c_uint32(v[0])
v[n - 1] = c_uint32(v[n - 1] + MX(z, y, total,
key, n - 1, e).value).value
z.value = v[n - 1]
rounds -= 1

return v


def decrypt(n, v, key):
delta = 0x67452301
# rounds = 6 + 52//n
rounds = 12

total = c_uint32(rounds * delta)
y = c_uint32(v[0])
e = c_uint32(0)

while rounds > 0:
e.value = (total.value >> 2) & 3
for p in range(n - 1, 0, -1):
z = c_uint32(v[p - 1])
v[p] = c_uint32((v[p] - MX(z, y, total, key, p, e).value)).value
y.value = v[p]
z = c_uint32(v[n - 1])
v[0] = c_uint32(v[0] - MX(z, y, total, key, 0, e).value).value
y.value = v[0]
total.value -= delta
rounds -= 1

return v


# test
if __name__ == "__main__":
# 该算法中每次可加密不只64bit的数据,并且加密的轮数由加密数据长度决定
v = [0xD8F758F5, 0x526849DB, 0xE2D72563, 0x485EEFAC, 0x608F4BC6,
0x5859F76A, 0xB03565A3, 0x3E4091C1, 0xD3DB5B9A, 0x00000000]
k = [0x0EFCDAB89, 0x10325476, 0x98BADCFE, 0x0C3D2E1F0]
n = 9

# print("Data is : ", hex(v[0]), hex(v[1]))
# res = encrypt(n, v, k)
# print("Encrypted data is : ", hex(res[0]), hex(res[1]))
res = decrypt(n, v, k)
print("Decrypted data is : ", res)
for i in range(len(res)):
print(long_to_bytes(res[i])[::-1].decode(), end="")
"""
Data is : 0x12345678 0x78563412
Encrypted data is : 0xef86c2bb 0x25f31b5e
Decrypted data is : 0x12345678 0x78563412
"""

6.10

[WUSTCTF 2020]level4

1
2
3
4
5
6
7
8
9
10
11
12
13
def PreOrder(Postorder,Inorder):
length = len(Postorder)
if length == 0:
return 0
root = Postorder[length-1]
for i in range(length):
if root == Inorder[i]:
break
print(root,end="")
PreOrder(Postorder[0:i],Inorder[0:i])
PreOrder(Postorder[i:length-1],Inorder[i+1:length])
PreOrder("20f0Th{2tsIS_icArE}e7__w","2f0t02T{hcsiI_SwA__r7Ee}")
#二叉树遍历 前中求后

6.11

[长城杯 2021 院校组]Just_cmp-re

1
2
3
4
5
6
7
8
9
10
11
enc = [0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x07, 0x0A, 0x37, 0x0A, 
0x08, 0x0A, 0x06, 0x06, 0x0B, 0x38, 0x07, 0x0A, 0x3B, 0x08,
0x38, 0x0E, 0x0F, 0x3B, 0x3A, 0x0A, 0x0B, 0x06, 0x09, 0x07,
0x3B, 0x37, 0x0D, 0x0F, 0x07, 0x38, 0x0F, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]


flag = ''
for i in range(len(enc)):
print(chr(enc[i]+0x2a),end="")

6.12

[MoeCTF 2022]ezTea

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
#include <stdio.h>
#include <stdint.h>
void decrypt (uint32_t* v, uint32_t* k) { //
uint32_t v0 = v[0], v1 = v[1], sum = 0xd33b470*32;
uint32_t delta = 0xd33b470;
for (int i = 0; i < 32; i++) {
v1 -= ((v0<<4) + k[2]) ^ (v0 + sum) ^ ((v0>>5) + k[3]);
v0 -= ((v1<<4) + k[0]) ^ (v1 + sum) ^ ((v1>>5) + k[1]);
sum -= delta;
}
v[0] = v0;
v[1] = v1;
}
int main() {

int8_t enc[] = {0x17, 0x65, 0x54, 0x89, 0xed, 0x65, 0x46, 0x32, 0x3d, 0x58, 0xa9, 0xfd, 0xe2, 0x5e,
0x61, 0x97, 0xe4, 0x60, 0xf1, 0x91, 0x73, 0xe9, 0xe9, 0xa2, 0x59, 0xcb, 0x9a, 0x99,
0xec, 0xb1, 0xe1, 0x7d};
uint32_t k[4] = {1, 2, 3, 4};

for(int i = 0; i<32;i+=8){
uint32_t v[2] = {*(uint32_t *)&enc[i], *(uint32_t *)&enc[i+4]};
decrypt(v, k);

for (int j = 0; j < 2; j++)
{
for (int k = 0; k < 4; k++)
{
printf("%c", v[j] & 0xff);
v[j] >>= 8;
}
}

}
return 0;
}

6.13

[MoeCTF 2021]大佬请喝coffee

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from z3 import *

arrayOfChar = [Int("input[%d]"%i) for i in range(9)]

s = Solver()
s.add(arrayOfChar[0] * 4778 + arrayOfChar[1] * 3659 + arrayOfChar[2] * 9011 + arrayOfChar[3] * 5734 + arrayOfChar[4] * 4076 + arrayOfChar[5] * 6812 + arrayOfChar[6] * 8341 + arrayOfChar[7] * 6765 + arrayOfChar[8] * 7435 == 5711942 )
s.add(arrayOfChar[0] * 4449 + arrayOfChar[1] * 5454 + arrayOfChar[2] * 4459 + arrayOfChar[3] * 5800 + arrayOfChar[4] * 6685 + arrayOfChar[5] * 6120 + arrayOfChar[6] * 7357 + arrayOfChar[7] * 3561 + arrayOfChar[8] * 5199 == 4885863 )
s.add(arrayOfChar[0] * 3188 + arrayOfChar[1] * 6278 + arrayOfChar[2] * 9411 + arrayOfChar[3] * 5760 + arrayOfChar[4] * 9909 + arrayOfChar[5] * 7618 + arrayOfChar[6] * 7184 + arrayOfChar[7] * 4791 + arrayOfChar[8] * 8686 == 6387690 )
s.add(arrayOfChar[0] * 8827 + arrayOfChar[1] * 7419 + arrayOfChar[2] * 7033 + arrayOfChar[3] * 9306 + arrayOfChar[4] * 7300 + arrayOfChar[5] * 5774 + arrayOfChar[6] * 6588 + arrayOfChar[7] * 5541 + arrayOfChar[8] * 4628 == 6077067 )
s.add(arrayOfChar[0] * 5707 + arrayOfChar[1] * 5793 + arrayOfChar[2] * 4589 + arrayOfChar[3] * 6679 + arrayOfChar[4] * 3972 + arrayOfChar[5] * 5876 + arrayOfChar[6] * 6668 + arrayOfChar[7] * 5951 + arrayOfChar[8] * 9569 == 5492294 )
s.add(arrayOfChar[0] * 9685 + arrayOfChar[1] * 7370 + arrayOfChar[2] * 4648 + arrayOfChar[3] * 7230 + arrayOfChar[4] * 9614 + arrayOfChar[5] * 9979 + arrayOfChar[6] * 8309 + arrayOfChar[7] * 9631 + arrayOfChar[8] * 9272 == 7562511 )
s.add(arrayOfChar[0] * 6955 + arrayOfChar[1] * 8567 + arrayOfChar[2] * 7949 + arrayOfChar[3] * 8699 + arrayOfChar[4] * 3284 + arrayOfChar[5] * 6647 + arrayOfChar[6] * 3175 + arrayOfChar[7] * 8506 + arrayOfChar[8] * 6552 == 5970432 )
s.add(arrayOfChar[0] * 4323 + arrayOfChar[1] * 4706 + arrayOfChar[2] * 8081 + arrayOfChar[3] * 7900 + arrayOfChar[4] * 4862 + arrayOfChar[5] * 9544 + arrayOfChar[6] * 5211 + arrayOfChar[7] * 7443 + arrayOfChar[8] * 5676 == 5834523 )
s.add(arrayOfChar[0] * 3022 + arrayOfChar[1] * 8999 + arrayOfChar[2] * 5058 + arrayOfChar[3] * 4529 + arrayOfChar[4] * 3940 + arrayOfChar[5] * 4279 + arrayOfChar[6] * 4606 + arrayOfChar[7] * 3428 + arrayOfChar[8] * 8889 == 4681110)
if s.check() == sat:
m = s.model()
for i in range(9):
print(chr(int(str(m[arrayOfChar[i]]))),end = '')

6.15

[MoeCTF 2022]D_flat

1
2
3
4
5
6
7
<?php 
$flag = [109,111,101,99,116,102,123,68,95,102,108,97,116,101,95,105,115,95,67,95,115,104,97,114,112,33,125];
for ($i=0; $i < count($flag); $i++) {
echo chr($flag[$i]);
}
?>
moectf{D_flate_is_C_sharp!}

6.16

[MoeCTF 2022]fake_key

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
_BOOL8 __fastcall sub_4015A2(__int64 a1, __int64 a2)
{
char v2; // dl
int v3; // eax
int v5; // [rsp+8h] [rbp-8h]
int v6; // [rsp+Ch] [rbp-4h]

v6 = 0;
v5 = 0;
while ( v6 <= 28 )
{
v2 = *(_BYTE *)(a1 + v6);
v3 = v6++;
if ( v2 == *(_BYTE *)(a2 + v3) )
++v5;
}
return v5 == 29;
}
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char const *argv[])
{
for (int i = 0; i <= 28; ++i)
{
printf("%d,", rand() % 10);
}
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cip = [0x15, 0x21, 0x0F, 0x19, 0x25, 0x5B, 0x19, 0x39, 0x5F, 0x3A,
0x3B, 0x30, 0x74, 0x07, 0x43, 0x3F, 0x09, 0x5A, 0x34, 0x0C,
0x74, 0x3F, 0x1E, 0x2D, 0x27, 0x21, 0x12, 0x16, 0x1F]
key = [
0x79, 0x75, 0x6E, 0x7A, 0x68, 0x31, 0x6A, 0x75, 0x6E, 0x54,
0x43, 0x4C, 0x2C, 0x74, 0x72, 0x61, 0x63, 0x6B, 0x59, 0x59,
0x44, 0x53
]
rand_num = [1, 7, 4, 0, 9, 4, 8, 8, 2, 4, 5, 5, 1, 7,
1, 1, 5, 2, 7, 6, 1, 4, 2, 3, 2, 2, 1, 6, 8]
tmp = []

for i in range(len(cip)):
tmp.append(cip[i]-rand_num[i])

for i in range(len(tmp)):
print(chr(tmp[i] ^ key[i % len(key)]), end='')
# print(tmp)

6.17

[SDCTF 2022]A Bowl of Pythons

1
2
3
4
5
6
7
f = b'co\\7\x7f\x7f`|p\x15\x0e\x8a\x0fP\x14\x18\xfe\xa9\xf3\xe2y\xdd'
# if bytes((g[i] ^ (a(i) & 0xff) for i in range(len(g)))) != f:
for i in range(len(f)):
s = a(i) & 0xff
flag = s ^ f[i]
print(chr(flag), end='')
#an_3xtra_YuMMY_LaZagnA

6.18

[MoeCTF 2022]Art

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
data='02 18 0f f8 19 04 27 d8 eb 00 35 48 4d 2a 45 6b 59 2e 43 01 18 5c 09 09 09 09 b5 7d'
data=data.split(' ')
def encode(first,second):
return ord(first)^ord(second)+ord(first)%17^0x19
flag='moectf{'
for i in range(6,28):
current_first=flag[i]
print("current_first:"+current_first+"\n")
expected_value=int(data[i],16)
for letter in printable:
result=encode(current_first,letter)
if result==expected_value:
flag+=letter
break
print(flag)

6.19

[长城杯 2022 高校组]baby_re

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
from new import *



flag = '5WEU5ROREb0hK+AurHXCD80or/h96jqpjEhcoh2CuDh='
word = list(word)

def test1():
x = ''
for i in range(0, len(flag)//4):
print(x)
t = 1
for i1 in word:
for i2 in word:
for i3 in word:
if t == 0:
break
tmp1 = f'{i1}{i2}{i3}'
tmp2 = mmo(x + tmp1)()
if tmp2 == flag[:len(tmp2)]:
print(tmp2)
x += tmp1
t = 0

test1()
#5WEU5ROREb0hK+AurHXCD80or/h96jqpjEhcoh2C
x ='8b98aa2e10ac53e21240ee10a9054b'
1
2
3
4
5
6
7
8
9
10
11
12
x ='8b98aa2e10ac53e21240ee10a9054b'

for i1 in word:
for i2 in word:
tmp1 = f'{i1}{i2}'
tmp2 = mmo(x + tmp1)()
if tmp2 == flag:
print(tmp2)
print(x + tmp1)

# 5WEU5ROREb0hK+AurHXCD80or/h96jqpjEhcoh2CuDh=
# flag = 8b98aa2e10ac53e21240ee10a9054be3

6.20

[MoeCTF 2021]midpython

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
              2 LOAD_CONST               0 ((69, 70, 79, 72, 88, 75, 85, 127, 89, 85, 74, 19, 74, 122, 107, 103, 75, 77, 9, 73, 29, 28, 67))
4 CALL_FINALLY 1 (to 7)
6 STORE_NAME 0 (key)

2 8 LOAD_CONST 1 (<code object <lambda> at 0x000001C308563EA0, file "\\Mac\Home\NSSCTF\problems\moeCTF_2021\Challenges\Reverse\midpython\Midpython.py", line 2>)
10 LOAD_CONST 2 ('<lambda>')
12 MAKE_FUNCTION 0
14 STORE_NAME 1 (xxor)

3 16 LOAD_CONST 3 (<code object <lambda> at 0x000001C308563F50, file "\\Mac\Home\NSSCTF\problems\moeCTF_2021\Challenges\Reverse\midpython\Midpython.py", line 3>)
18 LOAD_CONST 2 ('<lambda>')
20 MAKE_FUNCTION 0
22 STORE_NAME 2 (xoor)

4 24 LOAD_CONST 4 (<code object <lambda> at 0x000001C30856A030, file "\\Mac\Home\NSSCTF\problems\moeCTF_2021\Challenges\Reverse\midpython\Midpython.py", line 4>)
26 LOAD_CONST 2 ('<lambda>')
28 MAKE_FUNCTION 0
30 STORE_NAME 3 (xorr)

5 32 LOAD_NAME 4 (len)
34 LOAD_NAME 0 (key)
36 CALL_FUNCTION 1
38 STORE_NAME 5 (length)

6 40 LOAD_NAME 6 (input)
42 LOAD_CONST 5 ('>>>input your flag:\n>>>')
44 CALL_FUNCTION 1
46 STORE_NAME 7 (ipt)

7 48 LOAD_CONST 6 (1)
50 STORE_NAME 8 (flag)

8 52 LOAD_NAME 4 (len)
54 LOAD_NAME 7 (ipt)
56 CALL_FUNCTION 1
58 LOAD_NAME 5 (length)
60 COMPARE_OP 2 (==)
62 POP_JUMP_IF_FALSE 114

9 64 LOAD_NAME 9 (range)
66 LOAD_NAME 5 (length)
68 CALL_FUNCTION 1
70 GET_ITER
>> 72 FOR_ITER 38 (to 112)
74 STORE_NAME 10 (i)

10 76 LOAD_NAME 3 (xorr)
78 LOAD_NAME 11 (ord)
80 LOAD_NAME 7 (ipt)
82 LOAD_NAME 10 (i)
84 BINARY_SUBSCR
86 CALL_FUNCTION 1
88 LOAD_NAME 10 (i)
90 CALL_FUNCTION 2
92 LOAD_NAME 0 (key)
94 LOAD_NAME 10 (i)
96 BINARY_SUBSCR
98 COMPARE_OP 3 (!=)
100 POP_JUMP_IF_FALSE 72

11 102 LOAD_CONST 7 (0)
104 STORE_NAME 8 (flag)

12 106 POP_TOP
108 JUMP_ABSOLUTE 118
110 JUMP_ABSOLUTE 72
>> 112 JUMP_FORWARD 4 (to 118)

14 >> 114 LOAD_CONST 7 (0)
116 STORE_NAME 8 (flag)

15 >> 118 LOAD_NAME 8 (flag)
120 LOAD_CONST 6 (1)
122 COMPARE_OP 2 (==)
124 POP_JUMP_IF_FALSE 136

16 126 LOAD_NAME 12 (print)
128 LOAD_CONST 8 ('>>>Right!!')
130 CALL_FUNCTION 1
132 POP_TOP
134 JUMP_FORWARD 8 (to 144)

18 >> 136 LOAD_NAME 12 (print)
138 LOAD_CONST 9 ('>>>Wrong!!')
140 CALL_FUNCTION 1
142 POP_TOP
>> 144 LOAD_CONST 10 (None)
146 RETURN_VALUE

Disassembly of <code object <lambda> at 0x000001C308563EA0, file "\\Mac\Home\NSSCTF\problems\moeCTF_2021\Challenges\Reverse\midpython\Midpython.py", line 2>:
2 0 LOAD_FAST 0 (x)
2 LOAD_FAST 1 (y)
4 BINARY_XOR
6 LOAD_CONST 1 (11)
8 BINARY_XOR
10 RETURN_VALUE

Disassembly of <code object <lambda> at 0x000001C308563F50, file "\\Mac\Home\NSSCTF\problems\moeCTF_2021\Challenges\Reverse\midpython\Midpython.py", line 3>:
3 0 LOAD_GLOBAL 0 (xxor)
2 LOAD_FAST 0 (x)
4 LOAD_FAST 1 (y)
6 CALL_FUNCTION 2
8 LOAD_CONST 1 (45)
10 BINARY_XOR
12 RETURN_VALUE

Disassembly of <code object <lambda> at 0x000001C30856A030, file "\\Mac\Home\NSSCTF\problems\moeCTF_2021\Challenges\Reverse\midpython\Midpython.py", line 4>:
4 0 LOAD_GLOBAL 0 (xoor)
2 LOAD_FAST 0 (x)
4 LOAD_FAST 1 (y)
6 CALL_FUNCTION 2
8 LOAD_CONST 1 (14)
10 BINARY_XOR
12 RETURN_VALUE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
xxor = lambda x, y: (x ^ y) ^ 11
xoor = lambda x, y: (xxor(x, y) ^ 45)
xorr = lambda x, y: (xoor(x, y) ^ 14)

length = len(key)
ipt = input(">>>input your flag:\n>>>")
flag = 1

if len(ipt) == length:
for i in range(length):
if xorr(ord(ipt[i]), i) != key[i]:
flag = 0
break
else:
flag = 0

if flag == 1:
print(">>>Right!!")
else:
print(">>>Wrong!!")

1
2
3
4
5
6

xxor = lambda x, y: (x ^ y) ^ 11 ^ 45 ^ 14

for i in range(len(key)):
print(chr(xxor(key[i], i)), end='')
#moectf{Pyth0n_M@st3r!!}

6.21

[MoeCTF 2021]EinfachRe

1
2
3
4
5
6
def EinfachRe():
enflag = [0x28, 0x15, 0x3a, 0x1b, 0x44, 0x14, 6] #在IDA中找到相应值
flag = 'moectf'
for i in range(6):
print(chr(ord(flag[i]) ^ enflag[i]), end='')
EinfachRe()

6.22

[MoeCTF 2022]Broken_hash

1
2
3
4
5
6
7
8
enc = [1685343386, 75247601, 2732016274, 2243884926, 1897909239, 1721636361, 1807588790, 1765918884, 2976794803, 3727823238, 1381099714, 4220491175, 1897909239, 3411820461, 911641333, 4220491175, 2192374122, 1977406832, 2129661504, 4220491175, 1273573706, 3411820461, 2732016274, 3727823238, 4220491175, 1184006056, 2976794803, 3619791888, 1450407363, 1897909239, 4220491175, 2618945779, 3493194004, 4220491175, 1765918884, 192746389, 3619791888, 3363470462, 4220491175, 3619791888, 3727823238, 1381099714, 4220491175, 3577220178, 3198786875, 3470489938, 4220491175, 1933927200, 3619791888, 3727823238, 4220491175, 1478334949, 2732016274, 1897909239, 4220491175, 104278034, 4220491175, 1933927200, 3470489938, 4015252052, 4220491175, 2668773965, 1721636361, 4220491175, 2618945779, 4275009157, 192746389, 406055089, 4220491175, 2674318596, 2732016274, 3619791888, 4220491175, 1765918884, 2255269711, 75247601, 1685343386, 4220491175, 3577220178, 3470489938, 3727823238, 2168798531, 3411820461, 2976794803, 3313039427, 3470489938, 3727823238, 3817631495, 2342426536, 2413797087, 3515255702, 2477773265, 2374754181, 2560548742, 3750860446, 4123238593]
dic=[0x0BEA99D3B,0x0B16E48B3,0x5C6054F,0x36568AF5,0x0BEA2375F,0x567375C3,0x0BF0FD0CB,0x4BE9314A,0x7F2A2EBE,0x0C87A7C7E,0x0D7C1A410,0x9E3919E7,0x85BEF77E,0x5251E8C2,0x0A2D74292,0x669E1609,0x5C1DFF11,0x0CB5C3FAD,0x0FECF7685,0x0B0F33A9A,0x1833E8B1,0x0B7D1395,0x64744C9A,0x0DE321186,0x47C2FF1,0x0EF53E254,0x1902B329,0x866CAF4F,0x4A528AE0,0x711FCBF7,0x0CEDB7952,0x352B172C,0x0AFEA7FF6,0x3175EDAB,0x0D035E914,0x20D324AE,0x6372812,0x46927FA8,0x73456320,0x4E3F843,0x75DCD570,0x6941C8A4,0x581D99E5,0x7EF00E40,0x7A260E4D,0x0C578F843,0x17947C53,0x786C70,0x9C19F0F3,0x1D795AC9,0x9F12424D,0x0AB021E08,0x77ACB10,0x0D1D0F68E,0x82ACF96A,0x9F66DD04,0x8AD9BAF7,0x0AAE6D8C9,0x0E73CAEF,0x0BFC92893,0x0D5380C52,0x81453D43,0x94D2FB03,0x17AA5D21,0x359A6F74,0x0E3FC2922,0x0B12D13F1,0x0E3F11899,0x8BC73EC0,0x0F9B5524E,0x3C661DDC,0x0A4896A25,0x0EADC6BE1,0x0C6059399,0x41274AD3,0x0CCB1F1EC,0x717EEA6E,0x0D9C61FD,0x0FB8F95A7,0x6BBD9DB6,0x0BF9FE524,0x0E38C6F07,0x7C710092,0x0BEA99D3B,0x0BEA99D3B,0x0BEA99D3B,0x0BEA99D3B,0x0BEA99D3B]
dictionary = {3198786875: '0', 2976794803: '1', 96863567: '2', 911641333: '3', 3198302047: '4', 1450407363: '5', 3205484747: '6', 1273573706: '7', 2133470910: '8', 3363470462: '9', 3619791888: 'a', 2654542311: 'b', 2243884926: 'c', 1381099714: 'd', 2732016274: 'e', 1721636361: 'f', 1545469713: 'g', 3411820461: 'h', 4275009157: 'i', 2968730266: 'j', 406055089: 'k', 192746389: 'l', 1685343386: 'm', 3727823238: 'n', 75247601: 'o', 4015252052: 'p', 419607337: 'q', 2255269711: 'r', 1246923488: 's', 1897909239: 't', 3470489938: 'u', 892016428: 'v', 2951380982: 'w', 829812139: 'x', 3493194004: 'y', 550708398: 'z', 104278034: 'A', 1184006056: 'B', 1933927200: 'C', 82049091: 'D', 1977406832: 'E', 1765918884: 'F', 1478334949: 'G', 2129661504: 'H', 2049314381: 'I', 3313039427: 'J', 395607123: 'K', 7892080: 'L', 2618945779: 'M', 494492361: 'N', 2668773965: 'O', 2869042696:
'P', 125487888: 'Q', 3520132750: 'R', 2192374122: 'S', 2674318596: 'T', 2329524983: 'U', 2867255497: 'V', 242469615: 'W', 3217631379: 'X', 3577220178: 'Y', 2168798531: 'Z', 2496854787: '!', 397040929: '#', 899313524: '$', 3824953634: '%', 2972521457: '&', 3824228505: '(', 2345090752: ')', 4189409870: '<', 1013325276: '=', 2760469029: '>', 3940314081: '?', 3322254233: '@', 1093094099: '[', 3434213868: '\\', 1904142958: ']', 228352509: '^', 4220491175: '_', 1807588790: '{', 3214927140: '|', 3817631495: '}', 2087780498: '~'}
for i in range(len(enc)):
print(dictionary[enc[i]],end = '')


6.23

[HUBUCTF 2022 新生赛]Anger?Angr

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
from z3 import *

a1 = [BitVec('a1%s' % i,8) for i in range(32) ]
print(a1)
s=Solver()
s.add(BV2Int(a1[10]) <= 40 , 24 * BV2Int(a1[30]) % 84 == 12 , BV2Int(a1[16]) != 66)
s.add(BV2Int(a1[4]) > 51 , BV2Int(a1[15]) > 90 , BV2Int(a1[18]) != 38)

s.add(BV2Int(a1[3]) <= 107 , 61 * BV2Int(a1[20]) % 95 == 2 , BV2Int(a1[27]) != 67)
s.add(BV2Int(a1[29]) <= 69 , 39 * BV2Int(a1[18]) % 57 == 27 , BV2Int(a1[29]) <= 90)
s.add(a1[21] > 42 , a1[0] > 35 , a1[7] != 74)
s.add(a1[19] <= 79 , a1[15] > 74 , a1[22] > 92)
s.add(a1[14]<=89,a1[24]!=95)
s.add( a1[26] > 36)
s.add(a1[22]>53,BV2Int(a1[12])!=33)
s.add( (29 * BV2Int(a1[6])) % 33 == 24)
s.add( 41 * BV2Int(a1[26]) % 31 == 27)
s.add(BV2Int(a1[16]) != 71 )
s.add( 22 * BV2Int(a1[24]) % 96 == 60)
s.add(a1[25] != 102 , a1[18] != 95)
s.add( 38 * BV2Int(a1[6]) % 54 == 36)
s.add(a1[4]>52)
s.add(a1[11]<=76)
s.add( 72 * BV2Int(a1[6]) % 86 == 42 )
s.add(a1[5] <= 109 , a1[9] > 44 , a1[8] > 77)
s.add(a1[28] != 107 , a1[17] > 73)
s.add( 69 * BV2Int(a1[5]) % 3==0)
s.add(a1[0] != 70 , a1[13] > 72 , a1[1] <= 108)
s.add(a1[14]!=97)
s.add(a1[1]<=90)
s.add( 87 * BV2Int(a1[31]) % 69 == 45)
s.add(a1[11] <= 99 , a1[24] != 107 , a1[26] <= 111)
s.add(a1[0] > 36 , a1[3] <= 65 , a1[2] > 41)
s.add(a1[23] != 84 , a1[16] != 101 , a1[13] <= 99)
s.add(a1[19] > 33 , a1[25] <= 122 , a1[28] != 67)
s.add(86 * BV2Int(a1[17]) % 74 == 64 , BV2Int(a1[10]) != 87 , BV2Int(a1[30]) <= 108)
s.add(BV2Int(a1[8])!=87)
s.add(46 * BV2Int(a1[12]) % 26 == 20 , 50 * BV2Int(a1[9]) % 52 == 22)
s.add(BV2Int(a1[8]) > 47 ,BV2Int(a1[21]) <= 100 , BV2Int(a1[11]) > 34)
s.add(BV2Int(a1[27]) != 127 , BV2Int(a1[21]) > 42 )
s.add( 5 * BV2Int(a1[10]) % 32 == 20)
s.add( BV2Int(a1[12]) <= 107)
s.add(BV2Int(a1[19]) != 91 , BV2Int(a1[29]) != 124)
s.add( 57 * BV2Int(a1[13]) % 13 == 2 , BV2Int(a1[27]) <= 100 , 61 * BV2Int(a1[22]) % 67 == 66)
s.add(BV2Int(a1[7]) <= 118 , BV2Int(a1[1]) != 64 , BV2Int(a1[30]) > 44)
s.add(BV2Int(a1[5]) != 43 , BV2Int(a1[31]) != 88 , BV2Int(a1[31]) > 35)
s.add(BV2Int(a1[20]) <= 101 , BV2Int(a1[15]) > 64 , BV2Int(a1[4]) != 43)

s.add(BV2Int(a1[17])>56)
s.add(BV2Int(a1[28])<=115)
s.add( (BV2Int(a1[25]) *64) % 21 == 4 )
s.add(BV2Int(a1[20]) != 43 , BV2Int(a1[2]) <= 82 , BV2Int(a1[2]) > 39)
s.add(BV2Int(a1[23]) > 34 , BV2Int(a1[7]) > 52 , BV2Int(a1[14]) > 44)
s.add(BV2Int(a1[3]) <= 83 , 59 * BV2Int(a1[9]) % 86 == 69 , BV2Int(a1[23]) <= 103)
for i in range(0,32):
s.add(BV2Int(a1[i])<127)
s.add(BV2Int(a1[i])>30)
s.check()
m=s.model()
print(m)
res=''
for i in range(0,32):
res+=(chr(m[a1[i]].as_long()))
print(res)