Log in

View Full Version : Stack Unwinding : Reliability Panorama


OpenRCE_adityaks
November 24th, 2007, 18:50
Reliability Check in Code Debugging
The stack unwinding is undertaken as realm of dissecting stack on various conditional facts in a program. As it has been noticed many times that a reverse engineer finds himself in mesh while debugging a program. The point of talk is is it good enough to unwind stack on certain parameters and leaving the other part behind. Debugging a heavy code is always a hard process if cross structural references in modules are high. The concept rotates around the structural interdependences. Debugging with an adequate symbols somewhat lowers a job of debugger from efficiency point of view. It means the program can be disseminated according to standard symbols loaded in the debugger. The stack is always processed for a single thread. But what if threads are undertaken in large number. Every single thread has a one stack. Sometimes a duplicate entry can be found in the system while debugging. The breakpoints whether conditional (bp) or direct running (g), intrinsically depends on the Return Addresses. Even the manipulated threads possess a valid return address but execution depends whther it successfully returned or not. It has been noticed while applying a breakpoint a hang condition occurs. It occurs mainly if a working thread is entangled somewhere or the function has not been returned. Backtracing(bk) stack is a good practise.

The processing and debugging depends on time , complexity and resource utilization.It becomes stringent if ambiguity occurs in any of three parameters defined above. So in order to trap a bug in requisite time period the unwinding of stack with conditional entities have to be devised while debugging.

Lets say:
Code:


Tn is a set of number of threads.
Tn={t1,t2,t3,t4,..............tn}

Xn is a set of complexity.
Xn={x1,x2,x3,x4,..............xn}

A simple one to one mapping says:
Xn{x1,x2,x3,.........xn} ---------> Tn{ti,t2,t3,............tn}

Condition : Interdependency i.e. mapping one to many / many to one

This raise the complexity interdependency issue to maximum.


So a reverse engineer in order to circumvent this issue and try to be focussed in traversing the code irrespective of ingrained complexity. It makes the analysis even better to look at the certain specific part of codes rather than looking every perspective. Even it is advised to leverage as much as information from the code so that interim understanding of process functions is encountered. Lets look at general example to traverse through stack in an efficient manner. This makes the Register Checks easy for a given thread at given point of time.

I simply attached Google talk process , I found there are 7 threads running in it:

0:006> ~
0 Id: 7d4.174 Suspend: 1 Teb: 7ffdd000 Unfrozen
1 Id: 7d4.7a4 Suspend: 1 Teb: 7ffdc000 Unfrozen
2 Id: 7d4.1b8 Suspend: 1 Teb: 7ffda000 Unfrozen
3 Id: 7d4.2d8 Suspend: 1 Teb: 7ffd8000 Unfrozen
4 Id: 7d4.7fc Suspend: 1 Teb: 7ffd7000 Unfrozen
5 Id: 7d4.2bc Suspend: 1 Teb: 7ffd6000 Unfrozen
. 6 Id: 7d4.2dc Suspend: 1 Teb: 7ffdb000 Unfrozen

I try to run [~ *kv] command. Lets see the unfiltered and complex output:

0:006> ~ *kv

0 Id: 7d4.174 Suspend: 1 Teb: 7ffdd000 Unfrozen
ChildEBP RetAddr Args to Child
0012e838 7e4191be 7e4191f1 0012fb20 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
*** WARNING: Unable to verify checksum for C:\Program Files\Google\Google Talk\googletalk.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Program Files\Google\Google Talk\googletalk.exe
0012e858 0040271e 0012fb20 00000000 00000000 USER32!NtUserGetMessage+0xc
WARNING: Stack unwind information not available. Following frames may be wrong.
00000000 00000000 00000000 00000000 00000000 googletalk+0x271e

1 Id: 7d4.7a4 Suspend: 1 Teb: 7ffdc000 Unfrozen
ChildEBP RetAddr Args to Child
0150fe18 7c90e399 77e76703 0000018c 0150ff70 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\RPCRT4.dll -
0150fe1c 77e76703 0000018c 0150ff70 00000000 ntdll!NtReplyWaitReceivePortEx+0xc (FPO: [5,0,0])
WARNING: Stack unwind information not available. Following frames may be wrong.
0150ff80 77e76c22 0150ffa8 77e76a3b 00153118 RPCRT4!I_RpcBCacheFree+0xcb
0150ff88 77e76a3b 00153118 0012e6b0 0012e22c RPCRT4!I_RpcBCacheFree+0x5ea
0150ffa8 77e76c0a 00156b40 0150ffec 7c80b683 RPCRT4!I_RpcBCacheFree+0x403
0150ffb4 7c80b683 0016f370 0012e6b0 0012e22c RPCRT4!I_RpcBCacheFree+0x5d2
0150ffec 00000000 77e76bf0 0016f370 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])

2 Id: 7d4.1b8 Suspend: 1 Teb: 7ffda000 Unfrozen
ChildEBP RetAddr Args to Child
018fff50 7e4191be 7e4191f1 018fff90 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
018fff70 0042a07c 018fff90 00000000 00000000 USER32!NtUserGetMessage+0xc
WARNING: Stack unwind information not available. Following frames may be wrong.
018fffb0 0042a188 7c80b683 00cd4130 00000000 googletalk+0x2a07c
018fffec 00000000 0042a17f 00cd4130 00000000 googletalk+0x2a188

3 Id: 7d4.2d8 Suspend: 1 Teb: 7ffd8000 Unfrozen
ChildEBP RetAddr Args to Child
0218fd90 7c90e9c0 7c8025cb 00000280 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0218fd94 7c8025cb 00000280 00000000 0218fdc8 ntdll!ZwWaitForSingleObject+0xc (FPO: [3,0,0])
0218fdf8 7c802532 00000280 054bbe50 00000000 kernel32!WaitForSingleObjectEx+0xa8 (FPO: [Non-Fpo])
0218fe0c 0045c60c 00000280 054bbe50 01705790 kernel32!WaitForSingleObject+0x12 (FPO: [Non-Fpo])
WARNING: Stack unwind information not available. Following frames may be wrong.
0218ff90 00473a25 00000001 00000000 01705760 googletalk+0x5c60c
0218ffb0 0040fa98 7c80b683 01705760 00000000 googletalk+0x73a25
0218ffec 00000000 0040fa8f 01705760 00000000 googletalk+0xfa98

4 Id: 7d4.7fc Suspend: 1 Teb: 7ffd7000 Unfrozen
ChildEBP RetAddr Args to Child
0228ff1c 7c90e9c0 7c8025cb 000002cc 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0228ff20 7c8025cb 000002cc 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc (FPO: [3,0,0])
0228ff84 7c802532 000002cc ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xa8 (FPO: [Non-Fpo])
0228ff98 71abd174 000002cc ffffffff 0012e360 kernel32!WaitForSingleObject+0x12 (FPO: [Non-Fpo])
0228ffb4 7c80b683 000002cc 0012e360 7c90ee18 WS2_32!SockAsyncThread+0x2b (FPO: [Non-Fpo])
0228ffec 00000000 71abd149 001997e0 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])

5 Id: 7d4.2bc Suspend: 1 Teb: 7ffd6000 Unfrozen
ChildEBP RetAddr Args to Child
0238fecc 7c90e9ab 7c8094e2 00000002 0238fef8 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0238fed0 7c8094e2 00000002 0238fef8 00000001 ntdll!ZwWaitForMultipleObjects+0xc (FPO: [5,0,0])
0238ff6c 7c80a075 00000002 0238ffa4 00000000 kernel32!WaitForMultipleObjectsEx+0x12c (FPO: [Non-Fpo])
0238ff88 72d2312a 00000002 0238ffa4 00000000 kernel32!WaitForMultipleObjects+0x18 (FPO: [Non-Fpo])
0238ffb4 7c80b683 00000000 00000000 00150000 wdmaud!MixerCallbackThread+0x42 (FPO: [Non-Fpo])
0238ffec 00000000 72d230e8 00000000 00000000 kernel32!BaseThreadStart+0x37 (FPO: [Non-Fpo])

# 6 Id: 7d4.2dc Suspend: 1 Teb: 7ffdb000 Unfrozen
ChildEBP RetAddr Args to Child
0151ffc8 7c9507a8 00000005 00000004 00000001 ntdll!DbgBreakPoint (FPO: [0,0,0])
0151fff4 00000000 00000000 00000000 00000000 ntdll!DbgUiRemoteBreakin+0x2d (FPO: [Non-Fpo])

Again the output is too messy to get to it. To reduce complexity and unwind stack in a best possible way , a direct call is made to [!uniqstack] to filter it and to the point layout:

0:006> !uniqstack
Processing 7 threads, please wait

. 0 Id: 7d4.174 Suspend: 1 Teb: 7ffdd000 Unfrozen
Start: googletalk+0x15719a (0055719a)
Priority: 0 Priority class: 32 Affinity: 1
ChildEBP RetAddr
0012e838 7e4191be ntdll!KiFastSystemCallRet
0012e858 0040271e USER32!NtUserGetMessage+0xc
WARNING: Stack unwind information not available. Following frames may be wrong.
00000000 00000000 googletalk+0x271e

. 1 Id: 7d4.7a4 Suspend: 1 Teb: 7ffdc000 Unfrozen
Start: kernel32!BaseThreadStartThunk (7c810659)
Priority: 0 Priority class: 32 Affinity: 1
ChildEBP RetAddr
0150fe18 7c90e399 ntdll!KiFastSystemCallRet
0150fe1c 77e76703 ntdll!NtReplyWaitReceivePortEx+0xc
WARNING: Stack unwind information not available. Following frames may be wrong.
0150ff80 77e76c22 RPCRT4!I_RpcBCacheFree+0xcb
0150ff88 77e76a3b RPCRT4!I_RpcBCacheFree+0x5ea
0150ffa8 77e76c0a RPCRT4!I_RpcBCacheFree+0x403
0150ffb4 7c80b683 RPCRT4!I_RpcBCacheFree+0x5d2
0150ffec 00000000 kernel32!BaseThreadStart+0x37

. 2 Id: 7d4.1b8 Suspend: 1 Teb: 7ffda000 Unfrozen
Start: kernel32!BaseThreadStartThunk (7c810659)
Priority: 0 Priority class: 32 Affinity: 1
ChildEBP RetAddr
018fff50 7e4191be ntdll!KiFastSystemCallRet
018fff70 0042a07c USER32!NtUserGetMessage+0xc
WARNING: Stack unwind information not available. Following frames may be wrong.
018fffb0 0042a188 googletalk+0x2a07c
018fffec 00000000 googletalk+0x2a188

. 3 Id: 7d4.2d8 Suspend: 1 Teb: 7ffd8000 Unfrozen
Start: kernel32!BaseThreadStartThunk (7c810659)
Priority: 0 Priority class: 32 Affinity: 1
ChildEBP RetAddr
0218fd90 7c90e9c0 ntdll!KiFastSystemCallRet
0218fd94 7c8025cb ntdll!ZwWaitForSingleObject+0xc
0218fdf8 7c802532 kernel32!WaitForSingleObjectEx+0xa8
0218fe0c 0045c60c kernel32!WaitForSingleObject+0x12
WARNING: Stack unwind information not available. Following frames may be wrong.
0218ff90 00473a25 googletalk+0x5c60c
0218ffb0 0040fa98 googletalk+0x73a25
0218ffec 00000000 googletalk+0xfa98

. 4 Id: 7d4.7fc Suspend: 1 Teb: 7ffd7000 Unfrozen
Start: kernel32!BaseThreadStartThunk (7c810659)
Priority: 0 Priority class: 32 Affinity: 1
ChildEBP RetAddr
0228ff1c 7c90e9c0 ntdll!KiFastSystemCallRet
0228ff20 7c8025cb ntdll!ZwWaitForSingleObject+0xc
0228ff84 7c802532 kernel32!WaitForSingleObjectEx+0xa8
0228ff98 71abd174 kernel32!WaitForSingleObject+0x12
0228ffb4 7c80b683 WS2_32!SockAsyncThread+0x2b
0228ffec 00000000 kernel32!BaseThreadStart+0x37

. 5 Id: 7d4.2bc Suspend: 1 Teb: 7ffd6000 Unfrozen
Start: kernel32!BaseThreadStartThunk (7c810659)
Priority: 15 Priority class: 32 Affinity: 1
ChildEBP RetAddr
0238fecc 7c90e9ab ntdll!KiFastSystemCallRet
0238fed0 7c8094e2 ntdll!ZwWaitForMultipleObjects+0xc
0238ff6c 7c80a075 kernel32!WaitForMultipleObjectsEx+0x12c
0238ff88 72d2312a kernel32!WaitForMultipleObjects+0x18
0238ffb4 7c80b683 wdmaud!MixerCallbackThread+0x42
0238ffec 00000000 kernel32!BaseThreadStart+0x37

. 6 Id: 7d4.2dc Suspend: 1 Teb: 7ffdb000 Unfrozen
Start: ntdll!DbgUiRemoteBreakin (7c95077b)
Priority: 0 Priority class: 32 Affinity: 1
ChildEBP RetAddr
0151ffc8 7c9507a8 ntdll!DbgBreakPoint
0151fff4 00000000 ntdll!DbgUiRemoteBreakin+0x2d

Total threads: 7

So the output structured is very easy to traverse and module names with desired return addresses can be undertaken easily. So a conditional output is set not to look at the duplicate entries and a filtered output is required. Now further one can set easily use set [S] command to find the register checks.

Query?
On the contrary can it be considered as good practice? Just to avoid the big chunks of code. Well skill set seems to be this.

Cheers
0kn0ck



https://www.openrce.org/blog/view/910/Stack_Unwinding_:_Reliability_Panorama