-
-
Notifications
You must be signed in to change notification settings - Fork 83
/
Copy patharch.py
96 lines (74 loc) · 2.03 KB
/
arch.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
import re
from capstone import *
from keystone import *
class Arch:
def __init__(self):
self.cs = Cs(*self._cs)
self.cs.detail = True
self.ks = Ks(*self._ks)
def asm(self, asm, addr=0, att_syntax=False):
if not asm:
return ''
# asm start label for use with relative offsets
asm = '_PKST_:;' + asm
saved = self.ks.syntax
if att_syntax:
self.ks.syntax = KS_OPT_SYNTAX_ATT
tmp, _ = self.ks.asm(asm, addr=addr)
self.ks.syntax = saved
return ''.join(map(chr, tmp))
def dis(self, raw, addr=0):
return list(self.cs.disasm(str(raw), addr))
def jmp(self, dst):
raise NotImplementedError
def call(self, dst):
raise NotImplementedError
def ret(self):
raise NotImplementedError
def nop(self):
raise NotImplementedError
class x86(Arch):
_cs = CS_ARCH_X86, CS_MODE_32
_ks = KS_ARCH_X86, KS_MODE_32
def call(self, dst): return 'call 0x%x;' % dst
def jmp(self, dst): return 'jmp 0x%x;' % dst
def ret(self): return 'ret;'
def nop(self): return 'nop;'
# memcpy should be pc-relative
# dst and src are offsets from the _PKST_ label
def memcpy(self, dst, src, size):
return '''
push edi
push esi
push ecx
call ref
ref: pop edi
sub edi, ref - _PKST_
mov esi, edi
add edi, %d
add esi, %d
mov ecx, %d
rep movsb
pop ecx
pop esi
pop edi
''' % (dst, src, size)
class x86_64(x86):
_cs = CS_ARCH_X86, CS_MODE_64
_ks = KS_ARCH_X86, KS_MODE_64
def memcpy(self, dst, src, size):
return '''
push rdi
push rsi
push rcx
lea rdi, [rip - _PKST_ + %d]
lea rsi, [rip - _PKST_ + %d]
mov rcx, %d
rep movsb
pop rcx
pop rsi
pop rdi
''' % (dst, src, size)
class arm(Arch):
_cs = CS_ARCH_ARM, CS_MODE_ARM
_ks = KS_ARCH_ARM, KS_MODE_ARM