WEB开发网
开发学院软件开发Delphi 在Delphi中利用CreateRemoteThread远程注入例子 阅读

在Delphi中利用CreateRemoteThread远程注入例子

 2006-02-04 14:00:28 来源:WEB开发网   
核心提示:花了一个下午翻了MSDN,写了这个例子,为了安全,我用Delphi建了个什么也没有作的程序PRjzzhost.exe,将它用作被注入的宿主进程.写了一个TestDll.Dll,里面只有一个Log函数,用来在文件Test.Txt中输出信息.最重要的一个程序project1.exe是用来注入的.测试环境: windows

花了一个下午翻了MSDN,写了这个例子,为了安全,我用Delphi建了个什么也没有作的程序PRjzzhost.exe,将它用作被注入的宿主进程.
写了一个TestDll.Dll,里面只有一个Log函数,用来在文件Test.Txt中输出信息.最重要的一个程序project1.exe是用来注入的.
测试环境: windows server 2003 + delphi 7.0
程序很简单,高手就不用看了.废话不说了,看代码吧!

测试用的TestDll.Dll源代码(它将被注入到prjzzhost.exe中去):

程序代码
library TestDll;

uses
 SysUtils,
 System,
 windows,
 Classes;

 procedure Log( s : PChar);stdcall;
 var
  F : TextFile;
 begin
  assignfile(f,'Test.txt');
  if fileexists('Test.txt') then append(f)
  else rewrite(f);
  writeln(f,s);
  closefile(f);
 end;

 procedure DllEntryPoint(dwReason:DWord);
 begin
   case dwReason of
   DLL_PROCESS_ATTACH:
    Log('dll process Attach');
   DLL_PROCESS_DETACH:
   Log('dll process Detach');
   DLL_THREAD_ATTACH:
    Log('dll thread Attach');
   DLL_THREAD_DETACH:
    Log('dll thread Detach');
   end;

 end;

 exports
  Log;

begin
 DllProc := @DllEntryPoint;
 DllEntryPoint(DLL_PROCESS_ATTACH);
end.




被注入的宿主进程prjzzhost.exe(它什么也没有作,好无辜哦:),这里就不给出代码了,因为太简单了,哈哈.


最后,最重要的来了:
project1.exe的源代码:

程序代码
unit Unit1;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls,tlhelp32;

type

 TLog = procedure(s : PChar);stdcall;
 TServiceMain = procedure(argc : Integer; VAR argv : pchar);stdcall;

 EDLLLoadError = class(Exception);

 TForm1 = class(TForm)
  Button3: TButton;
  procedure Button3Click(Sender: TObject);
 private
  { Private declarations }
 public
  { Public declarations }
 end;


var
 Form1: TForm1;

implementation

{$R *.dfm}

{ 列举进程 }
procedure GetMyProcessID(const AFilename: string; const PathMatch: Boolean; var ProcessID: DWORD);
var
 lppe: TProcessEntry32;
 SsHandle: Thandle;
 FoundAProc, FoundOK: boolean;
begin
 ProcessID :=0;
 { 创建系统快照 }
 SsHandle := CreateToolHelp32SnapShot(TH32CS_SnapProcess, 0);

 { 取得快照中的第一个进程 }
 { 一定要设置结构的大小,否则将返回False }
 lppe.dwSize := sizeof(TProcessEntry32);
 FoundAProc := Process32First(Sshandle, lppe);
 while FoundAProc do
 begin
  { 进行匹配 }
  if PathMatch then
   FoundOK := AnsiStricomp(lppe.szExefile, PChar(AFilename)) = 0
  else
   FoundOK := AnsiStricomp(PChar(ExtractFilename(lppe.szExefile)), PChar(ExtractFilename(AFilename))) = 0;
  if FoundOK then
  begin
   ProcessID := lppe.th32ProcessID;
   break;
  end;
  { 未找到,继续下一个进程 }
  FoundAProc := Process32Next(SsHandle, lppe);
 end;
 CloseHandle(SsHandle);
end;


{ 设置权限 }
function EnabledDebugPrivilege(const Enabled : Boolean) : Boolean;
var
 hTk : THandle; { 打开令牌句柄 }
 rtnTemp : Dword; { 调整权限时返回的值 }
 TokenPri : TOKEN_PRIVILEGES;
const
 SE_DEBUG = 'SeDebugPrivilege'; { 查询值 }
begin
 Result := False;
 { 获取进程令牌句柄,设置权限 }
 if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,hTk)) then
 begin
  TokenPri.PrivilegeCount := 1;
  { 获取Luid值 }
  LookupPrivilegeValue(nil,SE_DEBUG,TokenPri.Privileges[0].Luid);

  if Enabled then
   TokenPri.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
  else
   TokenPri.Privileges[0].Attributes := 0;

  rtnTemp := 0;
  { 设置新的权限 }
  AdjustTokenPrivileges(hTk,False,TokenPri,sizeof(TokenPri),nil,rtnTemp);

  Result := GetLastError = ERROR_SUCCESS;
  CloseHandle(hTk);

 end;
end;


{ 调试函数 }
procedure OutPutText(var CH:PChar);
var
 FileHandle: TextFile;
Begin
 AssignFile(FileHandle,'zztest.txt');
 Append(FileHandle);
 Writeln(FileHandle,CH);
 Flush(FileHandle);
 CloseFile(FileHandle);
END;

{ 注入远程进程 }
function InjectTo(const Host, Guest: string; const PID: DWORD = 0): DWORD;
var
 { 被注入的进程句柄,进程ID}
 hRemoteProcess: THandle;
 dwRemoteProcessId: DWORD;

 { 写入远程进程的内容大小 }
 memSize: DWORD;

 { 写入到远程进程后的地址 }
 pszLibFileRemote: Pointer;

 iReturnCode: Boolean;
 TempVar: DWORD;

 { 指向函数LoadLibraryW的地址 }
 pfnStartAddr: TFNThreadStartRoutine;

 { dll全路径,需要写到远程进程的内存中去 }
 pszLibAFilename: PwideChar;
begin
 Result := 0;
 { 设置权限 }
 EnabledDebugPrivilege(True);

 { 为注入的dll文件路径分配内存大小,由于为WideChar,故要乘2 }
 Getmem(pszLibAFilename, Length(Guest) * 2 + 1);
 StringToWideChar(Guest, pszLibAFilename, Length(Guest) * 2 + 1);

 { 获取进程ID }
 if PID > 0 then
   dwRemoteProcessID := PID
 else
   GetMyProcessID(Host, False, dwRemoteProcessID);

 { 取得远程进程句柄,具有写入权限}
 hRemoteProcess := OpenProcess(PROCESS_CREATE_THREAD + {允许远程创建线程}
   PROCESS_VM_OperaTION + {允许远程VM操作}
   PROCESS_VM_WRITE, {允许远程VM写}
   FALSE, dwRemoteProcessId);

 { 用函数VirtualAllocex在远程进程分配空间,并用WriteProcessMemory中写入dll路径 }
 memSize := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR);
 pszLibFileRemote := PWIDESTRING(VirtualAllocEx(hRemoteProcess, nil, memSize, MEM_COMMIT, PAGE_READWRITE));
 TempVar := 0;
 iReturnCode := WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, memSize, TempVar);

 if iReturnCode then
 begin
  pfnStartAddr := GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW');
  TempVar := 0;
  { 在远程进程中启动dll }
  Result := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, TempVar);
 end;

 { 释放内存空间 }
 Freemem(pszLibAFilename);
end;

 { 测试 }
procedure TForm1.Button3Click(Sender: TObject);
begin

 InjectTo('prjzzhost.exe', extractfilepath(paramstr(0))+'TestDll.dll');
end;

end.




代码中并没有考虑dll被载入后的善后处理,请不要使用系统进程进行测试,以免发生意外.

Tags:Delphi 利用 CreateRemoteThread

编辑录入:爽爽 [复制链接] [打 印]
赞助商链接