Kayaker
October 15th, 2004, 00:08
Thanks Naides, let's see if this is helpful...
So, it's starting to look like XP SP2 sucks, er may have compatibility issues with Softice? OK, that wasn't helpful. No matter, maybe we can bypass the problem. Do your breakpoints work if you type ADDR <process> before setting them?
Let's say BMSG breakpoints don't work, what we really NEED is the starting address of the Message Queue which handles the WM_ messages. If you have that you should be able to set a different style of (conditional) BP on that address which will work just as well. How to find that address without deadlisting etc.? By some quirk of magic, Softice knows the address of the Message Queue and translates your "BMSG <hwnd> wm_*" messages directly into an address in its breakpoint table.
A couple of years ago I posted a preliminary examination of the Softice breakpoint table structure. I've updated it for Softice DriverStudio 4.31 and here are the results of my findings. The original stuff was from this thread and the screendumps and notes I made are in the attachment. For other notes on the details of breakpoints, see Softice Internals by +Spath.
IceDump & VXDLDR_LoadDevice error
http://woodmann.net/forum/showthread.php?t=4040&highlight=VXDLDR_LoadDevice
bpstructuredumps.zip (1.8 KB)
http://woodmann.net/forum/attachment.php?attachmentid=490
The SoftIce Breakpoint Table is a block of data in non-paged Sice memory consisting of 32 identical arrays, of a type Softice identifies as "TDJF". Each structure is 178h bytes in length. Thus you are limited to 32 breakpoints of all types, (only 4 of type BPM/BPIO). The structure has changed a bit from Softice 4.05, if my initial analysis was correct the size used to be 183h bytes and a total of 256 BP's were allowed.
Here is the breakpoint structure Softice uses, easily recognized by the beginning and ending ascii strings "TDJF". I renamed this structure BREAKPOINT_INFO here, substitute for the name TDJF. The structure is not fully defined and may have some errors (end disclaimer). I have not compared with any other structures that might be floating around.
Code:
0000 BREAKPOINT_INFO struc ; (sizeof=0x178)
0000 ascii_TDJF_1 db 4 dup(?) ; "TDJF"
0004 Breakpoint_Type db ? ; BPINT = 01h
0004 ; BPM/BPIO = 03h
0004 ; BPX = 05h
0004 ; BMSG = 06h
0004
0005 Enabled_Flag db ? ; toggled with BE, BD
0006 DRx_Register db ? ; DR3=83h, DR2=82h, DR1=81h, DR0=80h
0006 ; used with BPM/BPIO breakpoints
0006
0007 Address_1 dd ? ; Breakpoint address or BPIO port number
000B Address_2 dd ? ; unknown usage
000F Breakpoint_Mode db ? ; execute = 0
000F ; write = 1
000F ; read = 2
000F ; read/write = 3
000F
0010 unknown_dword_1 dd ?
0014 CodeSegment_CS dw ? ; 0008, 001B, etc.
0016 unknown_03h db ? ; seems to be 3 for all BP types
0017 Address_1_repeat dd ? ; Duplicate BP address
001B unknown_word_1 dw ?
001D unknown_byte_1 db ?
001E unknown_dword_2 dd ?
0022 unknown_dword_3 dd ?
0026 unknown_dword_4 dd ?
002A unknown_byte_2 db ?
002B BMSG_hWnd dd ? ; Class handle for BMSG breakpoints
002F unknown_word_2 dw ?
0031 unknown_byte_3 db ?
0032 unknown_byte_4 db ?
0032 ;
0033 unknown_dword_5 dd ?
0037 unknown_dword_6 dd ?
003B unknown_dword_7 dd ?
003B ;
003F unknown_byte_5 db ?
0040 unknown_byte_6 db ?
0041 unknown_byte_7 db ?
0042 unknown_byte_8 db ?
0042 ;
0043 unknown_dword_8 dd ?
0047 unknown_dword_9 dd ?
004B unknown_dword_10 dd ?
004F unknown_dword_11 dd ?
0053 unknown_dword_12 dd ?
0057 unknown_dword_13 dd ?
005B unknown_dword_14 dd ?
005F unknown_dword_15 dd ?
0063 unused_dword_1 dd ?
0067 unused_dword_2 dd ?
006B Length_Module_Name db ? ; byte length of string that follows
006C Module_Name_String db 264 dup(?) ; Name of process (breakpoint context)
0174 ascii_Tdjf_2 db 4 dup(?) ; "TDJF"
0178 BREAKPOINT_INFO ends
Now, back to the other issue of finding the address of our BP. The field TDJF.Address_1 is it. If you've set a BMSG bp, this will be the starting address of the Message handling code that BMSG is supposed to break on.
So, Naides, you can check, #1 - if your bp's are being set properly, and #2 - if so, use the address directly if BMSG fails, but let Sice calculate the correct address to break on and scam it from the BP Table.
(ponders if Subclassing is always handled correctly...)
Er, how to find the Breakpoint Table? (an array of TDJF structures). The easiest way to find the starting address of the 1st structure is by searching for hex bytes 54 44 4A 46 ("TDJF"

in IDA on your ntice.sys version. Go 178h bytes from there and you've found the 2nd structure (beginning with 54 44 4A 46), etc., up to 32 times. Apply my structure definition and you can examine the Sice "breakpoint" commands.
In memory, which is what you really want, a simple byte scan of ntice code ("DRIVER ntice"

should also find the string "TDJF", or better yet, get the address directly from one of the BP commands. Here is the Sice code for BMSG, you should be able to find the BP Table address from any of the TDJF.field[ebx] instructions for your own system.
Code:
:000A39ED c_Bmsg proc near ; DATA XREF: .data:00111239
:000A39ED
:000A39ED var_1C = dword ptr -1Ch
:000A39ED
:000A39ED 55 push ebp
:000A39EE 8B EC mov ebp, esp
:000A39F0 83 EC 1C sub esp, 1Ch
:000A39F3 E8 F1 EC F8 FF call sub_326E9
:000A39F8 BE A2 F7 10 00 mov esi, offset bUserCommand
:000A39FD E8 70 AB FC FF call sub_6E572
:000A3A02 E8 42 65 FC FF call pSkipWord
:000A3A07 0F 82 65 01 00 00 jb loc_A3B72
:000A3A0D E8 14 A5 FC FF call pExpression2Integer
:000A3A12 0F 82 6B 01 00 00 jb loc_A3B83
:000A3A18 8D 7D E4 lea edi, [ebp+var_1C]
:000A3A1B 57 push edi
:000A3A1C 50 push eax
:000A3A1D E8 14 DB F9 FF call sub_41536
:000A3A22 0B C0 or eax, eax
:000A3A24 0F 84 7A 01 00 00 jz loc_A3BA4
:000A3A2A 8B 47 0C mov eax, [edi+0Ch]
:000A3A2D E8 FE 47 FA FF call pSwitchContext_InWinice
:000A3A32 E8 D3 0C 00 00 call pAllocateBP
:000A3A37 0F 82 5B 01 00 00 jb loc_A3B98
:000A3A3D 8B D8 mov ebx, eax
:000A3A3F 8B 47 04 mov eax, [edi+4]
:000A3A42 89 83 FA EB 11 00 mov TDJF.BMSG_hWnd[ebx], eax
:000A3A48 C7 83 F1 EB 11 00 FF FF+ mov TDJF.unknown_dword_3[ebx], 0FFFFFFFFh
:000A3A52 8B 57 14 mov edx, [edi+14h]
:000A3A55 83 3F 00 cmp dword ptr [edi], 0
:000A3A58 74 22 jz short loc_A3A7C
:000A3A5A C6 83 EC EB 11 00 20 mov TDJF.unknown_byte_1[ebx], 20h
:000A3A61 C6 83 E5 EB 11 00 03 mov TDJF.unknown_03h[ebx], 3
...
:000A470A pAllocateBP proc near ; CODE XREF: c_Bpint+25
:000A470A ; c_Bpx+1B6
:000A470A 53 push ebx
:000A470B 51 push ecx
:000A470C B9 1F 00 00 00 mov ecx, 1Fh
:000A4711 B8 00 00 00 00 mov eax, 0
:000A4716
:000A4716 loc_A4716: ; CODE XREF: pAllocateBP+1A
:000A4716 80 B8 D3 EB 11 00 00 cmp TDJF.Breakpoint_Type[eax], 0
:000A471D 74 0A jz short loc_A4729
:000A471F 05 78 01 00 00 add eax, 178h
:000A4724 E2 F0 loop loc_A4716
:000A4726 F9 stc
:000A4727 EB 28 jmp short loc_A4751
Cheers,
Kayaker