由于在书里没有找到具体的托管资源数据结构,这个过程主要通过dnlib源码进行分析。
以上是本次研究使用的样本,目的是能够顺利读取到托管数据中的PE文件,即“资源正文”(便于理解)。
源码开始就做了一个4字节的判定,因此在不明含义的时候,先把他当作一个四字节的固定标识来看。
接着是一个checkreader函数:
也就是标识符,后面4个字节(4-8)为numReader,8-12就是readersdSize,后面是resourceReaderFullName和resourceSetFullName两个字符串。
接下来,是三个整型,分别为version,numResources, numUserTypes:
可以看到,版本2,资源数目为2个:
验证一下:
顺便拿来另一个资源数据来看,版本2,资源数目12个。
后面就是基于numUserTypes读取了一波字符串,然后不当人的弄了一个reader的position赋值,~在C#里是按位取反运算符是一元运算符,具有"翻转"位效果,即0变成1,1变成0,所以 0000 0111 变成1111 1000:
复习了一下补码反码的知识:
负数 = 负数的绝对值按位取反+1
负数按位取反+1 =负数的绝对值
因此1111 1000值为-8
那也就是说,当前的位置(当前应该指向第0x0111个字节)会变成 (当前偏移+7)& 11111000,为0x0118。
之后基于numResources会连续获取两组整型数,offsets后面对的寻址有用。
获取到dataBaseOffset才算是真正即将开始资源正文,然后获取资源名称,和资源偏移加载资源:
至此,通过dataBase加上resourceOffset就能够准确地找到资源的正文了,前5字节为7bit编码整型数,表示资源类型。算法如下:
之后为正文内容,分析结束。
网友评论