zoukankan      html  css  js  c++  java
  • 字符串常量区读写属性强制修改为可写

    常见的0xC0000005错误,往往是程序尝试对不可写内存区域写入数据导致的,这是使用指针的时候的常见错误。不过字符串常量区(也叫数据区,确切的说,字符串常量区是数据区的一部分)、代码区、堆、栈都是系统临时分配的一段内存而已,他们本质上没有区别。通过修改PE文件,我们可以修改对应内存的读写属性,从而规避0xC0000005错误(程序成功地把数据写入字符串常量区)。示例程序:

    #include "stdafx.h"
    #include <stdlib.h>
    
    int _tmain(int argc, _TCHAR* argv[])
    {
      char *p = "hello world";
    
      system("pause");
    
      *(p + 2) = 'm';    //此处触发C05错误
    
      printf("%s
    ", p);
    
      system("pause");
      return 0;
    }
    

    如图所示,这个程序是可以编译通过并运行的:

    但是当我们把程序运行到*(p + 2) = 'm'这一行,程序会因为我们尝试对字符串常量区进行写入而触发C05错误,如图所示:

    现在我们对字符串常量区的读写属性进行修改。停止VS中的调试,用文本编辑器打开刚才编译链接生成的可执行文件,如图所示:

    可以看到里面有各种区域,我们关心的是rdata区,也就是只读数据区。这个区域的读写属性被编码成了一个字节,位于段落开始后的两行半处(习惯上每行看16字节,两行半就是40字节,十六进制偏移为0x28)。把它从原来的40修改成和data区一样的C0,如图所示:

    保存文件,再次运行(注意不要用VS重新编译源代码。重新编译的话,链接器会把rdata区域的读写属性重新置为默认的只读)。可以发现,我们成功地执行了程序的意图,把“hello”里的字母l改成了m,如图所示:

    PE文件中各个区域的读写属性是通过位来编码的,前四位二进制数(0000)分别代表写、读、执行、共享(英文缩写为WRES)。所以原来的40(4的二进制0100)代表的只读,被我们修改成了C0(C的二进制1100),也就是可写可读。

  • 相关阅读:
    IntentService使用以及源码分析
    Android HandlerThread源码解析
    Android Handler消息机制源码解析
    Gradle技术之四
    Android EditText实现小数点后几位的终级方案
    Gradle系列之三 Gradle概述以及生命周期
    Gradle系列之二 Groovy对文件的操作
    Gradle系列之一 Groovy语法精讲
    Context源码分析
    用EXCLE群发outlook邮件
  • 原文地址:https://www.cnblogs.com/zhugehq/p/6555881.html
Copyright © 2011-2022 走看看