forked from slick1015/pad_unpacker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
emulator.py
72 lines (55 loc) · 2.24 KB
/
emulator.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
from unicorn import *
from unicorn.arm_const import *
from logging import *
import hooks
import time
import os
DEFAULT_BASE = 0x400000
STACK_SIZE = 64 * 1024 * 1024 # I don't think we'll ever need more than 64 MB for the stack
BIN_SIZE = 128 * 1024 * 1024 # allocate 128 MB for the binary, probably overkill
DUMP_DIR = "dump"
class Emulator():
def __init__(self, base=DEFAULT_BASE):
self.base = base
self.uc = Uc(UC_ARCH_ARM, UC_MODE_ARM)
self.next_alloc_base = self.base
self.bin_base = self.alloc(BIN_SIZE)
self.stack_base = self.alloc(STACK_SIZE)
self.uc.reg_write(UC_ARM_REG_SP, self.stack_base + (STACK_SIZE // 2)) # point SP to the middle of the stack, just to be safe
hooks.register(self)
def start(self, start_address, end_address):
log("Emulation starting at {:#010x} with base {:#010x}".format(start_address, self.base))
linc()
self.uc.reg_write(UC_ARM_REG_PC, start_address)
self.uc.emu_start(start_address, end_address)
log("Emulation ended")
self.debug_dump()
ldec()
def stop(self):
log("Emulation stopping unexpectedly, PC at {:#010x}".format(self.uc.reg_read(UC_ARM_REG_PC)))
self.uc.emu_stop()
def alloc(self, size):
alloc_base = self.next_alloc_base
self.uc.mem_map(self.next_alloc_base, size)
self.next_alloc_base += size
return alloc_base
def allocations(self):
return [reg for reg in self.uc.mem_regions()]
def read_string(self, address):
buf = []
while True:
c = self.uc.mem_read(address, 1)[0]
if c == 0: # strings end with a null terminator
break
buf.append(c)
address += 1
return "".join(map(chr, buf))
def debug_dump(self):
local_dir = os.path.dirname(__file__)
out_dir = os.path.join(local_dir, DUMP_DIR, str(int(time.time())))
os.makedirs(out_dir)
for begin, end, prot in self.allocations():
filename = "{:#010x}-{:#010x}.bin".format(begin, end)
pathname = os.path.join(out_dir, filename)
with open(pathname, "wb") as f:
f.write(self.uc.mem_read(begin, end - begin))