我们知道,可以用CreateProcess执行一个外部程序,或者更简单的调用shellapi执行。我的要求是,知道一个外部程序,可能是(.com,.exe,.pif,.sys,.vxd)等,怎么让这个文件入驻内存,并且将ip指向代码开始段,开始执行这个代码,然后使这个代码执行时空集成为一个进程。然后返回主程序,那个被执行的代码程序和主程序完全没有关系。怎么办?
是不是,就是自己手工实现CreateProcessAPI的功能呀?

解决方案 »

  1.   

    我觉得不是CreateProcessAPI的功能,是程序加载器。
    这个你找个调式器应该就可以找到类似的代码了。
    一般调试器都有这功能的ollydbg、windbg之类的。
      

  2.   

    接分在其它进程中建立线程,看下面的例子,是从别人那粘贴过来的:
    unit unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls;const
      WM_HOOKED = WM_USER + 3221;  {Hook安装成功的消息}type
      TThreadProVarList = record  {变量列表}
        SendMessage: DWORD;
        ExitProcess: DWORD;
        ExitThread: DWORD;        {上面用来保存API真实地址}
        WndHandle: DWORD;
      end;  TForm1 = class(TForm)
        Button1: TButton;
        Button2: TButton;
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
      private
        {在目标进程中申请的内存地址}
        ThreadAdd: Pointer;
        PID, PHandle: DWORD;   {目标窗口进程ID,句柄和线程ID}
        ThreadHandle, ThreadID: Thandle;  {新的远程线程的ID和句柄}
        procedure WMHOOKED(var Msg: TMessage);message WM_HOOKED;
      public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure ThreadPro;
    var
      VarList: TThreadProVarList;
    begin
      asm
        mov eax, $FFFFFFFF   {到$FFFFFFFF的偏移是7}
        mov VarList.SendMessage, eax
        mov eax, $FFFFFFFF   {这个$FFFFFFFF是在上一个偏移位置加8}
        mov VarList.WndHandle, eax
        mov eax, $FFFFFFFF
        mov VarList.ExitProcess, eax
        mov eax, $FFFFFFFF
        mov VarList.ExitThread, eax
        push 0
        push 0
        push 4245            {4245就是自定义的WM_HOOKED}
        push VarList.WndHandle
        call VarList.SendMessage
        push 0
        call VarList.ExitThread
      end;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      {要注入线程的窗口句柄和临时存放的句柄}
      WndHandle, TmpHandle: THandle;
      DllModule, SendPro, WriteCount: DWORD;
      ExitPro, ExitTPro: DWORD;
    begin
      {先查找到要注入远程线程的窗口}
      WndHandle := FindWindow(nil, '记事本');
      {得到其进程和线程ID}
      GetWindowThreadProcessId(WndHandle, PID);
      {以完全访问权限打开进程句柄}
      PHandle := OpenProcess(PROCESS_ALL_ACCESS, False, PID);
      {在目标进程中分配内存}
      ThreadAdd := VirtualAllocEx(PHandle, nil, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
      {把自定义函数写入到目标进程中}
      WriteProcessMemory(PHandle, ThreadAdd, @ThreadPro, 4096, WriteCount);
      {以挂起方式建立远端线程,以便修改}
      ThreadHandle := CreateRemoteThread(PHandle, nil, 0, ThreadAdd, nil, CREATE_SUSPENDED, ThreadID);
      {得到API真实的地址}
      DllModule := LoadLibrary('User32.dll');
      SendPro := DWORD(GetProcAddress(DllModule, 'SendMessageW'));
      DllModule := LoadLibrary('Kernel32.dll');
      ExitPro := DWORD(GetProcAddress(DllModule, 'ExitProcess'));
      ExitTPro := DWORD(GetProcAddress(DllModule, 'ExitThread'));
      {把API真实地址和数据写入到在目标进程中的函数中}
        TmpHandle := Self.Handle;
        WriteProcessMemory(PHandle, Pointer(LongInt(ThreadAdd)+7), @SendPro, SizeOf(DWORD), WriteCount);
        WriteProcessMemory(PHandle, Pointer(LongInt(ThreadAdd)+15), @TmpHandle, SizeOf(DWORD), WriteCount);
        WriteProcessMemory(PHandle, Pointer(LongInt(ThreadAdd)+23), @ExitPro, SizeOf(DWORD), WriteCount);
        WriteProcessMemory(PHandle, Pointer(LongInt(ThreadAdd)+31), @ExitTPro, SizeOf(DWORD), WriteCount);
      {开始运行远端线程}
      ResumeThread(ThreadHandle);
      CloseHandle(ThreadHandle);
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      {释放在目标进程中分配的内存}
      VirtualFreeEx(PHandle, ThreadAdd, 4096, MEM_DECOMMIT);
      {关闭不用的句柄}
      CloseHandle(PHandle);
    end;procedure TForm1.WMHOOKED(var Msg: TMessage);
    begin
      MessageBox(self.Handle, '建立远端线程成功', '!!!', MB_OK);
    end;