D. *_*sin -2 c self-modifying self-reference
在运行时,汇编程序或机器代码(它是什么?)应该在RAM中的某个位置.我可以以某种方式访问它,读取甚至写入它吗?
这仅用于教育目的.
所以,我只能编译这段代码.我真的在这里读书吗?
#include <stdio.h>
#include <sys/mman.h>
int main() {
void *p = (void *)main;
mprotect(p, 4098, PROT_READ | PROT_WRITE | PROT_EXEC);
printf("Main: %p\n Content: %i", p, *(int *)(p+2));
unsigned int size = 16;
for (unsigned int i = 0; i < size; ++i) {
printf("%i ", *((int *)(p+i)) );
}
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我补充一下
*(int*)p =4;
Run Code Online (Sandbox Code Playgroud)
那是一个分段错误.
从答案中,我可以构造以下代码,在运行时修改它自己:
#include <stdio.h>
#include <sys/mman.h>
#include <errno.h>
#include <string.h>
#include <stdint.h>
void * alignptr(void * ptr, uintptr_t alignment) {
return (void *)((uintptr_t)ptr & ~(alignment - 1));
}
// pattern is a 0-terminated string
char* find(char *string, unsigned int stringLen, char *pattern) {
unsigned int iString = 0;
unsigned int iPattern;
for (unsigned int iString = 0; iString < stringLen; ++iString) {
for (iPattern = 0;
pattern[iPattern] != 0
&& string[iString+iPattern] == pattern[iPattern];
++iPattern);
if (pattern[iPattern] == 0) { return string+iString; }
}
return NULL;
}
int main() {
void *p = alignptr(main, 4096);
int result = mprotect(p, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
if (result == -1) {
printf("Error: %s\n", strerror(errno));
}
// Correct a part of THIS program directly in RAM
char programSubcode[12] = {'H','e','l','l','o',
' ','W','o','r','l','t',0};
char *programCode = (char *)main;
char *helloWorlt = find(programCode, 1024, programSubcode);
if (helloWorlt != NULL) {
helloWorlt[10] = 'd';
}
printf("Hello Worlt\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这真太了不起了!谢谢你们!
原则上,实际上您的操作系统可以保护自己免受危险代码的侵害!
在计算机拥有非常微小的记忆(20世纪50年代)的时代,自我修改代码可能被视为一种"巧妙的技巧".它后来(当它不再需要时)被认为是不好的做法 - 导致代码很难维护和调试.
在更现代的系统中(在20世纪末),它成为一种表明病毒和恶意软件的行为.因此,所有现代桌面操作系统都不允许修改程序的代码空间,并且还阻止执行注入数据空间的代码.具有MMU的现代系统可以将存储器区域标记为只读,并且例如不可执行.
如何获取代码空间地址的简单问题 - 这很简单.例如,函数指针值通常是函数的地址:
int main()
{
printf( "Address of main() = %p\n", (void*)main ) ;
}
Run Code Online (Sandbox Code Playgroud)
另请注意,在现代系统中,此地址将是虚拟而非物理地址.