SDN系列(46)——WinDbg Preview TTD入门

一、安装WinDbg Preview

WinDbg Preview与传统的WinDbg不是一个东西。

可以从Microsoft Store安装WinDbg Preview,可能需要先登录,匿名时可能搜不到WinDbg Preview。

在cmd中执行windbgx,即可打开WinDbg Preview

尽管官方要求从Microsoft Store安装WinDbg Preview,但安装结束后可以用Process Explorer找出WinDbg Preview安装目录,将之复制到别处仍可使用。比如安装到

C:\Program Files\WindowsApps\Microsoft.WinDbg_1.2111.9001.0_neutral__8wekyb3d8bbwe\

复制到

X:\Green\windbgx\1.2111.9001.0\

Win10企业版2016 LTSB没有Microsoft Store,但可以使用绿色版WinDbg Preview,包括TTD技术。

微软这帮缺德货解释为什么只通过Microsoft Store提供WinDbg Preview,官方口径是,他们在快速迭代,通过Microsoft Store可以获取最新版。但我认为这只是托辞,实际是强推Microsoft Store。

参看

《不通过Microsoft Store的GUI界面安装Store App》
http://scz.617.cn:8/windows/202201282230.txt

二、TTD.exe

“Launch executable (advanced)”功能实际调用的是TTD.exe

TTD.exe的很多参数无法通过WinDbg Preview指定,这没关系,可以直接用TTD.exe。

$ tree /A /F .

| TTD.exe
| TTDInject.exe
| TTDLoader.dll
| TTDRecord.dll
| TTDRecordCPU.dll
|
—wow64
TTD.exe
TTDInject.exe
TTDLoader.dll
TTDRecord.dll
TTDRecordCPU.dll

TTD技术关键在于生成.run文件,为生成它只涉及上面列举的文件,wow64是用于32位 PE的。

在管理员级cmd中执行

$ TTD.exe -ring -maxFile 2048 -out “TTDTest_0%.run” -launch TTDTest_0.exe

生成2GB的TTDTest_002.run,虽然很大,但不会增长,情况可控。

执行TTD.exe需要管理员级cmd,分析.run不需要。在普通cmd中执行

$ windbgx TTDTest_002.run

三、tttracer.exe

某些版本的Win10自带一个神秘的tttracer.exe,帮助里没有任何参数介绍

$ where tttracer
C:\Windows\System32\tttracer.exe

tttracer.exe实际就是TTD.exe

TTD技术关键在于生成.run文件,为生成它只需要下面列举的文件,这些文件来自非LTSB版Win10的System32目录,换句话说,全是自带的。

ttdinject.exe
ttdloader.dll
ttdrecord.dll
ttdrecordcpu.dll
tttracer.exe

四、notepad示例

用ResourceHacker查看

C:\Windows\zh-cn\notepad.exe.mui

在Menu项中看到


POPUP “格式(&O)”
{
MENUITEM “自动换行(&W)”, 32
MENUITEM “字体(&F)…”, 33

}

$ tttracer.exe -ring -maxFile 2048 -out “notepad%.run” -launch notepad.exe

$ tttracer.exe -stop all

用”-stop”可以让notepad保持运行,而不是被杀掉。

$ windbgx notepad01.run

r $t0=0n33;dx -g @$cursession.TTD.Calls(“notepad!NPCommand”).Select(c=>new{Time=c.TimeStart,RetAddr=c.ReturnAddress,hWnd=c.Parameters[0],wParam=c.Parameters[1]}).Where(c=>c.wParam==@$t0)

上述命令比TTD执行快多了,找到”2787F:62″,点击或!tt转移过去。pc找到这里

notepad!NPCommand+0x9ee:
00007ff69098aa86 e869b90100 call notepad!memset (00007ff6909a63f4)

附近代码对应

格式
字体

本小节的意思是,能dx就不要TTD执行,否则将失去TTD的强大与效率。

下面这两条命令的效果一样,但后者更高效

ba w1 0x97e64ff730;g-
r $t0=0x97e64ff730;r $t1=8;dx -r1 @$cursession.TTD.Memory(@$t0,@$t0+@$t1,”w”).Last().TimeStart.SeekTo()

五、Calculator示例

Win10的calc与Win7的calc不一样,前者好像是个Store App?我用不惯新版,从Win7 复制旧版calc到Win10用。不过,本小节的目标是新版calc,也就是Calculator.exe。

启动calc,切换到”程序员模式”,切换到16进制模式,然后上TTD。

tttracer.exe -ring -maxFile 2048 -out “calc_%.run” -attach

依次输入

51201314 * 41414141 =

得到结果

0x14add2aaaa10ec14

停止TTD

tttracer.exe -stop

tttracer.exe -stop all

假设生成calc_04.run

原始需求是,结合TTD技术寻找前述算术运算相关代码。假设前述calc进程仍在活动中,挂普通调试器进去搜内存,这样方便些。如果直接在.run中搜内存,可能非常慢,还有可能干脆搜不着。

cdb.exe -noinh -snul -hd -o -p

查看进程空间内存布局

.logopen Z:\work\MSDN_46\calc.txt
!address -f:stack,heap
.logclose

查看calc.txt,类似这种输出

BaseAddress EndAddress+1 RegionSize Type State Protect Usage

  90`5ca00000       90`5caf7000        0`000f7000 MEM_PRIVATE MEM_RESERVE                                    Stack      [~0; 3238.2b4c]


905e0fe000 905e100000 000002000 MEM_PRIVATE MEM_COMMIT PAGE_READWRITE Stack [~17; 3238.df0] 21ef0930000 21ef0940000 000010000 MEM_MAPPED MEM_COMMIT PAGE_READWRITE Heap [ID: 1; Handle: 0000021ef0930000; Type: Segment]

21efe47e000 21efe500000 0`00082000 MEM_PRIVATE MEM_RESERVE Heap [ID: 0; Handle: 0000021ef09a0000; Type: SegmentHeap Segment]

在堆区搜索特征字节流

s -[w]b 21ef0930000 21efe500000 14 ec 10 aa aa d2 ad 14
0000021e`fe44c2d0 14 ec 10 aa aa d2 ad 14-00 00 00 00 00 00 08 00 …………….

开始鞭尸

windbgx calc_04.run
.prompt_allow +reg +ea +dis

如果没有自动生成calc_04.idx,用如下命令手工生成

!ttdext.index -force
!ttdext.index -status

移动到.run尾部再查看内存,否则指定内存可能还没被写入期待中的值

!tt 100

理论上当然可以用数据断点加反向执行去找相关代码,但鞭尸时有更快的方案

r $t0=0x21efe44c2d0;r $t1=4;r $t2=0xaa10ec14;dx -g @$cursession.TTD.Memory(@$t0,@$t0+@$t1,”rw”).Where(m=>m.Value==@$t2)

============================================================================

= = (+) Time = (+) PC = (+) Size = (+) Old = (+) New = (+) Access =

= [0x4c1] – 2FA64F:9F4 – 0x7ff7bc7394d8 – 0x4 – 0x2a10ec14 – 0xaa10ec14 – Write =

!tt 2FA64F:9F4
rax=000000002a10ec14 rbx=0000021efd553600 rcx=000000000000001f
rdx=00000000aa10ec14 rsi=0000000000000001 rdi=000000000000001f
rip=00007ff7bc7394d8 rsp=000000905d1fcdc0 rbp=000000905d1fcf10
r8=0000021efe44c2d0 r9=0000000000000001 r10=0000000000003730
r11=000000905d1fce00 r12=00007ff7bc95f1b0 r13=0000000000000001
r14=0000000000000000 r15=0000021ef7ccef20
iopl=0 nv up ei ng nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000286
Calculator!VSDesignerDllMain+0x120ae8:
00007ff7bc7394d8 418910 mov dword ptr [r8],edx ds:0000021efe44c2d0=2a10ec14

这个位置在写乘法运算的结果,结合TTD.Memory与反向执行,不断定位源头,直至

============================================================================

= = (+) Time = (+) PC = (+) Size = (+) Old = (+) New = (+) Access =

= [0x14] – 2EA868:9A – 0x7ff8594c1421 – 0x10 – 0x0 – 0x100000001 – Write =
= [0x15] – 2EA868:9B – 0x7ff8594c1425 – 0x10 – 0x100000001 – 0x100000001 – Write =
= [0x19] – 2EA8B3:BC – 0x7ff7bc70c218 – 0x4 – 0x0 – 0x2a10ec14 – Write =

= [0xd3] – 2ED8F7:8F – 0x7ff7bc6f1146 – 0x10 – 0x0 – 0x100000001 – Write =

!ttdext.tt 2EA8B3:BC
rax=00000000295ba555 rbx=0000000000000001 rcx=000000002a10ec14
rdx=000000002a10ec14 rsi=0000021efe461820 rdi=0000000041414141
rip=00007ff7bc70c218 rsp=000000905d1fcd00 rbp=ffffffffffffe6d4
r8=000000002a10ec14 r9=0000000000000000 r10=0000021efe46182c
r11=0000000000000001 r12=0000021efe44c2b0 r13=0000021efe45ff00
r14=0000021efe45e3d0 r15=0000021efe461830
iopl=0 nv up ei pl nz na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
Calculator!VSDesignerDllMain+0xf3828:
00007ff7bc70c218 43890c8a mov dword ptr [r10+r9*4],ecx ds:0000021efe46182c=00000000

注意到rdi等于0x41414141,在IDA中简单看看,回TTD中反向执行

g- 0x7ff7bc70c1d8
Time Travel Position: 2EA8B3:A9
rax=0000000051201314 rbx=0000000000000001 rcx=0000000000000000
rdx=0000000000000002 rsi=0000021efe461820 rdi=0000000041414141
rip=00007ff7bc70c1d8 rsp=000000905d1fcd00 rbp=ffffffffffffe6d4
r8=0000000000000000 r9=0000000000000000 r10=0000021efe46182c
r11=0000000000000001 r12=0000021efe44c2b0 r13=0000021efe45ff00
r14=0000021efe45e3d0 r15=0000021efe461830
iopl=0 nv up ei pl zr na po nc
cs=0033 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000246
Calculator!VSDesignerDllMain+0xf37e8:
00007ff7`bc70c1d8 480fafc7 imul rax,rdi

借助TTD调试,相对简单地定位了16进制”51201314*41414141=”的现场。

这样验证,普通调试时,设断干扰乘法运算,将GUI输入的0x41414141换成1

ba e1 0x7ff7bc70c1d8 “.if(@rdi==0x41414141){r rax,rdi;r rdi=1};gc”

TTD调试比普通调试慢很多,即便是正向执行,前者也慢。二者是互补关系,不要只依赖TTD调试。

版权声明

本站“技术博客”所有内容的版权持有者为绿盟科技集团股份有限公司(“绿盟科技”)。作为分享技术资讯的平台,绿盟科技期待与广大用户互动交流,并欢迎在标明出处(绿盟科技-技术博客)及网址的情形下,全文转发。
上述情形之外的任何使用形式,均需提前向绿盟科技(010-68438880-5462)申请版权授权。如擅自使用,绿盟科技保留追责权利。同时,如因擅自使用博客内容引发法律纠纷,由使用者自行承担全部法律责任,与绿盟科技无关。

Spread the word. Share this post!

Meet The Author

C/ASM程序员

Leave Comment