Exetools

Exetools (https://forum.exetools.com/index.php)
-   General Discussion (https://forum.exetools.com/forumdisplay.php?f=2)
-   -   parent? (https://forum.exetools.com/showthread.php?t=4620)

Line79 07-19-2004 21:25

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...

TQN 07-20-2004 19:29

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

redbull 07-20-2004 23:18

The same applies to detecting API spy applications and the rest

bilbo 07-23-2004 22:45

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

TQN 07-24-2004 15:42

1 Attachment(s)
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

Viasek 07-24-2004 16:23

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

TQN 07-24-2004 17:44

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

Viasek 07-25-2004 03:57

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.

bilbo 07-26-2004 16:14

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!

JMI 07-26-2004 16:35

Ohh! :eek: The Hobbits is reaching the physic hotline and sees into the future. Trouble he is and the stinking Hobbits has the precious. :eek: But the Hobbits has good information and me wants more, more, more.

Regards,


All times are GMT +8. The time now is 15:28.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2026, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX