/
inject_model_with_snapshot.py
112 lines (87 loc) · 3.36 KB
/
inject_model_with_snapshot.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
# $ ./triton ./examples/inject_model_with_snapshot.py ./samples/crackmes/crackme_xor a
# [+] Take a snapshot at the prologue of the function
# [+] Still not the good password. Restore snapshot.
# [+] Inject the character 'e' in memory
# [+] Still not the good password. Restore snapshot.
# [+] Inject the character 'e' in memory
# [+] Inject the character 'l' in memory
# [+] Still not the good password. Restore snapshot.
# [+] Inject the character 'e' in memory
# [+] Inject the character 'l' in memory
# [+] Inject the character 'i' in memory
# [+] Still not the good password. Restore snapshot.
# [+] Inject the character 'e' in memory
# [+] Inject the character 'l' in memory
# [+] Inject the character 'i' in memory
# [+] Inject the character 't' in memory
# [+] Still not the good password. Restore snapshot.
# [+] Inject the character 'e' in memory
# [+] Inject the character 'l' in memory
# [+] Inject the character 'i' in memory
# [+] Inject the character 't' in memory
# [+] Inject the character 'e' in memory
# [+] Good password found!
# Win
# [+] Analysis done!
from triton import *
import smt2lib
password = dict()
symVarMem = None
def csym(instruction):
# 0x40058b: movzx eax, byte ptr [rax]
if instruction.address == 0x40058b:
global symVarMem
symVarMem = getRegValue(IDREF.REG.RAX)
return
def cafter(instruction):
# 0x40058b: movzx eax, byte ptr [rax]
if instruction.address == 0x40058b:
convertRegToSymVar(IDREF.REG.RAX, 32)
# 0x4005ae: cmp ecx, eax
if instruction.address == 0x4005ae:
zfId = getRegSymbolicID(IDREF.FLAG.ZF)
zfExpr = getFullExpression(getSymExpr(zfId).ast)
expr = smt2lib.smtAssert(smt2lib.equal(zfExpr, smt2lib.bvtrue())) # (assert (= zf True))
models = getModel(expr)
global password
for k, v in models.items():
password.update({symVarMem: v})
return
def cbefore(instruction):
# Prologue of the function
global snapshot
if instruction.address == 0x40056d and isSnapshotEnable() == False:
takeSnapshot()
print '[+] Take a snapshot at the prologue of the function'
return
# 0x40058b: movzx eax, byte ptr [rax]
if instruction.address == 0x40058b:
rax = getRegValue(IDREF.REG.RAX)
if rax in password:
setMemValue(rax, 1, password[rax])
print '[+] Inject the character \'%c\' in memory' %(chr(password[rax]))
# Epilogue of the function
if instruction.address == 0x4005c8:
rax = getRegValue(IDREF.REG.RAX)
# The function returns 0 if the password is valid
# So, we restore the snapshot until this function
# returns something else than 0.
if rax != 0:
print '[+] Still not the good password. Restore snapshot.'
restoreSnapshot()
else:
print '[+] Good password found!'
disableSnapshot()
return
return
def fini():
print '[+] Analysis done!'
if __name__ == '__main__':
# Start the symbolic analysis from the 'check' function
startAnalysisFromSymbol('check')
addCallback(cafter, IDREF.CALLBACK.AFTER)
addCallback(cbefore, IDREF.CALLBACK.BEFORE)
addCallback(csym, IDREF.CALLBACK.BEFORE_SYMPROC)
addCallback(fini, IDREF.CALLBACK.FINI)
# Run the instrumentation - Never returns
runProgram()