NepCTF 2023
S3a Lv3

与AI共舞的哈夫曼

image

  1. 下载文件 源码
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
import heapq
import os

class HuffmanNode:
def __init__(self, char, freq):
self.char = char
self.freq = freq
self.left = None
self.right = None

def __lt__(self, other):
return self.freq < other.freq

def build_huffman_tree(frequencies):
heap = [HuffmanNode(char, freq) for char, freq in frequencies.items()]
heapq.heapify(heap)

while len(heap) > 1:
left = heapq.heappop(heap)
right = heapq.heappop(heap)
merged = HuffmanNode(None, left.freq + right.freq)
merged.left = left
merged.right = right
heapq.heappush(heap, merged)

return heap[0]

def build_huffman_codes(node, current_code, huffman_codes):
if node is None:
return

if node.char is not None:
huffman_codes[node.char] = current_code
return

build_huffman_codes(node.left, current_code + '0', huffman_codes)
build_huffman_codes(node.right, current_code + '1', huffman_codes)

def compress(input_file, output_file):
with open(input_file, 'rb') as f:
data = f.read()

frequencies = {}
for byte in data:
if byte not in frequencies:
frequencies[byte] = 0
frequencies[byte] += 1

root = build_huffman_tree(frequencies)
huffman_codes = {}
build_huffman_codes(root, '', huffman_codes)

compressed_data = ''
for byte in data:
compressed_data += huffman_codes[byte]

padding = 8 - len(compressed_data) % 8
compressed_data += '0' * padding

with open(output_file, 'wb') as f:
# Write frequency information
f.write(bytes([len(frequencies)]))
for byte, freq in frequencies.items():
f.write(bytes([byte, (freq >> 24) & 0xFF, (freq >> 16) & 0xFF, (freq >> 8) & 0xFF, freq & 0xFF]))

# Write compressed data
for i in range(0, len(compressed_data), 8):
byte = compressed_data[i:i+8]
f.write(bytes([int(byte, 2)]))

if __name__ == "__main__":
input_file = 'input.txt'
compressed_file = 'compressed.bin'
decompressed_file = 'decompressed.txt'

# 压缩文件
compress(input_file, compressed_file)

# 解压缩文件
decompress(compressed_file, decompressed_file)
  1. 观察源码发现 缺少解压缩函数 编写解压缩函数
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
def decompress(input_file, output_file):
# 读取压缩文件中的数据
with open(input_file, 'rb') as f:
compressed_data = f.read()
# print(compressed_data)
# 读取频率信息
num_symbols = compressed_data[0]
# print(num_symbols)
frequencies = {}
index = 1
for _ in range(num_symbols):
symbol = compressed_data[index]
# print(symbol)
freq = (compressed_data[index + 1] << 24) | (compressed_data[index + 2] << 16) | (compressed_data[index + 3] << 8) | compressed_data[index + 4]
frequencies[symbol] = freq
index += 5

# 重建 Huffman 树
root = build_huffman_tree(frequencies)

# 解压缩数据
current_node = root
decompressed_data = []
for byte in compressed_data[index:]:
byte_value = int(byte)
for i in range(7, -1, -1):
bit = (byte_value >> i) & 1
if bit == 0:
current_node = current_node.left
else:
current_node = current_node.right

if current_node.char is not None:
decompressed_data.append(current_node.char)
current_node = root

# 将解压缩后的数据写入文件
with open(output_file, 'wb') as f:
f.write(bytes(decompressed_data))
  1. 运行代码得到decompressed.txt

image

codes

image

  1. 进入访问页面后:
image
  1. 观察得到 需要输入C语言代码,输入system后没有正常显示,猜测可能是被过滤了

  2. 于是通过argv 直接打印命令行参数

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv) {
// 打印命令行参数
printf("Command line arguments:\n");
for (int i = 0; i < 20; i++) {
printf("argv[%d]: %s\n", i, argv[i]);
}

return 0;
}

image

 Comments
Comment plugin failed to load
Loading comment plugin