Log in

View Full Version : Possible DoS with Int 2D in softice


WaxfordSqueers
November 23rd, 2006, 21:49
I came across this warning about softice and Int 2D:

http://www.derkeiler.com/Mailing-Lists/Securiteam/2005-05/0166.html

I did a reasonable search of the archives and came across Kayaker's post on video problems with softice. He mentioned a patch for Int 2D, but it seemed aimed at video problems. I'm wondering if maybe the patch process mentioned in Kayakers article was aimed more at this denial of service possibility? If so, should it maybe be applied generally, even if your video is working fine in softice?

I'm wondering also about problems some people have complained about where softice crashes for no apparent reason. Has this Int 2D problem been mentioned before in this capacity?

Neitsa
November 24th, 2006, 12:15
Hello,

I studied the problem a while ago ,when it was dicovered by Piotr Bania. I paste some of my comments that I discussed with my team mates. (sorry if the translation is awfull, english is not my native language).

AFAIK it is not related to a video problem but as the paper says, with debug message.

the int 2D is hooked by DbgMsg.sys (part of DriverStudio) even if softice is not active.

Here's a simple look at int 2D with the Kernel debugger (softice is not active):

Code:

kd> !idt 2d

Dumping IDT:

2d: b8d93b5c *** ERROR: Module load completed but symbols could not be loaded for DbgMsg.SYS

DbgMsg+0xB5C


On any system with Driver studio installed a simple code like this will bring a BSOD :

Code:

mov eax, 1
xor ecx, ecx
xor edx ,edx

int 2Dh


http://neitsabes.online.fr/Ztrash-bin/BSOD_DbgMsg.png

Normally a call to int 2D is issued when calling DbgPrint :

Code:

invoke LoadLibrary, addr ntdll ; "ntdll"
invoke GetProcAddress,eax, addr DbgPrint
push 12345678h; value to convert
push offset Format ; "converted value is %lu" [our format string]
call eax ; call DbgPrint func


in DbgPrint a call is made to _vnsprintf which then call the int2D (somewhere in NTDLL) :

Code:

7C93057E 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] ; 1 : service number
7C930581 |. 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C] ; pointer on stack : "converted value is 305419896"
7C930584 |. 8B55 10 MOV EDX,DWORD PTR SS:[EBP+10] ; 0x1C : length of string
7C930587 |. 8B5D 14 MOV EBX,DWORD PTR SS:[EBP+14] ; -1
7C93058A |. 8B7D 18 MOV EDI,DWORD PTR SS:[EBP+18] ; 0
7C93058D |. CD 2D INT 2D
7C93058F |. CC INT3
7C930590 |. 5B POP EBX


We then switch to ring0 and go to DbgMsg.sys. The problem lies around here, in an inlined strlen :

Code:

.text:00010DE0 000 push ebp
.text:00010DE1 004 mov ebp, esp
.text:00010DE3 004 push ecx
.text:00010DE4 008 mov eax, [ebp+arg_0] ; buffer of the formated string (in context of the ring3 process, this address is the one from the stack of the calling process)
.text:00010DE7 008 push ebx
.text:00010DE8 00C push esi
.text:00010DE9 010 mov esi, ecx
.text:00010DEB 010 push edi
.text:00010DEC 014 lea ecx, [eax+1] ; address of the next char in the string
.text:00010DEF 014 xor ebx, ebx
.text:00010DF1
.text:00010DF1 loc_10DF1: ; CODE XREF: sub_10DE0+16j
.text:00010DF1 014 mov dl, [eax] ; !!!!!!!!!


If you remember what we've done previously to get the BSOD (passing 0 as the adress of the buffer), you'll kickly see that that DbgMsg.sys is trying to reference the 0 address... leading to a BSOD :

Code:

.text:00010DF1 014 mov dl, [eax] ; EAX = 0 ? ouch !!!!


To be patched, this problem requires a patching in this DbgMsg.sys function to check if the adress passed by the caller is valid and then can be referenced. Checking only for 0 isn't sufficient...

Maybe calling MmIsAddressValid function could do the trick but i haven't tested it...

I would be glad if someone has an idea on how to patch this flaw

evlncrn8
November 24th, 2006, 14:26
well u did like 1/2 the work
a simple patch checking for eax != 0 or mmisaddressvalid call could be done via detouring the mov dl,[eax] to the checking code.. hardly rocket science patching that

WaxfordSqueers
November 24th, 2006, 18:55
Quote:
[Originally Posted by Neitsa;62617]I studied the problem a while ago ,when it was dicovered by Piotr Bania. I paste some of my comments that I discussed with my team mates. (sorry if the translation is awfull, english is not my native language).


Hi Neitsa...thanks for the detailed reply. Your English is OK...I understand what you are saying, with no effort.

Quote:
[Originally Posted by Neitsa;62617]AFAIK it is not related to a video problem but as the paper says, with debug message.
This is Kayakers article:

http://www.woodmann.com/forum/showthread.php?t=7199&highlight=kayaker+video

Half way through it, you can see a reference to INT 2D that covers points 6 to 13. It talks about an INT 2D 'patch', and I think that info comes from NuMega/Compuware. Kayaker will probably check in, but if he doesn't, I'll PM him to see if he can elaborate.

I also found this interesting article from Dr. Dobb's journal:

http://www.ddj.com/dept/windows/184416239

It is written by Joe Flores, a programmer for NuMega. He claims INT 2D is used by the NT debugging service to transfer control to service routines. I'm just wondering if the alterations to the registry in Kayakers post could affect the way INT 2D operates. As you and evlncrn8 pointed out, fixing the problem would require alterations to the code. I'm wondering if NuMega had a way of doing it via the registry. I don't see how, yet I'm wondering why they call it a patch.

I'll need some time to digest the rest of your reply. I'm slowly getting into lower-level routines, but I need to read so much to understand a little.

thanks again for your response.

WaxfordSqueers
November 24th, 2006, 19:00
Quote:
[Originally Posted by evlncrn8;62618]well u did like 1/2 the work
a simple patch checking for eax != 0 or mmisaddressvalid call could be done via detouring the mov dl,[eax] to the checking code.. hardly rocket science patching that
Howdy...thanks for reply. Are you talking about a patch that requires a jump to a pocket in the code where you insert your own code, or something simpler?

Kayaker
November 25th, 2006, 00:30
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

Neitsa
November 26th, 2006, 11:29
Thanks a lot Kayaker, that's a very interesting post !

I'll have to study and trace the code to understand it fully, though

WaxfordSqueers
November 26th, 2006, 21:32
Quote:
[Originally Posted by Kayaker;62629]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:


Kayaker...your welcome for the link, and thanks for yours. Also, thanks for your hard work in the reply, and sorry for the lateness of my reply. It was late at night when I first saw it, and not much was sinking in.

I've been dickering around with softice, but more in relationship to my other post, to which you replied. It's the one in the newbie forum about 'access violations and other dirty deeds'. I'm going to update that one, and I'd appreciate your consideration of what I have learned.

Some of it raised further questions about softice in XP SP2 with regard to the BPM command. I want to get into the current issue about the INT 2D, but the access violations have me consumed. Also, I'm in the middle of Silver's DX crackme.

Like Neitsa, I need to sit down with your reply for a bit, but your info for XP was of immediate interest..