January 18, 2022

羊城杯 2020-babyre

0x00 日常查壳

无壳64位

image-20220118200622606

0x01 分析main函数

找到主函数,发现是openssl库的DES加密,然后开头一段DES加密,密钥和密文已经给了

image-20220118200831539

通过动调查看初始化的密钥

image-20220118201010738

记录下网卡又出127.0.0.1

image-20220118201213500

参考文章:https://blog.csdn.net/baidu_18624493/article/details/122297400

接着报错,ubuntu18.04后已经不支持这个库了,于是我换了18.04解决了这个问题

image-20220120100857133

参考文章:https://askubuntu.com/questions/1173587/e-package-libssl1-0-0-has-no-installation-candidate

动调运行到这,查看内存得到初始化后的密钥

PS: v5的数据没必要,开始在那bangzhu了一会

image-20220118201340863

得到密钥

1
2
3
4
5
6
7
8
9
10
11
12
13
from Crypto.Cipher import DES, AES
from Crypto.Util.number import *


# key = b'\xBC\x9C\x10\xE0\xC2\x84\x84\x4D'
key = b'\xAD\x52\xF2\x4C\xE3\x2C\x20\xD6'
iv = b'\x00\x00\x00\x00\x00\x00\x00\x00'
c = long_to_bytes(0xAF4EEC8428A9BDBA2266FEEEEE0D8A2)
lun = DES.new(key = key, mode = DES.MODE_CBC, iv = iv)

key = lun.decrypt(c)
print(key)
#b'th1s1sth3n1c3k3y'

0x02 分析SMC后的函数

就是我们又输入一段,然后经过AES加密,两段异或的加密,最后比较(比较那段ida抽风了,去汇编上看即可)

image-20220118202530412

动调得到密文

image-20220118203157196

于是来理一下第二段输入

  1. AES加密
  2. 一段异或加密(解密倒着来即可)
  3. 一段异或加密(已知最后一位)

0x03 GetFlag!

最后一段异或加密我们结果是分叉的,也就是有多解的情况,所以我们要穷举所有结果,于是就要写个DFS(深度优先搜索)即可

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
from Crypto.Cipher import DES, AES
from Crypto.Util.number import *


# key = b'\xBC\x9C\x10\xE0\xC2\x84\x84\x4D'
key = b'\xAD\x52\xF2\x4C\xE3\x2C\x20\xD6'
iv = b'\x00\x00\x00\x00\x00\x00\x00\x00'
c = long_to_bytes(0xAF4EEC8428A9BDBA2266FEEEEE0D8A2)
lun = DES.new(key = key, mode = DES.MODE_CBC, iv = iv)

key = lun.decrypt(c)
print(key)
#b'th1s1sth3n1c3k3y'

ef = "BDADB4841063B3E1C6842D6FBA8874C49032EA2EC6286570C97578A00B9FA6"
ef = bytearray.fromhex(ef) #变成16进制的字节数组

flag = [0 for i in range(32)]
flag[31] = 0xC4
flags = []

# 其实就是异或存在多解 于是在0xFF中如有能恢复第一个字符的 就都整条恢复
def Deep_Search(flag, deep):
if deep == 0:
flags.append(flag.copy())
else:
for i in range(0xFF):
if ((2 * (i ^ 0x13) + 7) ^ (i % 9 + flag[deep] + 2)) & 0xFF == ef[deep - 1]: #恢复第一个异或
flag[deep - 1] = i #赋值到flag
Deep_Search(flag, deep - 1) #整条递归恢复

Deep_Search(flag, 31)

for flag in flags:
for i in range(31, -1, -1):
for j in range(int(i / 4) - 1, -1, -1):
# for j in range(int(i / 4)): 两种都可以
# print(j, end = " ")
flag[i] ^= flag[j]
t = AES.new(key, AES.MODE_ECB).decrypt(bytes(flag))
print(t)

# 当一个数异或多个数时 如 a ^ b ^ c ^ d = e
# 那么当他要反过来推回来 不管是正着异或 e ^ b ^ c ^ d 还是倒过来 e ^ d ^ c ^ b 答案都为 a

GetFlag!(buuoj上MD5加密后上交)

image-20220120100425547

关于DFS扩展

本来想直接塞这篇博客,学习一番,决定单独出一篇放到Book里

DASCTF X SU
🍬
HFCTF2022
🍪

About this Post

This post is written by P.Z, licensed under CC BY-NC 4.0.