我喜欢这个例子,所以我在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) 我发现了一篇关于自修改代码的文章,并试图做一些例子,但我总是得到分段错误.就像我能理解的那样,内存权限存在违规行为.代码段是(r)ead/e(x)ecute,因此写入的尝试导致此错误.有没有办法通过在运行时或之前更改内存权限来测试程序?我正在使用linux,这个例子是用GAS汇编编写的.
.extern memcpy
.section .data
string:
.asciz "whatever"
string_end:
.section .bss
.lcomm buf, string_end-string
.section .text
.globl main
main:
call changer
mov $string, %edx
label:
push string_end-string
push $buf
push $string
call memcpy
changer:
mov $offset_to_write, %esi
mov $label, %edi
mov $0xb, %ecx
loop1:
lodsb
stosb
loop loop1
ret
offset_to_write:
push 0
call exit
end:
Run Code Online (Sandbox Code Playgroud)
所以在osgx建议的修改后,这是一个工作代码.(实际上,如果你组装并链接并运行它崩溃,但如果你看着使用gdb,它确实修改了它的代码!)
.extern memcpy
.section .data
string:
.asciz "Giorgos"
string_end:
.section .bss
.lcomm buf, string_end-string
.section .text
.globl main
main:
lea (main), %esi # get the …Run Code Online (Sandbox Code Playgroud) 如您所知,当子程序调用时,当前PC(程序计数器)值存储在堆栈中.我想在子程序中修改它,如下所示.我希望使用gcc编译器在Intel Core-i7 3632QM上执行此操作.
void main()
{
foo();
}
void foo()
{
pop return address from stack;
modify return address;
push it to stack;
}
Run Code Online (Sandbox Code Playgroud)