Lingze's blog Lingze's blog
timeline
about
friends
categories
tags

lingze

bin不是垃圾桶的意思!
timeline
about
friends
categories
tags
  • ctf_wp
  • Tigress
lingze
2020-07-14
目录

challenge0

# challenge 0000-0

desc:

One level of virtualization, random dispatch.
一层虚拟, 随机调度。
1
2

# 分析:

首先题目本身main函数直接, 关键位置都在vm函数中, 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
1
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]
1

# 反汇编

这个地方有几个坑,

其一在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]) ...
1
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
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
1
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)
1
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()
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

然后得到反汇编出的结果,大体如下:

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

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
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;
}
1
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()
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

运行截图:

然后开始加入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()
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

一堆挺乱的操作, 但是这个已经是代表了其算法, 简化一些是和我们之前得到的相同, 使用 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)
1
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()
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

运行截图,后面几个稍微复杂, 但是也比之前可读性高了许多。

# 多说一句

其实对于miasm来说, 能跟踪符号,在指定位置插入符号,并在对应位置取出符号,自动获取到一个比较具有可读性的语句是一个非常棒的特性, 另外动态符号执行技术体现的很棒, 在dse.attach以后,任何一个位置可以直接sb.jitter.cpu获取到确定的一些数据,而同时通过dse.ir_arch.arch.regs也可以获得这个位置的符号化表达式,

但是这里的限制也在符号, 如果某个位置没有符号的处理,仅靠dse应该很难对他们进行跟踪和分析,比如这个vm中,使用miasm就无法形成一个反汇编器, 要么直接给出最后的巨大的那个表达式,要么就在其中比较有意义且带有符号的位置断一下,

前面一个题目的fcsc中keyloolol的反汇编器, 也是因为本身是一个寄存器机器, 对每个寄存器符号化,每个操作都会牵扯到对于几个符号的处理, 于是在虚拟机调度和返回的两个位置设置解析符号和打印语句。形成一个反汇编器。

当然,这些都是目前的想法, 或许在下一步的学习会看到更多手法。

#vm
上次更新: 6/24/2025, 5:07:55 AM
Theme by Vdoing | Copyright © 2019-2025 lingze | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式