按照网上资料,我现在按照PE结构自己读取资源节已经没有什么问题了——因为网上资料上对资源部分的结构描述的还算详细,所以按照原理总是可以写出来的。而.rdata 段,貌似有全部变量和常量吧,这个却没找到资料描述是以什么样子的格式(或者说结构)存储的,那到底该怎么读取呢?
========================================之所要读取这个段,原因是这样的:
找到一个第三方的程序,里面有一段字符串我想要修改,但是他不在资源节里,也就是这个字符串是属于汉化领域所谓的“非标资源”。
当然,我向简单修改的话,只需要使用二进制编辑器(如UE)查找数据并修改保存就可以了。
但是第一这个程序更新频繁,第二我的目的是想利用学到的PE结构知识写个通用的“内存”补丁,在程序启动时在内存中修改,免得每次都要查找修改(在其资源节中也有需要修改的地方,我已经写完了,证实可用)!我用PE结构的方式遍历过这个程序的各个节并取出各自的二进制数据,发现我想要修改的数据就是在.rdata 段中。
当然,我知道这个段的属性是只读的,但是我发帖子问的不是“如何修改只读”的问题,这个我想修改段的属性可以解决吧(即使解决不了也没关系,我的目的是加深对PE结构的了解)所以我的问题就是怎么用PE结构的方式读取到.rdata的数据(不是读入二进制在查找数据的方法哦,因为我要写内存补丁)。
请前辈们帮帮忙,其实最关键的只要有前辈能给出这部分的数据的存储结构就可以了,感激不尽!!!

解决方案 »

  1.   

    没有规定的结构,里面放的常量,字符串,在代码中有地址就行,不需要什么组织结构
    变量不会放在rdata,因为只读
    如果那个模块有.reloc,你可以在那里面搜索字符串的地址
      

  2.   

    那该怎么查呢?我这个程序之后4个段,分别是:
    * “节表名称” | “.text”
    * “节表名称” | “.rdata”
    * “节表名称” | “.data”
    * “节表名称” | “.rsrc”
    没有 .reloc ,我该如何确定字符串的地址呢???
      

  3.   

    楼主可以参考一下:
    http://hi.baidu.com/gufengboy/home
    http://hi.baidu.com/ses2010/blog/item/d0b5fa20da4ea4be4623e8a1.html找资料最好还是到codeproject/codeguru去,鬼子还是比较专业的。
      

  4.   

    暴力搜索?是不是就是在该段搜索我需要的字符串的二进制位置呢?我这样尝试过,是可以找到一个位置的,但是我写的是内存补丁,找到位置后我也尝试将其换成RVA,可貌似是无效的,我调试该程序运行时读取这个RVA的内存数据,不是我要的字符串!这2个资料我确实没翻到哦,还是很详细的,值得学习。
    但是这2篇文章关于.rdata的部分,都是说如何写入一个导入表结构信息,就是DLL引用的部分,没有提及到字符串常量的部分啊这貌似跟我的需求不符啊
      

  5.   

    那两个地址对你没帮助既然你能找到位置,就能换成rva
    你现在能不能编程找到rdata的VirtualAddress和PointerToRawData
      

  6.   


    当然可以了啊但是找到rdata的VirtualAddress和PointerToRawData之后该怎么操作呢?我尝试过好几种方式想要计算出我要查找的那个字符串的RVA,但当该程序运行时,我读取他的进程内存,却不是我想要的数据啊(我读取的方法应该没有问题,因为我读取资源节的内存数据都是完全正确的)
      

  7.   

    因为我使用的是易语言,CSDN没这个版块,所以发在这里,因此我就不写易语言的代码了,我描述下我的方法:
    1、对于资源节的获取:
    DOS头偏移找到NT头,NT头+24字节找到可选头,可选头+可选头结构的大小就找到 节表数组开始的位置;
    获取可选头最后一个数组成员中的第三个成员(资源目录)的 VirtualAddress(RAV1),然后遍历节表数组,判断 当前数组.VirtualAddress ≤ RAV1 ≤ 当前数组.VirtualAddress + 当前数组.VirtualSize 的话,那么 当前数组.PointerToRawData 就是资源节在文件中的偏移量,然后再分析资源数据就可以找到我想修改的部分了
    2、对于我修改的那个字符串的获取:
    我不知道怎么用上面类似先获取第三个数据目录的 VirtualAddress 方法(资源节是固定的3,我却不知道我要找的字符串到底是几)
    所以我是这样找的:
    同上,在找资源的时候,到了遍历节表数组时,我获取每个节表数组.PointerToRawData,然后通过这个文件偏移,我读取出 当前数组.VirtualSize 个大小的二进制数据 *B,然后我在 *B 中寻找我想要修改的那个字符串的二进制数据,发现确实能找到,并且此时判断 当前数组.Name 成员,名称确实是 .rdata。找到的位置 X 是相对于 *B 的,然后通过 X + 当前数组.PointerToRawData 就可以计算出我要修改的字符串相对于整个文件的偏移 P1,但这个是文件中的偏移,内存中的RVA P2就是:
    P2 = P1 - 数组.PointerToRawData + 数组.VirtualAddress 也就是 = X +  数组.VirtualAddress 我认为就是找到了 我要修改的字符串在内存中的 RVA,但是在程序运行时我获取该进程的内存数据,却不是我要修改的字符串不知道我这样对不对啊
      

  8.   

    你先找到rdata在文件中的位置
      

  9.   

    不懂按照我上面的说法,我遍历节表数组,数组每个成员的 PointerToRawData 不就是文件偏移吗?
    只要这个成员指定的 PointerToRawData 开始、VirtualSize 大小的数据中包含了我需要的,那么:
    1、它的 PointerToRawData 不就应该是你所说的rdata在文件中的位置吗???这个位置 + 在文件中找到要修改的数据偏移量,理论上在文件中就可以取到与“要修改的数据”同样的二进制数据吧?但实际却不是这样
    2、它的 VirtualAddress 不就应该是我要找的那个节的RVA吗???然后我只要这个 RVA + 在文件中找到我要修改的数据偏移量,理论上在程序运行时就可以取到与“要修改的数据”同样的二进制数据吧(当然要加基址ImageBase)?但实际却不是这样感觉像是对的,但实践证明我说的这些都不对但是为什么呢???唉!
      

  10.   

    你找到rdata的pointertorawdata
    和rawdatasize就可以巴rdata读到内存,然后搜索字符串,找到字符串的节内偏移,加上rdata的virtualaddr即可
      

  11.   


    你说的这个不跟我上面的理解一样吗???(rawdatasize 应该是 SizeOfRawData 吧,只是这个大小你说的与我不一样)。我测试过了结果一样都是错的,无论是在文件中搜索还是在内存中搜索(因为这与我上面说的方法找到的文件起始位置(即 pointertorawdata)都是一样的,所以结果必然还是不对喽)