patchme

main 函数里有个 gets,同时翻了翻发现有一段代码,里面有个 mprotect 下面是对一个大数据段的异或操作,显然是个 SMC,一个比较 pwn 的方法是利用 get 的漏洞改汇编然后跑出 flag,也可以直接逆。

1676625036917

1676625328606

由于只是一个简单异或,考虑用 idapython 直接实现 smc 的解密

1
2
3
4
5
from idc_bc695 import *
addr = 0x14C6
for i in range(961):
PatchByte(addr, Byte(addr) ^ (0x66) & 0xFF)
addr += 1

解密完的数据 analyze 以后得到关键代码

1676625413976

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <bits/stdc++.h>
#include <stdint.h>
using namespace std;
long long v9[6], v13[6];
int main()
{
v9[0] = 0x5416D999808A28FALL;
v9[1] = 0x588505094953B563LL;
v9[2] = 0xCE8CF3A0DC669097LL;
v9[3] = 0x4C5CF3E854F44CBDLL;
v9[4] = 0xD144E49916678331LL;
v9[5] = 0x55BBD0DA616BAC;
v13[0] = 0x3B4FA2FCEDEB4F92LL;
v13[1] = 0x7E45A6C3B67EA16LL;
v13[2] = 0xAFE1ACC8BF12D0E7LL;
v13[3] = 0x132EC3B7269138CELL;
v13[4] = 0x8E2197EB7311E643LL;
v13[5] = 0x28C9B5AE540AC1;
for (int i = 0; i <= 46; ++i)
putchar((char)(*((int8_t *)v9 + i) ^ *((int8_t *)v13 + i)));
}

运行得到 hgame{You_4re_a_p@tch_master_0r_reverse_ma5ter}

kmusic

把 dll 文件扔进 exeinfo 里面发现是 .net 文件,用 dnspy64 打开,定位到 main 函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private static void Main()
{
ApplicationConfiguration.Initialize();
byte[] data = Resources.data;
for (int i = 0; i < data.Length; i++)
{
byte[] array = data;
int num = i;
array[num] ^= 104;
}
Activator.CreateInstance(Assembly.Load(data).GetType("WinFormsLibrary1.Class1"), new object[]
{
Program.form1
});
Application.Run(Program.form1);
}

发现是对一段 data 进行异或,但是数据在哪里不知道,用附加进程进行动调 (然后发现是个小黑子程序)

1676628125336

调试到 for 循环结束以后查看 data 的内存

1676628468399

1676628477226

发现是 MZ 开头,显然是一个 PE 文件,我们把它 dump 下来

1676629053435

发现还是用 C# 写的 .net 文件,继续用 dnspy 反编译,里面有一个巨大的 if 里面有个 array 数组

1676629674517

我们需要知道 num 数组里到底有些啥,直接上 z3即可。

1
2
3
4
5
6
7
8
9
10
11
from z3 import *
sol = Solver()

num = [BitVec("num[%d]" % i, 16) for i in range(13)]
for i in range(13):
sol.add(num[i] >= 0)

sol.add(num[0] + 52296 + num[1] - 26211 + num[2] - 11754 + (num[3] ^ 41236) + num[4] * 63747 + num[5] - 52714 + num[6] - 10512 + num[7] * 12972 + num[8] + 45505 + num[9] - 21713 + num[10] - 59122 + num[11] - 12840 + (num[12] ^ 21087) == 12702282 , num[0] - 25228 + (num[1] ^ 20699) + (num[2] ^ 8158) + num[3] - 65307 + num[4] * 30701 + num[5] * 47555 + num[6] - 2557 + (num[7] ^ 49055) + num[8] - 7992 + (num[9] ^ 57465) + (num[10] ^ 57426) + num[11] + 13299 + num[12] - 50966 == 9946829 , num[0] - 64801 + num[1] - 60698 + num[2] - 40853 + num[3] - 54907 + num[4] + 29882 + (num[5] ^ 13574) + (num[6] ^ 21310) + num[7] + 47366 + num[8] + 41784 + (num[9] ^ 53690) + num[10] * 58436 + num[11] * 15590 + num[12] + 58225 == 2372055 , num[0] + 61538 + num[1] - 17121 + num[2] - 58124 + num[3] + 8186 + num[4] + 21253 + num[5] - 38524 + num[6] - 48323 + num[7] - 20556 + num[8] * 56056 + num[9] + 18568 + num[10] + 12995 + (num[11] ^ 39260) + num[12] + 25329 == 6732474 , num[0] - 42567 + num[1] - 17743 + num[2] * 47827 + num[3] - 10246 + (num[4] ^ 16284) + num[5] + 39390 + num[6] * 11803 + num[7] * 60332 + (num[8] ^ 18491) + (num[9] ^ 4795) + num[10] - 25636 + num[11] - 16780 + num[12] - 62345 == 14020739 , num[0] - 10968 + num[1] - 31780 + (num[2] ^ 31857) + num[3] - 61983 + num[4] * 31048 + num[5] * 20189 + num[6] + 12337 + num[7] * 25945 + (num[8] ^ 7064) + num[9] - 25369 + num[10] - 54893 + num[11] * 59949 + (num[12] ^ 12441) == 14434062 , num[0] + 16689 + num[1] - 10279 + num[2] - 32918 + num[3] - 57155 + num[4] * 26571 + num[5] * 15086 + (num[6] ^ 22986) + (num[7] ^ 23349) + (num[8] ^ 16381) + (num[9] ^ 23173) + num[10] - 40224 + num[11] + 31751 + num[12] * 8421 == 7433598 , num[0] + 28740 + num[1] - 64696 + num[2] + 60470 + num[3] - 14752 + (num[4] ^ 1287) + (num[5] ^ 35272) + num[6] + 49467 + num[7] - 33788 + num[8] + 20606 + (num[9] ^ 44874) + num[10] * 19764 + num[11] + 48342 + num[12] * 56511 == 7989404 , (num[0] ^ 28978) + num[1] + 23120 + num[2] + 22802 + num[3] * 31533 + (num[4] ^ 39287) + num[5] - 48576 + (num[6] ^ 28542) + num[7] - 43265 + num[8] + 22365 + num[9] + 61108 + num[10] * 2823 + num[11] - 30343 + num[12] + 14780 == 3504803 , num[0] * 22466 + (num[1] ^ 55999) + num[2] - 53658 + (num[3] ^ 47160) + (num[4] ^ 12511) + num[5] * 59807 + num[6] + 46242 + num[7] + 3052 + (num[8] ^ 25279) + num[9] + 30202 + num[10] * 22698 + num[11] + 33480 + (num[12] ^ 16757) == 11003580 , num[0] * 57492 + (num[1] ^ 13421) + num[2] - 13941 + (num[3] ^ 48092) + num[4] * 38310 + num[5] + 9884 + num[6] - 45500 + num[7] - 19233 + num[8] + 58274 + num[9] + 36175 + (num[10] ^ 18568) + num[11] * 49694 + (num[12] ^ 9473) == 25546210 , num[0] - 23355 + num[1] * 50164 + (num[2] ^ 34618) + num[3] + 52703 + num[4] + 36245 + num[5] * 46648 + (num[6] ^ 4858) + (num[7] ^ 41846) + num[8] * 27122 + (num[9] ^ 42058) + num[10] * 15676 + num[11] - 31863 + num[12] + 62510 == 11333836 , num[0] * 30523 + (num[1] ^ 7990) + num[2] + 39058 + num[3] * 57549 + (num[4] ^ 53440) + num[5] * 4275 + num[6] - 48863 + (num[7] ^ 55436) + (num[8] ^ 2624) + (num[9] ^ 13652) + num[10] + 62231 + num[11] + 19456 + num[12] - 13195 == 13863722)

if(sol.check()):
print(sol.model())

1676632429034

然后执行下面的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
num = [0 for i in range(13)]
num[1] = 72
num[7] = 53
num[11] = 93
num[5] = 86
num[10] = 15
num[9] = 199
num[12] = 133
num[4] = 189
num[0] = 236
num[6] = 62
num[3] = 106
num[8] = 120
num[2] = 213
array = [
132, 47, 180, 7, 216, 45, 68, 6, 39, 246, 124, 2, 243, 137, 58, 172, 53, 200, 99, 91, 83, 13, 171, 80, 108, 235,
179, 58, 176, 28, 216, 36, 11, 80, 39, 162, 97, 58, 236, 130, 123, 176, 24, 212, 56, 89, 72]

for i in range(len(array)):
print(chr(array[i] ^ (num[i % 13])), end="")

得到 hgame{z3_1s_very_u5eful_1n_rever5e_engin3ering}

cpp

1677810292430

函数调用反编译出来是 fastcall, 没办法静态找到调用的是哪个函数,直接动调就行。

1677811572657

跳到 v6 这里的 时候,结合下面的函数调用,很像一个密钥的初始化函数,但是不知道是啥加密算法,但是无所谓,我们接着跟踪代码对输入的 flag 进行了什么操作,进入第二个调用

1677811653232

动调到箭头指向的这一步,发现在异或之前,flag 都没有改变,于是考虑直接把与flag异或的值给 dump 出来,注意这里应该是改了大小端序的。

1677813097053

1677811523513

后面进入 check 函数

1677810678571

跟踪进入函数sub_7FF7A87A4990,发现是memcpy

1677810734440

找到相对应的参数,可以 dump 出密文

1677813687356

写出 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
#include <bits/stdc++.h>
using namespace std;
unsigned char key[] = {
0x4E, 0xA0, 0x37, 0x40, 0x46, 0x02, 0xDA, 0xFD, 0x21, 0xFA,
0x6E, 0x3C, 0xAF, 0xD9, 0x9C, 0xCF, 0xB9, 0x47, 0x33, 0x67,
0xE0, 0x4E, 0xEC, 0x0D, 0xD1, 0xC4, 0x80, 0x13, 0x32, 0xA9,
0xB2, 0x3A, 0xA7, 0x50, 0x5D, 0x02, 0x82, 0x39, 0x4A, 0x83
};
unsigned int key_ex[10];
unsigned char cipher[] = {
0x28, 0x50, 0xC1, 0x23, 0x98, 0xA1, 0x41, 0x36, 0x4C, 0x31,
0xCB, 0x52, 0x90, 0xF1, 0xAC, 0xCC, 0x0F, 0x6C, 0x2A, 0x89,
0x7F, 0xDF, 0x11, 0x84, 0x7F, 0xE6, 0xA2, 0xE0, 0x59, 0xC7,
0xC5, 0x46, 0x5D, 0x29, 0x38, 0x93, 0xED, 0x15, 0x7A, 0xFF
};

int main() {
for(int i = 0; i < 10; i++) {
key_ex[i] = *(int*)(key + i * 4);
}
for (int i = 0; i < 10; i++) {
putchar(cipher[i*4 + 0] ^ (key_ex[i] >> 24));
putchar(cipher[i*4 + 1] ^ (key_ex[i] >> 16));
putchar(cipher[i*4 + 2] ^ (key_ex[i] >> 8));
putchar(cipher[i*4 + 3] ^ (key_ex[i] >> 0));
}
}

运行得到 hgame{Cpp_1s_much_m0r3_dlff1cult_th4n_C}

shellcode

golang逆向,一眼看见 base64_decode 函数,考虑直接把解码后的 shellcode dump出来

1677832244051

然后贴到 010editor 里用 ida64 打开,创建函数反编译以后发现是个 TEA ,密钥是常数,密文应该就是 flag.enc

1677832364247

写出 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
#include <bits/stdc++.h>
#include <stdint.h>
using namespace std;
unsigned char cipher[] = {0x20, 0x69, 0xB3, 0xE4, 0xD0, 0x24, 0x69, 0x93, 0x44, 0xD1, 0x16, 0xA8, 0xF5, 0xD5, 0x82, 0xAA, 0xDA, 0xF0, 0x79, 0x36, 0x06, 0xFD, 0x32, 0x7F, 0xD3, 0xC0, 0x60, 0x34, 0x39, 0x49, 0x21, 0xB7, 0xA2, 0x69, 0x72, 0xE5, 0xFA, 0x51, 0x6A, 0x83};
uint32_t enc[10];
void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1 = v[1], i;
uint32_t delta = 0x0ABCDEF23;
uint32_t sum = delta * 0x20;
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()
{
unsigned int key[4] = {22, 33, 44, 55};
for(int i = 0; i < 10; i++)enc[i] = *(unsigned int*)(cipher + 4 * i);
for(int i = 0; i < 10; i += 2 )decrypt(enc + i, key);
for(int i = 0; i < 10; i++)
{
unsigned int x = enc[i];
while(x)
{
printf("%c", x % 256);
x /= 256;
}
}
}

得到 hgame{th1s_1s_th3_tutu's_h0mew0rk}