黑客风云——风云网络
设为首页 加入收藏 我要投稿 网站地图

您现在的位置: 黑客风云 >> 黑客文章 >> 黑客进阶 >> 黑客编程 >> 正文
·完美空间提供500M免费AS04-10·企业安全之YY内网准入以04-09
·企业安全之意识与策略04-09·剑走偏锋:IIS漏洞利用04-09
·我来免费网提供100M免费04-09·1122mb.com提供20G超大免04-08
·映像劫持与反劫持技术04-07·让所有"暴力删除工具"无04-07
·入侵88red系统的详细过程04-07·Sql Injection脚本注入终04-07
·vbs+delphi 反弹后门生成04-07·飞讯网提供100MB免费PHP04-07
·突破SQL注入攻击时输入框04-04·结合内核和病毒技术的最04-04
·Real Player rmoc3260.d04-04·亿万网络今月最后为您提04-04
·php+mysql 5 sql inject04-03·Real Player rmoc3260.d04-03
·oblog文件下载漏洞04-03·免费啦提供1G-2G免费全能04-03
·完全解析网页后门和挂马04-02·一句话开3389(只测试过04-02
·萧萧免费空间网提供100M04-02·谷道免费空间网提供1G免04-01
·从本地入手解决双线路由03-31·sablog 1.6 多个跨站漏洞03-31
·富文本编辑器的跨站脚本03-31·Cookie注入是怎样产生的03-31
[推荐]从内存中加载并启动一个exe(Delphi源码)
      ★★★★★

从内存中加载并启动一个exe(Delphi源码)

文章整理发布:黑客风云 文章来源:www.05112.com 更新时间:2007-6-5 11:11:40


{ 是否包含可重定向列表 }
function HasRelocationTable(peH: PImageNtHeaders): Boolean;
begin
  result := (peH.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress <> 0)
      and (peH.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size <> 0);
end;

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

{ 重定向PE用到的地址 }
procedure DoRelocation(peH: PImageNtHeaders; OldBase, NewBase: Pointer);
var
  Delta: Cardinal;
  p: PImageBaseRelocation;
  pw: PWord;
  i: Integer;
begin
  Delta := Cardinal(NewBase) - peH.OptionalHeader.ImageBase;
  p := pointer(cardinal(OldBase) + peH.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
  while (p.VirtualAddress + p.SizeOfBlock <> 0) do
  begin
    pw := pointer(Integer(p) + Sizeof(p^));
    for i := 1 to (p.SizeOfBlock - Sizeof(p^)) div 2 do
    begin
      if pw^ and $F000 = $3000 then
        Inc(PCardinal(Cardinal(OldBase) + p.VirtualAddress + (pw^ and $0FFF))^, Delta);
      inc(pw);
    end;
    p := Pointer(pw);
  end;
end;

type
  TZwUnmapViewOfSection = function (Handle, BaseAdr: Cardinal): Cardinal; stdcall;

{ 卸载原外壳占用内存 }
function UnloadShell(ProcHnd, BaseAddr: Cardinal): Boolean;
var
  M: HModule;
  ZwUnmapViewOfSection: TZwUnmapViewOfSection;
begin
  result := False;
  m := LoadLibrary('ntdll.dll');
  if m <> 0 then
  begin
    ZwUnmapViewOfSection := GetProcAddress(m, 'ZwUnmapViewOfSection');
    if assigned(ZwUnmapViewOfSection) then
      result := (ZwUnmapViewOfSection(ProcHnd, BaseAddr) = 0);
    FreeLibrary(m);
  end;
end;

{ 创建外壳进程并获取其基址、大小和当前运行状态 }
function CreateChild(Cmd: string; var Ctx: TContext; var ProcHnd, ThrdHnd, ProcId, BaseAddr, ImageSize: Cardinal): Boolean;
var
  si: TStartUpInfo;
  pi: TProcessInformation;
  Old: Cardinal;
  MemInfo: TMemoryBasicInformation;
  p: Pointer;
begin
  FillChar(si, Sizeof(si), 0);
  FillChar(pi, SizeOf(pi), 0);
  si.cb := sizeof(si);
  result := CreateProcess(nil, PChar(Cmd), nil, nil, False, Create_SUSPENDED, nil, nil, si, pi);  // 以挂起方式运行进程
  if result then
  begin
    ProcHnd := pi.hProcess;
    ThrdHnd := pi.hThread;
    ProcId := pi.dwProcessId;

    { 获取外壳进程运行状态,[ctx.Ebx+8]内存处存的是外壳进程的加载基址,ctx.Eax存放有外壳进程的入口地址 }
    ctx.ContextFlags := CONTEXT_FULL;
    GetThreadContext(ThrdHnd, ctx);
    ReadProcessMemory(ProcHnd, Pointer(ctx.Ebx+8), @BaseAddr, SizeOf(Cardinal), Old);  // 读取加载基址
    p := Pointer(BaseAddr);

    { 计算外壳进程占有的内存 }
    while VirtualQueryEx(ProcHnd, p, MemInfo, Sizeof(MemInfo)) <> 0 do
    begin
      if MemInfo.State = MEM_FREE then
        break;
      p := Pointer(Cardinal(p) + MemInfo.RegionSize);
    end;
    ImageSize := Cardinal(p) - Cardinal(BaseAddr);
  end;
end;

{ 创建外壳进程并用目标进程替换它然后执行 }
function AttachPE(CmdParam: string; peH: PImageNtHeaders; peSecH: PImageSectionHeaders;
    Ptr: Pointer; ImageSize: Cardinal; var ProcId: Cardinal): Cardinal;
var
  s: string;
  Addr, Size: Cardinal;
  ctx: TContext;
  Old: Cardinal;
  p: Pointer;
  Thrd: Cardinal;
begin
  result := INVALID_HANDLE_VALUE;
  s := PrepareShellExe(CmdParam, peH.OptionalHeader.ImageBase, ImageSize);
  if CreateChild(s, ctx, result, Thrd, ProcId, Addr, Size) then
  begin
    p := nil;
    if (peH.OptionalHeader.ImageBase = Addr) and (Size >= ImageSize) then  // 外壳进程可以容纳目标进程并且加载地址一致
    begin
      p := Pointer(Addr);
      VirtualProtectEx(result, p, Size, PAGE_EXECUTE_READWRITE, Old);
    end
    else if IsNT then  // 98 下失败
    begin
      if UnloadShell(result, Addr) then  // 卸载外壳进程占有内存
        // 重新按目标进程加载基址和大小分配内存
        p := MyVirtualAllocEx(Result, Pointer(peH.OptionalHeader.ImageBase), ImageSize, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
      if (p = nil) and hasRelocationTable(peH) then  // 分配内存失败并且目标进程支持重定向
      begin
        // 按任意基址分配内存
        p := MyVirtualAllocEx(result, nil, ImageSize, MEM_RESERVE or MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if p <> nil then
          DoRelocation(peH, Ptr, p);  // 重定向
      end;
    end;
    if p <> nil then
    begin
      WriteProcessMemory(Result, Pointer(ctx.Ebx+8), @p, Sizeof(DWORD), Old);  // 重置目标进程运行环境中的基址
      peH.OptionalHeader.ImageBase := Cardinal(p);
      if WriteProcessMemory(Result, p, Ptr, ImageSize, Old) then  // 复制PE数据到目标进程
      begin
        ctx.ContextFlags := CONTEXT_FULL;
        if Cardinal(p) = Addr then
          ctx.Eax := peH.OptionalHeader.ImageBase + peH.OptionalHeader.AddressOfEntryPoint  // 重置运行环境中的入口地址
        else
          ctx.Eax := Cardinal(p) + peH.OptionalHeader.AddressOfEntryPoint;
        SetThreadContext(Thrd, ctx);  // 更新运行环境
        ResumeThread(Thrd);           // 执行
        CloseHandle(Thrd);
      end
      else begin  // 加载失败,杀掉外壳进程
        TerminateProcess(Result, 0);
        CloseHandle(Thrd);
        CloseHandle(Result);
        Result := INVALID_HANDLE_VALUE;
      end;
    end
    else begin // 加载失败,杀掉外壳进程
      TerminateProcess(Result, 0);
      CloseHandle(Thrd);
      CloseHandle(Result);
      Result := INVALID_HANDLE_VALUE;
    end;
  end;
end;

function MemExecute(const ABuffer; Len: Integer; CmdParam: string; var ProcessId: Cardinal): Cardinal;
var
  peH: PImageNtHeaders;
  peSecH: PImageSectionHeaders;
  Ptr: Pointer;
  peSz: Cardinal;
begin
  result := INVALID_HANDLE_VALUE;
  if alignPEToMem(ABuffer, Len, peH, peSecH, Ptr, peSz) then 
  begin
    result := AttachPE(CmdParam, peH, peSecH, Ptr, peSz, ProcessId);
    VirtualFree(Ptr, peSz, MEM_DECOMMIT);
    //VirtualFree(Ptr, 0, MEM_RELEASE);
  end;
end;

initialization
  MyVirtualAllocEx := GetProcAddress(GetModuleHandle('Kernel32.dll'), 'VirtualAllocEx');

end.


写了一个简单程序测试通过:)

program Test;

//{$APPTYPE CONSOLE}

uses
  SysUtils,
  Classes,
  PEUnit in 'PEUnit.pas';

var
  ABuffer: array of byte;
  Stream: TFileStream;
  ProcessId: Cardinal;
begin
  Stream:=TFileStream.Create('Target.exe', fmOpenRead);
  try
    SetLength(ABuffer, Stream.Size);
    Stream.ReadBuffer(ABuffer[0], Stream.Size);
    MemExecute(ABuffer[0], Stream.Size, '', ProcessId);
  finally
    Stream.Free;
  end;
end.

上一页  [1] [2] [3] 

文章录入:cainiaowang    责任编辑:cainiaowang 
【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
VIP 专 区
Copyright @2006 黑客风云 ●业务联系:QQ 联系怪人 联系奇人 Email:给怪人发邮件 给奇人发邮件
ICP备案:冀06009886