qiling-labs练习

qiling-labs练习

参考

Hijack - Qiling Framework Documentation

QilingLab Quickstart - Autumnal

屏蔽器 - QilingLab – 发布

环境搭建

1
2
3
4
5
pip install qiling
git clone https://github.com/qilingframework/qiling.git
cd qiling
git submodule update --init --recursive
pip install .

基础模板

1
2
3
4
5
6
7
8
9
10
11
from qiling import *

def challenge1(ql: Qiling):
pass

if __name__ == '__main__':
path = ['qilinglab-x86_64'] # 我们的目标
rootfs = "./qiling/examples/rootfs/x8664_linux" # 在你clone下来的仓库里
ql = Qiling(path, rootfs)
challenge1(ql) # 在ql.run()之前,做好我们的hook工作
ql.run()

挑战

挑战 1:在指针0x1337存储 1337。

挑战 2:使系统调用返回正确的值。

挑战 3:制造和“碰撞”。

挑战 4:进入“禁止”循环。

挑战 5:猜出对 的每一个调用。

挑战 6:避免无限循环。

挑战 7:不要浪费时间等待 .

挑战 8:解压结构体并在目标地址写入。

挑战 9:修复一些字符串作以使 iMpOsSiBlE 成真。

挑战 10:伪造行文件以返回正确的内容。

挑战 11:绕过 CPUID/MIDR_EL1 检查。uname/dev/urandomgetrandomrand()sleepcmdline

完整脚本

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
from qiling import *
from qiling.const import *
from qiling.os.const import *
from qiling.os.mapper import QlFsMappedObject
import struct

def challenge1(ql: Qiling):
ql.mem.map(0x1000, 0x1000)
ql.mem.write(0x1337, ql.pack16(1337))

def hook_rdi(ql: Qiling,*args):
rdi = ql.arch.regs.rdi
ql.mem.write(rdi, b'QilingOS\x00')
ql.mem.write(rdi + 65 * 3, b'ChallengeStart\x00')

def challenge2(ql: Qiling):

ql.os.set_syscall('uname', hook_rdi, QL_INTERCEPT.EXIT)


class my_uradom(QlFsMappedObject):
def read(self, size):
if size == 1:

return b'\x10'
else:
return b'\x00' * size

def close(self):
return 0

def hook_getrandom(ql:Qiling, buf, size, flags):
ql.mem.write(buf, b'\x00' * size)
ql.arch.regs.rax = 0

def challenge3(ql:Qiling):
ql.os.set_syscall('getrandom', hook_getrandom, QL_INTERCEPT.CALL)
ql.add_fs_mapper('/dev/urandom', my_uradom())

def hook_eax(ql:Qiling):
ql.arch.regs.eax = 1

def challenge4(ql:Qiling):
base_address = ql.loader.load_address
# 计算目标钩子地址(0xE43 是 cmp 指令的位置)
hook_addr = base_address + 0xE43
print(f"设置钩子地址: {hex(hook_addr)}")
ql.hook_address(hook_eax, hook_addr)

def hook_rand(ql:Qiling):
ql.arch.regs.rax = 0


def challenge5(ql:Qiling):
ql.os.set_api('rand', hook_rand, QL_INTERCEPT.CALL)

def hook_while_true(ql: Qiling):
ql.arch.regs.rax = 0

def challenge6(ql: Qiling):
libc_base = ql.loader.load_address
ql.hook_address(hook_while_true, libc_base + 0xF16)


def hook_sleep(ql: Qiling):
return

def challenge7(ql: Qiling):
ql.os.set_api('sleep', hook_sleep, QL_INTERCEPT.CALL)

def hook_sleep(ql: Qiling):
return

def challenge7(ql: Qiling):
ql.os.set_api('sleep', hook_sleep, QL_INTERCEPT.CALL)

def hook_mem(ql:Qiling):
rax = ql.arch.regs.rax # 结构体首地址
ql.log.info(f"\u001b[31m[+] rax: {hex(rax)}\u001b[0m")

data = ql.mem.read(rax, 24) # 读取结构体数据
ql.log.info(f"\u001b[31m[+] data: {data.hex()}\u001b[0m")

str_addr, magic_num, check_addr = struct.unpack("QQQ", data) # 解析结构体数据
ql.log.info(f"\u001b[31m[+] str_addr: {hex(str_addr)}\u001b[0m")
ql.mem.read(str_addr, 0x10) # 读取字符串数据
ql.log.info(f"\u001b[31m[+] str: {ql.mem.string(str_addr)}\u001b[0m")
ql.log.info(f"\u001b[31m[+] magic_num: {hex(magic_num)}\u001b[0m")
ql.log.info(f"\u001b[31m[+] check_addr: {hex(check_addr)}\u001b[0m")

ql.mem.write(check_addr, b'\x01') # 将check_addr的值设置为1
check = ql.mem.read(check_addr, 8) # 读取check_addr的值
ql.log.info(f"\u001b[31m[+] check: {check.hex()}\u001b[0m")


def challenge8(ql: Qiling):
libc_base = ql.loader.load_address
hook_addr = libc_base + 0x00FB5
ql.log.info(f"\u001b[31m[+] hook_addr: {hook_addr}\u001b[0m")
ql.hook_address(hook_mem, hook_addr)

def hook_data(ql:Qiling):
print("challenge9")
rax = ql.arch.regs.rax
print("data",ql.mem.read(rax,8))
ql.mem.write(rax,b'\x01')
print("has change")


def challenge9(ql: Qiling):
libc_base = ql.loader.load_address
hook_addr = libc_base + 0x1061
ql.log.info(f"\u001b[31m[+] hook_addr: {hook_addr}\u001b[0m")
ql.hook_address(hook_data, hook_addr)

def hook_strcmp(ql: Qiling):
print("start challenge 10 hook")
data_address = ql.arch.regs.rax
ql.log.info(f"\u001b[31m[+] data_address: {hex(data_address)}\u001b[0m")
ql.mem.read(data_address, 0x10) # 读取字符串数据
ql.log.info(f"\u001b[31m[+] str: {ql.mem.string(data_address)}\u001b[0m")
ql.mem.write(data_address, b'qilinglab\x00') # 将check_addr的值设置为1
ql.log.info(f"\u001b[31m[+] str: {ql.mem.string(data_address)}\u001b[0m")



def challenge10(ql: Qiling):
print("start challenge 10")
libc_base = ql.loader.load_address
hook_addr = libc_base + 0x112D
ql.log.info(f"\u001b[31m[+] hook_addr: {hook_addr}\u001b[0m")
ql.hook_address(hook_strcmp, hook_addr)


def challenge10(ql: Qiling):
print("start challenge 10")
libc_base = ql.loader.load_address
hook_addr = libc_base + 0x112D
ql.log.info(f"\u001b[31m[+] hook_addr: {hook_addr}\u001b[0m")
ql.hook_address(hook_strcmp, hook_addr)

def hook_cpuid(ql: Qiling, *args):
ql.arch.regs.ebx = 0x696C6951
ql.arch.regs.ecx = 0x614C676E
ql.arch.regs.edx = 0x20202062

def challenge11(ql: Qiling):
libc_base = ql.loader.load_address
hook_addr = libc_base + 0x1191
ql.hook_address(hook_cpuid, hook_addr)


if __name__ == '__main__':
path = [r'D:\qil\qilinglab-x86_64']
rootfs = r"D:\qil\qiling\examples\rootfs\x8664_linux"
ql = Qiling(path, rootfs)
challenge1(ql)
challenge2(ql)
challenge3(ql)
challenge4(ql)
challenge5(ql)
challenge6(ql)
challenge7(ql)
challenge8(ql)
challenge9(ql)
challenge10(ql)
challenge11(ql)
ql.verbose = 0
ql.run()

image