Log in

View Full Version : modify the PIB? (Hey squidge)


Aquatic
January 24th, 2004, 19:08
I saw this post about hiding Olly by modifying the PIB: http://www.exetools.com/forum/showthread.php?s=&threadid=3164

Can you elaborate on the PIB method? What is the PIB?

Many thanks!

0xf0001
January 24th, 2004, 20:53
Hi!
Have a look at the Win32 API CreateProcess().

BOOL CreateProcess(
LPCTSTR lpApplicationName, // pointer to name of executable module
LPTSTR lpCommandLine, // pointer to command line string
LPSECURITY_ATTRIBUTES lpProcessAttributes, // pointer to process security attributes
LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to thread security attributes
BOOL bInheritHandles, // handle inheritance flag
DWORD dwCreationFlags, // creation flags
LPVOID lpEnvironment, // pointer to new environment block
LPCTSTR lpCurrentDirectory, // pointer to current directory name
LPSTARTUPINFO lpStartupInfo, // pointer to STARTUPINFO
LPPROCESS_INFORMATION lpProcessInformation // pointer to PROCESS_INFORMATION
);

When a process is spawned by the debugger - the debugger sets the DEBUG_PROCESS flag in the dwCreationFlags. It is about how to modify the
information so the process does not see the debugger.

Anyway the _Process information structure_ that fits in the PiB is defined also here:

typedef struct _PROCESS_INFORMATION { // pi
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
} PROCESS_INFORMATION;


Members

hProcess

Returns a handle to the newly created process. The handle is used to specify the process in all functions that perform operations on the process object.

hThread

Returns a handle to the primary thread of the newly created process. The handle is used to specify the thread in all functions that perform operations on the thread object.

dwProcessId

Returns a global process identifier that can be used to identify a process. The value is valid from the time the process is created until the time the process is terminated.

dwThreadId

Returns a global thread identifiers that can be used to identify a thread. The value is valid from the time the thread is created until the time the thread is terminated.

greetz, 0xf001

JMI
January 24th, 2004, 21:01
I believe the reference is to the "Process Identification Block." You will find some information about it here:
Process identification block
Abbr: PIB. An area of virtual memory which holds the information relating to each process. The term is also used to mean a port

http://www.rainingdata.com/support/techpubs2/1722head.html

and by searching, using your favorite search engine.

Regards,

0xf0001
January 24th, 2004, 21:53
uups, better to read before posting .... and to sleep befor reading and ...
i can remember in xine3 this came up under win95 it was fs:[20] anyway,
sorry - you may forget my posting

0xf001

Kayaker
January 24th, 2004, 23:17
Hi

Erm, Actually it's a PEB, Process Environment Block, not a PIB, whatever that is. In user mode it is located at 7FFDF000h and is pointed to by fs:[30].

The IsDebuggerPresent code in question was this:

Code:

77E72740 mov eax, dword ptr fs:[00000018]
77E72746 mov eax, dword ptr [eax+30]
77E72749 movzx eax, byte ptr [eax+02]
77E7274D C3 ret

change the movzx eax, byte ptr [eax+02]
to
XOR EAX, EAX
then fill the rest with nops


The fs:[00000018] is a pointer to the per-thread data structure TEB (Thread Environment Block), this is it's partial structure in Win2K:

Code:

TEB STRUCT
Tib NT_TIB <> ; 000h
EnvironmentPointer PVOID ? ; 01Ch
Cid CLIENT_ID <> ; 020h
ActiveRpcInfo PVOID ? ; 028h
ThreadLocalStoragePointer PVOID ? ; 02Ch
Peb PVOID ? ; 030h PTR PEB
...


You can see that the next line, dword ptr [eax+30] points to the PEB, and byte ptr [eax+02] points to the BeingDebugged flag:

Code:

PEB STRUCT ; sizeof = 1E8h
InheritedAddressSpace BYTE ? ; 0000h
ReadImageFileExecOptions BYTE ? ; 0001h
BeingDebugged BYTE ? ; 0002h
...



Now what's a PIB? Dunno, but it might be a bit of confusion due to the fact you can also get to this byte flag through the PROCESS_BASIC_INFORMATION structure. I've also seen it referred to as PDB (Process DataBase).

Here's the same trick more or less as IsDebuggerPresent incorporated in a kernel mode driver as antidebug code:

Code:

.data?
hProcess HANDLE ?
hDebuggerProcess HANDLE ?
ReturnLength DWORD ?
pCLIENT_ID CLIENT_ID <>
pEventObject_ATTRIBUTES OBJECT_ATTRIBUTES <>
pPROCESS_BASIC_INFORMATION PROCESS_BASIC_INFORMATION <>

.code
lea edi, pEventObject_ATTRIBUTES
lea esi, pCLIENT_ID

assume editr OBJECT_ATTRIBUTES
mov [edi].dwLength, sizeof OBJECT_ATTRIBUTES
mov [edi].RootDirectory, 0
mov [edi].ObjectName, 0
; can set to object name if ClientID.UniqueProcess not used
mov [edi].Attributes, 0
mov [edi].SecurityDescriptor, 0
mov [edi].SecurityQualityOfService, 0

assume esitr CLIENT_ID
invoke PsGetCurrentProcessId ; check if our own app is being debugged
mov [esi].UniqueProcess, eax
mov [esi].UniqueThread, 0

invoke ZwOpenProcess, offset hProcess,\ ; OUT PHANDLE phProcess
PROCESS_ALL_ACCESS,\ ; IN ACCESS_MASK AccessMask
edi,\ ; IN pEventObject_ATTRIBUTES ObjectAttributes
esi ; IN PCLIENT_ID pClientId

invoke ZwQueryInformationProcess, hProcess,\
ProcessBasicInformation,\ ; ntddk.inc ; enum _PROCESSINFOCLASS
offset pPROCESS_BASIC_INFORMATION,\
SIZEOF pPROCESS_BASIC_INFORMATION,\
offset ReturnLength
; invoke ZwClose, hProcess ; can delete now useless thread handle

;--------------------------------------------------------
mov eax, pPROCESS_BASIC_INFORMATION.PebBaseAddress
bt dword ptr [eax], 16
; Bit Test to see if BeingDebugged flag is at byte 002 of PEB
jc @F
jmp nodebugger
@@:

;===================================================
; Let's get the handle of the debugger so we can kill it:
mov eax, pPROCESS_BASIC_INFORMATION.InheritedFromUniqueProcessId ; Debugger PID

; redefine CLIENT_ID to that of the remote process
mov [esi].UniqueProcess, eax

invoke ZwOpenProcess, offset hDebuggerProcess,\ ; OUT PHANDLE phProcess
PROCESS_ALL_ACCESS,\ ; IN ACCESS_MASK AccessMask
edi,\ ; IN pEventObject_ATTRIBUTES ObjectAttributes
esi ; IN PCLIENT_ID pClientId

; Debugger handle is now in hDebuggerProcess,
; exit driver, clean up and kill the process
;...

nodebugger:
assume esi:nothing
assume edi:nothing


Have fun,
Kayaker

nikolatesla20
January 25th, 2004, 01:01
ALso, a ring 3 debugger can be detected by calling NtQueryInformationProcess in ntdll.dll from another ring3 app with the constant ProcessDebugPort (0x07h). This function takes a pointer also as an argument, to store its return value. If it returns anything other than a zero, it means that process in question is operating as a debugger.

This trick is used in SoftProtect. Of course you can easily defeat it by hooking NtQueryInformationProcess and returning a zero in [esp+8].

-nt20

AndreaGeddon
January 25th, 2004, 06:58
i think that thread refers to "process information block" with pib, that is (if i remember good)
struct pib { /* PIB Process Information Block */
ULONG pib_ulpid; /* Process I.D. */
ULONG pib_ulppid; /* Parent process I.D. */
ULONG pib_hmte; /* Program (.EXE) module handle */
PCHAR pib_pchcmd; /* Command line pointer */
PCHAR pib_pchenv; /* Environment pointer */
ULONG pib_flstatus; /* Process' status bits */
ULONG pib_ultype; /* Process' type code */
}
this as TIB (and PDB & TDB) is used on consumer win, its different from nt systems where you have TEB/PEB and TIB has a different meaning (NT_TIB), so the implementation of IsDebuggerPresent is different in the two systems, on nt its like Kayaker explained, on 9x/me it reads the PDB.DebugeeCB field to determine if process is debugged or not quite similiar to PEB.BeingDebugged
Bye!
AndreaGeddon

Aquatic
January 25th, 2004, 17:33
Thanks for the replies.

Too bad there isn't an Olly plugin for the PIB/PEB.