自修改代码[C ++]

时间:2011-04-26 06:05:03

标签: c++ self-modifying

我正在阅读关于自修改代码的密码破解者期刊文章,并且有这段代码:

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; 
}

这段代码应该在堆栈上执行Demo()。我理解大部分代码,但是他们分配'func_len'的部分让我困惑。据我所知,他们从另一个随机指针地址中减去一个随机指针地址。

有人在意解释吗?

2 个答案:

答案 0 :(得分:7)

代码依赖于编译器函数布局的知识 - 这可能与其他编译器不可靠。

func_len行经过更正以包含最初缺失的-后,通过减去Demo中的地址来确定函数_Demo的长度(应该从Demo()中的地址(包含起始地址_main)中包含main())的起始地址。这被假定为函数Demo的长度,然后将其按字节方式复制到缓冲区buff中。然后将buff的地址强制转换为函数指针,然后调用该函数。但是,由于_Demo_main实际上都没有被初始化,因此代码在极端情况下是错误的。此外,还不清楚unsigned int是否足以准确地保持指针;演员应该是来自uintptr_t<stdint.h>的{​​{1}}。

如果错误是固定的,如果关于代码布局的假设是正确的,如果代码是与位置无关的代码,并且没有防止执行数据空间的保护,则这是有效的。它不可靠,不便携,不推荐。但它确实说明了,如果它有效,代码和数据非常相似。

我记得在两个进程之间拉一个类似的特技,将一个函数从一个程序复制到共享内存,然后让另一个程序从共享内存中执行该函数。这是大约四分之一世纪以前的事情,但这种技术与它所尝试的机器相似并且“有效”。我从来不需要使用这种技术,谢天谢地!

答案 1 :(得分:5)

此代码使用未初始化的变量_main_Demo,因此它无法正常工作。即使它们意味着不同的东西,它们也可能假设在内存中有一些特定的函数排序。

我的意见:不要相信这篇文章。