CISCN rustbaby

CISCN rustbaby

其实早该写完但是忙学校考试去了然后感冒躺了两天就拖了几天……

当时自己做的时候看代码看的头痛太多了不知道怎么下手,网上看到说是rust语言exe的强混淆

后面看偶像视频讲解豁然开朗,记录一下尝试的过程

通过这个题目进行一个做rust题目的分析思路总结ciscn24-rust_baby 逆向速览_哔哩哔哩_bilibili

image-20240520181641812

直接在字符串界面进行搜索

.rc搜索查看是否有调用一些奇怪的库等

针对这个题目来说都是rust的一些标准库,所以直接上

image-20240520183859908

进行base64解码以后得到下面的信息

1
2
3
4
5
{
"where":"where is your flag?:",
"omg":"correct flag",
"nonono":"nope, wrong flag"
}
1
2
3
4
5
6
{
"henhenaaa!":[1,1,4,5,1,4,1,9,1,9,8,1,0],
"cryforhelp":"igdydo19TVE13ogW1AT5DgjPzHwPDQle1X7kS8TzHK8S5KCu9mnJ0uCnAQ4aV3CSYUl6QycpibWSLmqm2y/GqW6PNJBZ/C2RZuu+DfQFCxvLGHT5goG8BNl1ji2XB3x9GMg9T8Clatc=",
"whatadoor":"1145141919810WTF"
}

思路:根据标准数据输入流找到调试位置

策略:乱打断点,找到输入数据看在哪里

image-20240527143831864

最开始直接运行程序发现有where is flag字符串提示,但是IDA打开后并没有找到,所以先通过下断点调试来找到输入

image-20240527204625689

找到输入,即为v21,然后在下一条的代码中对v165进行加密,函数sub_1400028C3不好判断在干嘛,可以直接当作黑盒进行分析

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
_int64 __fastcall sub_1400028C3(__int64 a1, unsigned __int64 a2, unsigned __int64 a3)
{
__int64 *v3; // rax
__int64 i; // rcx
__int64 *v5; // rax
__int64 j; // rcx
__int64 v7; // rax
char v8; // cl
char v9; // r9
__int64 v11; // [rsp+0h] [rbp-20h] BYREF
__int64 v12[2]; // [rsp+8h] [rbp-18h]
__int64 v13; // [rsp+18h] [rbp-8h]
void *retaddr; // [rsp+20h] [rbp+0h]

v12[0] = a1;
v3 = &v11;
v11 = 0i64;
for ( i = 0i64; i != 64; i += 8i64 )
{
*(_BYTE *)v3 = a2 >> i;
v3 = (__int64 *)((char *)v3 + 1);
}
v5 = &v11;
v12[1] = v11;
v11 = 0i64;
for ( j = 0i64; j != 64; j += 8i64 )
{
*(_BYTE *)v5 = a3 >> j;
v5 = (__int64 *)((char *)v5 + 1);
}
v13 = v11;
v11 = 0i64;
v7 = -4i64;
do
{
v8 = *((_BYTE *)&v13 + 2 * v7 + 1);
v9 = (*((_BYTE *)&v13 + 2 * v7) ^ *((_BYTE *)&retaddr + 2 * v7) | v8 ^ *((_BYTE *)&retaddr + 2 * v7 + 1)) & 1;
*((_BYTE *)v12 + 2 * v7) = v7 + *((_BYTE *)v12 + (*((_BYTE *)&v13 + 2 * v7) & 7)) - v9 + 4;
*((_BYTE *)v12 + 2 * v7 + 1) = v7 + *((_BYTE *)v12 + (v8 & 7)) - v9 + 4;
++v7;
}
while ( v7 );
return v11;
}

最后调试得到结果

1
2
3
4
5
11111111---> 00112233
22222222---> 11223344
12345678---> 01234679
aaaaaaaa--->``aabbcc
abcdefgh---> `acdfgij

规律(这样写会简单一点,理解版见最下面)

1
2
3
4
5
6
7
delta = -1				    		       

input+= delta

if i % 2 =1

delta -= 1

image-20240527152832818

如上图我们可以知道一共加密了8*13=104个字符

下一个加密如下图

image-20240527183940961

经过多次调试我们可以发现v96应该是一个固定值(每次调试输入八字节的时候都一样),所以可以选择输入0去异或然后得到密钥值(paste data选择hex )

image-20240527183847678

image-20240527194548155

image-20240527192454187(不用全选数据,直接在需要paste的第一个地址选中就行)

看最后比较逻辑其实是在v86这个地方

image-20240527154101872

最后比较的即是r8b和[r14+rdx],点开发现r8b里面存的就是最开始我们解出来字符串(cry for help:)

“igdydo19TVE13ogW1AT5DgjPzHwPDQle1X7kS8TzHK8S5KCu9mnJ0uCnAQ4aV3CSYUl6QycpibWSLmqm2y/GqW6PNJBZ/C2RZuu+DfQFCxvLGHT5goG8BNl1ji2XB3x9GMg9T8Clatc=”

image-20240527190522563

image-20240527200047106

image-20240527211744360

最后因为之前获得的key和加密数据是经过base64编码后得来的

所以脚本最后如下

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
from base64 import *
b64_cipher =
"igdydo19TVE13ogW1AT5DgjPzHwPDQle1X7kS8TzHK8S5KCu9mnJ0uCnAQ4aV3CSYUl6QycpibWSLmq
m2y/GqW6PNJBZ/C2RZuu+DfQFCxvLGHT5goG8BNl1ji2XB3x9GMg9T8Clatc="
b64_key =
"3F8gIsJ5GVY12otH0xn8VRTN0ntYWQlC3iy0SNnyG6lA4ab7/zjB1eLod3hvIgTmFj4MNVJc/cHlWRz
Qrlqy3Rn4QuYsiVnlEZzIe4Fwf2+8bwKP9/TIcK4C+FvicggJb79LObXQHqM="
key = b64decode(b64_key)
cipher = b64decode(b64_cipher)
flag = []
for i in range(len(cipher)):
flag.append(cipher[i] ^ key[i])
def fun(cipher):
for i in range(len(cipher)):
cipher[i] ^= 0x33
if i == 0 or i == 1:
cipher[i] += 1
if i == 4 or i == 5:
cipher[i] -= 1
if i == 6 or i == 7:
cipher[i] -= 2
return cipher
for i in range(0, len(flag), 8):
a = fun(flag[i:i + 8])//最开始八个一组
for j in a:
print(chr(j), end='')

flag{6e2480b3-4f02-4cf1-9bc0-123b75f9a922}EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import base64
t = 'igdydo19TVE13ogW1AT5DgjPzHwPDQle1X7kS8TzHK8S5KCu9mnJ0uCnAQ4aV3CSYUl6QycpibWSLmqm2y/GqW6PNJBZ/C2RZuu+DfQFCxvLGHT5goG8BNl1ji2XB3x9GMg9T8Clatc='
t = base64.b64decode(t)
t = bytearray(t)
########################print(t)
a2 = b'3F8gIsJ5GVY12otH0xn8VRTN0ntYWQlC3iy0SNnyG6lA4ab7/zjB1eLod3hvIgTmFj4MNVJc/cHlWRzQrlqy3Rn4QuYsiVnlEZzIe4Fwf2+8bwKP9/TIcK4C+FvicggJb79LObXQHqM='
realkey = base64.b64decode(a2)
for i in range(len(t)):
t[i] ^= realkey[i]
def dec2(x):
x = bytearray(x)
dd = -1
for i in range(len(x)):
x[i] ^= 0x33
x[i] -= dd
if i % 2 == 1:
dd += 1
return bytes(x)
for i in range(len(t) // 8):
print(dec2(t[i*8:i*8+8]).decode('ascii'), end='')

CISCN rustbaby
http://example.com/2024/05/28/CISCN rustbaby/
作者
John Doe
发布于
2024年5月28日
许可协议