12558网页游戏私服论坛

 找回密码
 立即注册
游戏开服表 申请开服
游戏名称 游戏描述 开服状态 游戏福利 运营商 游戏链接
攻城掠地-仿官 全新玩法,觉醒武将,觉醒技能 每周新区 经典复古版本,长久稳定 进入游戏
巅峰新版攻 攻城掠地公益服 攻城掠地SF 新兵种、新武将(兵种) 进入游戏
攻城掠地公 散人玩家的天堂 新开 进入游戏
改版攻城掠 上线即可国战PK 稳定新区 全新改版,功能强大 进入游戏
少年江山 高福利高爆率 刚开一秒 江湖水落潜蛟龙 进入游戏
太古封魔录 开服送10亿钻石 福利多多 不用充钱也可升级 进入游戏
神魔之道 签到送元宝 稳定开新区 送豪华签到奖励 进入游戏
神奇三国 统帅三军,招揽名将 免费玩新区 激情国战,征战四方 进入游戏
龙符 三日豪礼领到爽 天天开新区 助你征战无双 进入游戏
王者之师 免费领豪华奖励 免费玩新区 6元送6888元宝 进入游戏
查看: 447|回复: 0

winDBG调试跨模块释放Bug

[复制链接]

345

主题

345

帖子

700

积分

实习版主

Rank: 7Rank: 7Rank: 7

积分
700
发表于 2019-8-20 11:29:00 | 显示全部楼层 |阅读模式
1      概述
打开windbg附加待调试程序再F5运行。之后程序发生异常而中断。Windbg捕捉到了主进程的的异常信息。异常信息格式为:

  图1
1中第1行的调试信息表明堆管理器检测到了DLL_Test.exe进程在调用RtlfreeaHeap从堆0x00240000上释放堆块0x001A3480(用户指针)时指定的地址参数非法。第2行信息表明应用程序是因为断点异常而中断到了调试器,其中(8e8.540)DLL_Test.exe的进程ID和线程ID。事实上,这是堆管理器检测到错误情况并判断当前进程是被调试后故意触发了断点异常。


2      Bug重现
在分析bug的过程一般会有下面4步:定位bug类型、定位bug位置、分析bug成因、解决bug方案。


2.1  定位bug类型
步骤1打开windbgctr+E选择一个要调试的程序。(注意使用!heap命令需要加载ntdll的符号)
步骤2WINdbg命令输入窗口中输入g命令运行起来。WINdbg将会捕捉到异常如图2

2
通过图2,从提示信息中可知,程序在从堆区(00c50000)中释放用户指针(00ca3480)时发生异常。
注:堆块的释放过程。堆管理器在指定的堆区(如00c50000)寻找要释放的堆块(如00ca3480所在的堆块),如果找到则将该堆区的堆块的状态改成空闲状态然后将该堆块添加到堆区的空闲链表中;如果没有找到则触发异常。
步骤3执行!heap –x 00ca3480命令。可以看到00ca3480指针位于00ca0000堆区的00ca3478堆块上。
注:00ca3478是堆块的入口地址;00ca3480用户使用的指针如newmalloc函数返回的地址;00ca0000是所属堆区的地址。到这里可以确定该bug属于内存释放异常中的跨模块释放bug

2.2  定位bug位置
步骤4执行k命令。查看函数调用栈,通过栈回溯的方法来找到触发异常的指针是从哪里来的。

3
用户模式下在最近的一个函数是DLL_Test!free。而DLL_Test!free要释放的指针是由DLL_Test!MyTestFunction函数给他传递的。所以导致异常的函数在DLL_Test!MyTestFunction函数中且位于0118188e的上一条指令及call DLL_Test!free
步骤5执行ub 0118188eL20.如图4.
  4
结合图3,可知函数DLL_Test!operatordelete就是DLL_Test!free函数。且释放的函数指针是从ESP+34h中取出来的。而ESP+34h是在0118183a的位置处赋值的,该位置为一个函数调用即ESP+34h是在DLL_Test!_imp_?getMemberNamesValueJson函数中赋值的。
步骤6 重新调试即重复步骤1. 当程序加载完毕后,执行Bp DLL_Test!MyTestFunction+0xa7DLL_Test!MyTestFunction+0xa7下断点。如图5.

5
注:没有使用绝对地址是因为在下次运行时基地址会发生变化。
步骤7到断点位置后执行u012d1817 L20命令查看代码。并在012d183a处下断点。当走到012d183aF8跟进去看一下给ESP+34h赋值的过程。

图6
步骤8 直接运行到断点处,并用0:000>dd 002af688查看002af688的内容。

图7
跟进getMemberNames函数。getMemberNames中的70dd4f7e位置处是一条all lib_json!std::vector指令。lib_json!std::vector函数会在lib_json模块所属堆中申请一块堆块,并将该堆块的用户指针赋值给ESP+34h
图8
到这里就可以清楚的认识到问题的原因了即,ESP+34h的指针指向的位置是json模块申请的堆块,而且这个堆块属于json模块的堆,但在释放的时候是DLL_Test.exe中的free函数释放的,而DLL_Test.exe中的free函数只能释放属于DLL_Test.exe模块的堆中的堆块。

2.3  解决bug方案
json!getMemberNames函数中申请,并且在json模块再提供一个释放接口。DLL_Test.exe使用一个指针去接受json!getMemberNames返回的数据,使用完后调用json模块提供的释放接口进行释放。这样申请和释放都在json模块中了,就不会出现跨模块释放的问题了。
时间有限后续再补充MT与跨模块之间的关系。
来源:http://www.12558.net
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
楼主热帖
回复

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|12558网页游戏私服论坛 |网站地图

GMT+8, 2024-5-18 11:20 , Processed in 0.295899 second(s), 31 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表