PBCTF2021: Binary Tree

PBCTF2021: Binary Tree

用代码实现了一个图,利用 capstone 提取一下图数据,跑一遍最短路径就可以得出flag

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
from capstone import *
import copy
from pwn import *

import graphviz
from graphviz import nohtml
from six import print_

elf = ELF("main.elf")
md = Cs(CS_ARCH_X86, CS_MODE_64)
md.detail = True
initkey = elf.read(0x4000AD, 32)


def bin2str(m):
t = ''
for i in range(100):
nn = m[i * 8: i * 8 + 8]
t += chr(int("".join([str(i) for i in nn])[::-1], 2))
return t


g = graphviz.Digraph('g', filename='btree.gv',
node_attr={'shape': 'record', 'height': '.1'})


class MyNode:
def __init__(self, offset):
self.offset = offset
self.min_path = []
self.min_cost = 0

class Edge:
def __init__(self, start, end, lr):
self.start = start
self.end = end
self.lr = lr

g_nodes = {}
g_edges = []

def decode_block(offset, key_data, vv = 0):
bin_offset = offset + 0x400176
bin_data = bytearray(elf.read(bin_offset, 32))
for i in range(32):
bin_data[i] ^= key_data[i]

next_ = []
key_ = []

for i in md.disasm(bin_data, 0x4000AD):
ins = "0x%x:\t%s\t%s" % (i.address, i.mnemonic, i.op_str)
if 'lea' in ins and 'rbx' in ins:
next_.append(int(i.op_str.split('[rdi + ')[1][:-1], 16))
if 'add' in ins and 'r9' in ins:
key_.append(int(ins.split('r9, ')[1], 16))

g_nodes[offset] = MyNode(offset)
min_cost = 0xffffff
min_edge = None
min_node = None
for edge in g_edges:
if edge.end == offset:
node = g_nodes[edge.start]
cur_cost = node.min_cost + vv
if cur_cost < min_cost:
min_cost = cur_cost
min_edge = edge
min_node = node
if min_edge != None:
g_nodes[offset].min_path = min_node.min_path.copy()
g_nodes[offset].min_cost = min_cost
g_nodes[offset].min_path.append(min_edge.lr)

if len(next_) == 2:
g.node('node_' + hex(offset)[2:], nohtml('<f0> |<f1> %x|<f2>' % vv))
g.edge('node_%x:f0' % offset, 'node_%x:f1' % next_[0])
g.edge('node_%x:f2' % offset, 'node_%x:f1' % next_[1])

g_edges.append(Edge(offset, next_[0], 1))
g_edges.append(Edge(offset, next_[1], 0))
else:
g.node('node_' + hex(offset)[2:], nohtml('<f0> |<f1> %x|<f2>' % min_cost))
print("min:%x" % min_cost)
if min_cost <= 0x49da:
print("yes !!!")
print(g_nodes[offset].min_path)
print(bin2str(g_nodes[offset].min_path))
return next_, key_, bin_data

def draw():
hist = []
worklist = [(0, initkey, 0)]
while len(worklist) > 0:
t = worklist[0]
del(worklist[0])
if t[0] in hist:
continue
hist.append(t[0])
next_, key_, bin_data = decode_block(t[0], t[1], t[2])
if len(next_) == 2:
worklist.append((next_[0], bin_data, key_[0]))
worklist.append((next_[1], bin_data, key_[1]))
draw()
print("Finish.")
input(">>>")
g.view()

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!