【问题标题】:RunPE dump process运行PE转储进程
【发布时间】:2012-10-29 20:41:15
【问题描述】:

从runpe启动时是否可以dump自己的进程?

进程的起始地址等在哪里?

编辑:

我有这个单元可以从内存中运行一个可执行文件:

unit uExecFromMem;

interface

uses Windows;

function ExecuteFromMem(szFilePath:string; pFile:Pointer):DWORD;

type
  PImageBaseRelocation = ^TImageBaseRelocation;
  TImageBaseRelocation = packed record
     VirtualAddress: DWORD;
     SizeOfBlock: DWORD;
  end;

function NtUnmapViewOfSection(ProcessHandle:DWORD; BaseAddress:Pointer):DWORD; stdcall; external 'ntdll';

implementation

procedure PerformBaseRelocation(f_module: Pointer; INH:PImageNtHeaders; f_delta: Cardinal); stdcall;
var
  l_i: Cardinal;
  l_codebase: Pointer;
  l_relocation: PImageBaseRelocation;
  l_dest: Pointer;
  l_relInfo: ^Word;
  l_patchAddrHL: ^DWord;
  l_type, l_offset: integer;
begin
  l_codebase := f_module;
  if INH^.OptionalHeader.DataDirectory[5].Size > 0 then
  begin
    l_relocation := PImageBaseRelocation(Cardinal(l_codebase) + INH^.OptionalHeader.DataDirectory[5].VirtualAddress);
    while l_relocation.VirtualAddress > 0 do
    begin
      l_dest := Pointer((Cardinal(l_codebase) + l_relocation.VirtualAddress));
      l_relInfo := Pointer(Cardinal(l_relocation) + 8);
      for l_i := 0 to (trunc(((l_relocation.SizeOfBlock - 8) / 2)) - 1) do
      begin
        l_type := (l_relInfo^ shr 12);
        l_offset := l_relInfo^ and $FFF;
        if l_type = 3 then
        begin
          l_patchAddrHL := Pointer(Cardinal(l_dest) + Cardinal(l_offset));
          l_patchAddrHL^ := l_patchAddrHL^ + f_delta;
        end;
        inc(l_relInfo);
      end;
      l_relocation := Pointer(cardinal(l_relocation) + l_relocation.SizeOfBlock);
    end;
  end;
end;

function AlignImage(pImage:Pointer):Pointer;
var
  IDH:          PImageDosHeader;
  INH:          PImageNtHeaders;
  ISH:          PImageSectionHeader;
  i:            WORD;
begin
  IDH := pImage;
  INH := Pointer(DWORD(pImage) + IDH^._lfanew);
  GetMem(Result, INH^.OptionalHeader.SizeOfImage);
  ZeroMemory(Result, INH^.OptionalHeader.SizeOfImage);
  CopyMemory(Result, pImage, INH^.OptionalHeader.SizeOfHeaders);
  for i := 0 to INH^.FileHeader.NumberOfSections - 1 do
  begin
    ISH := Pointer(DWORD(pImage) + IDH^._lfanew + 248 + i * 40);
    CopyMemory(Pointer(DWORD(Result) + ISH^.VirtualAddress), Pointer(DWORD(pImage) + ISH^.PointerToRawData), ISH^.SizeOfRawData);
  end;
end;

function ExecuteFromMem(szFilePath:string; pFile:Pointer):DWORD;
var
  PI:           TProcessInformation;
  SI:           TStartupInfo;
  CT:           TContext;
  IDH:          PImageDosHeader;
  INH:          PImageNtHeaders;
  dwImageBase:  DWORD;
  pModule:      Pointer;
  dwNull:       DWORD;
begin
  Result := 0;
  IDH := pFile;
  if IDH^.e_magic = IMAGE_DOS_SIGNATURE then
  begin
    INH := Pointer(DWORD(pFile) + IDH^._lfanew);
    if INH^.Signature = IMAGE_NT_SIGNATURE then
    begin
      FillChar(SI, SizeOf(TStartupInfo), #0);
      FillChar(PI, SizeOf(TProcessInformation), #0);
      SI.cb := SizeOf(TStartupInfo);
      if CreateProcess(nil, PChar(szFilePath), nil, nil, FALSE, CREATE_SUSPENDED, nil, nil, SI, PI) then
      begin
        CT.ContextFlags := CONTEXT_FULL;
        if GetThreadContext(PI.hThread, CT) then
        begin
          ReadProcessMemory(PI.hProcess, Pointer(CT.Ebx + 8), @dwImageBase, 4, dwNull);
          if dwImageBase = INH^.OptionalHeader.ImageBase then
          begin
            if NtUnmapViewOfSection(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase)) = 0 then
              pModule := VirtualAllocEx(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE)
            else
              pModule := VirtualAllocEx(PI.hProcess, nil, INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
          end
          else
            pModule := VirtualAllocEx(PI.hProcess, Pointer(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
          if pModule <> nil then
          begin
            pFile := AlignImage(pFile);
            if DWORD(pModule) <> INH^.OptionalHeader.ImageBase then
            begin
              PerformBaseRelocation(pFile, INH, (DWORD(pModule) - INH^.OptionalHeader.ImageBase));
              INH^.OptionalHeader.ImageBase := DWORD(pModule);
              CopyMemory(Pointer(DWORD(pFile) + IDH^._lfanew), INH, 248);
            end;
            WriteProcessMemory(PI.hProcess, pModule, pFile, INH.OptionalHeader.SizeOfImage, dwNull);
            WriteProcessMemory(PI.hProcess, Pointer(CT.Ebx + 8), @pModule, 4, dwNull);
            CT.Eax := DWORD(pModule) + INH^.OptionalHeader.AddressOfEntryPoint;
            SetThreadContext(PI.hThread, CT);
            ResumeThread(PI.hThread);
            FreeMem(pFile, INH^.OptionalHeader.SizeOfImage);
            Result := PI.hThread;
          end;
        end;
      end;
    end;
  end;
end;

end.

然后我有 Application1 和 Application2。

Application1 将 Application2(完整的可执行文件)存储在内存中。 然后Application1像这样从内存中启动Application2:

ExecuteFromMem(paramstr(0), @Application2InMemory) // uses Application1 as Host

现在 Application2 已加载到内存中并已启动! Application2 如何将它的数据(Application2.exe)返回到磁盘(或返回到 var)?

【问题讨论】:

  • “转储自己的进程”是什么意思?进程的“起始地址”是什么意思? “从runpe开始时”是什么意思? RunPE 通过启动一个可疑的进程来工作。暂停时很难做任何事情。
  • 我的意思是如何获取加载到应用程序中的 .exe 文件?完整的文件在内存中
  • 我们能否提供更多详细信息。我不知道你在做什么?
  • 对不起。我编辑了我的问题。希望现在清楚了。
  • 哦,我明白了。这里根本不需要内存加载器!下载到临时文件。然后启动一个新进程来应用更新。等到第一个程序卸载。然后将临时文件复制到可执行位置,覆盖原始 exe 文件。然后启动新的可执行文件。这就是它的意思。值得一提的是,内存加载程序在 Windows 上完全不受支持,并且几乎总是被恶意软件使用。 AV 软件知道这一点。

标签: delphi winapi process dump


【解决方案1】:

您正在从 Application1 再次启动 Application1 但已暂停。在恢复 Application1 之前,您正在从磁盘加载 Application2 并将其复制到 Application1(的第二个实例)的内存中的地址。附加代码负责复制 PE 头、DOS 头、NT 头、可选头等,并在需要时调整重定位。

实际上你 Application2 在内存中,它只是在任务管理器中被称为 Application1。因此,如果您将 Application2 从 Application2 转储到磁盘,您将得到 Application2,试试吧!

【讨论】:

  • "你正在从 Application1 再次启动 Application1" - 我实际上是从 Application1 启动 Application2。
  • 进程在内存中。你知道基址。在 Delphi 代码中是 HINSTANCEINH^.OptionalHeader.SizeOfImage 给你尺寸。将其转储到磁盘,您就完成了。对于更新者来说,这仍然是一个非常糟糕的主意!
  • @BenjaminWeiss:不,ExecuteFromMem 的第一个参数是 ParamStr(0),它是“self”(Application1),这是 CreateProcess 调用中启动的应用程序...
  • @BenjaminWeiss 你有什么理由不接受这个答案吗?
猜你喜欢
  • 2015-09-04
  • 1970-01-01
  • 2012-10-01
  • 1970-01-01
  • 2018-04-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多