IOT

有个明文flag,我看不太懂但我大受震撼

sharkp

关键字搜索一下,关注以下两个包

有个elf文件,导出一下

沙箱跑一下得到ip115.195.88.161

这个接口有命令执行 setSystemAdmin

DS

easydatalog

翻阅了一下,看到大段的十六进制信息,应该有zip、jpg什么的,提取一下十六进制数据,根据文件头文件尾信息提取出图片和压缩文件,python extract.py error.log

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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import re

def is_http_header(line):
"""检查是否为 HTTP 请求头行"""
http_patterns = [
r'HTTP/[\d.]+',
r'Content-Type:',
r'Content-Length:',
r'User-Agent:',
r'Accept',
r'Host:',
r'Connection:',
r'\d+ bytes',
r'\\r\\n$'
]

for pattern in http_patterns:
if re.search(pattern, line):
return True
return False

def extract_hex_content(log_content):
"""从日志内容中提取十六进制数据"""
hex_data = ""
current_data = ""

for line in log_content.split('\n'):
if 'dumpio_in (data-HEAP):' not in line:
continue

content = line.split('dumpio_in (data-HEAP):')[1].strip()

if is_http_header(content):
continue

# 查找包含 JPEG 或 ZIP 文件头的行
if '=FFD8FF' in content or '=504B0304' in content:
# 提取等号后的数据部分
match = re.search(r'=((?:[A-Fa-f0-9]+))(?:&|$)', content)
if match:
if current_data: # 如果有之前的数据,先保存
hex_data += current_data
current_data = ""
current_data = match.group(1)
else:
# 检查行中是否包含非十六进制字符
parts = content.split('&')
if parts and validate_hex_string(parts[0]):
current_data += parts[0] # 只添加&之前的部分
if len(parts) > 1: # 如果遇到&,说明当前文件结束
hex_data += current_data
current_data = ""

if current_data: # 添加最后一段数据
hex_data += current_data

return hex_data

def validate_hex_string(hex_string):
"""验证字符串是否为有效的十六进制数据"""
return bool(re.match('^[A-Fa-f0-9]+$', hex_string))

def find_jpeg_files(hex_string):
"""在十六进制字符串中查找JPEG文件"""
jpeg_header = "FFD8FF"
jpeg_footer = "00FFD9"
jpeg_files = []

pos = 0
while True:
# 查找JPEG文件头
start = hex_string.find(jpeg_header, pos)
if start == -1:
break

# 查找JPEG文件尾
end = hex_string.find(jpeg_footer, start)
if end == -1:
break

# 包含结尾的00FFD9
end += 6

# 提取JPEG文件内容并验证
jpeg_file = hex_string[start:end]
if len(jpeg_file) > 6 and validate_hex_string(jpeg_file):
jpeg_files.append(jpeg_file)

pos = end

return jpeg_files

def find_zip_files(hex_string):
"""在十六进制字符串中查找ZIP文件"""
zip_header = "504B0304"
zip_footer = "504B0506"
zip_files = []

pos = 0
while True:
# 查找ZIP文件头
start = hex_string.find(zip_header, pos)
if start == -1:
break

# 查找ZIP文件尾部标记
footer_pos = hex_string.find(zip_footer, start + 8)
if footer_pos == -1:
break

# 从footer位置向后查找,直到遇到非十六进制字符或&
end = footer_pos + 6 # 包含504B0506
while end < len(hex_string):
if not validate_hex_string(hex_string[end:end+2]):
break
end += 2

# 提取ZIP文件内容并验证
zip_file = hex_string[start:end]
if len(zip_file) > 8 and validate_hex_string(zip_file):
zip_files.append(zip_file)

pos = end

return zip_files

def save_files(files, file_type):
"""将提取的文件保存到磁盘"""
for i, hex_content in enumerate(files):
try:
# 将十六进制字符串转换为字节
binary_content = bytes.fromhex(hex_content)

# 保存文件
filename = f"extracted_{i}.{file_type}"
with open(filename, "wb") as f:
f.write(binary_content)
print(f"已保存文件: {filename} (大小: {len(binary_content)} 字节)")
print(f"文件头32字节: {binary_content[:32].hex().upper()}")
except Exception as e:
print(f"保存文件 {i} 时出错: {str(e)}")

def process_log(log_content):
"""处理日志内容并提取文件"""
# 1. 提取十六进制内容
hex_data = extract_hex_content(log_content)
print(f"提取的十六进制数据总长度: {len(hex_data)}")

if not hex_data:
print("未找到有效的十六进制数据")
return
with open("hex_data.txt", "w") as f:
f.write(hex_data)
# 2. 查找并保存JPEG文件
jpeg_files = find_jpeg_files(hex_data)
print(f"找到 {len(jpeg_files)} 个JPEG文件")
if jpeg_files:
save_files(jpeg_files, "jpg")

# 3. 查找并保存ZIP文件
zip_files = find_zip_files(hex_data)
print(f"找到 {len(zip_files)} 个ZIP文件")
if zip_files:
save_files(zip_files, "zip")

if __name__ == "__main__":
import sys

if len(sys.argv) > 1:
with open(sys.argv[1], 'r') as f:
log_content = f.read()
else:
log_content = sys.stdin.read()

process_log(log_content)

图片是个盲水印,一把梭

根据密码解压zip文件得到data.csv

easyrawencode

vol先确定镜像文件的系统配置文件profile volatility_2.6_win64_standalone.exe -f "easyrawencode.raw" imageinfo

vol扫一下

volatility_2.6_win64_standalone.exe -f "easyrawencode.raw" --profile=Win7SP1x64 filescan | findstr /i /r "\.png \.jpg \.gif \.zip \.rar \.7z \.pdf \.txt \.doc"

rsa目录下有个encrypted_data.zip

扫一下rsa目录发现三个文件volatility_2.6_win64_standalone.exe -f "easyrawencode.raw" --profile=Win7SP1x64 filescan | find "rsa"

hack.py内容如下,hackkey在环境变量里

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
import os
import hashlib
from Crypto.Cipher import AES, PKCS1_OAEP
from Crypto.PublicKey import RSA

hackkey = os.getenv('hackkey')
if not hackkey:
raise ValueError("Environment variable 'hackkey' is not set")

with open('private.pem', 'r') as f:
private_key = RSA.import_key(f.read())
public_key = private_key.publickey().export_key()

aes_key = hashlib.sha256(hackkey.encode()).digest()

with open('data.csv', 'rb') as f:
data = f.read()

cipher_aes = AES.new(aes_key, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(data)
cipher_rsa = PKCS1_OAEP.new(RSA.import_key(public_key))
enc_aes_key = cipher_rsa.encrypt(aes_key)

with open('encrypted_data.bin', 'wb') as f:
f.write(ciphertext)

print(enc_aes_key.hex())
print(cipher_aes.nonce.hex())
print(tag.hex())

控制台获取一下enc_aes_keycipher_aes_noncetag

volatility_2.6_win64_standalone.exe -f "easyrawencode.raw" --profile=Win7SP1x64 consoles

获取环境变量volatility_2.6_win64_standalone.exe -f "easyrawencode.raw" --profile=Win7SP1x64 envars | findstr /i "hackkey"得到4etz0hHbU3TgKqduFL

根据数据解密encrypted_data.zip解压出来的encrypted_data.bin

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
import os
import hashlib
from Crypto.Cipher import AES, PKCS1_OAEP
from Crypto.PublicKey import RSA

hackkey = '4etz0hHbU3TgKqduFL'

with open('private.pem', 'r') as f:
private_key = RSA.import_key(f.read())

enc_aes_key = bytes.fromhex("20d96098010eb9b326be6c46e1ce1ca679e29f1d65dec055cf8c46c6436c3356af2dc312b2d35466308b9fff0dd427b44a37e34fca12992e45db2ddd81884bd8eb5bccd3c595e8a9a352bd61322e1d52329d6c8638bbfce65edffbc4d3a5759e88c0f90e31ce518837552a3a09d8e7e3c374f3857bfe501cce2066fb233ff1f5faac18d73c3b665a54e8c55574f16bf4678c5ce835d2a14a65f8c1cec012435a8c06314cbe727a3a9b6060dfd6cdb850073423841178f6f409bb7ce8d4863c6f58855954d34af3d2964c488c9057c8c5072a54e43f1f8039d32409eb1ff3abca41c0b302788c4c56c1a4be4506ff5b8aff0242e21c0ee7ffee2da20ed9434334")
cipher_aes_nonce = bytes.fromhex('d919c229aab6535efa09a52c589c8f47')
tag = bytes.fromhex('5b204675b1b173c32c04b0b8a100ee29')

cipher_rsa = PKCS1_OAEP.new(private_key)
aes_key = cipher_rsa.decrypt(enc_aes_key)

with open('encrypted_data.bin', 'rb') as f:
ciphertext = f.read()

cipher_aes = AES.new(aes_key, AES.MODE_EAX, nonce=cipher_aes_nonce)
data = cipher_aes.decrypt_and_verify(ciphertext, tag)

with open('data.csv', 'wb') as f:
f.write(data)

需要解密个性签名,经过尝试是先base64后rc4,key是密码

1
2
3
4
5
6
7
8
9
10
11
from Crypto.Cipher import ARC4
import base64
with open('data.csv', 'r', encoding='utf-8') as f:
lines = f.readlines()
for line in lines[1:]:
line = line.strip().split(',')
rc4key = line[2].encode()
rc4 = ARC4.new(rc4key)
signature = rc4.decrypt(base64.b64decode(line[6]))
with open('decrypted_data.csv', 'a', encoding='gbk') as f:
f.write(f'{line[0]},{line[1]},{line[2]},{line[3]},{line[4]},{line[5]},{signature.decode()}\n')

搜索拿到flag DASCTF{fc450e2a9062a39049d501cb5ce287d0}