【发布时间】:2012-01-03 18:34:41
【问题描述】:
我正在编写一个 EXE 包装器(某种打包器)来保护我的 EXE,然后它将直接执行到内存中。下面的示例显示了将计算器执行到内存中。
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
FS := TFileStream.Create('calc.exe', fmOpenRead or fmShareDenyNone);
SetLength(eu, FS.Size);
FS.Read(eu[0], FS.Size);
FS.Free;
SInfo.cb := Sizeof(TStartupInfo);
CreateProcess(nil, Pchar(paramstr(0)), nil, nil, FALSE, CREATE_SUSPENDED, nil,
nil, SInfo, PInfo);
IDH := @eu[0];
INH := @eu[IDH^._lfanew];
imgbase := DWORD(VirtualAllocEx(PInfo.hProcess,
Ptr(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage,
MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE));
ShowMessage(IntToHex(imgbase, 8));
WriteProcessMemory(PInfo.hProcess, Ptr(imgbase), @eu[0],
INH^.OptionalHeader.SizeOfHeaders, SIZE_T(btsIO));
for i := 0 to INH^.FileHeader.NumberOfSections - 1 do
begin
ISH := @eu[IDH^._lfanew + Sizeof(TImageNtHeaders) + i *
Sizeof(TImageSectionHeader)];
WriteProcessMemory(PInfo.hProcess, Ptr(imgbase + ISH^.VirtualAddress),
@eu[ISH^.PointerToRawData], ISH^.SizeOfRawData, SIZE_T(btsIO));
end;
CONT.ContextFlags := CONTEXT_FULL;
GetThreadContext(PInfo.hThread, CONT);
CONT.Eax := imgbase + INH^.OptionalHeader.AddressOfEntryPoint;
WriteProcessMemory(PInfo.hProcess, Ptr(CONT.Ebx + 8), @imgbase, 4,
SIZE_T(btsIO));
ShowMessage('Press ok on ENTER');
SetThreadContext(PInfo.hThread, CONT);
ResumeThread(PInfo.hThread);
CloseHandle(PInfo.hThread);
CloseHandle(PInfo.hProcess);
end;
我更改了代码以包含一个额外的资源。在这一点上,令我惊讶的是,Imagebase 变成了零!
{$R *.dfm}
{$R test.res} //extra resourse added
procedure TForm1.Button1Click(Sender: TObject);
var
i: Integer;
begin
FS := TFileStream.Create('calc.exe', fmOpenRead or fmShareDenyNone);
SetLength(eu, FS.Size);
FS.Read(eu[0], FS.Size);
FS.Free;
SInfo.cb := Sizeof(TStartupInfo);
CreateProcess(nil, Pchar(paramstr(0)), nil, nil, FALSE, CREATE_SUSPENDED, nil,
nil, SInfo, PInfo);
IDH := @eu[0];
INH := @eu[IDH^._lfanew];
imgbase := DWORD(VirtualAllocEx(PInfo.hProcess,
Ptr(INH^.OptionalHeader.ImageBase), INH^.OptionalHeader.SizeOfImage,
MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE));
ShowMessage(IntToHex(imgbase, 8));
.....
.....
- 在第一个示例中,我得到 Imagebase = 01000000(代码运行良好)
- 在第二个示例中(我在项目中添加了额外资源),我得到 Imagebase = 00000000(代码失败..)
谁能解释一下为什么会这样..?
【问题讨论】:
-
您知道不支持从内存执行吗?
-
感谢大卫的评论。据我所知,这是合法且允许的。看看 UPX 是如何执行压缩的 exe 的。首先,原始代码被解压缩到内存中,然后它被执行。大多数著名的 exe 打包程序也是如此。 ASPack 也做同样的事情,但是,它具有比 UPX 更好的加密和保护机制来防止破解。在这里,我们不是试图执行恶意代码,而是试图创建一个与 UPX 或 ASPack 完全相同的合法包装器。希望这能以更好的方式阐明情况。
-
好吧,我的意思是 MS 不支持从内存中加载图像,并且这样做的代码在面对未来的版本甚至操作系统更新时可能会中断。我了解您为什么要这样做我只是想确保您知道不支持这样做。
-
您可能希望查看
GetLastError返回的内容,但也许将 null 作为第二个参数传递给VirtualAllocEx可能会解决问题。 -
忽略 David Heffernan,它是受支持的。
标签: delphi delphi-xe2