通常说一个static变量初始化被包装在一个中if以防止它被多次初始化。
对于这种情况和其他一次性条件,在第一次通过自我修改后让代码删除条件会更有效。
C++ 编译器是否允许生成这样的代码,如果不允许,为什么?我听说它可能会对缓存产生负面影响,但我不知道详细信息。
我搜索编译器存在的编程语言,并支持自修改代码.我听说Lisp支持这些功能,但我想知道是否有更多具有这些功能的C/C++/D-Like语言.
澄清我的意思:
我希望能够以某种方式在运行时访问程序代码并对其应用任何类型的更改,即删除命令,添加命令,更改它们.好像我有我的程序的AstTree.当然,我不能用编译语言拥有那棵树,所以它必须做得与众不同.编译需要将自修改命令转换为它们的二进制等效修改,以便它们在运行时与编译的代码一起工作.
我不想依赖于VM,这就是我的意思与编译:)
lisp reflection programming-languages compiled self-modifying
我想有一个带有JavaScript的html文件,其中(文件)能够修改其上下文.更多细节,我想象它.我有一个html文件,我用浏览器打开.我有一个文本区域,我在那里键入我的文本,然后按提交按钮.因此,表单的上下文保存在html文件中的某处.最简单,最稳定的方法是什么?
我写了一个简短的程序来读取一个windows obj文件并找到.text部分并在其中运行代码.为此,我进行了以下Windows API函数调用(完整代码[gist.github.com],对于那些感兴趣的人):
HANDLE FileHandle = CreateFile("lib.obj",
GENERIC_READ | GENERIC_EXECUTE,
FILE_SHARE_READ, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
HANDLE MappingHandle = CreateFileMapping(FileHandle, 0, PAGE_EXECUTE_READ, 0, 0, 0);
void *Address = MapViewOfFile(MappingHandle, FILE_MAP_EXECUTE | FILE_MAP_READ,
0, 0, 0);
Run Code Online (Sandbox Code Playgroud)
然后,我在文件中找到.text部分,并将指针转换为C++中的函数指针,并简单地调用该函数.这实际上似乎对我有用.
我是否在映射到文件的虚拟内存范围内调用FlushInstructonCache时出错?
我问这个是因为我最近阅读的是VirtualAlloc文档,它在底部注明:
在创建一个可执行的区域时,调用程序负责通过在代码设置到位后适当调用FlushInstructionCache来确保缓存一致性.否则,尝试从新的可执行区域执行代码可能会产生不可预测的结果.
我的代码是否可能导致CPU在指令缓存中执行旧指令?
MapViewOfFile或CreateFileMapping页面上没有这样的注释.
我有一个生成自修改代码的程序(如果您有兴趣,请参阅https://tigress.wtf/selfModify.html)。它在 x86 Darwin 和 Linux 上运行。在达尔文,我编译
gcc -g -segprot __TEXT rwx rwx self_modifying.c -o self_modifying.exe
Run Code Online (Sandbox Code Playgroud)
最近,这似乎不起作用,我明白了
dyld: malformed mach-o image: __TEXT segment maps start of file but is writable
Run Code Online (Sandbox Code Playgroud)
当我运行程序时。
我在 MacOS 10.15.3 上运行 clang 6.0.1 版。任何帮助,将不胜感激。
我正在阅读关于自修改代码的密码破解者期刊文章,并且有以下代码片段:
void Demo(int (*_printf) (const char *,...))
{
_printf("Hello, OSIX!n");
return;
}
int main(int argc, char* argv[])
{
char buff[1000];
int (*_printf) (const char *,...);
int (*_main) (int, char **);
void (*_Demo) (int (*) (const char *,...));
_printf=printf;
int func_len = (unsigned int) _main - (unsigned int) _Demo;
for (int a=0; a<func_len; a++)
buff[a] = ((char *) _Demo)[a];
_Demo = (void (*) (int (*) (const char *,...))) &buff[0];
_Demo(_printf);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这段代码应该在堆栈上执行Demo().我理解大部分代码,但是他们分配'func_len'的部分让我困惑.据我所知,他们从另一个随机指针地址中减去一个随机指针地址.
有人在意解释?
首先,我对这篇文章的篇幅感到抱歉,但我想清楚地解释这个问题.
我尝试在C中编写一种小型自修改程序,但是我遇到了一些麻烦,我不确切知道为什么.
平台是: Ubuntu/Linux 2.6.32-40 x86_64,prog是基于x86 arch,gcc(Ubuntu 4.4.3-4ubuntu5.1)4.4.3,GNU ld(GNU Binutils for Ubuntu)2.20.1-system.20100303
该程序的目的是创建一个读/写/执行内存块(使用memalign(3)和mprotect(2)),复制一个在这块内存中调用p()(在.text段中定义)的小函数,然后执行通过指针复制函数.该p()函数只显示一条消息printf(puts).
为了得到的代码的开始和结束地址p()(以复制),我用的是函数本身的地址和地址dummy()刚过创建功能p()在.text.
int p() { ... } <- address where the copy starts
int dummy() { ... } <- address where the copy stops
Run Code Online (Sandbox Code Playgroud)
成功完成块内存创建和复制,但是当块中的代码运行时,会发生段错误.通过使用gdb它很明显我们输入了块的代码(复制函数的主体),但是对printf的调用失败了.当反汇编p()函数和块中的代码时,我发现'call'中使用的地址不一样.
而且我不知道为什么地址不正确,当代码被复制时它被显示,并且它与objdump(或gdb)在我反汇编p()函数时给我的相同.
创建二进制文件是-static为了避免got/plt …
我正在尝试编写自我修改的 asm 代码。
在某些时候,我尝试以下操作:(NASM 编译器)
start_of_code:
; ... snip ...
cmp byte [rax], 0x66
jae above_label
add byte[rax], 0x20
; ... snip ...
above_label:
inc rax
loop start_of_code
Run Code Online (Sandbox Code Playgroud)
gdb 在开始时显示以下值x/8xb $rax:
0x12 0x12 0x11 0x20 0x18 0xfe 0x83 0x9b
Run Code Online (Sandbox Code Playgroud)
前两次迭代没问题,0x12按照我的预期进行比较,没有发生跳转。随着0x11然而,cmp设置OF代替标志CF 和jae执行
目前我有 2 个猜测,要么 gdb 没有首先报告正确的内存位置,0x9b 实际上是被比较的地址,或者其他地方。这似乎不太可能,因为添加似乎像我期望的那样工作。
或者这可能是对齐问题。在 cmp 之前添加 NOP 指令似乎会以某种方式影响结果。我真的不知道为什么
编辑:当我尝试
mov bl, byte [rax]
Run Code Online (Sandbox Code Playgroud)
bl 得到 0xcc
这对我来说没有意义。gdb 不报告任何0xcc附近的任何值[rax]
在JavaScript/Python等动态语言中,可以在运行时覆盖或"修改"函数.例如,为了修改alertJS中的函数,可以这样做:
const _prev_alert = window.alert;
window.alert = function() {
_prev_alert.apply(this, arguments);
console.log("Alert function was called!");
}
Run Code Online (Sandbox Code Playgroud)
这将输出"调用警报功能!" 每次alert调用函数时都到控制台.
现在,显然这样的事情在Kotlin-JVM或Kotlin-Native的运行时期间是不可能的,因为它们具有静态特性.但是,对于那些相同的语言,是否有可能在编译期间修改未编译的函数?我不是指来自库的预编译函数,而是我在我正在开发的同一个项目中编写的函数.
例如,假设我有一个我写的函数get_number.我可以修改get_number为返回一个不同的数字而不改变它在main中的调用方式而不直接修改它的代码吗?(或者有一种方法我可以写原件,get_number所以修改可能在线下吗?)
fun main(args: Array<String>) {
println(get_number())
}
fun get_number(): Int {
return 3
}
// Without modifying the code above, can I get main to print something besides 3?
Run Code Online (Sandbox Code Playgroud)
我一直在阅读Kotlin的Annotations and Reflections元编程,所以也许那些可以控制编译器的行为并覆盖get_number代码?或者这是完全的疯狂,这种性质的唯一方法是通过在Kotlin上开发我自己的,独立的元编程包装器?
此外,只是为了澄清,这个问题不是关于Kotlin-JS,答案(如果存在)应该适用于Kotlin-JVM或Native.
我认为热补丁假设用 2 字节跳转覆盖任何 2 或更多字节长的指令对于并发执行相同的代码是安全的。
因此取指令被假定为原子的。
考虑到使用前缀可以有超过 8 字节的指令,并且它可以跨越任何对齐的边界,它确实是原子的吗?(或者热补丁是否依赖于函数开始的 16 字节对齐?如果是这样,那么大小超过 8 字节又是什么?)
上下文:LLVM 在https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/interception/interception_win.cpp中拦截了 API 函数。这至少用于 Address Sanitizer,也许也用于其他用途。它将 HotPatch 实现为第三种方法(第 61 行):
// 3) HotPatch
//
// The HotPatch hooking is assuming the presence of an header with padding
// and a first instruction with at least 2-bytes.
//
// The reason to enforce the 2-bytes limitation is to provide the minimal
// space to encode a short jump. HotPatch technique is only rewriting one …Run Code Online (Sandbox Code Playgroud) self-modifying ×10
assembly ×3
c++ ×3
gdb ×2
atomic ×1
breakpoints ×1
c ×1
compiled ×1
dyld ×1
hotpatching ×1
html ×1
javascript ×1
kotlin ×1
lisp ×1
mach-o ×1
macos ×1
malformed ×1
objdump ×1
overloading ×1
reflection ×1
winapi ×1
windows ×1
x86 ×1
x86-64 ×1