-
Notifications
You must be signed in to change notification settings - Fork 4
/
cmplog.py
90 lines (69 loc) · 1.82 KB
/
cmplog.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
from pyda import *
from pwnlib.elf.elf import ELF
from pwnlib.util.packing import u64, u32
import string
import sys
import subprocess
from collections import defaultdict
p = process()
e = ELF(p.exe_path)
e.address = p.maps[p.exe_path].base
plt_map = { e.plt[x]: x for x in e.plt }
def get_cmp(proc):
p = subprocess.run(f"objdump -M intel -d {proc.exe_path} | grep cmp", shell=True, capture_output=True)
output = p.stdout.decode()
cmp_locs = {}
for l in output.split("\n"):
if len(l) <= 1:
continue
# TODO: memory cmp
if "QWORD PTR" in l:
continue
if ":\t" not in l:
continue
cmp_locs[int(l.split(":")[0].strip(), 16)] = l.split()[-1]
return cmp_locs
cmp_locs_unfiltered = get_cmp(p)
cmp_locs = {}
for (a, v) in cmp_locs_unfiltered.items():
info = v.split(",")
if len(info) != 2:
continue
if "[" in info[0] or "[" in info[1]:
continue
if "0x" in info[0] or "0x" in info[1]:
continue
cmp_locs[a] = info
print(f"cmp_locs: {len(cmp_locs)}")
eq_count = 0
neq_count = 0
reg_map = {
"eax": "rax",
"ebx": "rbx",
"ecx": "rcx",
"edx": "rdx",
"esi": "rsi",
"edi": "rdi",
"ebp": "rbp",
"esp": "rsp",
"r8d": "r8",
}
counts_by_pc = defaultdict(int)
good_cmps = defaultdict(int)
def cmp_hook(p):
global eq_count, neq_count
info = cmp_locs[p.regs.pc - e.address]
counts_by_pc[p.regs.pc - e.address] += 1
reg1 = reg_map.get(info[0], info[0])
reg2 = reg_map.get(info[1], info[1])
r1 = p.regs[reg1]
r2 = p.regs[reg2]
eq = r1 == r2
if eq:
eq_count += 1
else:
neq_count += 1
print(f"cmp @ {hex(p.regs.rip - e.address)} {reg1}={hex(r1)} {reg2}={hex(r2)} {eq}")
for x in cmp_locs:
p.hook(e.address + x, cmp_hook)
p.run()