Dev.K.
Dev.K.

Reputation: 2488

Using Windbg PyKD Python Extension to Print/Break at Only Call Instructions

Using WinDBG's python extension I want to print only call instructions in console. [A kind of one step debugging ]

My Code:

from pykd import *
pid = raw_input ('pid >>> ')
id=attachProcess(int(pid))
print id
while 1:
    trace()
    r_o = dbgCommand('r')
    line = r_o.split('\n')[-2]
    sp_line = line.split()
    addr = int(sp_line[0],16)
    ins = sp_line[2]
    if ins == "call":
        print line

I tried above code and got below result.

Output :

C:\Program Files (x86)\Debugging Tools for Windows (x86)\winext>db.py
[+] Starting...
pid >>> 3516
0
76ec000d c3              ret
76f4f926 eb07            jmp     ntdll!DbgUiRemoteBreakin+0x45 (76f4f92f)
76f4f92f c745fcfeffffff  mov     dword ptr [ebp-4],0FFFFFFFEh ss:002b:0029ff84=00000000
76f4f936 6a00            push    0
76f4f938 e8df86fbff      call    ntdll!RtlExitUserThread (76f0801c)
76ed0096 83c404          add     esp,4

Here the problem seems to be, after the debugger breaks into the process, the debug thread gets initiated and the debug thread is getting terminated after sometime, because its the current thread [We can see last call is made to ntdll!RtlExitUserThread]. Hence even if the debugee app runs I don't see any thing in command line.

I've seen a script which uses winappdbg and does the similar operation. Here is the script :

https://github.com/MarioVilas/winappdbg/blob/master/tools/ptrace.py

And I want to build something similar.

Upvotes: 0

Views: 3466

Answers (2)

blabb
blabb

Reputation: 9007

not a pykd answer but windbgs inbuilt pc/tc (step / trace to next call) will print out all the calls

0:000> .printf "%y\n" , @eip
multithread!wmain (00411430)
0:000> $ iam at start of winmain and i have disabled all output except disassembly via .prompt_allow
0:000> $ i have set a breakpoint on winmains exit 
0:000> $ code for demo is exact copy paste of msdn sample code for createthread documentation
0:000> $lets roll and log all call instructions 

0:000> tc 1000000

0041147c ff1530824100    call    dword ptr [multithread!_imp__GetProcessHeap (00418230)]
00411484 e8e9fcffff      call    multithread!ILT+365(__RTC_CheckEsp) (00411172)
0041148a ff152c824100    call    dword ptr [multithread!_imp__HeapAlloc (0041822c)]
7c955264 e827ffffff      call    ntdll!LdrpTagAllocateHeap (7c955190)
7c9551b0 e80faffbff      call    ntdll!RtlAllocateHeap (7c9100c4)
7c9100ce e8f8e7ffff      call    ntdll!_SEH_prolog (7c90e8cb)
removed =====================
7c923b25 e80b000000      call    ntdll!LdrShutdownProcess+0x1e0 (7c923b35)
7c923b3a e8a1d5fdff      call    ntdll!RtlLeaveCriticalSection (7c9010e0)
7c923b2a e8d7adfeff      call    ntdll!_SEH_epilog (7c90e906)
7c81cac3 ff153410807c    call    dword ptr [kernel32!_imp__CsrClientCallServer (7c801034)]
7c912de3 e8f6acffff      call    ntdll!NtRequestWaitReplyPort (7c90dade)
7c90dae8 ff12            call    dword ptr [edx]
7c90e512 0f34            sysenter
7c81cacc ffd6            call    esi
7c90de78 ff12            call    dword ptr [edx]
7c90e512 0f34            sysenter
7c90e514 c3              ret

if you are following the code in the msdn sample and would want to trace the thread calls a breakpoint ( hack but will work in most situations) can be used

.prompt_allow to disable everything except dis-assembly
set a conditional break-point on CreateThread
condition being setting another break point on poi(@esp+c) LpThreadStartRoutine and continuing
the next three pc 1000000 are step until next calls and one quit
we know we have three threads in the sample so we automated pc 10000000
three times if you don't know how many threads prior to execution manually enter pc 1000000 manually on each thread exit .

:cdb -c ".prompt_allow -src -reg -sym -ea ;g wmain;bp kernel32!CreateThread \"ba e1 poi( @esp+c) \\"? $tid ;pc 100000 \\";gc\";pc 100000;pc 1000000;pc 1000000 ;pc 1000000;pc 10000000;pc 1000000; pc 10000000;q" multithread.exe | grep -iE "W rite|Eval"

Evaluate expression: 2148 = 00000864
004011c6 ff1520204000    call    dword ptr [multithread!_imp__WriteConsoleW (004
02020)]
Evaluate expression: 2780 = 00000adc
004011c6 ff1520204000    call    dword ptr [multithread!_imp__WriteConsoleW (004
02020)]
Evaluate expression: 3440 = 00000d70
004011c6 ff1520204000    call    dword ptr [multithread!_imp__WriteConsoleW (004
02020)]

Upvotes: 3

Thomas Weller
Thomas Weller

Reputation: 59513

trace() probably works the same way as t in WinDbg. That means, it follows one thread only, while the other threads are frozen (frozen is similar to suspended, but visible for the debugger only, so even a thread is resumed it will still not execute if frozen).

When you trace the debugger thread, WinDbg will give you the warning

WARNING: Step/trace thread exited

if the thread exits. If you used Enter to repeat the t command, it will stop working at that time. If you enter t again, it behaves like g (go, without tracing).

Since pykd uses the WinDbg API, I guess it will just do the same.

To trace a different thread in WinDbg, you would use ~5t, where 5 is the thread number. I don't know a way in WinDbg to trace multiple threads simultaneously.

See also: Similar topic, answered by pykd team

Upvotes: 1

Related Questions