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),也就是可写可读。

  • 相关阅读:
    题解:luoguP1861 星之器
    题解:LOJ540游戏
    Yii框架常见问题
    常用ubuntu命令
    Python中的映射数据类型 dict
    Python中的编码问题:ASCII码 Unicoden编码 UTF8编码
    Python中的列表、元组的增、删、改、查
    Python 数据类型之 集合 set
    Python中常见的字符串的操作方法:
    Python程序的控制结构用多分支结构处理身体指标BMI问题
  • 原文地址:https://www.cnblogs.com/zhugehq/p/6555881.html
Copyright © 2011-2022 走看看