I want to hook the following NTDLL systemcalls in Windows NT 4.0 :
NtCreateProcess
NtCreateThread
NtTerminateProcess
NtTerminateThread
I read the article "Windows NT System-Call Hooking" in Dr. Dobb's Journal
from January 1997. It's about hooking Registry-API-calls in a program
named NTRegmon, which can be downloaded from ntinternals.com with source-
code. I tried to build in my required functionality, but somehow there
are no equivalent names in the NTOSKRNL Service Table. The equivalent
API-methods have different names somehow.
Does anyone know what functions (maybe PsXxx) I should call in the NTOSKRNL
Service Table to succeed in hooking the API-functions named above. I read
all the NtInternals documentation already.
Thanks in advance,
Theo Gulcher
Secure Application Software Engineer
Siemens AF Munich Germany
mail : gul...@rocketmail.com
-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/ Now offering spam-free web-based newsreading
> I want to hook the following NTDLL systemcalls in Windows NT 4.0 :
>
> NtCreateProcess
> NtCreateThread
> NtTerminateProcess
> NtTerminateThread
>
> I read the article "Windows NT System-Call Hooking" in Dr. Dobb's Journal
> from January 1997. It's about hooking Registry-API-calls in a program
> named NTRegmon, which can be downloaded from ntinternals.com with source-
> code. I tried to build in my required functionality, but somehow there
> are no equivalent names in the NTOSKRNL Service Table. The equivalent
> API-methods have different names somehow.
Not completely sure I understand you, but let me guess that the
problem is that you tried to use code analogous to that provided by
the ntinternals guys, and it doesn't work because ZwCreateProcess et
al. aren't exported from ntoskrnl.exe. Is that correct?
If so, you'll need to look at ntdll.dll (which *does* export these
symbols), and pull the system call numbers out of the linkage code in
ntdll.dll. Then, you can index into the NT system service table in the
same way as done in the NTRegmon code. (Yes I know. Doing all that
programmatically from inside your kernel mode driver will be ugly and
no fun.)
- GH
Thanks for your quick answer. And you're right that is exactly my problem.
I have probvlems with that SYSCALL definition of the NTInternals way, it
causes an error when loading the device driver.
The definition is :
#define SYSCALL(_function) ServiceTable->ServiceTable[
*(PULONG)((PUCHAR)_function+1)]
I found entry values as you described in ntdll.dll with Quickview :
NtCreateProcess 0x00007724
NtCreateThread 0x00007774
etc...
My Questions :
1. Are these the values you mean ?
2. How can I retrieve these values programmaticaly in my device driver ?
3. How shouls I use these values in this SYSCALL definition ?
Thanks in advance...
Theo Guelcher
> In article <3524fb57.1391321164@milo>,
> hami...@arm.un.org (Gil Hamilton) wrote:
> >
> > Not completely sure I understand you, but let me guess that the
> > problem is that you tried to use code analogous to that provided by
> > the ntinternals guys, and it doesn't work because ZwCreateProcess et
> > al. aren't exported from ntoskrnl.exe. Is that correct?
> >
> > If so, you'll need to look at ntdll.dll (which *does* export these
> > symbols), and pull the system call numbers out of the linkage code in
> > ntdll.dll. Then, you can index into the NT system service table in the
> > same way as done in the NTRegmon code. (Yes I know. Doing all that
> > programmatically from inside your kernel mode driver will be ugly and
> > no fun.)
> I have probvlems with that SYSCALL definition of the NTInternals way, it
> causes an error when loading the device driver.
>
> The definition is :
>
> #define SYSCALL(_function) ServiceTable->ServiceTable[
> *(PULONG)((PUCHAR)_function+1)]
>
> I found entry values as you described in ntdll.dll with Quickview :
>
> NtCreateProcess 0x00007724
> NtCreateThread 0x00007774
> 1. Are these the values you mean ?
Yes, well sort of. Now use "dumpbin /disasm ntdll.dll" (dumpbin is in
the SDK) to get a disassembled listing of the DLL. Also, use "dumpbin
/headers ntdll.dll" to find the image base -- should be 77F60000H.
Add the offset of the particular symbol, and you should see in your
listing something like:
77F67724: B8 1B 00 00 00 mov eax,1Bh
77F67729: 8D 54 24 04 lea edx,dword ptr [esp+4]
77F6772D: CD 2E int 2Eh
77F6772F: C2 10 00 ret 10h
The "1BH" is the system call number for NtCreateProcess.
> 2. How can I retrieve these values programmaticaly in my device driver ?
Good question. This is the hard part. It's not impossible though. The
executable file format (used by DLLs too) is documented by Microsoft.
It's just a matter of reading up the right bits from the file and
pulling the numbers out of it. That is, you're just doing
programmatically what we just did with dumpbin.
> 3. How shouls I use these values in this SYSCALL definition ?
The ntinternals folks had previously defined a variable called
ServiceTable as used in the macro. They had initialized it by
assigning to it the value of the ntoskrnl.exe export
"KeServiceDescriptorTable". So, what they're doing is pulling the
system call number directly out of the system call linkage code (i.e.
1 byte past the symbol's offset) and using it to index into the
KeServiceDescriptorTable (the NT system call dispatch table).
So, armed with the syscall number from above, and assuming you can
figure out the NtCreateProcess prototype, you can call it by
indirecting through the dispatch table. If you'd rather call
ZwCreateProcess, just duplicate the assembly code above and name it
appropriately.
- GH
Hi Theo
-------
This is not exactly what you need... But I hope you find it
useful....
For example... a little program that shows how you can hook
a system service in order to run a process in the security
context of the OS.
After the program has finished press CTRL+ALT+DEL to visit
progman on the logon screen.
Compile with VC++ >= 4.0. No special libs required.
Note: Because this is not a security hole, you must be an
administrator or someone who can enable SE_DEBUG_NAME.
-> Tested under NT351(SP5) and NT4 w/o service packs.
If it doesn't work on your computer... feel free to seek
for errors and tell me what I made wrong.
Bye
Peter
//-------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h>
#pragma pack (1)
typedef struct
{
BYTE mov_eax;
void *address;
WORD jump_eax;
} JUMPINSTRUCTION;
// Global variables for assembly function
HANDLE hparent;
DWORD servicenumber;
// Our new NtCreateProcess
void __declspec (naked) CatchCreateProcess()
{
__asm
{
// Change parent process handle
mov eax, hparent
mov dword ptr [esp+16], eax
// ...depends on version...FUCK 'EM!!!
mov eax, servicenumber
// Load parameters table
lea edx, dword ptr [esp+4]
// Enter kernel mode...
int 2eh
// Skip parameters and return to caller
retn 20h
}
}
// This routine will switch on SE_DEBUG_NAME which is
// not enabled by default. (Not truly interesting)
BOOL EnablePrivilege (HANDLE hprocess, LPSTR privilege, BOOL on_off)
{
HANDLE hToken;
LUID DebugValue;
TOKEN_PRIVILEGES tkp;
if (!OpenProcessToken (hprocess,
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hToken))
goto errexit;
if (!LookupPrivilegeValue((LPSTR) NULL,
privilege,
&DebugValue))
goto errexit;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = DebugValue;
if (on_off)
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED |
SE_PRIVILEGE_ENABLED_BY_DEFAULT |
SE_PRIVILEGE_USED_FOR_ACCESS;
else
tkp.Privileges[0].Attributes = NULL;
AdjustTokenPrivileges(hToken,
FALSE,
&tkp,
sizeof(TOKEN_PRIVILEGES),
(PTOKEN_PRIVILEGES) NULL,
(PDWORD) NULL);
if (GetLastError() != ERROR_SUCCESS)
goto errexit;
return TRUE;
errexit:
return FALSE;
}
// Let's go...
void main (void)
{
// Try to get a handle to the system process
EnablePrivilege ((HANDLE)0xffffffff, SE_DEBUG_NAME, TRUE);
hparent = OpenProcess (PROCESS_CREATE_PROCESS, TRUE, 0x02);
if (!hparent)
{
printf ("Sorry, Cannot open parent process...\n");
ExitProcess (0xffffffff);
}
// Calculate NtCreateProcess's entry number
servicenumber = 0x1e;
if ((LOBYTE(LOWORD(GetVersion()))) == 4)
servicenumber++;
// Fetch address of NtCreateProcess
HMODULE hmodule = GetModuleHandle ("ntdll.dll");
JUMPINSTRUCTION *createprocesshook = (JUMPINSTRUCTION*)
GetProcAddress (hmodule,
"NtCreateProcess");
// Enable write acess to VM which contains ntdll's image.
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery (createprocesshook, &mbi,
sizeof (MEMORY_BASIC_INFORMATION));
DWORD dummy;
VirtualProtect (mbi.AllocationBase, mbi.RegionSize,
PAGE_EXECUTE_READWRITE, &dummy);
// Redirect NtCreateProcess....
createprocesshook->mov_eax = 0xb8;
createprocesshook->address = CatchCreateProcess;
createprocesshook->jump_eax = 0xe0ff;
// Call modified CreateProcess API....
PROCESS_INFORMATION pi;
STARTUPINFO sui;
ZeroMemory (&pi, sizeof (PROCESS_INFORMATION));
ZeroMemory (&sui, sizeof (STARTUPINFO));
sui.cb = sizeof (STARTUPINFO);
sui.lpDesktop = "WinSta0\\Winlogon";
BOOL cp_error = CreateProcess (NULL, "progman.exe",
NULL, NULL,
TRUE,
0,
NULL,
NULL,
&sui,
&pi);
Hi Peter,
I have the solution now for this problem. Works like the
NTRegmon example.... :))
If you want my test program send me a mail at rocketmail
bye,
theo gulcher
email : gulcher@@@@@@@@@rocketmail........com
Hi Theo...
I already know NTRegmon and all the other NtInternals stuff.
Hooking kernel code or extending the system service table
is not very tricky and therefore not very interesting to me.
... but if your program doesn't need a driver, send it along and
let me see.
Take a look at the web-page www.sonic.net/~undoc/ntaddsys.html.
-> Peter