Windbg插件0cchext

0cchext.dll是我一直在开发和维护的一个Windbg扩展程序。扩展程序中包含了一些或者有趣,或者实用,或者纯个人偏好的功能。这篇文章就来介绍一些主要的功能:


!a

!a - Assembles instruction mnemonics and puts the resulting
instruction codes into memory.

这个指令是写入汇编代码的扩展,虽然Windbg有自己的汇编命令a,但是这个命令无法配合脚本使用。你一旦输入命令a,Windbg就会进入汇编模式,此时你就无法让脚本继续进行了。所以我开发了!a,这个命令只会对一条命令进行汇编,并且将下一条汇编的地址存储在@#LastAsmAddr中,然后马上执行下面的命令,对脚本而已再好不过了。
例如下面这个脚本,他可以注入dll到debuggee

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ad /q ${/v:alloc_addr}
ad /q ${/v:@#LastAsmAddr}
x kernel32!LoadlibraryA
.foreach /pS 5 (alloc_addr {.dvalloc 0x200}) {r $.u0 = alloc_addr}
.block {aS ${/v:@#LastAsmAddr} 0; !a $u0 pushfd};
.block {!a ${@#LastAsmAddr} pushad}
.block {!a ${@#LastAsmAddr} push 0x$u0+0x100}
.block {!a ${@#LastAsmAddr} call kernel32!LoadLibraryA}
.block {!a ${@#LastAsmAddr} popad}
.block {!a ${@#LastAsmAddr} popfd}
.block { eza 0x$u0+0x100 "${$arg1}"}
r @eip=$u0
.block {g ${@#LastAsmAddr}}
.dvfree 0x$u0 0


!autocmd

!autocmd - Execute the debugger commands.(The config file is
autocmd.ini)

自动执行特定指令。有的时候我希望调试器附加到进程或者运行程序的时候能够自动运行一连串的命令,这个功能虽然可以由脚本完成,但是对我而言还是不够简洁,所以就有了这个命令。我可以在0cchext.dll的目录下,创建autocmd.ini文件,然后输入以下内容:

1
2
3
4
5
6
7
[notepad.exe]
.sympath+ c:\notepad_pdb
~*k
[calc.exe]
.sympath+ c:\calc_pdb
~*k

这样,在调试不同程序的时候输入!autocmd会执行不同的命令。


!bing & !google

!bing - Use bing to search.
!google - Use google to search.

这个命令非常简单,就是用bing和google去搜索指定的字符串。


!favcmd

!favcmd - Display the favorite debugger commands.(The config file is
favcmd.ini)

这个命令也非常简单,只需要把自己喜欢的命令一行一行的写在favcmd.ini文件里就行了,当然这个文件也需要和0cchext.dll在同一个目录。然后运行这个命令后,你所喜欢的命令就会打印到Windbg上,你可以用鼠标选择执行这些命令。

例如在文件中分别写入:

~*k
!address
!heap

20151005162754


!hwnd

!hwnd - Show window information by handle.

这个命令很简单,可以输入窗口句柄为参数,查看窗口相关信息。主要作用是在内核调试的时候,用调试器看到窗口信息会比较方便。


!url

!url - Open a URL in a default browser.

这个命令会打开一个url,实际上他就是一个ShellExecute。Windbg本来就有.shell功能了,这个似乎是多余了一点。


!init_script_env

!init_script_env - Initialize script environment.

这个命令是我给脚本准备的,他方便了脚本判断系统环境。如下图所示

20151005163744


!import_vs_bps

!import_vs_bps - Import visual studio breakpoints.

这个命令可以将VS存储在suo文件的断点导入到Windbg中。我有的时候会碰到这样的情况,VS里设置了一堆断点,但是调试环境里只有Windbg,那么我需要把这些断点转移到Windbg,有了这个命令,我只需要将VS解决方案的suo文件拷贝到调试环境中,然后运行这条命令即可。

例如

!import_vs_bps c:\proj\xxx.suo


!setvprot

!setvprot - Set the protection on a region of committed pages in the
virtual address space of the debuggee process.

这个命令能帮助我设置debuggee的内存属性,一个有趣的用法就是模仿Ollydbg的内存断点功能,比如给目标内存设置一个PAGE_GUARD属性,这样访问这部分内存的时候就会触发访问异常,调试器就能捕获到它了。

例如

!setvprot 0x410000 0x1000 0x100


!pe_export & !pe_import

!pe_export - Dump PE export functions
!pe_import - Dump PE import modules and functions

这两个命令可以分别帮助我们查看导出和导入函数,他们都支持通配符查找函数,在没有符号的情况下有时候会起到很好的作用。另外,他们配合好参数/b和.foreach命令,可以发挥出API Monitor的作用。

例如

.foreach( place { !pe_export /b kernel32 *Create* } ) { bp place “g” }


!wql

!wql - Query system information with WMI.

这也是我比较喜欢的一个功能,他可以在调试的时候通过WQL来查询系统的一些信息,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
0:000> !0cchext.wql select * from win32_process where name="explorer.exe"
-------------------------------------------------------------
Caption local CIM_STRING explorer.exe
CommandLine local CIM_STRING C:\Windows\Explorer.EXE
CreationClassName local CIM_STRING Win32_Process
CreationDate local CIM_DATETIME 2015-09-17 09:41:53.959
CSCreationClassName local CIM_STRING Win32_ComputerSystem
...
...
ThreadCount local CIM_UINT32 40
UserModeTime local CIM_UINT64 605439881
VirtualSize local CIM_UINT64 435580928
WindowsVersion local CIM_STRING 6.1.7601
WorkingSetSize local CIM_UINT64 109813760
WriteOperationCount local CIM_UINT64 399
WriteTransferCount local CIM_UINT64 1545945
-------------------------------------------------------------

!logcmd

!logcmd - Log command line to log file

这个命令是一个开关,打开后,他会记录调试的命令到文件中,这样下次调试相同的程序的时候就不需要在此去输入这些命令了,只需要读取这个命令文件,就可以用鼠标点击执行命令了。

20151005170422


!dpx

!dpx - Display the contents of memory in the given range.

这个命令是集dps dpa dpu大成者。他的会对目标指针做一个简单的判断,判断是符号,字符串,还是宽字符串。这样在我们查看栈信息的时候就不会漏掉一些有用的线索了。

1
2
3
4
5
6
7
8
9
10
11
0:000> !dpx esp 100
00c3f28c 7605cb33 [S] USER32!GetMessageA+0x53 (7605cb33)
...
00c3f2b4 012b6ca9 [S] usbview!WinMain+0xe3 (012b6ca9)
...
00c3f2f4 012ce723 [S] usbview!WinMainCRTStartup+0x151 (012ce723)
00c3f2f8 01260000 [S] usbview!__guard_check_icall_fptr <PERF> (usbview+0x0)
...
00c3f320 01025618 [A] "Winsta0\Default"
00c3f324 01025640 [A] "C:\Program Files (x86)\Windows Kits\10\Debuggers\x86\usbview.exe"
00c3f328 00000000 [D] ....

!dtx

!dtx - Displays information about structures. (The config file is
struct.ini)

这个命令主要用在逆向工程的时候。因为逆向工程的时候,我们往往没有符号文件,就不可能直接知道内存数据的结构是什么样子的,我们需要自己通过代码推断出来。在IDA中,我们可以自己设置结构体帮助分析。但是在Windbg中,并没有一个功能能方便的帮助我们用这推断的结构体去显示内存。不可否认我们其实可以用其他的办法来完成这个目的,但操作很繁琐。那么这个命令就解决了这些问题。我们可以在struct.ini文件中写入我们推断的结构体,然后通过这个命令去打印内存数据。当然,这个文件也必须在0cchext.dll的同目录下。

20151005172455

到目前位置脚本解析器支持的基本类型有BYTE WORD DWORD CHAR WCHAR,支持数组和指针,支持结构体嵌套,有了这些,对于基本的逆向就能够满足需求了。


现在0cchext.dll就是这些命令了,我也会根据自己的需求继续添加命令,如果你有什么有趣或者实用的想法,可以通过邮件或者留言告诉我。

debugging