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

2016-02-19 19:32 79 1 收藏

下面图老师小编要跟大家分享在Delphi中利用CreateRemoteThread远程注入例子,简单的过程中其实暗藏玄机,还是要细心学习,喜欢还请记得收藏哦!

【 tulaoshi.com - 编程语言 】

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

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/) 程序代码
  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被载入后的善后处理,请不要使用系统进程进行测试,以免发生意外.
  

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

来源:http://www.tulaoshi.com/n/20160219/1621245.html

延伸阅读
     一直都听说delphi中画布使用简单方便。现在我就利用画布实现一个简单的树机构的图形表示。系统支持节点选择、移动、保存树、打开树等。为了实现的方便用到了递归与指针,虽然效率有点问题但是在快速解决问题还是蛮好的。   程序写的比较乱,欢迎交流:sss@pacia.com.cn   源代码如...
标签: Delphi
第一步:根据需要,用FrontPage或者Dreamweaver做一个界面,界面加上图片,还可加上漂亮的动态Flash。Web界面与程序事件联系在一起的地方就是“超链接”,我们以一个简单的播放器程序为例。 比如:要做一个播放器,有“播放”按钮和“停止”按钮,分别设置“播放”按钮的链接为“Play_”;“停止”按钮的超链接为“Stop_”。并保存这个网...
标签: MySQL mysql数据库
不管是在编程时或者用软件连接MySql数据库都需要一个数据库用户名,在非常多的情况下我们还有必要通过超级用户帐号登陆或连接数据库,但是在安装MySql后只有一个超级管理权限的用户ROOT,而且ROOT限制只能在数据库本机上使用,这时候再用ROOT帐号就比较麻烦了。 幸运的是我们可以添加一个具有超级管理权限和能远程访问MySql数据库的超级用户,...
  keyword:  ActiveX, TGUID, CoCreateGUID, GUIDToString //---Test Program By Conan 2005/04/14---// unit Unit1; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,   Dialogs,   ActiveX, StdCtrls; type   T...
作者: 网易 学院 程序系教授管宁 以下两个例子要非常注意,函数传递的不是数组中数组元素的真实值而是数组在内存中的实际地址! /*程序作者:管宁 站点:www.cndev-lab.com 所有稿件均有版权,如要转载,请务必著名出处和作者*/ #include stdio.h void main(void) { void reversal(); static int a[10] = {0,1,2,3,4,5,6,7,8,9};...

经验教程

641

收藏

53
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部