![]() |
|
|
|
#1
|
|||
|
|||
|
parent?
Hello,
Anyone here knows whether it is possible to get the parent process name that executed our executable on windows NT (2K/XP), without any API? Like a field in the PEB, or TIB or something. If you have any infos... From Ring 3 btw Thanks i forgot oh btw, Daemon published something that does that, but it is for win9x only. if anyone knows how to do the same thing from NT... |
|
#2
|
|||
|
|||
|
Yes, you can. Use ToolHelp API functions to enum all processes in the system. Check the th32ProcessID field in the PROCESSENTRY32 struct. If it equal with current your process ID, store and remember the th32ParentProcessID field value. Enum again and when the th32ProcessID value equal with saved th32ParentProcessID field value, then the name of parent proces will stored in TCHAR szExeFile[MAX_PATH] field.
This way is same as the way some packers used to detect OllyDbg.exe. If I have time, I will write a OllyDbg plugin to hook and change this way. Regards ! TQN |
|
#3
|
|||
|
|||
|
The same applies to detecting API spy applications and the rest
|
|
#4
|
|||
|
|||
|
Quote:
Here you are! Platform Windows XP. Code:
// get_parent.c - coded by bilbo, 23jul04 - build with "cl -W3 get_parent.c"
// platform: Windows XP
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "advapi32")
#define DebugReadMemory 8
#define FCHK(a) if (!(a)) { printf(#a " failed\n"); exit(0); }
typedef DWORD (NTAPI *PZwSystemDebugControl)(DWORD ControlCode,
PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer,
ULONG OutputBufferLength, PULONG ReturnLength);
PZwSystemDebugControl ZwSystemDebugControl;
DWORD pSystemProc;
struct mem {
PVOID kernel_addr;
PVOID user_addr;
DWORD len;
};
void
EnablePrivilege(LPCSTR lpszName)
{
HANDLE hToken;
TOKEN_PRIVILEGES tok;
FCHK(OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken));
tok.PrivilegeCount = 1;
tok.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
FCHK(LookupPrivilegeValue(NULL, lpszName, &tok.Privileges[0].Luid));
FCHK(AdjustTokenPrivileges(hToken, FALSE, &tok, sizeof(tok), NULL, NULL));
}
/*
* read one long from kernel space
*/
DWORD
rd(DWORD addr)
{
struct mem mem;
DWORD m;
mem.kernel_addr = (PVOID)addr;
mem.user_addr = &m;
mem.len = 4;
FCHK(!ZwSystemDebugControl(DebugReadMemory, &mem, sizeof(mem), 0, 0, 0));
return m;
}
void
rdstr(DWORD addr, LPSTR buf, int buflen)
{
int i;
struct mem mem;
mem.kernel_addr = (PVOID)addr;
mem.user_addr = buf;
mem.len = 1;
for (i=0; i<buflen; i++) {
FCHK(!ZwSystemDebugControl(DebugReadMemory, &mem, sizeof(mem), 0,0,0));
if (!*buf++) break;
addr++;
// reassign structure mem
mem.kernel_addr = (PVOID)addr;
mem.user_addr = buf;
}
}
void
prepare_me(void)
{
HMODULE hModule;
// get the API address
FCHK(hModule = GetModuleHandle("ntdll.dll"));
FCHK((ZwSystemDebugControl = (PZwSystemDebugControl)
GetProcAddress(hModule, "ZwSystemDebugControl")));
EnablePrivilege(SE_DEBUG_NAME);
}
void
main(void)
{
DWORD eprocess, mypid, parentpid, tmppid;
char myname[17]={0}, parentname[17]={0};
prepare_me();
// get current EPROCESS from kernel space
eprocess = rd(0xFFDFF000+0x124); // KPRCB.KTHREAD
eprocess = rd(eprocess+0x44); // KTHREAD.KAPC_STATE.KPROCESS
// get pids from kernel space
mypid = rd(eprocess+0x84); // EPROCESS.UniqueProcessId
parentpid = rd(eprocess+0x14C); // EPROCESS.InheritedFromUniqueProcessId
// get my name from current EPROCESS
rdstr(eprocess+0x174, myname, 16); // EPROCESS.ImageFileName
// scan back process list to find parent EPROCESS
//printf("%x %d\n", eprocess, mypid);
eprocess = rd(eprocess+0x8C); // ActiveProcessLinks
while (1) {
tmppid = rd(eprocess+(0x84-0x88)); // UniqueProcessId
//printf("%x %d\n", eprocess, tmppid);
if (tmppid == parentpid) break;
eprocess = rd(eprocess+(0x8c-0x88)); // Blink
}
// get parent name from parent EPROCESS
rdstr(eprocess+(0x174-0x88), parentname, 16); // EPROCESS.ImageFileName
printf("mypid: %d(%.16s), parentpid: %d(%.16s)\n",
mypid, myname, parentpid, parentname);
}
|
|
#5
|
|||
|
|||
|
Thank for your code, bilbo !
I compiled your code, run on my Win 2000 Test Server. The call ZwSystemDebugControl failed, return STATUS_INVALID_INFO_CLASS (0xc0000003). Can you explain me the meaning of "#define DebugReadMemory 8". In the book "The Win2000 Native API Reference", we only have: typedef enum _DEBUG_CONTROL_CODE { DebugGetTraceInformation = 1, DebugSetInternalBreakpoint, DebugSetSpecialCall, DebugClearSpecialCalls, DebugQuerySpecialCalls, DebugDbgBreakPoint // maximize is 6 } DEBUG_CONTROL_CODE; If I remember correctly, Kayaker have posted a method to detect parent process and number of threads uses native API in a topic on Woodmann.net. I will search again now. Attached file is my source code and .exe of DetectOlly app, uses ToolHelp API. Regards ! TQN Last edited by TQN; 07-24-2004 at 15:55. |
|
#6
|
|||
|
|||
|
I compiled the exact code in an empty Win32 Console project running Windows XP compiled 0 errors 0 warnings. Ran without error, the results were:
mypid: 880(lsass.exe), parentpid: 824(winlogon.exe) Press any key to continue The only documentation on the structure I could find was typedef enum _DEBUG_CONTROL_CODE { DebugSysReadIoSpace = 14, DebugSysWriteIoSpace = 15, DebugSysReadMsr = 16, DebugSysWriteMsr = 17, DebugSysReadBusData = 18, DebugSysWriteBusData = 19, } DEBUG_CONTROL_CODE; Perhaps its a windows xp/2000 difference |
|
#7
|
|||
|
|||
|
Hi Viasek !
Something wrong here. I agree with you that the code will run well on WinXP. But the parent process display is not correct. If your app is a Win32 Console app, the parent process must be Cmd.exe if you run your app from console or Explorer.exe if you run your app from Explorer. We can use the tool Process Explorer of SysInternals to check this. Regards ! TQN |
![]() |
|
|