2013-05-01 78 views
5

是否有可能生成一个字节数组,然后让Windows像普通代码一样执行它? 假设我们有一些汇编代码:我可以在Delphi中随时编译代码并执行它吗?

inc ecx 

它是程序的一部分。之后,我们与NASM编译,我们得到一个EXE在上述行转换为这样的事情:

00000035 41 

是否有可能创建一个字节数组,与上面的字节填充和execute-所以增量实际发生?

我已经做出了我的超简单的解释型语言,但是因为它被解释为很慢。我不想为它编写一个真正的编译器,但我想让它更快 - 编译并即时运行。

回答

14

绝对如此。支持数据执行预防的处理器和操作系统可能会受到阻碍,但这很容易规避。只需拨打VirtualProtect即可将内存块标记为可执行文件。最好使用VirtualAlloc来分配您计划执行的内存。这样,您就拥有专门用于执行代码的整个内存页面。如果您拨打VirtualProtect来为您分配的GetMem可执行文件指定任意内存,则它实际上会标记整个页面,因此您可能会无意中将一些数据标记为可执行文件。如果这些数据受到威胁,它可能会被执行。这正是DEP旨在防范的原因,因此最好将数据和可执行代码保存在单独保护的区域中。

请记住,转换文本代码转换为机器代码的任务是编译,所以如果你不想写一个真实的编译器,你可能不希望生成机器码毕竟。

+0

谢谢。这是“编译”,但没有所有的EXE头文件,外部库等的链接。所以它应该更容易。 – Tom 2013-05-01 12:42:56

+1

您仍然需要重新定位(修复)它。除非您不使用任何数据(或通过在启动时在寄存器中传递的指针间接寻址),并且仅在分支或PIC附近。 – 2013-05-01 16:53:38

1

我认为具有数据执行保护(DEP)的现代处理器将不允许这样做。 请注意,有几个pascal脚本库可用于此目的。

+0

我知道它们就像RemObjects Pascal Script一样。但我不想用帕斯卡语言写作,我需要一些非常简单的东西。 – Tom 2013-05-01 12:41:29

+3

DEP不会阻止执行通过VirtualAlloc()或VirtualProtect()明确标记为执行的内存的指令。有像VCL和ATL这样的框架可动态分配可执行内存块以用作回调thunk,并且DEP可以正常工作。 – 2013-05-01 16:55:35

+1

也有表达式评估器。但他们通常模仿堆栈机器,因此只需要一个寄存器加载堆栈指针,如果代码是PIC – 2013-05-01 16:55:49

7
const 
    size = 32768; 
type 
    TFuncInt = function(param: Integer): Integer; // EAX -> EAX 
    TByteArray = array[0..size-1] of Byte; 
    PByteArray = ^TByteArray; 
var 
    arr: PByteArray; 
    func_param: Integer; 
    func_result: Integer; 
begin 
    arr := VirtualAlloc(nil, size, $3000, $40); 
    if arr <> nil then begin 
    arr[0] := $40; // inc EAX 
    arr[1] := $C3; // ret 
    func_param := 77; 
    func_result := TFuncInt(arr)(func_param); // 78 
    VirtualFree(arr, 0, $8000); 
    end; 
end; 
+0

看起来不错,谢谢! – Tom 2013-05-01 18:00:44

+1

@RobKennedy - 您的代码版本无法编译。在Delphi7中没有定义'Page_Execute_ReadWrite'。你应该手动定义它。或者使用数字值。 – 2013-05-01 19:13:04

+0

那么定义它。我不在乎你的开发环境多么过时;不要使用裸数字。他们对阅读代码的人没有任何意义。 – 2013-05-01 19:28:00

相关问题