查看: 1699|回复: 0
收起左侧

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

[复制链接]
yxwxqflbyg
发表于 2007-9-17 13:43:26 | 显示全部楼层 |阅读模式
花了一个下午翻了MSDN,写了这个例子,为了安全,我用Delphi建了个什么也没有作的程序prjzzhost.exe,将它用作被注入的宿主进程.
写了一个TestDll.Dll,里面只有一个Log函数,用来在文件Test.Txt中输出信息.最重要的一个程序project1.exe是用来注入的.
测试环境:

windowsserver 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被载入后的善后处理,请不要使用系统进程进行测试,以免发生意外
您需要登录后才可以回帖 登录 | 快速注册

本版积分规则

手机版|杀毒软件|软件论坛| 卡饭论坛

Copyright © KaFan  KaFan.cn All Rights Reserved.

Powered by Discuz! X3.4( 沪ICP备2020031077号-2 ) GMT+8, 2024-12-26 09:46 , Processed in 0.121484 second(s), 22 queries .

卡饭网所发布的一切软件、样本、工具、文章等仅限用于学习和研究,不得将上述内容用于商业或者其他非法用途,否则产生的一切后果自负,本站信息来自网络,版权争议问题与本站无关,您必须在下载后的24小时之内从您的电脑中彻底删除上述信息,如有问题请通过邮件与我们联系。

快速回复 客服 返回顶部 返回列表