用jemalloc替换东方深秘录中的内存分配器.PDF

用jemalloc替换东方深秘录中的内存分配器.PDF

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
用jemalloc替换东方深秘录中的内存分配器

用jemalloc 替换 东方深秘录 中的内存分配器 一、概述 在《东方深秘录 反调试分析》中提到一个奇怪的现象:当使用调试器加载程序时,游 戏会运行得非常缓慢、卡顿。经过分析后得知,这是由于动态内存分配函数HeapAlloc 与 HeapFree 在此情况下运行速度比平常慢导致的。文中给出的解决方案之一是把程序中原来 的内存分配器用高效的内存分配器替换掉。本文的目的就是实现这一解决方案。 本文中,所选用的高效内存分配器是jemalloc。它从 2005 年开始被 FreeBSD 的 libc 所采用,是速度最快的内存分配器之一。 二、C 语言动态内存分配函数简介 C 语言的动态内存分配函数主要由4个函数组成: (1)malloc(n): 分配一段大小为n 的内存 (2)calloc(n, s): 分配一段大小为n * s 的已清零内存 (3)free(p): 释放p 所指向的内存 (4)realloc(p, s): 将p 指向内存分配的大小重置为s 三、思路 最初的思路很简单,也很直接: (1)修改程序让程序开始执行时加载jemalloc 的动态链接库 (2)修改原始内存分配器的入口点指令,使其跳转到jemalloc 中的对应函数 然而,事情并非想象得那么顺利。上面的思路遇到了一个问题,在程序开始执行时,似 乎已经有某段代码调用了内存分配函数。因此,旧内存分配器与新内存分配器的衔接便成了 问题 (主要由于realloc)。因此只好修改原来的思路: (1)修改程序让程序加载我们自己编写的rmalloc 中间层 (2)修改原始内存分配器的入口点指令,使其跳转到rmalloc 中的对应函数 (3)rmalloc 检查调用请求。若传入的内存是旧内存分配器分配的,则交由旧内存 分配器处理;若是jemalloc 分配的,交由jemalloc 处理。 四、实现 (1)编写shellcode shellcode 是写入游戏程序里的一段代码,它的作用是加载并调用patch.dll 中 我们编写的程序。由于没有链接器的支持,我们编写的代码不能直接调用Windows 提供的API 函数,所以要使用shellcode 的方式来寻找API 函数的入口点。 (2)动态链接库patch.dll patch.dll 的主要任务是加载 rmalloc.dll,并且把旧内存分配器的入口点修 改为跳转到新内存分配器的指令。它还会顺便把 patch.dll 中的反调试代码禁用 掉。 (3)动态链接库rmalloc.dll rmalloc.dll 的主要任务是检查传入的内存指针是由哪个内存分配器管理的,并 且交由对应的内存分配器管理。 (4)编译jemalloc 由于我们编写的rmalloc 假设jemalloc 不向系统释放内存。所以jemalloc 必 须以 --disable-munmap 选项编译。 五、rmalloc 实现细节 rmalloc 使用内存指针所在页面来判断该指针是否由jemalloc 管理。由于内存页面 是按照 4KB 划分的。在 32 位系统下,用户空间最多只有 2GB/4KB=512K 个页面。因此 rmalloc 使用一个512KB 的数组来记录该页面是否由jemalloc 管理。 rmalloc 假定jemalloc 不向系统释放内存,因此一旦jmelloc 返回了一个指向某 个新页面的指针,就说明这个页面是由 jemalloc 管理的,而且这个关系在进程结束前都 不会改变。因此rmalloc 没有对页面记录数组使用互斥量,这是没有问题的。最坏情况下, 两个进程同时写入同一个标记,然而无论写入顺序如何,结果总是正确的。 六、修改程序 我们修改程序时,将shellcode 写入到了原来反调试器的代码位置。由于程序加载时 会修改用到外部函数的指令,因此我们的shellcode必须避开被修改的位置。为此,我们 把原始的shellcode 分割为三段,每段之间用JMP 指令跳转。 另外我们还修改了程序入口点的代码,这样程序刚开始执行时就会立刻运行我们编写的 代码。 七、总结 通过上述的修改,程序运行时首先会运行 shellco

文档评论(0)

youbika + 关注
实名认证
内容提供者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档