文章目录
- [GDOUCTF 2023]Check_Your_Luck
- [GDOUCTF 2023]Tea
- [GDOUCTF 2023]easy_pyc
- [GDOUCTF 2023]doublegame
- [GDOUCTF 2023]L!s!
- [GDOUCTF 2023]润!
- 附
[GDOUCTF 2023]Check_Your_Luck
根据 if
使用z3约束求解器。
EXP:
from z3 import *
# 创建整数变量
v, w, x, y, z = Ints('v w x y z')
# 创建Z3求解器
solver = Solver()
solver.add(v * 23 + w * -32 + x * 98 + y * 55 + z * 90 == 333322)
solver.add(v * 123 + w * -322 + x * 68 + y * 67 + z * 32 == 707724)
solver.add(v * 266 + w * -34 + x * 43 + y * 8 + z * 32 == 1272529)
solver.add(v * 343 + w * -352 + x * 58 + y * 65 + z * 5 == 1672457)
solver.add(v * 231 + w * -321 + x * 938 + y * 555 + z * 970 == 3372367)
# 检查是否存在解
if solver.check() == sat:
model = solver.model()
output_str = f"flag{{{model[v]}_{model[w]}_{model[x]}_{model[y]}_{model[z]}}}"
print(output_str)
else:
print("方程组无解")
# flag{4544_123_677_1754_777}
[GDOUCTF 2023]Tea
64bit的文件。IDA64打开
根据字符串定位
这里的v7是错误的,后面进行了修改。
之后对v8和v7进行操作。
一个XTEA的加密,找到密文,提取出来
加密的逻辑大概就是,明文的第一位和第二位进行XTEA加密,之后加密后的第二位继续和第三位XTEA,依次下去,逆向一下就好。
写个EXP解密:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
void decrypt (uint32_t* v,uint32_t* k,int wheel) {
uint32_t v0=v[0], v1=v[1], i;
uint32_t delta=0xF462900;
uint32_t sum = delta*(33+wheel);
for (i=0; i<33; i++) {
sum -= delta;
v1 -= (((v0 * 16) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11 ) & 3]);
v0 -= (((v1 * 16) ^ (v1 >> 5)) + v1) ^ (sum + k[(sum & 3)])^sum;
}
v[0]=v0; v[1]=v1;
}
int main()
{
uint32_t enflag[] = {444599258, 4154859931, 1226314200, 4060164904, 359413339, 1013885656, 2228535080, 4045045479, 856928850, 3718242937};
uint32_t key[4] = {2233,4455,6677,8899};
for(int i=8;i>=0;i-=1)
{
uint32_t temp[2];
temp[0] = enflag[i];
temp[1] = enflag[i+1];
int wheel = i;
decrypt(temp,key,wheel);
enflag[i] = temp[0];
enflag[i+1] = temp[1];
}
for (int i = 0; i < 10; i++)
{
for (int j = 3; j>=0; j--)
{
printf("%c", (enflag[i] >> (j * 8)) & 0xFF);
}
}
return 0;
}
//HZCTF{hzCtf_94_re666fingcry5641q q}
//HZCTF{hzCtf_94_re666fingcry5641qq}
[GDOUCTF 2023]easy_pyc
pyc文件,用uncompyle6反编译
一个简单的rsa加密。
EXP:
d = inverse(e,(p-1)*(q-1))
n = p*q
m = pow(c,d,n)
print(long_to_bytes(m))
# flag{IfYouWantItThenYouHaveToTakeIt}
[GDOUCTF 2023]doublegame
通过查找字符串定位到关键函数。
函数点进去看一看,最后发现都没有什么用。回去查看一下字符串,发现一个GAME OVER。
找到了。第一个game。如果分数大于13371337就进行第二个游戏,即score。
看 if
下面的函数。
一个迷宫题,用dfs解:
maze = ['0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', ' ', '0', ' ', '0', ' ', '0', ' ', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', ' ', ' ', '0', ' ', '0', '0', ' ', '0', ' ', '0', ' ', '0', '0', '0', '0', '0', ' ', '0', '0', '0', '0', '0', ' ', '0', ' ', '0', '0', ' ', '0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', ' ', '0', '0', ' ', '0', '0', '0', ' ', '0', '0', '0', ' ', '0', ' ', '0', '0', '0', ' ', '0', ' ', '0', ' ', '0', '0', ' ', '0', ' ', ' ', ' ', ' ', ' ', '0', ' ', '0', ' ', '0', ' ', ' ', ' ', '0', ' ', '0', ' ', '0', '0', ' ', '0', ' ', '0', ' ', '0', '0', '0', '0', '0', ' ', '0', '0', '0', ' ', '0', '0', '0', ' ', '0', '0', ' ', '0', ' ', '0', ' ', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', '0', ' ', '0', ' ', ' ', ' ', ' ', '0', ' ', '0', '0', '0', ' ', '0', ' ', '0', ' ', '0', '0', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', '0', ' ', ' ', ' ', ' ', ' ', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', '0', ' ', '0', '0', '0', '0', '0', ' ', '0', '0', '0', ' ', '0', '0', '0', ' ', '0', ' ', '0', ' ', '0', '0', ' ', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', '0', ' ', '0', '0', '0', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', '0', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', ' ', ' ', ' ', '0', ' ', '0', ' ', '0', ' ', '0', '0', ' ', '0', '0', '0', '0', '0', '0', '0', ' ', '0', ' ', '0', '0', '0', ' ', '0', '0', '0', '0', '0', ' ', ' ', ' ', ' ', '0', ' ', ' ', ' ', '0', ' ', '0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', ' ', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', ' ', '0', ' ', '0', ' ', '0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', '0', '0', '0', ' ', '0', ' ', '0', '0', '0', '0', '0', ' ', '0', ' ', '0', '0', '0', ' ', '0', '0', '0', '0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', ' ', '0', ' ', ' ', ' ', '0', ' ', ' ', ' ', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0']
maze[21*7+20] = '2'
# maze[x * 21 + y]
def check_point_valid(map, x, y):
if (x >= 0) and (x <= 20) and (y >= 0) and (y <= 20):
return (map[x * 21 + y] != '0') and ((map[x * 21 + y] == ' ') or (map[x * 21 + y] == '2'))
else:
return False
def gen_nex(map, x, y):
all_dir = []
# if check_point_valid(map, x - 1, y, z):
# all_dir.append((x - 1, y, z, 'q'))
# if check_point_valid(map, x + 1, y, z):
# all_dir.append((x + 1, y, z, 'u'))
if check_point_valid(map, x + 1, y):
all_dir.append((x + 1, y, 's'))
if check_point_valid(map, x - 1, y):
all_dir.append((x - 1, y, 'w'))
if check_point_valid(map, x, y - 1):
all_dir.append((x, y - 1, 'a'))
if check_point_valid(map, x, y + 1):
all_dir.append((x, y + 1, 'd'))
return all_dir
def check_success(map, x, y):
if map[x * 21 + y] == '2':
return True
else:
return False
def dfs(mapb, x, y, path):
map = mapb.copy()
if map[x * 21 + y] != '2':
map[x * 21 + y] = '0'
if check_success(map, x, y):
print(path)
return True
next_point = gen_nex(map, x, y)
for n in next_point:
pathn = path + n[2]
dfs(map, n[0], n[1], pathn)
outpus = ""
dfs(maze, 15, 0, outpus)
可以解出俩条路径,用最短的,dddssssddwwwwddssddwwwwwwddddssaassddddwwwwddwwwwddd
再加上一个MD5加密,
最后加上分数得到flag。
HZCTF{811173b05afff098b4e0757962127eac13371337}
[GDOUCTF 2023]L!s!
俩个文件。
用Bindiff 检查文件差异性
IDA分析后会留下一个i64或idb文件。
Ctrl+6 快捷键打开,(有些可能没插件)
绿色的是匹配度最高的。这里可以发现只有一个有差异。应该就是经过修改的地方。
发现是 extract_dirs_from_files
这个函数。
用IDA打开另一个文件,找到这个函数,比对俩个函数,
发现这里多出了一部分内容。
可以看到就只是做了一个异或而已。
EXP:
enc = [ 0x04, 0x16, 0x0F, 0x18, 0x0A, 0x37, 0x2E, 0x7D,
0x22, 0x28, 0x25, 0x2A, 0x2A, 0x13, 0x7D, 0x3F,
0x13, 0x2D, 0x13, 0x39, 0x3F, 0x7F, 0x2A, 0x39,
0x20, 0x13, 0x38, 0x7C, 0x7C, 0x20, 0x31, 0x00]
for j in range(100):
flag = []
for i in range(len(enc)):
flag.append(chr(enc[i]^j))
print(''.join(flag))
# HZCTF{b1ndiff_1s_a_us3ful_t00l}L
[GDOUCTF 2023]润!
UPX壳,看到EP Section UPX标志被修改了。
用WInhex修改回来。
一个迷宫题,不过是三维迷宫。
一开始init处创建了一次迷宫(一层)后面moving里面每u一次都会layer++。这里layer就是楼的意思。
用动态调试,输入uuuuuuuuuuuuuuuuuuu连续创建迷宫,把迷宫copy出来;
EXP:
maze = [0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1,
1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 2]
# maze[x * 64 + y * 8 + z]
def check_point_valid(map, x, y, z):
if (x >= 0) and (x <= 7) and (y >= 0) and (y <= 7) and (z >= 0) and (z <= 7):
return (map[x * 64 + y * 8 + z] != 1) and ((map[x * 64 + y * 8 + z] == 0) or (map[x * 64 + y * 8 + z] == 2))
else:
return False
def gen_nex(map, x, y, z):
all_dir = []
if check_point_valid(map, x - 1, y, z):
all_dir.append((x - 1, y, z, 'n'))
if check_point_valid(map, x + 1, y, z):
all_dir.append((x + 1, y, z, 'u'))
if check_point_valid(map, x, y - 1, z):
all_dir.append((x, y - 1, z, 'w'))
if check_point_valid(map, x, y + 1, z):
all_dir.append((x, y + 1, z, 's'))
if check_point_valid(map, x, y, z - 1):
all_dir.append((x, y, z - 1, 'a'))
if check_point_valid(map, x, y, z + 1):
all_dir.append((x, y, z + 1, 'd'))
return all_dir
def check_success(map, x, y, z):
if map[x * 64 + y * 8 + z] == 2:
return True
else:
return False
def dfs(mapb, x, y, z, path):
map = mapb.copy()
if map[x * 64 + y * 8 + z] != 2:
map[x * 64 + y * 8 + z] = 1
if check_success(map, x, y, z):
print(path)
return True
next_point = gen_nex(map, x, y, z)
for n in next_point:
pathn = path + n[3]
dfs(map, n[0], n[1], n[2], pathn)
outpus = ""
dfs(maze, 0, 0, 0, outpus)
解出来ssddssuuwwddndduuussdussasauudd
附
CTF-Reverse 迷宫地图类题目分析‘‘DFS和BFS算法‘‘