Log in

View Full Version : CsrPortHandle Different when Run Within Ollydbg and Outside of it


blabberer
May 27th, 2012, 17:25
i was poking around some csrss stuff and i happened to notice some thing peculiar

in ollydbg 1.10 as well as ollydbg 2.01(alpha 4) the latest release

it seems if i run a console app inside ollydbg the console app gets a Different CsrPortHandle and if i run the same app out of ollydbg it gets a different CsrPortHandle

ms debuggers viz cdb or windbg does not display this phenomenon

googled around for an explanation but cant find one

so this phenomenon can possibly be used as an anti debug measure ?? targeting ollydbg

i mailed oleh about the phenomenon


below is a snippet that shows the phenomenon compile and
run the exe out of ollydbg will get CsrPortHandle as 0x7ec
run within ollydbg CsrPortHandle will be 0x18

for windows xp - sp3 (haven't checked in any other os )

also attached a screen shot of different outcomes

Code:


#define UNICODE

#include <stdio.h>

#include <tchar.h>

#include <windows.h>

#include <winternl.h>

typedef struct _CLIENT_ID {

HANDLE UniqueProcess;

HANDLE UniqueThread;

} CLIENT_ID, *PCLIENT_ID;

typedef struct _WRITE_CONSOLEA_SUPPORT {

USHORT DataLength;

USHORT TotalLength;

USHORT Type;

USHORT DataInfoOffset;

CLIENT_ID ClientId;

ULONG64 DoNotUseThisField;

ULONG MessageId;

ULONG CallBackId;

ULONG64 NoUse;

ULONG ConsoleHandle;

HANDLE StdHandle;

char MsgBuff[0x50];

PCHAR MsgBuffAddress;

ULONG MsgBuffSize;

ULONG NoUse1;

BYTE Flag;

BYTE Pad0;

BYTE Pad1;

BYTE Pad2;

ULONG NoUse2;

ULONG NoUse3;

} WRITE_CONSOLEA_SUPPORT, *PWRITE_CONSOLEA_SUPPORT;

typedef

__kernel_entry

NTSTATUS

(NTAPI *pfnNtQueryInformationProcess ) (

IN HANDLE ProcessHandle,

IN PROCESSINFOCLASS ProcessInformationClass,

OUT PVOID ProcessInformation,

IN ULONG ProcessInformationLength,

OUT PULONG ReturnLength OPTIONAL

);

typedef

__kernel_entry

NTSTATUS

( NTAPI *pfnNtRequestWaitReplyPort ) (

IN HANDLE CsrPortHandle,

IN PWRITE_CONSOLEA_SUPPORT wcsin,

OUT PWRITE_CONSOLEA_SUPPORT wcsout

);

typedef

__kernel_entry

NTSTATUS

( NTAPI *pfnCsrNewThread ) (
void
);

int _tmain(void)

{

printf(

"lets call some syscall and see it in kd\n"

);

HANDLE CurrentStdHandle;

if ( ( CurrentStdHandle = GetStdHandle(

STD_OUTPUT_HANDLE

) ) == INVALID_HANDLE_VALUE) {

printf(

"GetStdHandle Failed with %08x \n" ,

GetLastError()

);

return 0;

}

printf (

"CurrentStdHandle is %08x\n",

CurrentStdHandle

);

DWORD CurrentPid = GetCurrentProcessId();

printf(

"current process id is %08x\n",

CurrentPid

);

HANDLE CurrentProcess;

if ( ( CurrentProcess = OpenProcess (

PROCESS_QUERY_INFORMATION,

FALSE,

CurrentPid

)) == NULL ) {

printf (

"OpenProcess(CurrentPid) Failed with %08x\n",

GetLastError()

);

CloseHandle(

CurrentStdHandle

);

return 0;

}

printf (

"OpenProcess Returned Handle %08x\n",

CurrentProcess

);

pfnNtQueryInformationProcess NtQueryInformationProcess;

pfnNtRequestWaitReplyPort NtRequestWaitReplyPort;

pfnCsrNewThread CsrNewThread;

if (( NtQueryInformationProcess = ( pfnNtQueryInformationProcess )GetProcAddress(

LoadLibrary(L"ntdll.dll",

"NtQueryInformationProcess"

) ) == NULL ) {

printf (

"Getproc NtQueryInfo Failed returned %08x\n",

GetLastError()

);

CloseHandle(

CurrentStdHandle

);

CloseHandle(

CurrentProcess

);

return 0;

}

printf(

"ntQueryInformationProcess is found at %x\n",

NtQueryInformationProcess

);

if (( NtRequestWaitReplyPort = (pfnNtRequestWaitReplyPort ) GetProcAddress (

LoadLibrary(L"ntdll.dll",

"NtRequestWaitReplyPort"

) ) == NULL ) {

printf (

"Getproc NtQueryInfo Failed returned %08x\n",

GetLastError()

);

CloseHandle(

CurrentStdHandle

);

CloseHandle(

CurrentProcess

);

return 0;

}

printf(

"NtRequestWaitReplyPort is found at %x\n",

NtRequestWaitReplyPort

);

if (( CsrNewThread = ( pfnCsrNewThread )GetProcAddress(

LoadLibrary(L"ntdll.dll",

"CsrNewThread"

) ) == NULL ) {

printf (

"Getproc CsrNewThread Failed returned %08x\n",

GetLastError()

);

CloseHandle(

CurrentStdHandle

);

CloseHandle(

CurrentProcess

);

return 0;

}

printf(

"CsrNewThread is found at %x\n",

CsrNewThread

);

HANDLE PortHandle = (**(PHANDLE *)((ULONG)CsrNewThread + 2));

printf (

"CsrPortHandle is %08x\n",

PortHandle

);


PROCESS_BASIC_INFORMATION PBasicInfo;

ULONG ReturnLength;

NTSTATUS Status;

Status = NtQueryInformationProcess(

CurrentProcess,

ProcessBasicInformation,

&PBasicInfo,

sizeof(PBasicInfo),

&ReturnLength

);

if( !NT_SUCCESS(Status) ) {

printf(

"NtQueryInformationProcess Failed With %08x\n",

Status

);

CloseHandle(

CurrentStdHandle

);

CloseHandle(

CurrentProcess

);

return 0;

}

printf(

"RTL_PROCESS_PARAMETERS For Current Process is at %08x\n"

"Console Handle as per windbg display type info is %08x\n",

PBasicInfo.PebBaseAddress->ProcessParameters,

PBasicInfo.PebBaseAddress->ProcessParameters->Reserved2[0]

);

if (( SetConsoleTextAttribute (

CurrentStdHandle,

FOREGROUND_RED | FOREGROUND_INTENSITY

) ) == 0) {

printf(

"SetConsoleTextAttribute Failed Returned %08x\n"

"Following text wont have colours\n"

);

}

WRITE_CONSOLEA_SUPPORT wcs;

memset(

&wcs,

0,

sizeof(wcs)

);

wcs.DataLength = 0x7c;

wcs.TotalLength = 0x98;

wcs.CallBackId = 0x2021e;

wcs.ConsoleHandle = (ULONG)PBasicInfo.PebBaseAddress->ProcessParameters->Reserved2[0];

wcs.StdHandle = CurrentStdHandle;

strcpy_s (

wcs.MsgBuff ,

80,

"Put on Black Helmets Entering a CoalMine Can be Fatal Blue Screen Anytime\n"

);

wcs.MsgBuffAddress = (PCHAR)&wcs.MsgBuff;

wcs.MsgBuffSize = sizeof("Put on Black Helmets Entering a CoalMine Can be Fatal Blue Screen Anytime\n";

wcs.Flag =1;



Status = NtRequestWaitReplyPort(

PortHandle,

&wcs,

&wcs

);

if( !NT_SUCCESS(Status) ) {

printf(

"NtRequestReplyPortWith Handle %08x Failed\n",

PortHandle

);



CloseHandle(

CurrentStdHandle

);

CloseHandle(

CurrentProcess

);

return 0;

}


CloseHandle(

CurrentStdHandle

);

CloseHandle(

CurrentProcess

);

return 0;

}

blabberer
May 27th, 2012, 17:42
Testing this with ida fre 5 debugger yields same result like ollydbg ie
CsrPortHandle Returned is 0x18 not 0x7ec
borland td32 also yields 0x18 not 0x7ec so probably ms knows something better it seems

blabberer
May 27th, 2012, 20:17
this phenomenon is probably because windbg and cdb sets bInheritHandle option in CreateProcess To True while ollydbg ida td32 set this to false

a sample output fro all three debuggers broken On CreateProcess
for windbg a commented output for CreateProcessAndAttach2Wide is shown below as well as CreateProcessW
the other 2 debuggers use CreateProcessA


Code:


0:010> ~10kbN
# ChildEBP RetAddr Args to Child
00 00b9fbf8 022f0f21 00000000 009e1d38 00000000 kernel32!CreateProcessW
01 00b9fcb0 021308ab 009e7a88 009e1d38 00b9fd1c dbgeng!LiveUserDebugServices::CreateProcessW+0x241
02 00b9fcf0 020fc3e9 009e1d38 00b9fd1c 00000000 dbgeng!LiveUserTargetInfo::StartCreateProcess+0xfb
03 00b9fd40 0102af55 009ead1c 00000000 00000000 dbgeng!DebugClient::CreateProcessAndAttach2Wide+0xd9
04 00b9ffa4 0102b5ab 00000000 00000000 00b9ffec windbg!StartSession+0x445
05 00b9ffb4 7c80b729 00000000 7e428dd9 004101ee windbg!EngineLoop+0x1b
06 00b9ffec 00000000 0102b590 00000000 00000000 kernel32!BaseThreadStart+0x37

0:010> .frame /r 3

03 00b9fd40 0102af55 dbgeng!DebugClient::CreateProcessAndAttach2Wide+0xd9
eax=02297966 ebx=00000000 ecx=02337490 edx=7c802336 esi=004101ee edi=7e428dd9
eip=020fc3e9 esp=00b9fcf8 ebp=00b9fd40 iopl=0 nv up ei pl zr na pe nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246
dbgeng!DebugClient::CreateProcessAndAttach2Wide+0xd9:
020fc3e9 8945f0 mov dword ptr [ebp-10h],eax ss:0023:00b9fd30=00000000

0:010> r $t0 = 00b9fd40 <----------- ebp for frame

0:010> ln poi poi poi (@$t0+8) vtable This Pointer

(02102610) dbgeng!DebugClient::QueryInterface | (02102620) dbgeng!DebugClient::Release
Exact matches:
dbgeng!DebugClient::QueryInterface = <no type information>

0:010> dq $t0+c l1
00b9fd4c 00000000`00000000 process server is NULL so Local Process ULONG64

0:010> du /c 100 poi(@$t0+0x14)
009e1d38 ""C:\Documents and Settings\Admin\My Documents\Visual Studio 2008\Projects\syscalltest\syscalltest\syscalltest.exe"" command line

0:010> ? poi (windbg!g_DebugCreateOptions+0);? poi (windbg!g_DebugCreateOptions+4);? poi (windbg!g_DebugCreateOptions+8);? poi (windbg!g_DebugCreateOptions+0xc);
Evaluate expression: 2 = 00000002
Evaluate expression: 1 = 00000001
Evaluate expression: 0 = 00000000
Evaluate expression: 0 = 00000000
0:010> .echo so The new process will inherit system handles from the debugger or process server. see DebugCreateOptions->EngCreateFlags

0:010> dd /c 1 (@$t0+0x1c) l5

00b9fd5c 00000010 size of DebugCreateOptions
00b9fd60 00000000
00b9fd64 00000000
00b9fd68 00000000
00b9fd6c 00000000


0:010> dd /c 1 00b9fbf8 l10 Stack For CreateProcessW .frame 0
00b9fbf8 02297cd5
00b9fbfc 022f0f21
00b9fc00 00000000
00b9fc04 009e1d3800 "C:\Documents and Settings\Admin\My Documents\Visual Studio 2008\Projects\syscalltest\syscalltest\syscalltest.exe"
00b9fc08 00000000
00b9fc0c 00000000
00b9fc10 00000001 1 = TRUE For Inherit Handles
00b9fc14 00000402 402 = CREATE_UNICODE_ENVIRONMENT | DEBUG_ONLY_THIS_PROCESS
00b9fc18 00000000
00b9fc1c 00000000
00b9fc20 00b9fc30 si
00b9fc24 00b9fca0 pi


Ollydbg 1.10

0:000> kb
ChildEBP RetAddr Args to Child
0013c450 0047795d 00000000 0013c908 00000000 kernel32!CreateProcessA
WARNING: Stack unwind information not available. Following frames may be wrong.
0013e1b8 004341e8 0013e288 ffffffff 0013f50c ollydbg!OpenEXEfile+0x641
0013f4a4 7e418734 00280328 00000111 000007da ollydbg!Animate+0x2710
0013f4d0 7e418816 004323d4 00280328 00000111 USER32!InternalCallWinProc+0x28
0013f538 7e4189cd 00000000 004323d4 00280328 USER32!UserCallWinProcCheckWow+0x150
0013f598 7e4196c7 0013f5c0 00000001 0013ff88 USER32!DispatchMessageWorker+0x306
0013f5a8 00439442 0013f5c0 00000000 004b00c4 USER32!DispatchMessageA+0xf
0013ff88 004ad357 00400000 00000000 00561ef6 ollydbg!Go+0x4a2e
0013ffc0 7c817077 013af6ee 013af736 7ffd9000 ollydbg!Createpatchwindow+0xe0f7
0013fff0 00000000 00401000 00000000 78746341 kernel32!BaseProcessStart+0x23
0:000> dd /c 1 0013c450 l8
0013c450 004a6c4f
0013c454 0047795d
0013c458 00000000
0013c45c 0013c908
0013c460 00000000
0013c464 00000000
0013c468 00000000
0013c46c 04000032 NORMAL_PRIORITY_CLASS | DEBUG_ONLY_THIS_PROCESS || CREATE_DEFAULT_ERROR_MODE CREATE_NEW_CONSOLE
0:000> da /c 100 0013c908
0013c908 ""C:\Documents and Settings\Admin\My Documents\Visual Studio 2008\Projects\syscalltest\syscalltest\syscalltest.exe""

IDAFRE5

0:000> kb
ChildEBP RetAddr Args to Child
0013df00 0196e578 0013f614 00000000 00000000 kernel32!CreateProcessA
WARNING: Stack unwind information not available. Following frames may be wrong.
0013e47c 0196589d 0013f614 00000000 0013ee14 win32_user!Ordinal2+0xe578
0013ecc0 0196ba79 0013f614 0013f214 0013ee14 win32_user!Ordinal2+0x589d
0013edf0 004db051 0013f614 0013f214 0013ee14 win32_user!Ordinal2+0xba79
0013fa18 004f1f4c 00000000 00000000 00000000 idag!StrchooseFinalize+0x13099
0013fa7c 0044c5d0 01073394 400e7548 01073904 idag!StrchooseFinalize+0x29f94
0013fbc0 400387f2 01073904 400e71a6 0013fe3c idag!GroverFinalize+0x38ebc
0013fd38 4010a9a8 7e418734 00220308 00000020 rtl60!ClassesTBasicActionExecute$qqrv+0x12
0013fd80 0044aa16 01180fd5 01031ecc 4010a623 vcl60!ControlsTWinControlWndProc$qqrr17MessagesTMessage+0x15c
0013fdbc 4003947a 00000111 000000f6 00000000 idag!GroverFinalize+0x37302
0013fdd4 7e418734 00220308 00000111 000000f6 rtl60!ClassesTDataModuleWriteHeight$qqrp15ClassesTWriter+0x22
0013fe00 7e418816 01180fd5 00220308 00000111 user32!InternalCallWinProc+0x28
0013fe68 7e4189cd 00000000 01180fd5 00220308 user32!UserCallWinProcCheckWow+0x150
0013fec8 7e4196c7 0013fef8 00000001 0013ff44 user32!DispatchMessageWorker+0x306
0013fed8 400f5834 0013fef8 0013ff00 00000000 user32!DispatchMessageA+0xf
0013ff44 00402273 00000000 00571034 00171ef5 vcl60!FormsTApplicationProcessMessage$qqrr6tagMSG+0x88
0013ff88 00567abf 00400000 00000000 00171ef5 idag!_GetExceptDLLinfo+0xbca
0013ffc0 7c817077 00def6ee 00def734 7ffd5000 idag!Droptargetinitialization$qqrv+0xc59f
0013fff0 00000000 00401650 00000000 78746341 kernel32!BaseProcessStart+0x23
0:000> dd /c 1 0013df00 l8
0013df00 0013df18
0013df04 0196e578
0013df08 0013f614
0013df0c 00000000
0013df10 00000000
0013df14 00000000
0013df18 00000000
0013df1c 04000023 NORMAL_PRIORITY_CLASS | DEBUG_ONLY_THIS_PROCESS | DEBUG_PROCESS | CREATE_DEFAULT_ERROR_MODE





remove probability it is the cause i ran another round and this time i edited the arg in stack for idafre5 and output comes out to 0x7ec instead of 0x18

see snap

Kayaker
May 27th, 2012, 23:40
Was looking at this a bit. You can see this in Process Explorer as well.

First, set up ProcEx to view handles (View/Lower Pane View/Handles), as well as unnamed handles (View/Show Unnamed Handles and Mappings).

Now open 3 instances of cmd.exe, one standard as opened under Windows, one under Olly/etc., and one under WinDbg.

Click on each cmd.exe process in Process Explorer and view the Port handle in the lower pane.

The standard cmd.exe has a Port handle of 0x18 (oops?), so does the one under Olly, but the one under WinDbg is, as reported, 0x7EC.

Strange though, ProcEx reports a Port handle of 0x18 when cmd is run outside of any debugger, whereas you found that CsrNewThread returns a CsrPortHandle value of 0x7EC. Not sure why, but if you look at just about any other gui process, they all seem to have a default 0x18 Port handle.

blabberer
May 30th, 2012, 14:28
i see so there is one more twist to the tale
well who knows whats right

anyway i found a bit of time to check this in win7 and in win7 it is completely different beast the leopard has even changed the spots

CsrNewThread Which pointed to Some RegisterTerminateThread in xp does not exist in win7 google says via geoff chappel that this api was discontinued from vista sp1 onwards

so what disassemble some other func and find xref and leech is that something new or are you a noob you may ask ?

well CsrClientCallServer is a function common in both os that pushes CsrPortHandle and leech we can

but boy the win7 coders really put in a lot of work to evade us it seems

the CsrPorthandle in win7 comes back with This End of pipe Is not open to blah blah


the whole Csr Stuff that console uses seems to be shifted to kernel32

and kernel32!ConsoleLpcHandle is used this handle isnt available readily yep convoluted search can grab it


but it seems this handle is filled up During LdrinitializeProcess via NtConnectPort using a basenamedObject

viewable via windbg !object \

viz \\RPC Control\Console-"surprise here the other Csrporthandle From Ntdll is used as string like -0x00000cf6-lpc-handle "

it seems to be 0x1c always ie call NtRequestReplyPort WIth (0x1c, &buff , &buff)

i cooked an NtConnectPort but i get back 0xc0000034 status_obj_name_not_found

probably i have to tweak the Security Qos crap arg a bit or tweak other params

well if these hurdles are passed the actual size and length of NtRequestReplyPort have changed too it seems reduced by 4 bytes

so it is 78 and 94 instead of 7c and 98

the dll << 16 | routine no stuff which yields 0x2021e

has been changed to just routine no

ie now these Csr things probably take just 0x1e instead of 0x2021e

also the position of msgbuff in the struct has changed (come forward by 4 bytes ) and Stdhandle is embedded after msgbuff

quiet a lot of hacks to be done to simulate a printf weeee

and hand spleunking stuff in debugger shows win7/ollydbg /windbg/ also has this peculiarities

the handle seems to 0x14 outside and 0x18 inside or viceversa dont remember now

anyway it would be good to solve the mystery