标签: self-modifying

是否存在运行时代码修改的智能案例?

你能想到运行时代码修改的任何合法(智能)用法(程序在运行时修改它自己的代码)吗?

现代操作系统似乎对执行此操作的程序不屑一顾,因为病毒已使用此技术来避免检测.

我能想到的是某种运行时优化,它可以通过在运行时知道某些在编译时无法知道的东西来删除或添加一些代码.

executable platform-agnostic cpu-architecture instructions self-modifying

119
推荐指数
10
解决办法
6266
查看次数

自修改代码有什么用?

自修改代码有什么用途吗?

我知道它们可以用于构建蠕虫/病毒,但我想知道程序员是否有必要使用自修改代码的一些好理由.

有任何想法吗?也是受欢迎的假设情况.

executable self-modifying

49
推荐指数
8
解决办法
1万
查看次数

如何在x86程序集中编写自修改代码

我正在为最近一直在研究的业余爱好虚拟机编写JIT编译器.我知道有点汇编,(我主要是一个C程序员.我可以阅读大多数汇编参考我不理解的操作码,并编写一些简单的程序.)但我很难理解这几个例子我在网上找到的自修改代码.

这是一个这样的例子:http://asm.sourceforge.net/articles/smc.html

提供的示例程序在运行时进行了大约四种不同的修改,其中没有一个被清楚地解释.Linux内核中断被多次使用,没有解释或详细说明.(作者在调用中断之前将数据移动到几个寄存器中.我假设他正在传递参数,但这些参数根本没有解释,让读者猜测.)

我正在寻找的是自修改程序代码中最简单,最直接的例子.我可以看到的东西,用于理解如何编写x86程序集中的自修改代码,以及它是如何工作的.您是否有任何资源可以指向我,或者您可以提供的任何示例都能充分证明这一点?

我正在使用NASM作为我的汇编程序.

编辑:我也在Linux上运行此代码.

x86 assembly jit self-modifying vm-implementation

46
推荐指数
2
解决办法
2万
查看次数

用于自修改代码的编程语言?

  • 我最近在考虑编写自我修改程序,我认为它可能是强大而有趣的.所以我目前正在寻找一种允许轻松修改程序自己的代码的语言.
  • 我读到了C#(作为一种解决方法)以及在运行时编译和执行代码的能力,但这太伤人了.
  • 我也在考虑装配.更改运行代码更容易,但它不是很强大(非常原始).

您能否建议一种支持在运行时修改代码的强大语言或功能?

这就是我在运行时修改代码的意思:

  Start:
  a=10,b=20,c=0;
  label1: c=a+b;
  ....
  label1= c=a*b;
  goto label1;
Run Code Online (Sandbox Code Playgroud)

并且可能正在建立一份说明清单:

  code1.add(c=a+b);
  code1.add(c=c*(c-1));
  code1. execute();
Run Code Online (Sandbox Code Playgroud)

programming-languages dynamic-languages self-modifying

34
推荐指数
7
解决办法
2万
查看次数

同性恋和"不受限制"的自我修改代码+ lisp是否真的可以自我修改?

我将继续承认我对Lisp的了解非常少.但是我对这门语言非常感兴趣,并计划在不久的将来开始认真学习它.我对这些问题的理解无疑是有缺陷的,所以如果我说出任何错误的内容,请评论并纠正我而不是贬低.

真正的同性恋和自我修改的语言

我正在寻找支持Homoiconicity(代码与数据表示相同)和不受限制的自我修改的编程语言示例(Unrestricted意味着您可以更改正在运行的代码的每个方面,而不仅仅是发出新代码或更改函数指针/代表).

到目前为止我发现的三个例子符合这个标准:

  1. 机器代码.Homoiconic在一切都是一个数字.无限制地可修改,因为它包含指针,可用于操纵任何内存地址,无论该地址是保存代码还是数据.
  2. Malbolge.与机器代码相同的推理.每条指令在执行后都会自行修改
  3. 脱氧核糖核酸.不是编程语言,但仍然很有趣.它不是与机器代码一样的自我修改; 实际指令+数据在哪里修改到位.然而,它是自我复制的,并且可以根据它的先前状态进行变异/进化(具有副作用,例如辐射时不时地拧紧它).无论如何,这只是一种间接的自我修改方式.简而言之,DNA可以自我修饰,但它可以通过在相关突变中重现自身的真实性来实现.DNA的物理串是"不可变的".

为什么Lisp不在此列表中

Lisp不在那个列表中,因为在我看来,Lisp 几乎只是Homoiconic,并且只支持受限制的自我修改.你可以做点什么

(+ 1 2 3)
Run Code Online (Sandbox Code Playgroud)

这将做同样的事情

(eval '(+ 1 2 3))
Run Code Online (Sandbox Code Playgroud)

第一个版本(+ 1 2 3)是原始代码,而第二个版本是数据.通过假设这个陈述的真实性,可以说Lisp甚至不是杀人的.代码与数据具有相同的表示形式,即它们都是列表/树/ S表达式.但事实上你必须明确地标记这些列表/树/ S表达式中的哪些是代码以及哪些是我的数据似乎说Lisp毕竟不是杀人的.这些表示非常相似,但它们的细节不同,您必须实际说明您是在处理代码还是数据.这绝不是一件坏事(实际上其他任何东西都会是疯狂的),但它强调了Lisp和机器代码之间的区别.在机器代码中,您不必明确标记哪些数字是指令,哪些是指针,哪些是数据.在实际需要解释之前,一切都只是一个数字,此时它可以是任何一个.

对于不受限制的自我修改,这是一个更强大的案例.当然,您可以获取代表某些代码并对其进行操作的列表.例如改变

'(+ 1 2 3)
Run Code Online (Sandbox Code Playgroud)

'(+ 1 4 3)
Run Code Online (Sandbox Code Playgroud)

然后你运行它eval.但是当你这样做时,你只是编译一些代码并运行它.您没有修改现有代码,只是发出并运行新代码.C#可以使用表达式树完全相同的事情,即使是一种不太方便的格式(由于C#代码对其AST具有不同的表示而产生,而不是Lisp,这它自己的AST).您是否可以实际获取整个源文件并在运行时开始修改整个源文件,对源文件所做的更改会对程序行为产生实时影响?

除非有某种方法可以做到这一点,否则Lisp既不是讽刺也不是自我修改.(为了推断定义的争论,Lisp不是同源的,也不是自我修改到与机器代码相同的程度.)

如何制作Lisp Homoiconic/Unrestrictedly self-modifiable

我可以看到3种可能的方法使Lisp像机器代码一样可以单调/自我修改.

  1. 非Von-Neumann架构.如果有人能发明一些令人惊奇的假设机器,其中程序的最低级别表示是一个可以直接执行的AST(不需要进一步编译).在这样的机器上,AST将代表可执行指令以及数据.不幸的是,问题不会得到解决,因为AST仍然必须是代码或数据.eval函数的预设不会改变这一点.在机器代码中,您可以根据需要在代码和数据之间来回切换.而使用eval和Lisp,一旦你将某些列表从数据转换为代码并执行它,就无法再将该列表作为数据返回.实际上,该列表已经永远消失,并且已经被它的价值所取代.我们会遗漏一些至关重要的东西,这恰好是指针.
  2. 列出标签.如果要求每个列表也具有唯一标签,则可以通过针对具有给定标签的列表运行函数来进行间接自修改.结合延续,这最终将允许自动修改代码与机器代码具有相同的意义.标签与机器代码存储器地址等效.例如,考虑一个Lisp程序,其中AST的顶部节点具有标签"main".在main中,你可以执行一个函数,它接受一个标签,一个Integer,一个Atom,并将原子复制到List,其标签与提供给函数的标签相匹配,在Integer指定的索引处.然后在main上调用当前的continuation.你去,自我修改代码.
  3. Lisp Macros.我没有花时间去理解Lisp宏,他们实际上可能正是我正在考虑的事情.

点1.结合2.将产生一个完全自我修改的Lisp.前提是可以生产所描述的神奇的Lisp机器.2.单独可以产生自我修改的Lisp,但是在冯·诺依曼架构上的实现可能非常低效.

问题

  1. 机器码,dna和malbolge以外的任何语言都可以完全自我修改并且是同音的吗?
  2. (如果你做了tl,请不要打扰回答;上面的文字博士).lisp真的是homoiconic +自我修改吗?如果你这样说,你能准确引用我在论证中误入歧途的地方吗?

附录

语言具有不受限制的自我修改但不具有杀戮性

  1. 部件.代码使用单词而不是数字,因此失去了homiconicity,但它仍然有指针,它保留对内存的完全控制并允许不受限制的自我修改.
  2. 任何使用原始指针的语言.例如C/C++/Objective C.与Assembly相同的参数
  3. 包含虚拟指针的JIT语言.例如,C#/ .net在不安全的上下文中运行.与Assembly相同的论点.

其他概念和语言可能在某种程度上相关/有趣:Lisp,Ruby,Snobol,Forth和它的编译时元编程,Smalltalk和它的反射,无类型的lambda演算,它的属性是一切都是函数(哪种意味着假设我们可以发明一台直接执行lambda演算的机器,lambda演算将是homoiconic而Von Neumann机器代码在所述机器上运行时不会.[并且Godels定理将是可执行的.哈哈,可怕的想法:P])

lisp assembly machine-code self-modifying homoiconicity

29
推荐指数
2
解决办法
5237
查看次数

如何在C中编写自修改代码?

我想编写一段不断变化的代码,即使变化微不足道.

例如,可能是类似的东西

for i in 1 to  100, do 
begin
   x := 200
   for j in 200 downto 1, do
    begin
       do something
    end
end

假设我希望我的代码在第一次迭代后应该将行更改为x := 200其他行x := 199,然后在下一次迭代后将其更改为x := 198依此类推.

写这样的代码可能吗?我需要使用内联汇编吗?

编辑:这就是我想用C做的原因:

该程序将在实验操作系统上运行,我不能/不知道如何使用从其他语言编译的程序.我需要这样一个代码的真正原因是因为这个代码是在虚拟机上的客户操作系统上运行的.管理程序是一个翻译代码块的二进制翻译器.翻译做了一些优化.它只翻译一次代码块.下次在guest中使用相同的块时,翻译器将使用先前翻译的结果.现在,如果代码被动态修改,那么翻译人员会注意到这一点,并将其先前的翻译标记为陈旧.因此迫使重新翻译相同的代码.这就是我想要实现的目标,迫使翻译人员进行多次翻译.通常,这些块是分支指令(例如跳转指令)之间的指令.我只是认为自修改代码将是实现这一目标的绝佳方式.

c self-modifying

27
推荐指数
6
解决办法
3万
查看次数

什么是代码洞穴,是否有任何合法用途?

我在StackOverflow问题中第一次遇到这个词" C#理论:将一个JMP写入asm中的编解码器 ".根据维基词典,我看到一个代码洞穴是:

一个未使用的内存块,有人(通常是软件破解者)可以使用它来注入自定义编程代码来修改程序的行为.

我找到了正确的定义吗?如果是这样,代码洞穴是否有合法用途?

assembly terminology definition self-modifying codecave

25
推荐指数
6
解决办法
1万
查看次数

x86指令缓存是如何同步的?

我喜欢这个例子,所以我在c中写了一些自修改代码...

#include <stdio.h>
#include <sys/mman.h> // linux

int main(void) {
    unsigned char *c = mmap(NULL, 7, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|
                            MAP_ANONYMOUS, -1, 0); // get executable memory
    c[0] = 0b11000111; // mov (x86_64), immediate mode, full-sized (32 bits)
    c[1] = 0b11000000; // to register rax (000) which holds the return value
                       // according to linux x86_64 calling convention 
    c[6] = 0b11000011; // return
    for (c[2] = 0; c[2] < 30; c[2]++) { // incr immediate data after every run
        // rest of …
Run Code Online (Sandbox Code Playgroud)

c assembly instructions self-modifying cpu-cache

24
推荐指数
3
解决办法
5151
查看次数

在程序集中编写JIT编译器

我用C编写了一个虚拟机,它对非JIT VM有很好的性能,但我想学习一些新东西,并提高性能.我当前的实现只是使用一个开关从VM字节码转换为指令,并将其编译为跳转表.就像我说的那样,它的性能不错,但是我遇到了一个只能用JIT编译器克服的障碍.

不久前我已经问了一个关于自我修改代码的类似问题,但我开始意识到我并没有问正确的问题.

所以我的目标是为这个C虚拟机编写一个JIT编译器,我想在x86汇编中完成它.(我使用NASM作为我的汇编程序)我不太确定如何去做这个.我对汇编感到满意,并且我已经查看了一些自我修改的代码示例,但我还没有弄清楚如何进行代码生成.

到目前为止,我的主要部分是使用我的参数将指令复制到可执行的内存块.我知道我可以在NASM中标记某一行,并使用静态参数从该地址复制整行,但这不是非常动态的,并且不适用于JIT编译器.我需要能够解释字节码中的指令,将其复制到可执行内存,解释第一个参数,将其复制到内存,然后解释第二个参数,并将其复制到内存中.

我已经了解了几个可以简化这项任务的库,比如GNU闪电,甚至是LLVM.但是,在使用外部资源之前,我想首先手动编写,以了解它是如何工作的.

这个社区可以提供任何资源或示例来帮助我开始这项任务吗?一个简单的例子显示了两个或三个指令,例如"add"和"mov"用于生成可执行代码,带有参数,动态地,在内存中,会产生奇迹.

c assembly jit code-generation self-modifying

23
推荐指数
2
解决办法
5232
查看次数

使用自修改代码观察在x86上获取过时的指令

我被告知并且从英特尔的手册中读到可以将指令写入内存,但是指令预取队列已经获取了陈旧的指令并将执行那些旧的指令.我没有成功观察到这种行为.我的方法如下.

英特尔软件开发手册从第11.6节开始说明

对当前在处理器中高速缓存的代码段中的存储器位置的写入导致相关联的高速缓存行(或多个行)无效.此检查基于指令的物理地址.此外,P6系列和奔腾处理器检查对代码段的写入是否可以修改已经预取执行的指令.如果写入影响预取指令,则预取队列无效.后一种检查基于指令的线性地址.

所以,看起来如果我希望执行陈旧的指令,我需要有两个不同的线性地址引用相同的物理页面.所以,我将内存映射到两个不同的地址.

int fd = open("code_area", O_RDWR | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO);
assert(fd>=0);
write(fd, zeros, 0x1000);
uint8_t *a1 = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC,
        MAP_FILE | MAP_SHARED, fd, 0);
uint8_t *a2 = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC,
        MAP_FILE | MAP_SHARED, fd, 0);
assert(a1 != a2);
Run Code Online (Sandbox Code Playgroud)

我有一个汇编函数,它接受一个参数,一个指向我想要更改的指令的指针.

fun:
    push %rbp
    mov %rsp, %rbp

    xorq %rax, %rax # Return value 0

# A far jump simulated with a far return
# Push the …
Run Code Online (Sandbox Code Playgroud)

c x86 caching self-modifying

23
推荐指数
3
解决办法
2563
查看次数