Parent Process Detection

By checking the parent process of a given process we can determine if the process is being debugged or not by expecting “explorer.exe” to be the usual parent process started by the user.
For this technique the following Windows APIs are used.

We also use a pointer to PROCESSENTRY32 structure which will store the information of each process taken from the snapshot.

typedef struct tagPROCESSENTRY32 {
  DWORD     dwSize;
  DWORD     cntUsage;
  DWORD     th32ProcessID;
  ULONG_PTR th32DefaultHeapID;
  DWORD     th32ModuleID;
  DWORD     cntThreads;
  DWORD     th32ParentProcessID;
  LONG      pcPriClassBase;
  DWORD     dwFlags;
  TCHAR     szExeFile[MAX_PATH];
} PROCESSENTRY32, *PPROCESSENTRY32;

First we get the PID of the explorer.exe process by taking a snapshot of all process and enumerating through the list. Next we again take a snapshot and locate the current Process ID (PID) of our process by enumerating through the list and then we evaluate if the Parent Process ID (PPID) of our current process is equal to “explorer.exe”.
In case if someone rename something else as “explorer.exe” we can write more checks to determine if the parent process is equal “explorer.exe”.

Here’s an example I wrote in C.

#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include "tlhelp32.h"
/* Title: Determining debugger present using the Parent Process detection.
* Author: Osanda Malith Jayathissa (@OsandaMalith)
* Website: http://osandamalith.wordpress.com
*/
int main(int argc, char *argv[]) {
int pid = 0;
int exp_pid = 0;
HANDLE handle = INVALID_HANDLE_VALUE;
PROCESSENTRY32 pe = {0};
pe.dwSize = sizeof(PROCESSENTRY32);
pid = GetCurrentProcessId();
handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (handle == INVALID_HANDLE_VALUE)
fprintf(stderr, "Cannot get a snapshot. Error: %x\n", GetLastError());
if(Process32First(handle, &pe)) {
do
if (!_tcsicmp(pe.szExeFile, _T("explorer.exe")))
exp_pid = pe.th32ProcessID;
while(Process32Next(handle, &pe));
}
if (exp_pid == –1)
fprintf(stderr, "Cannot get PID of explorer. Error: %x\n", GetLastError());
if(Process32First(handle, &pe)) {
do if (pe.th32ProcessID == pid)
MessageBoxA(NULL, pe.th32ParentProcessID == exp_pid ? "Debugger NOT Present\n" : "Debugger Present\n","Status", pe.th32ParentProcessID == exp_pid ? 0x40 : 0x30);
while(Process32Next(handle, &pe));
}
CloseHandle(handle);
return 0;
}

view raw
PPD_AntiDebug.c
hosted with ❤ by GitHub

https://github.com/OsandaMalith/Anti-Debug/blob/master/PPID/ppid.c

This is an example which I wrote in MASM.

.586
.model flat, stdcall
option casemap :none
; ¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤÷¤
; Author : Osanda Malith Jayathissa (@OsandaMalith)
; Title: Test if process is being debugged if PPID != explorer.exe
; Website: http://osandamalith.wordpress.com
; ¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤=÷=¤
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.data
exp db "explorer.exe",0
AppName db "Status",0
errSnapshot db "CreateToolhelp32Snapshot failed.",0
errProcFirst db "Process32First failed.",0
errExolorer db "Explorer.exe Not Found!"
expfound db "Explorer.exe Found",0
dbgFound db "Debugger Found!", 0
dbgNotFound db "Debugger Not Found!", 0
exp_pid dd 0
pid dd 0
.data?
hSnapshot HANDLE ?
ProcEnt PROCESSENTRY32 <?>
.code
start:
lea esi, offset ProcEnt
assume esi:ptr PROCESSENTRY32
mov [esi].dwSize, sizeof PROCESSENTRY32
invoke GetCurrentProcessId
mov pid, eax
invoke CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS, NULL
.IF (eax != INVALID_HANDLE_VALUE)
mov hSnapshot, eax
invoke Process32First, hSnapshot, ADDR ProcEnt
.IF (eax)
@@:
invoke lstrcmpi, ADDR exp , ADDR [ProcEnt.szExeFile]
.IF (!eax)
lea ebx, [esi].th32ProcessID
push [ebx]
pop exp_pid
jmp nextLoop
.ELSE
.ENDIF
invoke Process32Next, hSnapshot, ADDR ProcEnt
test eax,eax
jnz @B
.ELSE
invoke MessageBox, NULL, ADDR errProcFirst, ADDR AppName, MB_OK or MB_ICONERROR
.ENDIF
invoke CloseHandle, hSnapshot
.ELSE
invoke MessageBox, NULL, ADDR errSnapshot, ADDR AppName, MB_OK or MB_ICONERROR
.ENDIF
nextLoop:
invoke CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS, NULL
.IF (eax != INVALID_HANDLE_VALUE)
mov hSnapshot, eax
invoke Process32First, hSnapshot, ADDR ProcEnt
.IF (eax)
@@:
mov ebx, pid
.IF ( ebx == [esi].th32ProcessID )
mov ebx, [exp_pid]
.if ( ebx == [esi].th32ParentProcessID )
invoke MessageBox, NULL, ADDR dbgNotFound, ADDR AppName, MB_OK or MB_ICONINFORMATION
.else
invoke MessageBox, NULL, ADDR dbgFound, ADDR AppName, MB_OK or MB_ICONERROR
.endif
.ELSE
.ENDIF
invoke Process32Next, hSnapshot, ADDR ProcEnt
test eax,eax
jnz @B
.ELSE
invoke MessageBox, NULL, ADDR errProcFirst, ADDR AppName, MB_OK or MB_ICONERROR
.ENDIF
invoke CloseHandle, hSnapshot
.ELSE
invoke MessageBox, NULL, ADDR errSnapshot, ADDR AppName, MB_OK or MB_ICONERROR
.ENDIF
invoke ExitProcess, NULL
end start

view raw
ppid.asm
hosted with ❤ by GitHub

https://github.com/OsandaMalith/Anti-Debug/blob/master/PPID/ppid.asm

Example when we normally run the program.

View post on imgur.com

View post on imgur.com

When the PPID is not equal to explorer.exe.

View post on imgur.com

View post on imgur.com

One thought on “Parent Process Detection

Leave a Reply