Kayaker
October 16th, 2002, 02:42
And the explanation:
Ever since the DriverStudio versions of SoftIce came out people seemed to be having problems with getting Symbol Loader to break at WinMain. As it turns out there is a small difference in the winice driver from earlier versions in the routine which sets the "CC" breakpoint on the program entry point. This patcher fixes the problem by making a small patch in nmtrans.dll and should be universal for all versions of DriverStudio. Here is a *brief* explanation of the source of the problem...
============================================
To start with, here is the patch in the DriverStudio v2.7 nmtrans.dll. By changing the 1 instruction we affect a variable used in winice, and *ensure* that Symbol Loader will break at WinMain.
Code:
Original:
:1001CD7A 25FFFF0000 AND EAX, 0000FFFF ; PATCH HERE
:1001CD7F 50 push eax
:1001CD80 8B4DDA mov ecx, dword ptr [ebp-26]
:1001CD83 51 push ecx
:1001CD84 8D55B0 lea edx, dword ptr [ebp-50]
:1001CD87 52 push edx
* Reference To: nmtrans.DevIO_SetWLDRBreak
Patched:
:1001CD7A B8FFFF0000 MOV EAX, 0000FFFF ; PATCH
:1001CD7F 50 push eax
:1001CD80 8B4DDA mov ecx, dword ptr [ebp-26]
:1001CD83 51 push ecx
:1001CD84 8D55B0 lea edx, dword ptr [ebp-50]
:1001CD87 52 push edx
* Reference To: nmtrans.DevIO_SetWLDRBreak
==============================================
The nmtrans.dll function DevIO_SetWLDRBreak is used to communicate to the winice driver via a DeviceIOControl call that the user wants to break at the program entry point. The DevIO_ConnectToSoftICE function opens the vxd in the usual way with CreateFileA and returns a valid handle. Then DeviceIOControl is called, pushing the dwIoControlCode (9C40601C) for the proper function within the winice vxd to set the "Stop at WinMain" flag. For more info on the functioning of nmtrans.dll, see IceLoad by The Owl, G-RoM and Muffin.
This unique dwIoControlCode (9C40601C) in nmtrans.dll is our "ticket" into the correct function in winice itself. (All addresses are from DriverStudio v2.7)
...
_text:1001FFBD push 9C40601Ch ; dwIoControlCode
_text:1001FFC2 push esi ; hDevice
_text:1001FFC3 call ds

eviceIoControl ; communicate with winice
A search in winice.exe reveals the following code:
Code:
:C00007B0 mov ecx, [esi+0Ch] ; DeviceIOControl dwIoControlCode
:C00007B3 mov edx, ecx ; 9C40601Ch
:C00007B5 shr edx, 10h ; isolate HiWord
:C00007B8 cmp edx, 9C40h ; equal to 1st part of dwIoControlCode?
:C00007BE jnz short loc_0_C00007E0
:C00007C0 mov edx, ecx ; 9C40601Ch
:C00007C2 shr edx, 2 ; E7101807h
:C00007C5 and edx, 0FFFh ; 807h
:C00007CB cmp edx, 800h
:C00007D1 jl loc_0_C0000AAD
:C00007D7 sub edx, 800h ; 07h
:C00007DD inc edx ; 08h
:C00007DE mov ecx, edx
:C00007E0
:C00007E0 loc_0_C00007E0: ; CODE XREF: :C00007BE
:C00007E0 inc ecx ; 09h
:C00007E1 cmp ecx, 17h
:C00007E7 jnb loc_0_C0000AAD
:C00007ED JMP DS:OFF_0_C0007E10[ECX*4] ; JUMP TO CORRECT ROUTINE
What all this boils down to is getting the correct Index value of 09h in ECX. The JMP statement address then becomes C0007E10 + [09h*4], which leads to:
:C0007E34 dd offset loc_0_C0000928 ; main function called by DeviceIO_WLDR
Following the code...
Code:
:C000093F push dword ptr [eax+0Ch] ; 1
:C0000942 push dword ptr [eax+10h] ; 0
:C0000945 push dword ptr [eax+8] ; 0, BUT THIS IS THE CRITICAL VARIABLE!
:C0000948 push dword ptr [eax+4] ; CCh (ooh, what's this? ;-)
:C000094B push dword ptr [eax] ; filename of program to be loaded
:C000094D call sub_0_C003718D
That middle variable, dword ptr [eax+8], is going to turn out to be the critical one. It is moved into CX, then later into a small buffer containing the name of the program to be loaded, the "CC", some other flags and the word WINMAIN.
Code:
:C003719A mov ebx, [ebp+arg_0] ; filename of program to be loaded
...
:C00371B9 mov edx, [ebp+arg_4] ; CCh
:C00371BC mov cx, [ebp+arg_8] ; CRITICAL VALUE MOVED INTO CX
Now comes the major difference in the code between DriverStudio 2.7 and Softice 4.05, and the how and why that patching that instruction in nmtrans.dll works. Basically all we are doing is duplicating the code that existed in the 4.05 version.
Code:
DriverStudio 2.7:
:C003714A mov ds:dword_0_C0037FA6, edx ; CCh
:C0037150 mov ds:byte_0_C0037F7E, 4
:C0037157 mov ds:word_0_C0037FA2, 0FFFFh
:C0037160 mov ds:word_0_C0037FA0, cx ; WE WANT THIS TO BE 0FFFFh
:C0037167 mov ds:dword_0_C0037FAE, 0
:C0037171 movzx ecx, byte ptr [ebx]
Softice 4.05:
:C00607E4 mov ds:dword_0_C0061642, edx ; CCh
:C00607EA mov ds:byte_0_C006161A, 4
:C00607F1 mov ds:word_0_C006163E, 0FFFFh
:C00607FA mov ds:word_0_C006163C, 0FFFFh ; LACKING IN DRIVERSTUDIO
:C0060803 mov ds:dword_0_C006164A, 0
:C006080D movzx ecx, byte ptr [ebx]
This is basically the crux of the matter, but certainly doesn't convey the complexity of the Softice code or give an appreciation of the true excellence of the debugger. Getting lost in the codewoods is the only way to do that ;-)
Enjoy the patch
Kayaker