1
+ # Helper script for Windows kernel debugging with IDA Pro on VMware + GDB stub
2
+ # https://github.com/therealdreg/ida_vmware_windows_gdb
3
+ # GNU General Public License v3.0
4
+ #
5
+ # by David Reguera Garcia aka Dreg
6
+ # Twitter @therealdreg
7
+ # https://www.fr33project.org
8
+ # dreg@fr33project.org
9
+ # https://github.com/therealdreg
10
+ #
11
+ # Based on original vmware_modules.py from Hex Blog article: http://www.hexblog.com/?p=94
12
+ # Based on original IDA-VMware-GDB By Oleksiuk Dmytro (aka Cr4sh) https://github.com/Cr4sh/IDA-VMware-GDB
13
+ #
14
+ # WARNING: Currently only works in old x86 versions (simple port from vmware_modules.py)
15
+ #
16
+ # 2022/07/31 by Dreg
17
+ # - project renamed to hexblog_adapted.py
18
+ # - ported to python3
19
+ # - ported to idapython 7.4:
20
+ # - https://hex-rays.com/products/ida/support/ida74_idapython_no_bc695_porting_guide.shtml
21
+ # - https://www.hex-rays.com/products/ida/support/idapython_docs/index.html
22
+ # - idc.eval_idc('SendGDBMonitor
23
+ # - added ida_kernwin.open_segments_window(0) and ida_kernwin.open_names_window(0)
24
+ # - fixed bug in get_unistr with len
25
+ # - code style fixed using black
26
+ # - added changelog
27
+ # - added some prints
28
+ # - set all segments with +rwx
29
+ # - lincense GNU General Public License v3.0
30
+ # - comestic changes (new header...)
31
+ # - added PDB_MODULES list
32
+ # - ported to new pdb: netnode using $ pdb + altset 0 + supset 0
33
+ # - import new ida modules for inteli
34
+ # - tested:
35
+ # - hosts: windows 10.0.19044 Build 19044
36
+ # - ida pro 7.7, idapython 7.4
37
+ # - targets: windows xp sp3 x86
38
+ # - vmware workstation 16
39
+ # -
40
+ # for inteli: set ENV VAR PYTHONPATH=C:\Program Files\IDA Pro 7.7\python\3
41
+
42
+ import idc
43
+ import ida_idaapi
44
+ import ida_netnode
45
+ import ida_loader
46
+ import ida_kernwin
47
+
48
+
49
+ cred = '''
50
+ Helper script for Windows kernel debugging with IDA Pro on VMware + GDB stub
51
+ https://github.com/therealdreg/ida_vmware_windows_gdb
52
+ GNU General Public License v3.0
53
+ -
54
+ By Oleksiuk Dmytro (aka Cr4sh)
55
+ Twitter @d_olex
56
+ http://blog.cr4.sh
57
+ cr4sh0@gmail.com
58
+ https://github.com/Cr4sh
59
+ -
60
+ Mod by David Reguera Garcia aka Dreg
61
+ Twitter @therealdreg
62
+ https://www.fr33project.org
63
+ dreg@fr33project.org
64
+ https://github.com/therealdreg
65
+
66
+ WARNING: BEFORE OPEN IDA your must set env var: _NT_SYMBOL_PATH to windows symbols, ex: SRV*C:\winsymbols*
67
+ '''
68
+ print (cred )
69
+
70
+ # path to the local copy of System32 directory
71
+ local_sys32 = r"C:\dreg\system32"
72
+
73
+ # just comment the next line to load all PDB symbols
74
+ auto_pdb = [
75
+ x .lower ()
76
+ for x in ["hal.dll" , "ntoskrnl.exe" , "ntkrnlpa.exe" , "ntkrnlmp.exe" , "ntkrpamp.exe" ]
77
+ ]
78
+
79
+ # BEFORE OPEN IDA your must set env var: _NT_SYMBOL_PATH to windows symbols, ex: SRV*C:\winsymbols*
80
+
81
+ def get_unistr (addr ):
82
+
83
+ length = idc .read_dbg_word (addr )
84
+ start = idc .read_dbg_dword (addr + 4 )
85
+
86
+ print ("length: " , length )
87
+
88
+ if length > 1000 :
89
+ raise Exception ("get_unistr(): String too long" )
90
+
91
+ res = ""
92
+ while length > 0 :
93
+ c = idc .read_dbg_word (start )
94
+ if c == b"\x00 \x00 " :
95
+ break
96
+ res += chr (c ).encode ('utf-16' , 'surrogatepass' ).decode ('utf-16' )
97
+ start += 2
98
+ length -= 2
99
+
100
+ return res
101
+
102
+ fs_str = idc .eval_idc ('SendGDBMonitor("r fs")' )
103
+ print (fs_str )
104
+ kpcr = int (fs_str [13 :23 ], 16 )
105
+ print ("kpcr: 0x%08X" % kpcr )
106
+
107
+ kdversionblock = idc .read_dbg_dword (kpcr + 0x34 )
108
+ print ("kdversionblock: 0x%08X" % kdversionblock )
109
+
110
+ PsLoadedModuleList = idc .read_dbg_dword (kdversionblock + 0x18 )
111
+ print ("PsLoadedModuleList: 0x%08X" % PsLoadedModuleList )
112
+
113
+ cur_mod = idc .read_dbg_dword (PsLoadedModuleList )
114
+ print ("first cur_mod: 0x%08X" % cur_mod )
115
+ while cur_mod != PsLoadedModuleList and cur_mod != ida_idaapi .BADADDR :
116
+ BaseAddress = idc .read_dbg_dword (cur_mod + 0x18 )
117
+ print ("BaseAddress: 0x%08X" % BaseAddress )
118
+ SizeOfImage = idc .read_dbg_dword (cur_mod + 0x20 )
119
+ print ("SizeOfImage: 0x%08X" % SizeOfImage )
120
+ FullDllName = get_unistr (cur_mod + 0x24 )
121
+ print ("FullDllName: " , str (FullDllName ))
122
+ BaseDllName = get_unistr (cur_mod + 0x2C )
123
+ print ("BaseDllName: " , str (BaseDllName ))
124
+ # create a segment for the module
125
+ idc .AddSeg (BaseAddress , BaseAddress + SizeOfImage , 0 , 1 , idc .saRelByte , idc .scPriv )
126
+ idc .set_segm_attr (BaseAddress , idc .SEGATTR_PERM , 7 )
127
+ # set its name
128
+ idc .set_segm_name (BaseAddress , BaseDllName )
129
+ # get next entry
130
+ cur_mod = idc .read_dbg_dword (cur_mod )
131
+ print ("++++++++++" )
132
+ filename = ""
133
+ if FullDllName .lower ().startswith ("\\ windows\\ system32" ):
134
+ FullDllName = "\\ SystemRoot\\ system32" + FullDllName [17 :]
135
+ if FullDllName .find ("\\ " ) == - 1 :
136
+ FullDllName = "\\ SystemRoot\\ system32\\ DRIVERS\\ " + FullDllName
137
+ if FullDllName .lower ().startswith ("\\ systemroot\\ system32" ):
138
+ filename = local_sys32 + "\\ " + FullDllName [20 :]
139
+ print ("filename: " , str (filename ))
140
+ if len (auto_pdb ) == 0 or BaseDllName .lower () in auto_pdb :
141
+ print ("autoloading pdb..." )
142
+ node = ida_netnode .netnode ()
143
+ node .create ("$ pdb" )
144
+ node .altset (0 , BaseAddress )
145
+ node .supset (0 , filename )
146
+ ida_loader .load_and_run_plugin ("pdb" , 3 )
147
+ print ("------------" )
148
+
149
+ ida_kernwin .open_segments_window (0 )
150
+ ida_kernwin .open_names_window (0 )
0 commit comments