das202311月赛
# PREFACE:说实话一直打不明白这个 das,这今年最后一次算是比较认真打的一次,最后是稳稳第一拿下了但是好像和我关系不大… 不能说没有贡献吧但是光自己做肯定是差很多的… 还是 tcl5555555
# misc
帮着看了一眼,有一道题提出来的是一个 upx 打包的 elf,简单分析发现用的 upx-4.2.1-amd64_linux
版本,直接官网找了再 upx -d 即可,里面 base64 变表,解出来即可
# re
# letsgo
dll 里面 upx 3.94,自己 upx file
加一个 dll 壳,发现了三四个被修改了的标志位,修复即可 upx -d
主程序没东西,有两个地方加载了 dll,断点查看,这里是抽卡用的逻辑
里面有解压图片的操作:
def split_and_process_file(input_file_path): | |
# 读取原始文件 | |
with open(input_file_path, 'rb') as file: | |
data = file.read() | |
bytes_array = bytearray(data) | |
for i in range(len(bytes_array) - 1, -1, -1): | |
if i + 2 < len(bytes_array): | |
bytes_array[i] ^= bytes_array[i + 2] | |
bytes_array[i] ^= 0xf | |
bytes_array[i] ^= 0xf | |
with open(f'output_{1}.jpg', 'wb') as output_file: | |
output_file.write(bytes_array) | |
split_and_process_file('D:\\reverse\\challange\\das11\\re\\DAS10letsgo\\letsgo\\res\\wwww') | |
def split_and_process_file(input_file_path): | |
with open(input_file_path, 'rb') as file: | |
data = file.read() | |
split_pattern = b'\xff\xd8\xff\xe0' | |
parts = data.split(split_pattern) | |
for part_index, part in enumerate(parts): | |
bytes_array = bytearray(b'\xFF\xD8\xFF\xE0') + bytearray(part) | |
with open(f'flag_{part_index}.jpg', 'wb') as output_file: | |
output_file.write(bytes_array) | |
split_and_process_file('output_1.jpg') |
你们二次元差不多得了
于是你发现前面做的没有意义
那就只有这里了:
这里拿到 key:
这里是啥呢:
画一下图发现是蒙特卡罗模拟 π,下面 COERCE_UNSIGNED_INT64
强制将 π 解释为整数,然后作为 seed 生成一组 xor 用的随机数
下面就是一个 aes192,这里 ida 反编译不出来,看看汇编即可找到 key 和密文
最搞心态的一点是,这里的蒙特卡罗模拟是跑不出来的(而且本身模拟 golang 也是一个相当麻烦的操作),首先你得猜这里就是 π,以及四舍五入的情况,进行一定量的爆破操作,结果这地方魔改源码在 rand 里面多加了一个异或!
给你逆天逆完了
脚本:
package main | |
import ( | |
"fmt" | |
"math" | |
"math/rand" | |
) | |
func main() { | |
bits := math.Float64bits(math.Pi) | |
val := bits % 0x5F5E100 | |
rand.Seed(int64(val)) | |
key := make([]int, 0) | |
for i := 0; i < 24; i++ { | |
key = append(key, (rand.Int()^0xa)%100) | |
} | |
fmt.Println(key) | |
} |
import struct | |
from Crypto.Cipher import AES | |
arr = [37, 49, 98, 48, 14, 17, 9, 47, 56, 91, 37, 69, 17, 3, 82, 64, 54, 76, 80, 88, 54, 97, 0, 53] | |
rawkey = struct.pack("<3Q", 0x5B566461493D5E41, 0x293A774E2E4B3250, 0x4C650A692B391345) | |
print(rawkey) | |
for i in range(len(arr)): | |
arr[i] ^= rawkey[i] | |
key = bytes(arr) | |
aes = AES.new(key, AES.MODE_ECB) | |
m1 = aes.decrypt(bytes.fromhex("ff44ac7700732a16589f7ff8bdbaa923")) | |
m2 = aes.decrypt(bytes.fromhex("57c29c367a781ead5fb143469d75f319")) | |
print(m1 + m2) |
# ezpython
…
反编译拿到:
#!/usr/bin/env python | |
# visit https://tool.lu/pyc/ for more information | |
# Version: Python 3.11 | |
import pyDes | |
def adjust_length(str): | |
if len(str) < 8: | |
str = str.ljust(8, '0') | |
elif len(str) > 8: | |
str = str[:8] | |
return str | |
def yuanshen(array, start, end): | |
num = len(array) | |
dis = [ | |
float('inf')] * num | |
tree = [ | |
False] * num | |
parent = [ | |
-1] * num | |
dis[start] = 0 | |
# WARNING: Decompyle incomplete | |
def qidong(input, key, IV): | |
cipher = pyDes.des(key, pyDes.CBC, IV, pad = None, padmode = pyDes.PAD_PKCS5) | |
encrypted_data = cipher.encrypt(input) | |
encrypted_hex_list = encrypted_data() | |
return encrypted_hex_list | |
def main(): | |
data = [ | |
159, | |
41, | |
201, | |
125, | |
67, | |
60, | |
44, | |
34, | |
203, | |
56, | |
116, | |
186, | |
13, | |
71, | |
125, | |
30, | |
84, | |
123, | |
109, | |
54, | |
106, | |
56, | |
17, | |
124, | |
87, | |
236, | |
25, | |
12, | |
80, | |
178, | |
165, | |
123] | |
key = input('请输入key: ') | |
if len(key) != 8: | |
print('wrong key lenth!') | |
exit() | |
flag = input('请输入flag: ') | |
array = [ | |
[ | |
0, | |
float('inf'), | |
float('inf'), | |
1, | |
3, | |
4, | |
float('inf'), | |
float('inf'), | |
float('inf')], | |
[ | |
float('inf'), | |
0, | |
float('inf'), | |
float('inf'), | |
float('inf'), | |
2, | |
float('inf'), | |
4, | |
float('inf')], | |
[ | |
float('inf'), | |
float('inf'), | |
0, | |
8, | |
1, | |
float('inf'), | |
float('inf'), | |
float('inf'), | |
1], | |
[ | |
1, | |
float('inf'), | |
8, | |
0, | |
3, | |
5, | |
1, | |
2, | |
float('inf')], | |
[ | |
3, | |
float('inf'), | |
1, | |
3, | |
0, | |
float('inf'), | |
1, | |
5, | |
3], | |
[ | |
4, | |
2, | |
float('inf'), | |
5, | |
float('inf'), | |
0, | |
float('inf'), | |
1, | |
float('inf')], | |
[ | |
float('inf'), | |
float('inf'), | |
float('inf'), | |
1, | |
1, | |
float('inf'), | |
0, | |
float('inf'), | |
5], | |
[ | |
float('inf'), | |
4, | |
float('inf'), | |
2, | |
5, | |
1, | |
5, | |
0, | |
float('inf')], | |
[ | |
float('inf'), | |
float('inf'), | |
1, | |
float('inf'), | |
3, | |
float('inf'), | |
float('inf'), | |
float('inf'), | |
0]] | |
t = yuanshen(array, 1, 8) | |
IV = (lambda .0: pass# WARNING: Decompyle incomplete | |
)(t()) | |
IV = adjust_length(IV) | |
check = qidong(flag, key, IV) | |
if check == data: | |
print('yes,yes,yes!!') | |
return None | |
''.join('bad,bad,bad!!') | |
main() |
反编译有问题,iv 拿不到,但是就差八位
晚点出个完整的 python 各个版本应对策略(立 flag & 鸽)dis 一下自己看
结合一下就加上 DASCTF{
呗,给他爆一位: DASCTF{D0_U_4ls0_l1k3_7uansH3n}
TODO:后面再补,感觉麻烦死了新东西也不多 ,懒了