-
Notifications
You must be signed in to change notification settings - Fork 0
/
test_lifter.py
128 lines (105 loc) · 4.92 KB
/
test_lifter.py
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
import binascii
import pyvex
import archinfo
import angr
def test_strict_block_ends_cbz():
# ldr r3, [sp, #4]
# cbz r3, #0x8149
# mov.w r2, #0x10000000
# ldr r3, [pc, #0x38]
# str r2, [r3]
# add sp, #8
# pop {r4, r5, r6, pc}
p = angr.load_shellcode(b'\x01\x9b\x1b\xb1O\xf0\x80R\x0eK\x1a`\x02\xb0p\xbd', 'arm')
assert p.factory.block(1, strict_block_end=False).instructions == 7
assert p.factory.block(1, strict_block_end=True).instructions == 2
p.factory.default_engine.default_strict_block_end = False
assert p.factory.block(1).instructions == 7
p.factory.default_engine.default_strict_block_end = True
assert p.factory.block(1).instructions == 2
def test_strict_block_ends_with_size_x86():
# cmovnz cx, dx
# pop eax
# jecxz short loc_4010D7 ; the first block should end here
# sub edi, 2
# loop loc_4010c9
# nop
# nop
b = b"\x66\x0f\x45\xca\x58\xe3\x07\x83\xef\x02\xe2\xf4\x90\x90"
p = angr.load_shellcode(b, 'x86', load_address=0x4010c9)
# jecxz
assert p.factory.block(0x4010c9, size=len(b), strict_block_end=False).instructions == 7
assert p.factory.block(0x4010c9, strict_block_end=True).instructions == 3
assert p.factory.block(0x4010c9, size=len(b), strict_block_end=True).instructions == 3
# loop
assert p.factory.block(0x4010d0, strict_block_end=False).instructions == 4
assert p.factory.block(0x4010d0, strict_block_end=True).instructions == 2
assert p.factory.block(0x4010d0, size=7, strict_block_end=True).instructions == 2
def test_strict_block_ends_with_size_amd64():
# cmovnz cx, dx
# pop rax
# jrcxz short loc_4010D7 ; the first block should end here
# sub edi, 2
# loop loc_4010c9
# nop
# nop
b = b"\x66\x0f\x45\xca\x58\xe3\x07\x83\xef\x02\xe2\xf4\x90\x90"
p = angr.load_shellcode(b, 'amd64', load_address=0x4010c9)
# jrcxz
assert p.factory.block(0x4010c9, size=len(b), strict_block_end=False).instructions == 7
assert p.factory.block(0x4010c9, strict_block_end=True).instructions == 3
assert p.factory.block(0x4010c9, size=len(b), strict_block_end=True).instructions == 3
# loop
assert p.factory.block(0x4010d0, strict_block_end=False).instructions == 4
assert p.factory.block(0x4010d0, strict_block_end=True).instructions == 2
assert p.factory.block(0x4010d0, size=7, strict_block_end=True).instructions == 2
def test_no_cross_insn_boundary_opt_amd64():
# 0x4020f8: sub rsp, 8
# 0x4020fc: mov rax, qword ptr [rip + 0x221ef5]
# 0x402103: test rax, rax
# 0x402106: je 0x40210d
b = binascii.unhexlify("4883ec08488b05f51e22004885c07405")
p = angr.load_shellcode(b, 'amd64', load_address=0x4020f8)
# No optimization
block = p.factory.block(0x4020f8, size=len(b), opt_level=0)
assert len(block.vex.statements) == 32
# Full level-1 optimization
block = p.factory.block(0x4020f8, size=len(b), opt_level=1, cross_insn_opt=True)
assert len(block.vex.statements) == 20
# Level-1 optimization within each instruction
block = p.factory.block(0x4020f8, size=len(b), opt_level=1, cross_insn_opt=False)
stmts = block.vex.statements
assert len(stmts) == 25
# 12 | ------ IMark(0x402103, 3, 0) ------
assert isinstance(stmts[12], pyvex.IRStmt.IMark)
assert stmts[12].addr == 0x402103
# 13 | t6 = GET:I64(rax)
assert isinstance(stmts[13], pyvex.IRStmt.WrTmp)
assert isinstance(stmts[13].data, pyvex.IRExpr.Get)
assert stmts[13].data.offset == archinfo.arch_from_id('amd64').registers['rax'][0]
# 14 | PUT(cc_op) = 0x0000000000000014
assert isinstance(stmts[14], pyvex.IRStmt.Put)
assert stmts[14].offset == archinfo.arch_from_id('amd64').registers['cc_op'][0]
assert isinstance(stmts[14].data, pyvex.IRExpr.Const)
assert stmts[14].data.con.value == 0x14
# 15 | PUT(cc_dep1) = t6
assert isinstance(stmts[15], pyvex.IRStmt.Put)
assert stmts[15].offset == archinfo.arch_from_id('amd64').registers['cc_dep1'][0]
# 16 | PUT(cc_dep2) = 0x0000000000000000
assert isinstance(stmts[16], pyvex.IRStmt.Put)
assert stmts[16].offset == archinfo.arch_from_id('amd64').registers['cc_dep2'][0]
assert isinstance(stmts[16].data, pyvex.IRExpr.Const)
assert stmts[16].data.con.value == 0
# 17 | PUT(rip) = 0x0000000000402106
assert isinstance(stmts[17], pyvex.IRStmt.Put)
assert stmts[17].offset == archinfo.arch_from_id('amd64').registers['rip'][0]
assert isinstance(stmts[17].data, pyvex.IRExpr.Const)
assert stmts[17].data.con.value == 0x402106
# 18 | ------ IMark(0x402106, 2, 0) ------
assert isinstance(stmts[18], pyvex.IRStmt.IMark)
assert stmts[18].addr == 0x402106
if __name__ == '__main__':
test_strict_block_ends_cbz()
test_strict_block_ends_with_size_x86()
test_strict_block_ends_with_size_amd64()
test_no_cross_insn_boundary_opt_amd64()