• (转)远程线程DEMO


    AttachToProcess('Explorer.Exe', 'MyDll.Dll' );

    //查找指定的进程,然后返回进程ID
    procedure FindAProcess(const AFilename:string; const PathMatch:Boolean; var ProcessID: DWORD);
    //AFilename为要查找(进程ID)的文件名(可以包行路径)
    //PathMatch为查找的时候是否匹配路径
    var
      lppe:TProcessEntry32;
      SsHandle:Thandle;
      FoundAProc, FoundOK:boolean;
    begin
      SsHandle   := CreateToolHelp32SnapShot(TH32CS_SNAPALL,0);
      FoundAProc := Process32First(Sshandle,lppe);
      //枚举Process,然后判断是否是所要查找的Process
      while FoundAProc do
      begin
        //根据PathMatch的值来决定匹配的方式
        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;
    //  if not FoundAProc then showmessage(SysErrorMessage(GetLastError));
      CloseHandle(SsHandle);
    end;

    //激活或者停止指定的权限
    function EnabledDebugPrivilege(const bEnabled: Boolean):Boolean;
    var
      hToken: THandle;
      tp: TOKEN_PRIVILEGES;
      a: DWORD;
    const
      SE_DEBUG_NAME = 'SeDebugPrivilege';
    begin
      Result:=False;
      //打开当前Process的令牌(我一直叫Token为令牌)
      if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, hToken)) then
      begin
        //调整令牌的权限,也就是加上或者取消调试权限(SE_DEBUG_NAME)
        tp.PrivilegeCount :=1;
        LookupPrivilegeValue(nil,SE_DEBUG_NAME ,tp.Privileges[0].Luid);
        if bEnabled then
          tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
        else
          tp.Privileges[0].Attributes := 0;
        a:=0;
        AdjustTokenPrivileges(hToken,False,tp,SizeOf(tp),nil,a);
        Result:= GetLastError = ERROR_SUCCESS;
        CloseHandle(hToken);
      end;
    end;

    //在指定的进程中插入一个DLL文件
    function AttachToProcess(const HostFile, GuestFile : string;const PID:DWORD=0):DWORD;
    //HostFile为要绑定的宿主文件(Exe文件),GuestFile为要嵌入的客户文件(Dll文件)
    //如AttachToProcess('D:\TESTDLL.DLL','Notepad.exe') ;
    var
      hRemoteProcess: THandle;
      dwRemoteProcessId:DWORD;
      cb:DWORD;
      pszLibFileRemote: Pointer;
      iReturnCode:Boolean;
      TempVar:DWORD;
      pfnStartAddr:TFNThreadStartRoutine;
      pszLibAFilename: PwideChar;
    begin
      Result:=0;
      //激活当前Process的SE_DEBUG_NAME权限,如果不激活的话,一些服务进程将无法
      //打开
      EnabledDebugPrivilege(True);

      //给pszLibAFilename分配内存,为什么是Length(GuestFile)*2+1呢,因为咱们
      //等一会儿,要调用函数LoadLibraryW,而LoadLibraryW函数需要的参数是WideChar型
      Getmem(pszLibAFilename,Length(GuestFile)*2+1);
      StringToWideChar(GuestFile,pszLibAFilename,Length(GuestFile)*2+1);

      if PID>0 then dwRemoteProcessID:=PID else FindAProcess(HostFile,False,dwRemoteProcessID);
      //由于我们后面需要写入远程进程的内存地址空间并建立远程线程,所以需要申请
      //足够的权限(PROCESS_CREATE_THREAD、VM_OPERATION、VM_WRITE)。
      //然后,我们可以建立LoadLibraryW函数这个线程来启动我们的DLL,LoadLibraryW
      //函数是在kernel32.dll中定义的,用来加载DLL文件,它只有一个参数,就是DLL
      //文件的绝对路径名pszLibAFilename,(也就是DLL的全路径文件名),但是由于
      //DLL是在远程进程内调用的,所以我们首先还需要将这个文件名复制到远程地址空
      //间:(否则远程线程是无法读到这个参数的)
      hRemoteProcess := OpenProcess(PROCESS_CREATE_THREAD + //允许远程创建线程
                                    PROCESS_VM_OPERATION+ //允许远程VM操作
                                    PROCESS_VM_WRITE,//允许远程VM写
                                    FALSE, dwRemoteProcessId);

      //计算DLL路径名需要的内存空间
      cb := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR);
      //使用VirtualAllocEx函数在远程进程的内存地址空间分配DLL文件名缓冲区
      pszLibFileRemote := PWIDESTRING( VirtualAllocEx( hRemoteProcess, nil, cb, MEM_COMMIT, PAGE_READWRITE));
      //使用WriteProcessMemory函数将DLL的路径名复制到远程进程的内存空间
      TempVar:=0;
      iReturnCode := WriteProcessMemory(hRemoteProcess,pszLibFileRemote, pszLibAFilename, cb, TempVar);
      if iReturnCode then
      begin
        //计算LoadLibraryW的入口地址
        pfnStartAddr := GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW');
        //OK,万事俱备,我们通过建立远程线程时的地址pfnStartAddr(实际上就是LoadLibraryW
        //的入口地址)和传递的参数  pszLibFileRemote(实际上是我们复制过去的DLL的全路
        //径文件名)在远程进程内启动我们的DLL:
        //启动远程线程LoadLibraryW,通过远程线程调用用户的DLL文件
        TempVar:=0;
        Result := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, TempVar);
      end;
      Freemem(pszLibAFilename);
    end;
  • 相关阅读:
    【BestCoder #48】
    【一场模拟赛?】
    【普通の随笔】6.30
    【BestCoder #45】
    【BestCoder #44】
    【普通の惨败】GDOI2015卖萌记
    我的新博客
    【BZOJ 2964】Boss单挑战
    【NOI 2015】软件包管理器
    【NOI 2015】程序自动分析
  • 原文地址:https://www.cnblogs.com/chengxin1982/p/1626179.html
Copyright © 2020-2023  润新知