-
Notifications
You must be signed in to change notification settings - Fork 189
/
tracer_msr_branch.py
133 lines (100 loc) · 4.14 KB
/
tracer_msr_branch.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
129
130
131
132
133
#!c:\python\python.exe
# $Id: tracer_msr_branch.py 194 2007-04-05 15:31:53Z cameron $
import sys
from pydbg import *
from pydbg.defines import *
USAGE = "USAGE: tracer_msr_branch.py <PID>"
error = lambda msg: sys.stderr.write("ERROR> " + msg + "\n") or sys.exit(1)
begin = 0
end = 0
SysDbgReadMsr = 16
SysDbgWriteMsr = 17
ULONG = c_ulong
ULONGLONG = c_ulonglong
class SYSDBG_MSR(Structure):
_fields_ = [
("Address", ULONG),
("Data", ULONGLONG),
]
def read_msr():
msr = SYSDBG_MSR()
msr.Address = 0x1D9
msr.Data = 0xFF
status = windll.ntdll.NtSystemDebugControl(SysDbgReadMsr,
byref(msr),
sizeof(SYSDBG_MSR),
byref(msr),
sizeof(SYSDBG_MSR),
0);
print "ret code: %x" % status
print "%08x.%s" % (msr.Address, dbg.to_binary(msr.Data, 8))
def write_msr():
msr = SYSDBG_MSR()
msr.Address = 0x1D9
msr.Data = 2
status = windll.ntdll.NtSystemDebugControl(SysDbgWriteMsr,
byref(msr),
sizeof(SYSDBG_MSR),
0,
0,
0);
########################################################################################################################
def handler_breakpoint (dbg):
global begin, end
if not begin or not end:
print "initial breakpoint hit at %08x: %s" % (dbg.exception_address, dbg.disasm(dbg.exception_address))
print "putting all threads into single step mode"
for module in dbg.iterate_modules():
if module.szModule.lower().endswith(".exe"):
begin = module.modBaseAddr
end = module.modBaseAddr + module.modBaseSize
print "%s %08x -> %08x" % (module.szModule, begin, end)
for tid in dbg.enumerate_threads():
print " % 4d -> setting single step" % tid
handle = dbg.open_thread(tid)
dbg.single_step(True, handle)
write_msr()
dbg.close_handle(handle)
elif begin <= dbg.exception_address <= end:
print "bp: %08x: %s" % (dbg.exception_address, dbg.disasm(dbg.exception_address))
dbg.single_step(True)
write_msr()
return DBG_CONTINUE
########################################################################################################################
def handler_single_step (dbg):
global begin, end
disasm = dbg.disasm(dbg.exception_address)
ret_addr = dbg.get_arg(0)
in_module = False
if begin <= dbg.exception_address <= end:
print "ss: %08x: %s" % (dbg.exception_address, disasm)
in_module = True
# if the current instructon is 'sysenter', set a breakpoint at the return address to bypass it.
if disasm == "sysenter":
dbg.bp_set(ret_addr)
# if the current instruction is outside the main module and the return instruction is not, set a breakpoint on it
# and continue without single stepping.
elif not in_module and begin <= ret_addr <= end and ret_addr != 0:
dbg.bp_set(ret_addr)
# otherwise, re-raise the single step flag and continue on.
else:
dbg.single_step(True)
write_msr()
return DBG_CONTINUE
########################################################################################################################
def handler_new_thread (dbg):
dbg.single_step(True)
write_msr()
return DBG_CONTINUE
if len(sys.argv) != 2:
error(USAGE)
try:
pid = int(sys.argv[1])
except:
error(USAGE)
dbg = pydbg()
dbg.set_callback(EXCEPTION_BREAKPOINT, handler_breakpoint)
dbg.set_callback(EXCEPTION_SINGLE_STEP, handler_single_step)
dbg.set_callback(CREATE_THREAD_DEBUG_EVENT, handler_new_thread)
dbg.attach(pid)
dbg.run()