程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 在Delphi中利用CreateRemoteThread遠程注入例子

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

編輯:Delphi
 花了一個下午翻了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被載入後的善後處理,請不要使用系統進程進行測試,以免發生意外.
  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved