challenge0
# challenge 0000-0
desc:
One level of virtualization, random dispatch.
一层虚拟, 随机调度。
2
# 分析:
首先题目本身main函数直接, 关键位置都在vm函数中,
对应函数:
最后根据一个数组进行跳转, 数组地址在:0000000000602400,我们简单使用ida python脚本处理一下这个位置:
data = get_segm_by_name('.data')
start = 0x0000000000602400
end = data.endEA
p = start
while p < end:
MakeQword(p)
p += 8
2
3
4
5
6
7
8
将这一段全部设置好以后发现对应的地址全部设置为了函数, 那些其实就是一个个的handle,
然后简单调试中可以看到两个站内地址的使用极为频繁, 为: [rbp-70h]
对应的是opcode指令流, [rbp-80h]
对应虚拟栈。
其实这个时候基本可以将opcode取出,并开始调试对应opcode和参数,编写反汇编脚本,
opcode = [0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x6E, 0x60, 0xD1, 0x70, 0xD8, 0x34, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0xDF, 0x60, 0x8B, 0xA9, 0xFC, 0xD9, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x6E, 0x56, 0x56, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0xDF, 0x60, 0x80, 0xC4, 0x6B, 0x04, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x6E, 0x56, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0xDF, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1F, 0xA0, 0xBC, 0x38, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0xC7, 0x4A, 0x56, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x6E, 0x60, 0xC5, 0xC3, 0xD9, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x5D, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x6E, 0x60, 0xC5, 0xC3, 0xD9, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1F, 0xA0, 0xBC, 0x38, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0xC7, 0x4A, 0x56, 0x2B, 0x56, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0xDF, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0x4A, 0x56, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0x5D, 0x4A, 0x5D, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0x56, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0xDF, 0x60, 0xB7, 0x60, 0x7C, 0x2C, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0xC7, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0xC7, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0x5F, 0xC7, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x01, 0x00, 0x00, 0x00, 0x61, 0x0E, 0xDF, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x90, 0x0D, 0x40, 0x00]
# 反汇编
这个地方有几个坑,
其一在opcode内, 注意到这个[rbp - 70h]
的处理时而+1
时而+4
时而+8
, 其实是opcode对应byte类型,但是参数却不一定什么类型, 使用一个unpack函数简单抵消这个:
def unpack(arr):
a = 0
for i in range(len(arr)):
a += arr[i] << i
return a
# unpack(arr[i:i+4]) ...
2
3
4
5
6
# 踩坑
然后尝试编写了一个类似下面的脚本:
code
i = 0
a = 0
while i < len(opcode):
op = opcode[i]
if op == 0x60 or op == 0x0E1:
print('{:4}-- {:4}:: [-] push [{}]'.format(a, i, pack(opcode[i+1:i+9])))
i += 8
elif op == 0x90:
print('{:4}-- {:4}:: [-] push addr[{}]'.format(a, i, pack(opcode[i+1:i+5])))
i += 4
elif op == 0x27 or op == 0x3c or op == 0xe or op==0x5f:
print('{:4}-- {:4}:: [!] binary add'.format(a, i))
elif op == 0xdf:
print('{:4}-- {:4}:: [-] pop addr'.format(a, i))
elif op == 0x0C7:
print('{:4}-- {:4}:: [!] binary imul'.format(a, i))
elif op == 0x6E or op == 0x4e or op == 0x61 :
print('{:4}-- {:4}:: [v] pass'.format(a, i))
elif op == 0x8e:
print('{:4}-- {:4}:: [+] if val[{}]'.format(a, i,pack(opcode[i+1:i+5])))
i += 4
elif op == 0x56:
print('{:4}-- {:4}:: [!] binary or'.format(a, i))
else:
print('{:4}-- {:4}:: [:] asdf'.format(a, i))
i += 1
a += 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
还没有识别到的打印asdf
, 然后可以看到:
还有非常大量的没有获取到,但是大部分都在880+, 调试并获取突然他们是很麻烦的,
此时我们回头看关于handle, 其实跳转是关于我们处理好了的这个数据,
一般的vm中,对于opcode -> handle的映射是在一个switch中,为一对一映射, 而这个题目中是opcode处理以后查表得到对应handle,会出现多对一的映射关系,
因此我们也要做一个映射的函数处理opcode, 然后再输出对应的反汇编代码:
# 映射-反汇编
得到对应的运算:
data = [14, 39, 43, 60, 66, 74, 77, 78, 86, 93, 95, 96, 97, 110, 142, 144, 199, 223, 225, 242, 244]
def mapp(val):
v3 = 0
v4 = 0x14
v6 = val
while v4 >= v3:
v5 = v3 + ((v6 - data[v3]) * (v4 - v3) // (data[v4] - data[v3]))
if data[v5] >= v6:
if data[v5] <= v6:
v4 = -1
else:
v4 = v5 - 1
else:
v3 = v5 + 1
return v5
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
简单对几个对应的handle重命名, 然后ida python脚本导出:
base = 0x000000000602408
for i in range(21):
name = get_name(Qword(base + i * 16))
print(i, name)
2
3
4
5
然后得到大体的反汇编脚本:
code
def unpack(arr):
a = 0
for i in range(len(arr)):
a |= arr[i] << i*8
return a
opcode = [0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x6E, 0x60, 0xD1, 0x70, 0xD8, 0x34, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0xDF, 0x60, 0x8B, 0xA9, 0xFC, 0xD9, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x6E, 0x56, 0x56, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0xDF, 0x60, 0x80, 0xC4, 0x6B, 0x04, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x6E, 0x56, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0xDF, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1F, 0xA0, 0xBC, 0x38, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0xC7, 0x4A, 0x56, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x6E, 0x60, 0xC5, 0xC3, 0xD9, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x5D, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x61, 0x0E, 0x6E, 0x60, 0xC5, 0xC3, 0xD9, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1F, 0xA0, 0xBC, 0x38, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0xC7, 0x4A, 0x56, 0x2B, 0x56, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0xDF, 0x60, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0x4A, 0x56, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0x5D, 0x4A, 0x5D, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0x56, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0xDF, 0x60, 0xB7, 0x60, 0x7C, 0x2C, 0x00, 0x00, 0x00, 0x00, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0xC7, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0xC7, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0xE1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x3C, 0x90, 0x10, 0x00, 0x00, 0x00, 0x27, 0x6E, 0x5F, 0xC7, 0x60, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xC7, 0x8E, 0x01, 0x00, 0x00, 0x00, 0x61, 0x0E, 0xDF, 0xF4, 0x04, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x90, 0x0D, 0x40, 0x00]
data = [14, 39, 43, 60, 66, 74, 77, 78, 86, 93, 95, 96, 97, 110, 142, 144, 199, 223, 225, 242, 244]
def mapp(val):
v3 = 0
v4 = 0x14
v6 = val
while v4 >= v3:
v5 = v3 + ((v6 - data[v3]) * (v4 - v3) // (data[v4] - data[v3]))
if data[v5] >= v6:
if data[v5] <= v6:
v4 = -1
else:
v4 = v5 - 1
else:
v3 = v5 + 1
return v5
def disasm():
i = 0
a = 0
while i < len(opcode):
op = mapp(opcode[i])
# print(op)
if op in [18, 11]:
print('{:4} -- {:4}:: [-] push [{}]'.format(a, i, unpack(opcode[i+1:i+9])))
i += 8
elif op == 15:
print('{:4} -- {:4}:: [-] push addr [{}]'.format(a, i, unpack(opcode[i+1:i+5])))
i += 4
elif op in [0, 3, 10]:
print('{:4} -- {:4}:: [+] binary_add'.format(a, i))
elif op in [7, 19]:
print('{:4} -- {:4}:: [:] nop'.format(a, i))
elif op in [12, 13]:
print('{:4} -- {:4}:: [>] read addr'.format(a, i))
elif op == 5:
print('{:4} -- {:4}:: [+] binary_and'.format(a, i))
elif op == 1:
print('{:4} -- {:4}:: [+] binary add addr'.format(a, i))
elif op == 17:
print('{:4} -- {:4}:: [+] write addr\n\n\n\n'.format(a, i))
elif op == 4:
print('{:4} -- {:4}:: [+] binary_sub'.format(a, i))
elif op == 2:
print('{:4} -- {:4}:: [+] binary_>>'.format(a, i))
elif op == 8:
print('{:4} -- {:4}:: [+] binary_or'.format(a, i))
elif op == 16:
print('{:4} -- {:4}:: [+] binary_imul'.format(a, i))
elif op == 9:
print('{:4} -- {:4}:: [+] binary_<<'.format(a, i))
elif op == 6:
print('{:4} -- {:4}:: [:] ret'.format(a, i))
break
elif op == 20:
print('{:4} -- {:4}:: [:] jump'.format(a, i))
val = unpack(opcode[i+1:i+5])
i += val
elif op == 14:
print('{:4} -- {:4}:: [>] read {} addr'.format(a, i, ' output' if unpack(opcode[i+1:i+5]) else ' input'))
i += 4
else:
print('{:4}-- {:4}:: [:] asdf'.format(a, i))
i += 1
a += 1
disasm()
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
然后得到反汇编出的结果,大体如下:
details
如下, 使用python disassemble.py > disassemble.txt
0 -- 0:: [-] push [8]
1 -- 9:: [-] push [0]
2 -- 18:: [:] nop
3 -- 19:: [+] binary_imul
4 -- 20:: [>] read input addr
5 -- 25:: [>] read addr
6 -- 26:: [+] binary_add
7 -- 27:: [>] read addr
8 -- 28:: [-] push [886599889]
9 -- 37:: [+] binary_add
10 -- 38:: [-] push [0]
11 -- 47:: [-] push [8]
12 -- 56:: [-] push [0]
13 -- 65:: [+] binary_imul
14 -- 66:: [+] binary_add
15 -- 67:: [-] push addr [16]
16 -- 72:: [+] binary add addr
17 -- 73:: [+] write addr
18 -- 74:: [-] push [18446744073071798667]
19 -- 83:: [-] push [0]
20 -- 92:: [-] push [8]
21 -- 101:: [-] push [0]
22 -- 110:: [+] binary_imul
23 -- 111:: [+] binary_add
24 -- 112:: [-] push addr [16]
25 -- 117:: [+] binary add addr
26 -- 118:: [>] read addr
27 -- 119:: [-] push [8]
28 -- 128:: [-] push [0]
29 -- 137:: [:] nop
30 -- 138:: [+] binary_imul
31 -- 139:: [>] read input addr
32 -- 144:: [>] read addr
33 -- 145:: [+] binary_add
34 -- 146:: [>] read addr
35 -- 147:: [+] binary_or
36 -- 148:: [+] binary_or
37 -- 149:: [-] push [0]
38 -- 158:: [-] push [8]
39 -- 167:: [-] push [1]
40 -- 176:: [+] binary_imul
41 -- 177:: [+] binary_add
42 -- 178:: [-] push addr [16]
43 -- 183:: [+] binary add addr
44 -- 184:: [+] write addr
45 -- 185:: [-] push [74171520]
46 -- 194:: [-] push [8]
47 -- 203:: [-] push [0]
48 -- 212:: [:] nop
49 -- 213:: [+] binary_imul
50 -- 214:: [>] read input addr
51 -- 219:: [>] read addr
52 -- 220:: [+] binary_add
53 -- 221:: [>] read addr
54 -- 222:: [+] binary_or
55 -- 223:: [-] push [0]
56 -- 232:: [-] push [8]
57 -- 241:: [-] push [2]
58 -- 250:: [+] binary_imul
59 -- 251:: [+] binary_add
60 -- 252:: [-] push addr [16]
61 -- 257:: [+] binary add addr
62 -- 258:: [+] write addr
63 -- 259:: [-] push [1]
64 -- 268:: [-] push [15]
65 -- 277:: [-] push [951885855]
66 -- 286:: [-] push [0]
67 -- 295:: [-] push [8]
68 -- 304:: [-] push [0]
69 -- 313:: [+] binary_imul
70 -- 314:: [+] binary_add
71 -- 315:: [-] push addr [16]
72 -- 320:: [+] binary add addr
73 -- 321:: [>] read addr
74 -- 322:: [+] binary_imul
75 -- 323:: [+] binary_and
76 -- 324:: [+] binary_or
77 -- 325:: [-] push [64]
78 -- 334:: [+] binary_sub
79 -- 335:: [-] push [8]
80 -- 344:: [-] push [0]
81 -- 353:: [:] nop
82 -- 354:: [+] binary_imul
83 -- 355:: [>] read input addr
84 -- 360:: [>] read addr
85 -- 361:: [+] binary_add
86 -- 362:: [>] read addr
87 -- 363:: [-] push [500810693]
88 -- 372:: [+] binary_add
89 -- 373:: [+] binary_<<
90 -- 374:: [-] push [8]
91 -- 383:: [-] push [0]
92 -- 392:: [:] nop
93 -- 393:: [+] binary_imul
94 -- 394:: [>] read input addr
95 -- 399:: [>] read addr
96 -- 400:: [+] binary_add
97 -- 401:: [>] read addr
98 -- 402:: [-] push [500810693]
99 -- 411:: [+] binary_add
100 -- 412:: [-] push [1]
101 -- 421:: [-] push [15]
102 -- 430:: [-] push [951885855]
103 -- 439:: [-] push [0]
104 -- 448:: [-] push [8]
105 -- 457:: [-] push [0]
106 -- 466:: [+] binary_imul
107 -- 467:: [+] binary_add
108 -- 468:: [-] push addr [16]
109 -- 473:: [+] binary add addr
110 -- 474:: [>] read addr
111 -- 475:: [+] binary_imul
112 -- 476:: [+] binary_and
113 -- 477:: [+] binary_or
114 -- 478:: [+] binary_>>
115 -- 479:: [+] binary_or
116 -- 480:: [-] push [0]
117 -- 489:: [-] push [8]
118 -- 498:: [-] push [3]
119 -- 507:: [+] binary_imul
120 -- 508:: [+] binary_add
121 -- 509:: [-] push addr [16]
122 -- 514:: [+] binary add addr
123 -- 515:: [+] write addr
124 -- 516:: [-] push [4]
125 -- 525:: [-] push [63]
126 -- 534:: [-] push [1]
127 -- 543:: [-] push [7]
128 -- 552:: [-] push [0]
129 -- 561:: [-] push [8]
130 -- 570:: [-] push [0]
131 -- 579:: [+] binary_imul
132 -- 580:: [+] binary_add
133 -- 581:: [-] push addr [16]
134 -- 586:: [+] binary add addr
135 -- 587:: [>] read addr
136 -- 588:: [+] binary_and
137 -- 589:: [+] binary_or
138 -- 590:: [-] push [0]
139 -- 599:: [-] push [8]
140 -- 608:: [-] push [2]
141 -- 617:: [+] binary_imul
142 -- 618:: [+] binary_add
143 -- 619:: [-] push addr [16]
144 -- 624:: [+] binary add addr
145 -- 625:: [>] read addr
146 -- 626:: [+] binary_<<
147 -- 627:: [+] binary_and
148 -- 628:: [+] binary_<<
149 -- 629:: [-] push [0]
150 -- 638:: [-] push [8]
151 -- 647:: [-] push [3]
152 -- 656:: [+] binary_imul
153 -- 657:: [+] binary_add
154 -- 658:: [-] push addr [16]
155 -- 663:: [+] binary add addr
156 -- 664:: [>] read addr
157 -- 665:: [+] binary_or
158 -- 666:: [-] push [0]
159 -- 675:: [-] push [8]
160 -- 684:: [-] push [3]
161 -- 693:: [+] binary_imul
162 -- 694:: [+] binary_add
163 -- 695:: [-] push addr [16]
164 -- 700:: [+] binary add addr
165 -- 701:: [+] write addr
166 -- 702:: [-] push [746348727]
167 -- 711:: [-] push [0]
168 -- 720:: [-] push [8]
169 -- 729:: [-] push [3]
170 -- 738:: [+] binary_imul
171 -- 739:: [+] binary_add
172 -- 740:: [-] push addr [16]
173 -- 745:: [+] binary add addr
174 -- 746:: [>] read addr
175 -- 747:: [+] binary_imul
176 -- 748:: [-] push [0]
177 -- 757:: [-] push [8]
178 -- 766:: [-] push [2]
179 -- 775:: [+] binary_imul
180 -- 776:: [+] binary_add
181 -- 777:: [-] push addr [16]
182 -- 782:: [+] binary add addr
183 -- 783:: [>] read addr
184 -- 784:: [+] binary_imul
185 -- 785:: [-] push [0]
186 -- 794:: [-] push [8]
187 -- 803:: [-] push [0]
188 -- 812:: [+] binary_imul
189 -- 813:: [+] binary_add
190 -- 814:: [-] push addr [16]
191 -- 819:: [+] binary add addr
192 -- 820:: [>] read addr
193 -- 821:: [-] push [0]
194 -- 830:: [-] push [8]
195 -- 839:: [-] push [1]
196 -- 848:: [+] binary_imul
197 -- 849:: [+] binary_add
198 -- 850:: [-] push addr [16]
199 -- 855:: [+] binary add addr
200 -- 856:: [>] read addr
201 -- 857:: [+] binary_add
202 -- 858:: [+] binary_imul
203 -- 859:: [-] push [8]
204 -- 868:: [-] push [0]
205 -- 877:: [:] nop
206 -- 878:: [+] binary_imul
207 -- 879:: [>] read output addr
208 -- 884:: [>] read addr
209 -- 885:: [+] binary_add
210 -- 886:: [+] write addr
211 -- 887:: [:] jump
212 -- 892:: [:] ret
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
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# 逻辑
于是可以得到对应的逻辑, 大致如下:
#include <stdio.h>
int main() {
long long int a0, a1, a2, a3, a4, a5, aa;
a5 = 44;
a0 = a5 + 886599889;
a1 = a5 | a0 | 18446744073071798667l;
a2 = a5 | 74171520;
a3 = ((a5 + 500810693) >> (((a0 * 951885855) & 15) | 1)) | ((a5 + 500810693) << (64 - ((a1 * 951885855) & 15 | 1)));
a3 = ((a2 << (a0 & 7 ^ 1)) & 4 )<< 63 | a3;
a4 = (a0 + a1) * (a2 * (a3 * 746348727));
printf("%llu, ", a4);
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
得到逻辑, 成功!
这样, 就是, 拿头逆的过程了。
# 符号执行
使用miasm处理这个问题, 并且在这里记录一些坑点, 主要是miasm-blog中的解法, 在文章Playing with Dynamic symbolic execution (opens new window)
相关的东西已经在book的maism笔记里写了, 这里是总的脚本和一些注释,
# 复现miasm
先实现程序正常的运行, 其中用到了:命令行参数,canary, 简单实现xxx_strtoul
函数,
code
from miasm.analysis.sandbox import Sandbox_Linux_x86_64
from miasm.jitter.csts import PAGE_READ
def xxx_strtoul(jitter):
ret_ad, args = jitter.func_args_systemv(["str", 'endptrt', 'base'])
s = jitter.get_c_str(args.str)
ret = int(s, args.base)
print("%s ==> %d" % (s, ret))
return jitter.func_ret_systemv(ret_ad, ret)
parser = Sandbox_Linux_x86_64.parser(description = "ELF sandboxer")
parser.add_argument("filename", help = "ELF FileName")
options = parser.parse_args()
options.mimic_env = True
options.command_line = ['1234']
sb = Sandbox_Linux_x86_64(options.filename, options, globals())
sb.jitter.ir_arch.do_all_segm = True
FS_0_ADDR = 0x7ff70000
sb.jitter.cpu.FS = 0x4
sb.jitter.cpu.set_segm_base(sb.jitter.cpu.FS, FS_0_ADDR)
sb.jitter.vm.add_memory_page(FS_0_ADDR + 0x28, PAGE_READ, b'bbbbbbbb', "stack canary fs[0x28]")
sb.run()
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
运行截图:
然后开始加入dse engine 和 符号化变量,并获取最后的结果。
code
from miasm.analysis.sandbox import Sandbox_Linux_x86_64
from miasm.jitter.csts import PAGE_READ
from miasm.analysis.dse import DSEEngine
from miasm.expression.expression import ExprId
value = ExprId("value", 64)
def xxx_strtoul(jitter):
ret_ad, args = jitter.func_args_systemv(["str", 'endptrt', 'base'])
s = jitter.get_c_str(args.str)
ret = int(s, args.base)
print("%s ==> %d" % (s, ret))
jitter.func_ret_systemv(ret_ad, ret)
global dse
dse.attach(jitter)
dse.update_state_from_concrete()
dse.update_state({dse.ir_arch.arch.regs.RAX: value})
def xxx_printf_symb(dse):
result = dse.eval_expr(dse.ir_arch.arch.regs.RSI)
print(result)
print('exit')
parser = Sandbox_Linux_x86_64.parser(description = "ELF sandboxer")
parser.add_argument("filename", help = "ELF FileName")
options = parser.parse_args()
options.mimic_env = True
options.command_line = ['1234']
sb = Sandbox_Linux_x86_64(options.filename, options, globals())
sb.jitter.ir_arch.do_all_segm = True
FS_0_ADDR = 0x7ff70000
sb.jitter.cpu.FS = 0x4
sb.jitter.cpu.set_segm_base(sb.jitter.cpu.FS, FS_0_ADDR)
sb.jitter.vm.add_memory_page(FS_0_ADDR + 0x28, PAGE_READ, b'bbbbbbbb', "stack canary fs[0x28]")
dse = DSEEngine(sb.machine)
dse.add_lib_handler(sb.libs, globals())
sb.run()
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
一堆挺乱的操作, 但是这个已经是代表了其算法, 简化一些是和我们之前得到的相同, 使用 python symbol0-0.py challenge-0 > asdf
结果如下:
这里还可以考虑配合Expr系列对象的replace_expr
对象, 对符号化的变量带入具体值,并判断是否正确:
obraubed = int(dse.symb.expr_simp(result.replace_expr({value: ExprInt(1234, 64)})))
print(obraubed == sb.jitter.cpu.RSI)
2
# miasm分步
也是因为上面的数据太多了,在这里我使用类似的方式,编写分步给出反汇编结果的一个脚本, 主要是使用到我们vm中的写入内存的位置,在这个位置下断, 可以累计写入的次数,并截获写入地址和数据,可以看到, 一同写入六次, 最后一次写入的数据和最后打印的数据一致, 于是分段打印出来,
这里主要使用的是增加了对应地址的instrumentation, 通过dse.ir_arch和sb.jitter访问寄存器内的值, 获取符号或具体值。
对于几个变量的定义用了个字典,然后对src进行replace来替换了下,因为符号嵌套式的使用, 不怎么敢用。😅 😅
code
from miasm.analysis.sandbox import Sandbox_Linux_x86_64
from miasm.jitter.csts import PAGE_READ
from miasm.analysis.dse import DSEEngine
from miasm.expression.expression import ExprId, ExprInt
def xxx_strtoul(jitter):
ret_ad, args = jitter.func_args_systemv(["str", 'endptrt', 'base'])
s = jitter.get_c_str(args.str)
ret = int(s, args.base)
print("%s ==> %d" % (s, ret))
jitter.func_ret_systemv(ret_ad, ret)
global dse
dse.attach(jitter)
dse.update_state_from_concrete()
dse.update_state({dse.ir_arch.arch.regs.RAX: value})
def xxx_printf_symb(dse):
print("[!] print=>> %d" %(sb.jitter.cpu.RSI))
for val in already_disass:
print("%s = %s" %(val, already_disass[val]))
print('exit')
def symboliz_vm(dse):
global num
num += 1
print("[%d] addr:%d <== data: %d" %(num, sb.jitter.cpu.RAX, sb.jitter.cpu.RDX))
src = str(dse.eval_expr(dse.ir_arch.arch.regs.RDX))
for val in already_disass:
src = src.replace(already_disass[val], val)
already_disass['val_%d' %(num)] = src
parser = Sandbox_Linux_x86_64.parser(description = "ELF sandboxer")
parser.add_argument("filename", help = "ELF FileName")
options = parser.parse_args()
options.mimic_env = True
options.command_line = ['1234']
sb = Sandbox_Linux_x86_64(options.filename, options, globals())
sb.jitter.ir_arch.do_all_segm = True
FS_0_ADDR = 0x7ff70000
sb.jitter.cpu.FS = 0x4
sb.jitter.cpu.set_segm_base(sb.jitter.cpu.FS, FS_0_ADDR)
sb.jitter.vm.add_memory_page(FS_0_ADDR + 0x28, PAGE_READ, b'bbbbbbbb', "stack canary fs[0x28]")
value = ExprId("value", 64)
num = 0
already_disass = {}
dse = DSEEngine(sb.machine)
dse.add_lib_handler(sb.libs, globals())
write_addr = 0x0000000000400C70
dse.add_instrumentation(write_addr, symboliz_vm)
sb.run()
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
运行截图,后面几个稍微复杂, 但是也比之前可读性高了许多。
# 多说一句
其实对于miasm来说, 能跟踪符号,在指定位置插入符号,并在对应位置取出符号,自动获取到一个比较具有可读性的语句是一个非常棒的特性, 另外动态符号执行技术体现的很棒, 在dse.attach以后,任何一个位置可以直接sb.jitter.cpu获取到确定的一些数据,而同时通过dse.ir_arch.arch.regs也可以获得这个位置的符号化表达式,
但是这里的限制也在符号, 如果某个位置没有符号的处理,仅靠dse应该很难对他们进行跟踪和分析,比如这个vm中,使用miasm就无法形成一个反汇编器, 要么直接给出最后的巨大的那个表达式,要么就在其中比较有意义且带有符号的位置断一下,
前面一个题目的fcsc中keyloolol的反汇编器, 也是因为本身是一个寄存器机器, 对每个寄存器符号化,每个操作都会牵扯到对于几个符号的处理, 于是在虚拟机调度和返回的两个位置设置解析符号和打印语句。形成一个反汇编器。
当然,这些都是目前的想法, 或许在下一步的学习会看到更多手法。