Thanks for the link Waxford. I saw a reference to that article earlier today but didn't have time to dig up the article itself. Here's the other interesting paper where I saw it linked:
Tracing NT Kernel-Mode Calls
http://www.ddj.com/dept/windows/184416246
As mentioned the trick behind it all is that you can hook Int2D to monitor system module loading. In XP you can use PsSetLoadImageNotifyRoutine, which serves the same purpose in a very similar location.
I did look into the Numega Int2D patch to see what it did, I more or less followed the instructions in step 13 as per the forum thread you linked.
I searched for the bytes
"s MmLoadSystemImage L d88 85,c0,0f,84"
This search method as described isn't valid for WinXP or Win2Ksp4, for example the symbol is actually "_MmLoadSystemImage" in XP and you need to find a different way of getting into ntoskrnl context for a symbol based search to work.
The bytes 85,c0,0f,84 code for the instructions
test eax, eax
jz xxxxxxxx
If you search as described in the official Numega solution you won't find the right address for these very common instructions and will end up patching the wrong place in ntoskrnl (which is what I did at first), woe to the unwary XP user!
However, they do give an absolute Int2D patch address of 0x804c2b95 for Win2Ksp4, and this is correct. From this I was able to determine the patch point is actually within the function CacheImageSymbols, which is called from MmLoadSystemImage.
Here is some pseudocode which describes what happens within MmLoadSystemImage. What is important is that the Int2D patch patches CacheImageSymbols so that it ALWAYS returns true. This forces DbgLoadImageSymbols to be called no matter what, whenever a system image is loaded. DbgLoadImageSymbols in turn calls the Int2D interrupt which leads into the ntice driver DbgMsg.sys and also into siwvid.sys where the graphic adapters listed under NTICE in the registry are checked. This may be the relationship to Softice and video issues.
Code:
if (PsImageNotifyEnabled == TRUE)
{
PsCallImageNotifyRoutines(...);
}
if (CacheImageSymbols(ImageBase) == TRUE)
// Int2D patch applied always returns TRUE
{
DbgLoadImageSymbols(ULONG ImageBase, PSTRING ModuleName, -1);
}
... continue driver/module loading
If we look into the CacheImageSymbols function itself we can see the exact patch point, which matches the search bytes:
Code:
:u 804c2b57 L 5e
_CacheImageSymbols
:804C2B57 PUSH EBP
...
:804C2B85 PUSH EAX
:804C2B86 PUSH 06 // IMAGE_DIRECTORY_ENTRY_DEBUG
:804C2B88 PUSH 01
:804C2B8A PUSH DWORD PTR [EBP+08]
:804C2B8D CALL _RtlImageDirectoryEntryToData
:804C2B92 MOV [EBP-1C],EAX
:804C2B95 85C0 TEST EAX,EAX
:804C2B97 0F8406DA0200 JZ 804F05A3
:804C2B9D OR DWORD PTR [EBP-04],-01
:804C2BA1 PUSH 01
:804C2BA3 POP EAX
:804C2BA4 MOV ECX,[EBP-10]
:804C2BA7 MOV FS:[00000000],ECX
:804C2BAE POP EDI
:804C2BAF POP ESI
:804C2BB0 POP EBX
:804C2BB1 LEAVE
:804C2BB2 RET 0004
:u 804f05a3 L 0e
:804F05A3 OR DWORD PTR [EBP-04],-01
:804F05A7 XOR EAX,EAX
:804F05A9 JMP 804C2BA4
Having found this address you can create the NTICE registry entries:
"DoInt2dPatch"=dword:00000001
"Int2dLocation"=dword:804C2B95
When activated, you will find all the Int2D patch does is to insert 8 nops, overwriting the 'test eax, eax - jz' instructions. So what you get is:
Code:
:804C2B8D CALL _RtlImageDirectoryEntryToData
:804C2B92 MOV [EBP-1C],EAX
:804C2B95 nop nop
:804C2B97 nop nop nop nop nop nop
:804C2B9D OR DWORD PTR [EBP-04],-01
The following code should explain what RtlImageDirectoryEntryToData does:
Code:
#define IMAGE_DIRECTORY_ENTRY_DEBUG 6 // Debug Directory
typedef struct _IMAGE_DEBUG_DIRECTORY {
DWORD Characteristics;
DWORD TimeDateStamp;
WORD MajorVersion;
WORD MinorVersion;
DWORD Type;
DWORD SizeOfData;
DWORD AddressOfRawData;
DWORD PointerToRawData;
} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY;
// Look up the IMAGE_DEBUG_DIRECTORY directory in the IMAGE_OPTIONAL_HEADER.DataDirectory
pImageDebugDir = (PIMAGE_DEBUG_DIRECTORY) RtlImageDirectoryEntryToData(
(PVOID) BaseAddress, // IN PVOID Base
1, // BOOLEAN MappedAsImage
IMAGE_DIRECTORY_ENTRY_DEBUG, // ULONG DirectoryEntry
&size // PULONG Size
);
So it appears that the Int2D patch is just making sure that CacheImageSymbols returns successfully, even if RtlImageDirectoryEntryToData doesn't find a valid IMAGE_DEBUG_DIRECTORY pointer. In other words if a driver or other loadable system image was compiled in Release mode rather than Debug mode. The IMAGE_DEBUG_DIRECTORY pointer is never used anyway, it's just a way of forcing all images to go through Softice's Int2D handler.
If you're interested, there is Int2D patch code in the INIT section of ntice.sys, a string search for "DoInt2DPatch" etc. makes it easy to find. The Int2D handler (and others) can be found in this code (for DS3.2, do a search for the SIDT instruction otherwise). Or just break on DbgLoadImageSymbols and start tracing!
Code:
:00015215 HookInterrupts proc near ; CODE XREF: start__+A8
:00015215 60 pusha
:00015216 8B EC mov ebp, esp
:00015218 83 EC 08 sub esp, 8
:0001521B 66 8C 25 09 05 0F 00 mov word_F0509, fs
:00015222 0F 01 4D F8 sidt [ebp+var_8]
...
:000152D4 B8 2D 00 00 00 mov eax, 2Dh
:000152D9 B2 60 mov dl, 60h
:000152DB BF C1 82 0A 00 mov edi, offset Int2D_Handler
:000152E0 E8 C2 01 00 00 call HookInt
Finally, if you want to do the Int2D patch for XPsp2, the patch point is a bit different. Same byte sequence, different location. Now it's immediately *after* the CacheImageSymbols call rather than *within* it:
Code:
:004CF1EA 80 3D 34 5F 5B 00 00 cmp ds:_PsImageNotifyEnabled, 0
:004CF1F1 0F 85 26 AB 04 00 jnz loc_519D1D
:004CF1F7
:004CF1F7 loc_4CF1F7: ; CODE XREF: MmLoadSystemImage(x,x,x,x,x,x)+4B0B5
:004CF1F7 FF 37 push dword ptr [edi] ; ImageBase
:004CF1F9 E8 5D 0C 00 00 call _CacheImageSymbols@4
// Int2D patch address is here
:004CF1FE 85 C0 test eax, eax
:004CF200 0F 84 81 00 00 00 jz loc_4CF287
:004CF206 66 83 7D CC 16 cmp [ebp+Destination.Length], 16h
:004CF20B 0F 86 48 AB 04 00 jbe loc_519D59
:004CF211 6A 0B push 0Bh ; size_t
:004CF213 68 0C F3 4C 00 push offset off_4CF30C ; wchar_t *
:004CF218 FF 75 D0 push [ebp+Destination.Buffer] ; wchar_t *
:004CF21B E8 6F C6 F4 FF call __wcsnicmp
:004CF220 83 C4 0C add esp, 0Ch
:004CF223 85 C0 test eax, eax
:004CF225 0F 85 2E AB 04 00 jnz loc_519D59
:004CF22B 8B 45 CC mov eax, dword ptr [ebp+Destination.Length]
:004CF22E 89 85 40 FF FF FF mov [ebp+var_C0], eax
:004CF234 8B 45 D0 mov eax, [ebp+Destination.Buffer]
:004CF237 83 C0 16 add eax, 16h
:004CF23A 89 85 44 FF FF FF mov [ebp+var_BC], eax
:004CF240 66 83 85 40 FF FF FF EA add word ptr [ebp+var_C0], 0FFEAh
:004CF248 8D 85 40 FF FF FF lea eax, [ebp+var_C0]
:004CF24E 50 push eax
:004CF24F 68 34 00 DF FF push 0FFDF0034h
:004CF254 68 24 F3 4C 00 push offset aWsWz_0 ; "%ws%wZ"
:004CF259 FF 75 A0 push [ebp+P] ; char *
:004CF25C E8 CC 53 F6 FF call _sprintf
:004CF261 83 C4 10 add esp, 10h
:004CF264
:004CF264 loc_4CF264: ; CODE XREF: MmLoadSystemImage(x,x,x,x,x,x)+4B0CE
:004CF264 FF 75 A0 push [ebp+P] ; SourceString
:004CF267 8D 85 D0 FE FF FF lea eax, [ebp+DestinationString]
:004CF26D 50 push eax ; DestinationString
:004CF26E E8 4A 31 F3 FF call _RtlInitString@8 ; RtlInitString(x,x)
:004CF273 6A FF push 0FFFFFFFFh ; int
:004CF275 FF 37 push dword ptr [edi] ; ImageBase
:004CF277 8D 85 D0 FE FF FF lea eax, [ebp+DestinationString]
:004CF27D 50 push eax ; int
:004CF27E E8 1E 56 F6 FF call _DbgLoadImageSymbols@12
On my XPsp2 system the CacheImageSymbols address is 0x805A61F9, and the Int2D patch address would be 0x805A61FE.
So you would create the following registry entries and *then* either start Softice manually or reboot.
\REGISTRY\Machine\System\ControlSet\Services\NTice
"DoInt2dPatch"=dword:00000001
"Int2dLocation"=dword:805A61FE
Phew that was long, I guess I should update that "Official tech support - Configuring Softice to work on all video cards" thread to link to this one for proper implementation of the Int2D patch..
Kayaker