关于结局解密

初次接触网络安全领域

涉及知识点:

  • 文件内容分析(文件头,二进制/文本,网页源代码)
  • 密码学与加解密技术(暴力破解,base64,RSA,md5)
  • 程序逆向(或关键信息RSA私钥 明文写在程序内)

算是个CTF入门题,根据评论区线索自行操作了一番

1. 找到彩蛋

重启游戏 邮件下拉到底找到彩蛋

中间空白有线索

clue.jpg

图1

2. 寻找文件

在Steam打开本地文件

图2

双击发现无法打开图片

且大小只有几KB不像是图片,很有可能被修改后缀

用记事本打开

1
7z集' 缡?      "       訦Ot耥u_河槡俶藽鳭R鱣?f暱朢vPs梾o^埞??!

发现文件头为7z,猜测是压缩包7z格式

修改文件后缀尝试解压

发现解压需要密码

图3

3. 破解压缩包密码

由于是7z格式,可用工具较少

使用Passware Kit Forensic字典攻击(即常用密码进行暴力尝试)

密码较为简单 1分钟就完成解密

图4

压缩包密码: password

4. 解Base64编码

压缩包里clue/7/3/Hello.html

1
2
3
<!-- Zm9sZGVy77yaMjk5ZDEyZDg4ZTBlOTljMQ== -->

<h1>Hello Tom!</h1>

Base64 编码后的字符串长度通常是4的倍数。如果长度不是4的倍数,可能会在末尾有一个或两个等号(=)作为填充

Zm9sZGVy77yaMjk5ZDEyZDg4ZTBlOTljMQ==

对这段Base64编码进行转换

1
2
3
4
5
6
7
import base64

encoded_string = "Zm9sZGVy77yaMjk5ZDEyZDg4ZTBlOTljMQ=="
decoded_bytes = base64.b64decode(encoded_string)
decoded_string = decoded_bytes.decode('utf-8', errors='ignore')

print(decoded_string) # folder:299d12d88e0e99c1

输出folder:299d12d88e0e99c1

暗示文件夹/299d12d88e0e99c1/?

5. 寻找文件夹

较快的方法:使用Everything进行搜索

图5

文件夹中有

readme.exe

打开发现需要输入密码

1
2
password: 

runtime.txt

打开发现文本

1
gAp9xge69vuNF4Kyr/UcjO3iFlFt+e5OFZ5/zYcv703qor2K0eorwcbddlgX/6JiAq1+qnbKPnOZ+MHk7Vy55wKeLYShEvc44jZYT0HIoHLEczXOFgq8qdNsF7RhjNYNNKzDy1cc0i2pDXGTczxqct0CUkHUNI0jkpn9Vm8O19J/caIWb1NdOzfhr86gEzehkXh560sv5X8LBgo0kmJc9pEprJ+SV9vQ4pA4W+C7AtipyC7FU/51tUI/Dl9q2hpUnE1Qt4PyBDsRiaWWQ0ORQCANEapVc/b70ffxYDim5aBfvwYhc7DEo5oFcQUOiAorOnWayzz3CE0I+4qu5nRqgg==

发现这段Base64编码被加密 RSA AES?

已知一段加密数据

6. 寻找私钥

6.1 法1 查看源文件

关键信息明文写在程序里,可以减少反编译步骤

图6

6.2 法2 反编译exe

使用IDA64进行反编译exe

阅读理解C语言代码

图7

意思是若输入的是iamnottom会打印KEY

重新双击运行readme.exe

输入密码

6.3 得到私钥

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
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC04AAI4K7DdGTx
KL86f54wT0ouQrDlL4krCz7DfeuFtaRPbHR/X+2wV7iX+e+doquuAgJ56DyLaRgm
ZxV6ksn/vfg0qVJlKfgfqnUsH+5quun14oc7gsdNWHkJqUh9O8pTce/ElK2YbABi
9J06p4Z1PyxpjTkViFz+YVpY5zHo2ysa4tlH1VCpYjjzUQXAMD3NbroBXTYa2Lex
UI/Xb2mnZepcGc5/ovQAzf227ORwNS6TcQiz0Wa+V7Ggz3fNBqtqipVg6QHT71a7
TOfZCOPTOW6K49p70DX+3Z3ezpIiX/ZpgBGGAckMGsNsI8lGIAR3vjXsNBeQ0sn2
FFnp+T+9AgMBAAECggEAFo0TFAhHYdEiQLsO1JFSvL02B3yDJ5/8nyRAyAjsE3ip
Ksnf4H2qWeEl/7TGvkWo2AIiIubknZEV1LvnfqfMjZk22AIAZuKLsA8FmuHETQRO
5TxAFhhhFvCf7qdvhUWuHSdIeJ784dMdXTkYXVbDudyNgf98jYW56nFi3VC99UUg
TaZWXAwr0yjDVqRWe2TpqjDAqNauvVFOhJgsNQ2yJf+XjqTLngM05vQg97CY1BUa
pQ4YlvonfX2t4URxz5wsf88DJCRvjTuedezNFyMfyJyPWFylDsvoio9UTk000Tae
Zr7Ab0e+gMbdcgo7lgOw7jue0mM+SH/uILU8SaRHVQKBgQDpcibMd56CQ0MT7Kw/
Zue1hpjrcaWlCK5nZ/21Eyu5giAA8CcKvTAL08r4E/ZV7gs28wsk8TZ/wvP63Xqj
+Z+t98IRgJyFhed/2cUHRjEtGBkPbrzG0f2QgzDXx2Xkg27h6xXH7SSCZ6SV5Wr2
Ngnt9LuKmjnQx90sAhBxRpblIwKBgQDGWZr/DBncbK6/SKKr+h7sf8fWmEJvlC9E
2pyszEm6foKMxUKOCLpvzLuXZBDDj4tJrPg2oGaA2zU9TAvzX6spT7VnvJhwmP+r
+QUysTnv0rUZDs5mHGYbjWly+9J6GcYzb896kL6EMK9BNGVfSiH2vsV6ugYJIo61
Zkv/+6/FnwKBgQC7qp3QL7WIiKQLB29tRL+vKXYTiHgeVP1Hecz2XWQALMCnoGfy
dSaDy45Wok2cxNHVKctitlsWmFXk7VmjKpCYnR0xTtAFcyEooZuH/oCX/NBgnKg7
uSJ7o0uHm++opZRlH8SRxW1dPA6OxjCXn9eZqO1/Pf6Ofa2qrDolpha2OwKBgG23
y0Eh1HxVsiQlbbZr2QdBd62A8978vVj9BIWhS3dZ26U6yKIAugB1457Ov2ct1AKh
J3wwJgNJPp31nva1CN0FNnd3n2tJdsQOL43m8wFyMLL3ubxKIUFEa/wqyDa6YyS4
yLAnuPsuYwNSlHCtdTQkOuC0XfpXn1FAkPG8q3JJAoGBAMy4385KPM27iQE38UBm
9gh17VBqaUxd+9s6Zkb4noS00vR3S0oDrQaNIdPCJphm1xlewqx2jbYMQX7aDrgF
r7mV6V2V78Ex8P7YoL9CfndnoYcq5mZTwKhuKZaenHNYk33qAuEVOkwGI+JcedSn
OHYMpp6ckBxSzsNcekc+mH0i
-----END PRIVATE KEY-----

7. 解RSA加密

常见的填充方式包括:

  • PKCS#1 v1.5 :

    通常用于传统的RSA加密。

  • OAEP(Optimal Asymmetric Encryption Padding) :

    更安全的填充方式, 通常与SHA-256等哈希算法一起使用。

python无敌

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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
import base64

# Base64 编码的加密数据
encrypted_data_b64 = "gAp9xge69vuNF4Kyr/UcjO3iFlFt+e5OFZ5/zYcv703qor2K0eorwcbddlgX/6JiAq1+qnbKPnOZ+MHk7Vy55wKeLYShEvc44jZYT0HIoHLEczXOFgq8qdNsF7RhjNYNNKzDy1cc0i2pDXGTczxqct0CUkHUNI0jkpn9Vm8O19J/caIWb1NdOzfhr86gEzehkXh560sv5X8LBgo0kmJc9pEprJ+SV9vQ4pA4W+C7AtipyC7FU/51tUI/Dl9q2hpUnE1Qt4PyBDsRiaWWQ0ORQCANEapVc/b70ffxYDim5aBfvwYhc7DEo5oFcQUOiAorOnWayzz3CE0I+4qu5nRqgg=="
# RSA 私钥字符串
private_key_str = """-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC04AAI4K7DdGTx
KL86f54wT0ouQrDlL4krCz7DfeuFtaRPbHR/X+2wV7iX+e+doquuAgJ56DyLaRgm
ZxV6ksn/vfg0qVJlKfgfqnUsH+5quun14oc7gsdNWHkJqUh9O8pTce/ElK2YbABi
9J06p4Z1PyxpjTkViFz+YVpY5zHo2ysa4tlH1VCpYjjzUQXAMD3NbroBXTYa2Lex
UI/Xb2mnZepcGc5/ovQAzf227ORwNS6TcQiz0Wa+V7Ggz3fNBqtqipVg6QHT71a7
TOfZCOPTOW6K49p70DX+3Z3ezpIiX/ZpgBGGAckMGsNsI8lGIAR3vjXsNBeQ0sn2
FFnp+T+9AgMBAAECggEAFo0TFAhHYdEiQLsO1JFSvL02B3yDJ5/8nyRAyAjsE3ip
Ksnf4H2qWeEl/7TGvkWo2AIiIubknZEV1LvnfqfMjZk22AIAZuKLsA8FmuHETQRO
5TxAFhhhFvCf7qdvhUWuHSdIeJ784dMdXTkYXVbDudyNgf98jYW56nFi3VC99UUg
TaZWXAwr0yjDVqRWe2TpqjDAqNauvVFOhJgsNQ2yJf+XjqTLngM05vQg97CY1BUa
pQ4YlvonfX2t4URxz5wsf88DJCRvjTuedezNFyMfyJyPWFylDsvoio9UTk000Tae
Zr7Ab0e+gMbdcgo7lgOw7jue0mM+SH/uILU8SaRHVQKBgQDpcibMd56CQ0MT7Kw/
Zue1hpjrcaWlCK5nZ/21Eyu5giAA8CcKvTAL08r4E/ZV7gs28wsk8TZ/wvP63Xqj
+Z+t98IRgJyFhed/2cUHRjEtGBkPbrzG0f2QgzDXx2Xkg27h6xXH7SSCZ6SV5Wr2
Ngnt9LuKmjnQx90sAhBxRpblIwKBgQDGWZr/DBncbK6/SKKr+h7sf8fWmEJvlC9E
2pyszEm6foKMxUKOCLpvzLuXZBDDj4tJrPg2oGaA2zU9TAvzX6spT7VnvJhwmP+r
+QUysTnv0rUZDs5mHGYbjWly+9J6GcYzb896kL6EMK9BNGVfSiH2vsV6ugYJIo61
Zkv/+6/FnwKBgQC7qp3QL7WIiKQLB29tRL+vKXYTiHgeVP1Hecz2XWQALMCnoGfy
dSaDy45Wok2cxNHVKctitlsWmFXk7VmjKpCYnR0xTtAFcyEooZuH/oCX/NBgnKg7
uSJ7o0uHm++opZRlH8SRxW1dPA6OxjCXn9eZqO1/Pf6Ofa2qrDolpha2OwKBgG23
y0Eh1HxVsiQlbbZr2QdBd62A8978vVj9BIWhS3dZ26U6yKIAugB1457Ov2ct1AKh
J3wwJgNJPp31nva1CN0FNnd3n2tJdsQOL43m8wFyMLL3ubxKIUFEa/wqyDa6YyS4
yLAnuPsuYwNSlHCtdTQkOuC0XfpXn1FAkPG8q3JJAoGBAMy4385KPM27iQE38UBm
9gh17VBqaUxd+9s6Zkb4noS00vR3S0oDrQaNIdPCJphm1xlewqx2jbYMQX7aDrgF
r7mV6V2V78Ex8P7YoL9CfndnoYcq5mZTwKhuKZaenHNYk33qAuEVOkwGI+JcedSn
OHYMpp6ckBxSzsNcekc+mH0i
-----END PRIVATE KEY-----"""

# 解码 Base64 编码的数据
encrypted_data = base64.b64decode(encrypted_data_b64)

# 加载私钥
private_key = serialization.load_pem_private_key(
private_key_str.encode(),
password=None,
backend=default_backend()
)

def decrypt_data(encrypted_data):
# padding_type == "OAEP":
try:
print(f"Try padding_type OAEP to Decryption...")
return private_key.decrypt(
encrypted_data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
except Exception as e:
print(f"OAEP Decryption failed")

# padding_type == "PKCS1v15":
try:
print(f"Try padding_type PKCS1v15 to Decryption...")
return private_key.decrypt(
encrypted_data,
padding.PKCS1v15()
)
except Exception as e:
print(f"PKCS1v15 Decryption failed")

# 解密数据
decrypted_data = decrypt_data(encrypted_data)

# 输出解密后的数据
print(decrypted_data.decode()) # b4e9ab2f61cbfda4

b4e9ab2f61cbfda4

8. 解MD5加密

首先他有十六位

可能是某种数据的哈希值 例如

  • MD5(16/32位十六进制)
  • SHA-1(40位十六进制)
  • SHA-256(64位十六进制)

MD5加密后的位数有两种类型: 16位与32位 默认使用32位。
16位实际上是从32位字符串中取中间的第9位到第24位的部分

例如 “admin” :
16位加密 7a57a5a743894a0e
32位加密 21232f297a57a5a743894a0e4a801fc3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import hashlib
# 32位 - 0 16位 - 1
p1 = 1

# 目标哈希值
target_hash = "b4e9ab2f61cbfda4"

# 遍历所有可能的5位数字
for i in range(100000): # 从00000到99999
original_data = f"{i:05d}" # 格式化为5位数字
hash_value = hashlib.md5(original_data.encode()).hexdigest()

if p1:
hash_value = hash_value[8:24]

if hash_value == target_hash:
print(f"Found original data: {original_data}")
break
else:
print("Original data not found.")
Found original data: 95173

9.小结

解密成功

这个密码正好对应了本作游戏公司Odd Games

Odd有奇数的含义

给予创作者大大的肯定👍

测评

一款单人解密策略模拟游戏。玩家将穿越回到1999年躲避流氓软件的恶意安装。

前面的关卡还是比较常见。到了中间有不少关卡还是没见过,有些难找需要攻略。

优点:
- 主题玩法新颖
- 探索性强
- 构思巧妙

缺点:
- 内置小游戏戏份过重
- 体量小