红白机

6502汇编,直接找一个在线网站编译运行一下即可

Easy 6502 (codediy.github.io)

image-20240219145744166

Xor

upx -d去壳,然后一堆轮密钥异或,细致一些就可以

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
#include<bits/stdc++.h>
using namespace std;

char enc[] = "`agh{^bvuwTooahlYocPtmyiijj|ek'p";
char key1[] = "63290794207715587679621386735000";
char key7[] = "41803873625901363092606632787947";
char key2[20], key3[20], key4[20], key5[20], key6[20], key8[20], key9[20], key10[20], key11[20];
int main()
{
for(int i = 0; i < 16; i++)
{
key2[i] = key1[i];
key3[i] = key1[i + 16];
key8[i] = key7[i];
key9[i] = key7[i + 16];
}

for(int i = 0; i < 16; i++)key11[i] = enc[i], key10[i] = enc[i + 16];
for(int i = 0; i < 16; i++)
{
key10[i] = key10[i] ^ key8[16 - i] ^ key9[16 - i] ^ key8[i] ^ key9[i];
key11[i] = key11[i] ^ key8[16 - i] ^ key9[16 - i] ^ key8[i] ^ key9[i];
}

for(int i = 0; i < 16; i++)key6[i] = key10[i], key6[i + 16] = key11[i];

for(int i = 0; i < 16; i++)key4[i] = key6[i + 16], key5[i] = key6[i];

for(int i = 0; i < 16; i++)
{
key4[i] = key4[i] ^ key2[16 - i] ^ key3[16 - i] ^ key2[i] ^ key3[i];
key5[i] = key5[i] ^ key2[16 - i] ^ key3[16 - i] ^ key2[i] ^ key3[i];
}
printf("%s%s", key4, key5);
}

俄语学习

RC4,但是逆完了发现根本不要RC4,因为明文和密文都用了相同的轮密钥进行了加密,直接偏移即可

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
#include <bits/stdc++.h>
#include <string.h>
using namespace std;
unsigned char key_hex[] =
{
0xA7, 0xDF, 0xA7, 0xD6, 0xA7, 0xE9, 0xA7, 0xD6, 0xA7, 0xD4,
0xA7, 0xE0, 0xA7, 0xDF, 0xA7, 0xD6, 0xA7, 0xE9, 0xA7, 0xD6,
0xA7, 0xD4, 0xA7, 0xE0, 0xA7, 0xDF, 0xA7, 0xD6, 0xA7, 0xE9,
0xA7, 0xD6, 0xA7, 0xD4, 0xA7, 0xE0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned char key[44];
unsigned char enc[] = {
0x2B, 0x69, 0x26, 0x5B, 0x40, 0x59, 0x3A, 0x67, 0x38, 0x5B,
0x26, 0x6C, 0x24, 0x66, 0x38, 0x53, 0x38, 0x76, 0x24, 0x59,
0x26, 0x65, 0x3E, 0x7B
};
unsigned char key_bak[44];


int main()
{
for (int i = 0; i < 37; ++i )
{
key[i] = key_hex[i] - 'r';
key_bak[i] = key[i];
}
for(int i = 0; i < 24; i++)
{
printf("%c", enc[i] - key_bak[i] + 112);
}
}

Ezpython

用pyinstxtractor解包,再对ezpython.pyc进行反编译,发现缺少了以下函数

1
2
from gmssl import sm4
from secret import key, enc

再对 sm4.pycsecret.pyc进行反编译

密钥和密文是

1
2
key = 'BeginCTFBeginCTF'
enc = b'JmjJEAJGMT6F9bmC+Vyxy8Z1lpfaJzdEX6BGG/qgqUjUpQaYSON1CnZyX9YXTEClSRYm7PFZtGxmJw6LPuw1ww=='

直接 SM4 解密是错的,通过反编译的sm4.py发现有魔改,对密钥进行了异或 37 的操作

image-20240219150637763

异或密钥以后扔cyberchef解密

image-20240219165317020

Superguessor

有混淆和反调试,如果kernel32_IsDebuggerPresent返回结果为1异或0x44,为0异或0x33

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
#include<bits/stdc++.h>
using namespace std;
unsigned char enc[] =
{
0x51, 0x51, 0x52, 0x5F, 0x59, 0x43, 0x5D, 0x5F, 0x59, 0x49,
0x5A, 0x59, 0x56, 0x2E, 0x26, 0x1D, 0x2A, 0x37, 0x1A, 0x27,
0x29, 0x17, 0x28, 0x24, 0x2A, 0x38, 0x25, 0x21, 0x3D, 0x0F,
0x32, 0x3A, 0x3C, 0x3D, 0x36, 0x33, 0x2A
};
unsigned char key[] =
{
0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d,
0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61,
0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68
};

int main()
{
for(int j = 0; j <= 100; j++)
{
for(int i = 0; i < 37; i++)
{
printf("%c", enc[i] ^ (i + 51 + j));
}printf("\n");
}
}

real checkin xor

1
2
3
4
secret = [7, 31, 56, 25, 23, 15, 91, 21, 49, 15, 33, 88, 26, 48, 60, 58, 4, 86, 36, 64, 23, 54, 63, 0, 54, 22, 6, 55, 59, 38, 108, 39, 45, 23, 102, 27, 11, 56, 32, 0, 82, 24]
key = "ez_python_xor_reverse"
for i in range(len(secret)):
print(chr(secret[i] ^ ord(key[i%len(key)])), end = "")

出题人的密码是什么

花指令,nop 掉即可,然后交叉引用找到加密逻辑,通过改标志位绕过反调试

此外还有一个时间反调试

image-20240220151924646

逻辑如下

image-20240219182202977

image-20240219182219581

直接逆向,先异或,然后上面那个算法是判断最高位是不是1,然后对低位进行异或,那么我们就可以根据最低位来求出最高位

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
enc = bytes.fromhex('B4BBD8EBD06EABCA658E4BE94DD44AF37D29C2F99589A4859DCDDF77FD45CB5D7DFD934BBCF67CF32442F5D2DDE356AE')
enc = [((i ^ 0x25) - 5) & 0xFF for i in enc]
flag = b''
def decrypt(cipher):
key = 0x33077d
for _ in range(64):
if cipher & 1:
cipher = (cipher ^ key) >> 1
cipher |= 0x8000000000000000
else:
cipher = cipher >> 1
return cipher


for i in range(6):
cipher = int.from_bytes(enc[(i * 8):(i * 8 + 8)], 'little')
cipher = decrypt(cipher)
flag += cipher.to_bytes(8, 'little')
print(flag)

arc

解包后反编译,然后是一大坨 list

image-20240220155855232

其实就是通过大于小于符号和位运算嵌套最后的结果就是1或者0

所以整体的结构就是 list[list[int]][i][j] == data

直接爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
enc = list[list[int]]

for j, a in enumerate(enc):
for x in range(32, 127):
bj = 1
y = list(bin(sum(x << 6 ^ 4102 - j ^ _ for _ in b'beginCTF')).replace('0b', ''))
y = [int(_) for _ in y]
#print(a, y)
if len(y) != len(a):
continue
for i, elem in enumerate(y):
if a[i] != elem:
bj = 0
break
if bj == 1:
print(chr(x), end = '')
continue
#print()
# begin{Y@u_aRe_g00d_aT_play1ng_witH_sNake3}

goforfun

先用 go_parser 恢复符号表,然后动调查看逻辑

一个奇怪的 rc4,但是不用管流程,直接dump最后的异或流密钥即可

image-20240301144026373

然后是一个大整数的操作,就是把一个数组先用 BYTE 转化成一个大整数,然后再每次取模64,再除以64,得到一个最大不超过64的数组,再以这个数组为索引进行单表代换最后比对,直接逆即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
key = [0x84, 0xe, 0x79, 0xc1, 0x29, 0x3d, 0xe7, 0x86, 0x93, 0xf4, 0xb4, 0x66, 0x64, 0xaf, 0x19, 0x97, 0x85, 0x7, 0xe6, 0x4a, 0xc8, 0x3, 0x37]
enc = "HZ0sMJXqxHgUb2b9RNg+1xw"
table= "8G+cazk2jqb7w01CtoKH4FsrgR3vVmQ9pPhXLAleOd/nB6DfIxMWYiUZ5SEJyNuT"
ind = []
for i in enc:
ind.append(table.index(i))
# print(ind)

sum = 0
for i in ind[::-1]:
sum = sum * 64 + i
arr = []
while(sum):
arr.append(sum & 0xff)
sum >>= 8
arr = arr[::-1]
for i, j in enumerate(arr):
print(chr(j ^ key[i] ^ 0x2f), end = '')
# begin{go_a_nice_journey}

Not main

veh 异常处理,运行main函数前先利用 initterm 注册了一个 VEH 处理器,在main函数之前执行了一个构造函数

image-20240303163926130

并进行了一处反调试

image-20240303163942264

sub_B32AE0是注册的析构函数,patch掉以后走完main流程会进入析构函数

image-20240303164346417

发现是对之前的BeingDebugged进行检测,通过以后触发除零异常再进入 Handler 函数进行xxtea加密。

也就是走了一次main函数里的 tea 加密又走了一次 handler 里的 xxtea,解密即可

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
#include <stdio.h>
#include <stdint.h>
#define DELTA 0x61C88647
#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void xxtea(uint32_t *v, int n, uint32_t const key[4]){
uint32_t y, z, sum;
unsigned p, rounds, e;
//n是明文长度,sum对应图中的D,p对应图中的密钥下标索引,e是图中的D>>2

/* Coding Part */
if (n > 1) {
rounds = 6 + 52/n;//循环轮数
sum = 0 ;
z = v[n-1];
do{
sum -= DELTA;
e = (sum >> 2) & 3;
for (p=0; p<n-1; p++){
y = v[p+1];
z = v[p] += MX;//本质上还是双整形加密,用v[p]和v[p+1]对v[p]加密
/*
v[p] += MX;
z = v[p];
*/
}
y = v[0];
z = v[n-1] += MX;//一轮加密的最后用v[n-1]和v[0]对v[n-1]加密
}
while (--rounds);
}
else if (n < -1)/* Decoding Part */{
n = -n;
rounds = 6 + 52/n;
sum = -rounds*DELTA;
y = v[0];
do{
e = (sum >> 2) & 3;
for (p=n-1; p>0; p--){
z = v[p-1];
y = v[p] -= MX;
}
z = v[n-1];
y = v[0] -= MX;
sum += DELTA;
}
while (--rounds);
}
}

void teaDecrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=-DELTA * 32, i;//密文,此时sum=delta*32
uint32_t delta=DELTA;
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];
for (i=0; i<32; i++) {
v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
sum += delta;
}//解密函数主体 ,倒过来写即可
v[0]=v0; v[1]=v1;//置换
}

int main()
{
uint32_t enc[8]= {0x0CFBE0F1B, 0x5F3083F, 0x4220E43B, 0x3383AFEE, 0x0FA3237CE, 0x0ECADA66E, 0x0A8D47CA7, 0x0EFC51077};
uint32_t const key1[4]= {0x74, 0x72, 0x75, 0x65};
int n = 8;
xxtea(enc, -n, key1);
uint32_t key2[4] = {0x66, 0x61, 0x6B, 0x65};
for(int i = 0; i < 8; i += 2)
{
teaDecrypt(enc + i, key2);
}
for(int i = 0; i < 8; i++)
{
while(enc[i])
{
printf("%c", enc[i] & 0xFF);
enc[i] >>= 8;
}
}
return 0;
}
//begin{not_main_is_matter!}

ezvm

虚拟机,opcode如下

image-20240304213727115

然后就是摘棉花反汇编

1
2
3
4
5
6
7
data = [0xC7, 0x0B, 0xDB, 0x0C, 0xE5, 0x08, 0xAD, 0xDE, 0xAF, 0xCD, 0x67, 0xBF, 0x1F, 0xBF, 0x1E, 0x68, 0xFE, 0x25, 0xFD, 0x6F, 0x08, 0x50, 0xCD, 0x15, 0xB0, 0x21, 0x8B, 0x3E, 0xFD, 0x73, 0xED, 0x90]
for i in range(len(data)-1,0,-1):
data[i]^=data[i-1]
for i in range(len(data)-2,-1,-1):
data[i]-=data[i+1]
print(bytes(data))
#begin{r3@11y_A_B4by_34$y_FK_Vm!}