SHCTF-RE

REVERSE

[WEEK1]ez_asm

汇编代码 看不懂 GPT解题法万岁

1
2
3
4
5
6
test = b'nhuo[M`7mc7uhc$7midgbTf`7`$7%#ubf7 ci5Y'

flag = ''
for i in range(len(test)):
flag += chr((test[i]+ 0x0A)^ 0x1E)
print(flag)

flag{It_is_als0_impor@nt_t0_13arn_4sm!}

[WEEK1]easy_re

image.png

1
2
3
4
5
6
7
des = [0x66,0xC6,0x16,0x76,0xB7,0x45,0x27,0x97,0xF5,0x47,0x03,0xF5,0x37,0x03,0xC6,0x67,0x33,0xF5,0x47,0x86,0x56,0xF5,0x26,0x96,0xE6,0x16,0x27,0x97,0xF5,0x07,0x27,0x03,0x26,0xC6,0x33,0xD6,0xD7]  # 请将这里替换为实际的des数组
flag = ""

for i in des:
flag += chr((i >> 4) | ((i & 0xF) << 4))

print("The flag is:", flag)

The flag is: flag{Try_t0_s0lv3_the_binary_pr0bl3m}

[WEEK1]seed

image.png
没找到seed,只能开着动调一步一步找到10个随机数
[0x26,0x45,0x49,0x8e,0xb9,0x43,0xCD,0x9B,0xFA,0x0C]

1
2
3
4
5
6
strings=[0x40,0x29,0x28,0xE9,0xC2,0x04,0xA4,0xED,0x9F,0x53,0x5F,0x75,0x3C,0xD1,0xCD,0x2B,0xA8,0xC4,0x89,0x69,0x15,0x21,0x16,0xEF,0xD7,0x27,0x92,0xDF,0xCA,0x53,0x5F,0x2A,0x3C,0xD1,0xCE,0x03,0xA3,0xEF,0xA5,0x78,0x16,0x1A,0x2D,0xE1,0xC4]
key=[0x26,0x45,0x49,0x8e,0xb9,0x43,0xCD,0x9B,0xFA,0x0C]
flag=''
for i in range(len(strings)):
flag+=str(chr(strings[i]^key[i%10]))
print(flag)

flag{Give_y0u_the_se3d_and_D0_you_w@nt_t0_do}

[WEEK1]signin

image.png
flag点击就送
flag{flag1sinarray}

[WEEK1]easy_math

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
print("Please input flag:")
flag = input()
if len(flag)!=42:
print("Check your length!")
exit()

l=[]
for i in range(6):
s=""
for j in flag[i*7:i*7+7]:
s+=hex(ord(j))[2:]
l.append(int(s,16))
if (
(593*l[0] + 997*l[1] + 811*l[2] + 258*l[3] + 829*l[4] + 532*l[5])== 0x5b8e0aef71d34ff43 and \
(605*l[0] + 686*l[1] + 328*l[2] + 602*l[3] + 695*l[4] + 576*l[5])== 0x551a262360964ef7f and \
(373*l[0] + 512*l[1] + 449*l[2] + 756*l[3] + 448*l[4] + 580*l[5])== 0x49d158a5657d6931c and \
(560*l[0] + 635*l[1] + 422*l[2] + 971*l[3] + 855*l[4] + 597*l[5])== 0x625568d5abbabf4f3 and \
(717*l[0] + 507*l[1] + 388*l[2] + 925*l[3] + 324*l[4] + 524*l[5])== 0x50ee0c025e70e3c23 and \
(312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5])== 0x40e735f8aa2815f65):
print("Good job!")
else:
print("Wrong\nTry again!!!")
exit()

直接使用Z3求解即可

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
from z3 import *
from sympy import symbols, Eq, solve

# 定义变量
l = [Int('l_%i' % i) for i in range(6)]

# 定义方程
s = Solver()
s.add(593*l[0] + 997*l[1] + 811*l[2] + 258*l[3] + 829*l[4] + 532*l[5] == 0x5b8e0aef71d34ff43)
s.add(605*l[0] + 686*l[1] + 328*l[2] + 602*l[3] + 695*l[4] + 576*l[5] == 0x551a262360964ef7f)
s.add(373*l[0] + 512*l[1] + 449*l[2] + 756*l[3] + 448*l[4] + 580*l[5] == 0x49d158a5657d6931c)
s.add(560*l[0] + 635*l[1] + 422*l[2] + 971*l[3] + 855*l[4] + 597*l[5] == 0x625568d5abbabf4f3)
s.add(717*l[0] + 507*l[1] + 388*l[2] + 925*l[3] + 324*l[4] + 524*l[5] == 0x50ee0c025e70e3c23)
s.add(312*l[0] + 368*l[1] + 884*l[2] + 518*l[3] + 495*l[4] + 414*l[5] == 0x40e735f8aa2815f65)

# 求解方程
if s.check() == sat:
m = s.model()
t = [m.evaluate(l[i]).as_long() for i in range(6)]
print(t)
flag = ''
for num in t:
hex_str = hex(num)[2:]
for i in range(0, len(hex_str), 2):
flag += chr(int(hex_str[i:i+2], 16))
print(flag)

[WEEK1]ez_apk

image.png
jadx看不到r2的值,只能拿ida打开看。就这一点困了老半天
image.png
9LfnoVpi1HrzBSKxhNFeyY745R2g3QmqsTCZJuDvcMdkE8wPGbUXajtAW6的上面看到要解的密文
image.png
最后这段加密看了老半天,在开摆的时候想到58长度的密钥,蒙一手base58
image.png
flag{Jue_1_ju3_Y0ung_and_G0at_1s_go0d_for_yOuR_body}

[WEEK2]not gcc

image.png
使用clang notgcc.bc -o gcc编译成可执行文件
image.png
image.png
map提出来,开始解数独
image.png
然后把重复的地方换成0
image.png
image.png
flag{2e6b3024bbebd77293d4f9d431fbe22c}

[WEEK2]pycode

GPT逆出代码并写出解密代码

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
import base64

flag = '*******************'
value = ''
output = ''

for i in range(1000):
w = 1024
x = w % 3
y = w // 9
z = x * y
w -= z

for i in range(10000):
w = 20
x = w % 6
y = w // 3
z = x * y
w += z

for i in range(1000):
w = 1024
x = w % 3
y = w // 9
z = x * y
w -= z

for i in range(len(flag)):
temp = flag[i]
temp = chr(ord(temp) ^ 8)
value += temp

for i in range(len(flag)):
temp = value[i]
temp = chr(ord(temp) + 3)
output += temp

obfuscated_output = base64.b64encode(output.encode()).decode()
obfuscated_output = obfuscated_output[:-1]
obfuscated_output = obfuscated_output.replace('0', 't')
obfuscated_output = obfuscated_output.replace('c', '4')
obfuscated_output = obfuscated_output.replace('+', '-')

print(obfuscated_output)
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
import base64

obfuscated_output = '==AeAF3M-tzO-giQ-AUQosDQ9tGK7MDPuhC47tDNB5Tb8Yn4sdW4'

# 进行字符串替换操作的逆操作
obfuscated_output = obfuscated_output.replace('-', '+')
obfuscated_output = obfuscated_output.replace('4', 'c')
obfuscated_output = obfuscated_output.replace('t', '0')

# 进行base64解码
output = base64.b64decode(obfuscated_output[::-1]).decode()

# 初始化一个空字符串用于存储解密后的结果
value = ''

# 对output中的每个字符进行数学运算的逆操作,并将结果累加到value中
for i in range(len(output)):
temp = output[i]
temp = chr(ord(temp) - 3)
value += temp

# 初始化一个空字符串用于存储最终的解密结果
flag = ''

# 对value中的每个字符进行数学运算的逆操作,并将结果累加到flag中
for i in range(len(value)):
temp = value[i]
temp = chr(ord(temp) ^ 8)
flag += temp

print(flag)

[WEEK2]Authur’s_box

image.png
byte_408A80在函数sub_40182D被赋值
image.png
byte_418A80在函数sub_4016EC被赋值
image.png
byte_408980在函数sub_4017A5被赋值
image.png

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
# 全局变量
dword_418A80 = [0]*256
byte_408980 = [0]*256
byte_408A80 =[0]*256
Str = "HeREisYoUK3y" # 这需要被设置为实际的字符串
Str1=[0x51,0xDE,0x04,0xB3,0x8D,0x3A,0xEB,0xDE,0xBC,0xA7,0xDC,0x80,0xFC,0x51,0x21,0x10,0x88,0xEB,0x85,0xD5,0xA6,0x54,0xD9,0x52,0x98,0xD6,0x1C,0xBB,0xC3,0xAC,0x46,0x5B,0x08,0x39,0x39,0x11,0x0A,0xB5,0xA1,0xFA,0xCA,0x68]
flag=''
def sub_4017A5():
global dword_418A80, byte_408980, Str

for i in range(256):
dword_418A80[i] = i

v1 = len(Str)

for j in range(256):
byte_408980[j] = ord(Str[j % v1])

return sub_4016EC()

def sub_4016EC():
global dword_418A80, byte_408980

v3 = 0

for i in range(256):
v3 = (dword_418A80[i] + v3 + byte_408980[i]) % 256
v1 = dword_418A80[i]
dword_418A80[i] = dword_418A80[v3]
dword_418A80[v3] = v1

return dword_418A80

def sub_40182D(a2):
global dword_418A80, byte_408A80
v4 = 0
v6 = 0
i = 0
while a2:
a2 -= 1
v6 = (v6 + 1) % 256
i = (i + dword_418A80[v6]) % 256
v3 = dword_418A80[v6]
dword_418A80[v6] = dword_418A80[i]
dword_418A80[i] = v3
byte_408A80[v4] = (dword_418A80[(dword_418A80[v6] + dword_418A80[i]) % 256] ^ 0x52) & 0xFF
v4 += 1

return a2


sub_4017A5()
sub_40182D(42)
#print(byte_408A80)

for i in range(len(Str1)):
flag+=chr(Str1[i]^byte_408A80[i])

print(flag)

得到flag{1b36920e-c180-b250-6537-30238f5}

[WEEK3]java是最棒的语言吗

image.png
ChaCha20是对称加密,把开头改一下,把密文传入函数即可得到明文。
image.png

[WEEK3]easyre

扔IDA里面看不懂,先运行程序。发现在运行错误时会报错,猜测Python打包的exe。
image.png
我们用pyinstxtractor.py拆包,再用uncompyle6解main.pyc,得到程序源码。
image.png
image.png
观察程序,key的值实际上是求解3×1key(x2+x+1)dx=130243\times \int_{1}^{key} (x^2+x+1)dx=13024,可以直接用wolframalpha计算key的值为23。
接下来就是将encoded_data和key逐字节异或,再用marshal模块的loads函数将base解码后的encoded_data加载为Python对象<code object <module> at 0x000002206E186450, file "fun.py", line 1>。搜了一圈发现Python好像并不能将代码对象转为源代码(也可能是我没搜到),所以只能从对象属性下手看看有没有什么常量。
print(dir(code_obj))
image.png

  • co_argcount:函数的位置参数数量。
  • co_cellvars:函数中的闭包变量名称。
  • co_code:编译后的字节码。
  • co_consts:函数中使用的常量值。
  • co_filename:定义函数的文件名。
  • co_firstlineno:函数在源文件中的起始行号。
  • co_flags:解释函数特性的标志位。
  • co_freevars:在嵌套函数中被引用的自由变量名称。
  • co_kwonlyargcount:函数的仅关键字参数数量。
  • co_lnotab:字节码指令到源代码行号的映射。
  • co_name:函数名称。
  • co_names:函数中使用的全局变量名称。
  • co_nlocals:函数中局部变量的数量。
  • co_posonlyargcount:函数的仅位置参数数量(Python 3.8及更高版本)。
  • co_stacksize:函数需要的堆栈大小。
  • co_varnames:局部变量名称,包括参数。

看到co_cellvars、co_consts、co_freevars、co_names、co_varnames比较可疑,于是输出看看
image.png
看见常量名里有个rc4_encryptkeyflag,猜测加密方式是RC4,加密的flagb'\xd8\x94\x1e\xab\x9bft\xeb]@\x1b\xba\xe6\xe8\x133W\xdd\x0e\xe6\x924\xf1\x80mh\xeb=\x08a\x02\t.\xb5\x05B\xb0\xb0/D\x8cY'keyb'example_key',成功解出flag。
image.png
flag{d8e8d9d0-b2b1-7304-74b760-90b11ab6a3}

[WEEK3]crackme

image.png
lua语言,可以用unluac.jar逆向出源码

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
print("please input your flag:")
flag = io.read()
code = {}
secret = {54,57,566,532,1014,1,7,508,10,12,498,494,6,24,14,20,489,492,0,10,490,498,517,539,21,528,517,530,543,9,13,0,4,51,562,518,15,1,515,14,14,517,519,1,56,514,2,515,47,31,1,594,117,15}
l = string.len(flag)
for i = 1, l do
num = ((string.byte(flag, i) + i) % 333 + 444) % 555 - 1
table.insert(code, num)
end
for i = 1, l do
x = i - 1
if i + 2 >= l then
code[i] = code[i % l + 1] ~ code[(i + 1) % l + 1]
else
code[i] = code[(i + 1) % l] ~ code[(i + 2) % l]
end
end
for i = 1, l do
if secret[i] ~= code[i] then
print("Incorrect")
return
end
end
print("You win,flag is", flag)

由于lua数组从1开始,理逻辑的时候还是比较绕的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import string
secret=[15,54,57,566,532,1014,1,7,508,10,12,498,494,6,24,14,20,489,492,0,10,490,498,517,539,21,528,517,530,543,9,13,0,4,51,562,518,15,1,515,14,14,517,519,1,56,514,2,515,47,31,1,594,117]
secret[-1]=secret[-1]^secret[1]
for i in range(1,len(secret)):
secret[-i-1] = secret[-i]^secret[-i-1]

print(secret)
char=''
for i in range(len(secret)):
num = secret[i] + 1
num = (num + 111) % 555
num = (num + 333 - i-1) % 333
char += chr(num)
print(char)

虽然第一个字母不对但能用


SHCTF-RE
http://example.com/2023/10/30/SHCTF-WP-RE/
作者
pjx1314
发布于
2023年10月30日
许可协议