Exetools  

Go Back   Exetools > General > General Discussion

Notices

Reply
 
Thread Tools Display Modes
  #1  
Old 07-19-2004, 21:25
Line79
 
Posts: n/a
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...
Reply With Quote
  #2  
Old 07-20-2004, 19:29
TQN TQN is offline
VIP
 
Join Date: Apr 2003
Location: Vietnam
Posts: 358
Rept. Given: 143
Rept. Rcvd 24 Times in 13 Posts
Thanks Given: 196
Thanks Rcvd at 168 Times in 51 Posts
TQN Reputation: 24
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
Reply With Quote
  #3  
Old 07-20-2004, 23:18
redbull redbull is offline
Friend
 
Join Date: Mar 2004
Posts: 160
Rept. Given: 17
Rept. Rcvd 5 Times in 4 Posts
Thanks Given: 3
Thanks Rcvd at 6 Times in 6 Posts
redbull Reputation: 5
The same applies to detecting API spy applications and the rest
Reply With Quote
  #4  
Old 07-23-2004, 22:45
bilbo bilbo is offline
Friend
 
Join Date: Jul 2004
Posts: 103
Rept. Given: 36
Rept. Rcvd 15 Times in 12 Posts
Thanks Given: 15
Thanks Rcvd at 17 Times in 11 Posts
bilbo Reputation: 15
Quote:
Are you aware of a way to do that without any api ?
Without API and from RING 3?
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);
}
Have fun! bilbo
Reply With Quote
  #5  
Old 07-24-2004, 15:42
TQN TQN is offline
VIP
 
Join Date: Apr 2003
Location: Vietnam
Posts: 358
Rept. Given: 143
Rept. Rcvd 24 Times in 13 Posts
Thanks Given: 196
Thanks Rcvd at 168 Times in 51 Posts
TQN Reputation: 24
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
Attached Files
File Type: rar DetectOlly.rar (2.5 KB, 9 views)

Last edited by TQN; 07-24-2004 at 15:55.
Reply With Quote
  #6  
Old 07-24-2004, 16:23
Viasek
 
Posts: n/a
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
Reply With Quote
  #7  
Old 07-24-2004, 17:44
TQN TQN is offline
VIP
 
Join Date: Apr 2003
Location: Vietnam
Posts: 358
Rept. Given: 143
Rept. Rcvd 24 Times in 13 Posts
Thanks Given: 196
Thanks Rcvd at 168 Times in 51 Posts
TQN Reputation: 24
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
Reply With Quote
  #8  
Old 07-25-2004, 03:57
Viasek
 
Posts: n/a
From the command prompt:

Code:
 
C:\project\ParentID\Debug>parentid.exe
mypid: 880(lsass.exe), parentpid: 824(winlogon.exe)

C:\project\ParentID\Debug>parentid.exe
mypid: 1492(ParentID.exe), parentpid: 284(cmd.exe)

C:\project\ParentID\Debug>parentid.exe
mypid: 716(ParentID.exe), parentpid: 284(cmd.exe)

C:\project\ParentID\Debug>parentid.exe
mypid: 384(ParentID.exe), parentpid: 284(cmd.exe)

--Reopened Cmd prompt--

C:\project\ParentID\Debug>parentid
mypid: 800(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 620(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 948(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1116(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1152(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1132(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1120(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 632(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 944(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1272(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 224(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1188(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1308(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1276(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1304(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 276(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1424(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1160(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1452(ParentID.exe), parentpid: 696(cmd.exe)

C:project\ParentID\Debug>parentid
mypid: 928(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1220(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 220(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1952(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 520(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 516(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1492(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 740(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 780(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 572(ParentID.exe), parentpid: 696(cmd.exe)

C:\project\ParentID\Debug>parentid
mypid: 1472(ParentID.exe), parentpid: 696(cmd.exe)
I went into VS and ran it a few times (start w/ debugging) from there:

Code:
mypid: 1416(ParentID.exe), parentpid: 1360(vcspawn.exe)
Press any key to continue

mypid: 624(devenv.exe), parentpid: 1748(explorer.exe)
Press any key to continue

mypid: 440(ParentID.exe), parentpid: 196(vcspawn.exe)
Press any key to continue

mypid: 624(devenv.exe), parentpid: 1748(explorer.exe)
Press any key to continue

mypid: 624(devenv.exe), parentpid: 1748(explorer.exe)
Press any key to continue

mypid: 1276(ParentID.exe), parentpid: 1308(vcspawn.exe)
Press any key to continue

mypid: 1188(ParentID.exe), parentpid: 224(vcspawn.exe)
Press any key to continue
You are right something is wrong, but somethings working correctly some of the time - its not *always* incorrect, infact its more often correct it seems. It does look like the names match the process ID's correctly.
Reply With Quote
  #9  
Old 07-26-2004, 16:14
bilbo bilbo is offline
Friend
 
Join Date: Jul 2004
Posts: 103
Rept. Given: 36
Rept. Rcvd 15 Times in 12 Posts
Thanks Given: 15
Thanks Rcvd at 17 Times in 11 Posts
bilbo Reputation: 15
Viasek is right: the argument DebugReadMemory (8) has been added in Windows XP platform and it is not documented. Also arguments 14-19, pointed out by Viasek, have been added in Windows XP.

If you are interested in Win2k platform, you need another way to read kernel space (driver or callgate).

The "something wrong" is very interesting: I strangely cannot recreate it on my platform (Windows XP SP1), neither from Win32 console nor from Visual Studio. It is related to the way the current process id is inferred, not to the way used to retrieve the process name or the process parent!
It looks like, at the moment in which the current process structure is read from kernel, the scheduler has selected another process... To avoid this, you can simply retrieve the current process id from userland:

Code:
     mypid = 0x7FFDE020;  // &(TEB.CLIENT_ID.UniqueProcess)
     mypid = *(LPDWORD)mypid;
Regards, bilbo

P.S. This is my last post in this thread. I'm afraid JMI call me an FTP chaser!
Reply With Quote
  #10  
Old 07-26-2004, 16:35
JMI JMI is offline
Leader
 
Join Date: Jan 2002
Posts: 1,627
Rept. Given: 5
Rept. Rcvd 199 Times in 99 Posts
Thanks Given: 0
Thanks Rcvd at 98 Times in 96 Posts
JMI Reputation: 100-199 JMI Reputation: 100-199
Ohh! The Hobbits is reaching the physic hotline and sees into the future. Trouble he is and the stinking Hobbits has the precious. But the Hobbits has good information and me wants more, more, more.

Regards,
__________________
JMI
Reply With Quote
Reply


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



All times are GMT +8. The time now is 17:00.


Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX, chessgod101
( Since 1998 )