精易论坛

标题: 堆内存释放bug修复2.0 重写兼容数据执行保护 [打印本页]

作者: haishifu    时间: 2019-8-11 19:07
标题: 堆内存释放bug修复2.0 重写兼容数据执行保护
之前发过一个堆内存释放无效指针导致崩溃的帖子
原帖=  https://125.confly.eu.org/forum.php?mod=viewthread&tid=14327228&extra=


这个bug   win的dll也是存在的    貌似17年也有人发过帖子  利用这个bug可以进行页覆盖执行shellcode  前不久看到的攻击漏洞

但是这个bug正常使用中触发几率非常非常小,可能被window忽略了

但是这些bug一旦触发却会影响我们的程序,比如一些莫名其妙的崩溃,也许时它造成的。

距离发那个帖子也有很长时间了,不知道新版易语言有没有添加检测了 或者 微软有没有修复了

但是用低版本的还是有的,比如我


由于原帖的修复补丁采用的时shellcode方式,在系统开启了数据执行保护就直接崩溃了


因为一直懒得写,就没有再发,因为这个修复确实有点简单了  就hook一下。

好吧,多人反馈崩溃,今天就重写了个,编译性的静态hook,不再使用内存执行,兼容数据执行保护的

其实也是很简单的,虽然我这里只写了只能安装MOV edi,edi  栈帧头   开头的,

(静态无冲突hook的实现): 原理是很简单的,无非就是利用编译所生成的程序内存,因为在这块内存执行EDP是不会冲突的,完全可以预留一块内存并直接修改使用,但是要实现高速执行需要考虑到对齐的方式,这里就不再详细说了。

当然,我这里写的hook仅针对于这个堆内存释放api了  所以里面是没有静态且无冲突hook安装的动态实现的。这里面是静态实现了。



更新内容:
               1.不再使用内存执行
               2.不再使用HeapSize进行指针检测(因为HeapSize api也有bug的 检测不对劲的指针也会崩溃,不知道是特权指针还是什么指针的问题。。反正我没弄明白,指针是正常的就是崩了,可能是缺少了点什么东西。)
               3.使用自定义指针检测(虽然无法保证这个指针是堆内存的指针,但是问题不大),




测试动图



修复堆释放2.0.rar (338.15 KB, 下载次数: 467)

作者: haishifu    时间: 2019-8-11 19:34
@wscpf1919  多线程稳定性因素有很多的。比如一条线程使用内存过于离谱也会被内存管理杀,因为用的进程默认堆,这种情况就需要让线程拥有自己的堆了,虽然我早写好了。。。这个修复仅是修复内存重释放导致崩溃的bug,适合多线程的,如果线程所调用的命令有重释放bug的 ,也能提升一定的稳定性的。
作者: nanli    时间: 2019-8-11 21:07
下载看看
作者: weil    时间: 2019-8-11 21:09
66666的源码!
作者: 温柔wr    时间: 2019-8-11 21:21

作者: hellohexiang    时间: 2019-8-11 23:18
求挑战分享 文本按分隔符分割成文本数组的快速方法 看到易语言官方论坛那边说 一千万行数据按分隔符分割到文本数组只需260毫秒左右?这么快?很好奇!!!http://bbs.eyuyan.com/read.php?tid=408061&page=6
作者: haishifu    时间: 2019-8-12 01:33
hellohexiang 发表于 2019-8-11 23:18
求挑战分享 文本按分隔符分割成文本数组的快速方法 看到易语言官方论坛那边说 一千万行数据按分隔符分割到 ...

这个啊  我发现这个重释放会导致崩溃的时候就是在写快速分割的。  不过当时写了有个bug就放着了  实用性也不太大   分割了也只能读取,不能其他操作。。。后面弄链表数组了,快速又能对成员操作还能秒释放。听你一说翻出来修复bug,汇编代码用位运算实现的,看了半天,我都不知道我TM当初写的是啥。。。  不过修复好了

1000万行的话,一行5个字节这个速度



源码给你了。 快速分割.e (11.26 KB, 下载次数: 17)

作者: 毛超    时间: 2019-8-12 23:36
感谢分享!!!!!!!
作者: 土豆W    时间: 2019-8-13 08:56
感谢楼主666666
作者: feng5555    时间: 2019-8-13 13:04
修复堆释放?
作者: bustvr    时间: 2019-8-14 21:22
谢谢源码分享!!
作者: oppp999    时间: 2019-8-18 14:00
感谢楼主666666
作者: kmskik    时间: 2019-8-20 09:09
只需要在窗口创建完后调用一下就可以吗
作者: fdassd    时间: 2019-9-1 21:05
感谢分享.......
作者: 神马不是黑马    时间: 2019-9-5 18:14
提示: 作者被禁止或删除 内容自动屏蔽
作者: 心智帅哥    时间: 2019-9-17 22:59
顶起,谢谢楼主。
作者: 心智帅哥    时间: 2019-9-17 23:01
顶起,谢谢楼主。
作者: 心智帅哥    时间: 2019-9-21 23:22
谢谢楼主分享
作者: jjdd2    时间: 2019-9-25 09:17
可以的谢谢分享
作者: 列明    时间: 2019-9-25 11:06
你寫的每一個字我都認識,甚至你寫的每一句話我都理解,但是你寫的這個帖子我還是看不懂。
作者: 心智帅哥    时间: 2019-9-27 21:43
支持开源~!感谢分享
作者: 雨潇    时间: 2019-9-29 16:16
这个下过来学习一下。
作者: Dosnow    时间: 2019-9-30 21:23
没这么复杂,只要 adr-1 的地址有效就不会崩
崩的都是你用VirtualAlloc申请的内存作为堆内存释放了
Hook RtlFreeHeap 然后
0!=IsBadReadPtr(Adr-1) 的话就直接返回就可以了
作者: Dosnow    时间: 2019-10-5 16:20
本帖最后由 q78410326 于 2019-10-5 16:34 编辑
q78410326 发表于 2019-9-30 21:23
没这么复杂,只要 adr-1 的地址有效就不会崩
崩的都是你用VirtualAlloc申请的内存作为堆内存释放了
Hook  ...

既然你这么说 我就不和你争了  我也并没有说你的方法不对 更没有攻击你的意思
只是看到你图片上有检测指针是否有效的函数   后面的函数基本上就不需要了
你如果不知道是怎么崩的   你就用OD跟一下代码也很简单 易语言编译的垃圾代码比较多
系统API 影响不了你的性能的
该释放就要释放 不然会内存泄露的









作者: haishifu    时间: 2019-10-5 21:36
q78410326 发表于 2019-10-5 16:20
既然你这么说 我就不和你争了  我也并没有说你的方法不对 更没有攻击你的意思
只是看到你图片上有检测指 ...

我不是和你争哦  性能影不影响你自己测试就知道了。。还不知道怎么崩的,这话说的,你不知道什么是变量自销毁吗?另外再纠正你一下,VirtualAlloc申请的内存用堆释放并不会崩溃的只会释放不掉而已,无效指针才会崩,还有我为什么要hook两个呢?首先调用一般走用户api再走rt api,在用户层如果是无效的直接返回而无需再跳到rtl,另外hook  rtl是为了截获系统dll的释放,还有我发现我hook两个后的性能,比hook一个一样甚至还有快。最后再纠正你发的代码,你这个 -8 只适用于特定的数据结构,相当于字节集的数据指针-8就等于字节集的指针,而不是数据指针,最后的最后,内存不能随意偏移的,有可能你处于界限,而你减去的数值的内存是无效的,系统并没有分配给你,而人家传给你的指针却是有效的,这些很熟悉内存的都会知道,所以,内存是要严谨的,不然,就会出现那些莫名其妙的崩溃。
作者: 〃扯淡的人生    时间: 2019-10-5 21:39
看看~~~                     
作者: Dosnow    时间: 2019-10-7 09:07
haishifu 发表于 2019-10-5 21:36
我不是和你争哦  性能影不影响你自己测试就知道了。。还不知道怎么崩的,这话说的,你不知道什么是变量自 ...

VirtualAlloc申请的内存堆释放是必崩的 -1肯定是空指针
程序传进程的指针就是个空指针 减1也是空指针  所以就崩了
减1法过保护  你不要搞笑了  看看-1是怎么来的
上面是RtlFreeHeap的反汇编崩溃的地方   能看懂就看吧 看不懂我也懒的再回复了

性能的话你自己看吧 1是你模块的 2是IsBadReadPtr检测内存可读 3是SEH
哪个速度快自己看咯 SEH 0.5S



代码一并给你

#include <windows.h>
#include <ntdll.h>


void   Jmp(LPVOID dwTo, DWORD dwFrom)
{
        DWORD dwOldProtect;
        HANDLE Handle = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());
        VirtualProtectEx(Handle, (LPVOID)dwFrom, 10, PAGE_EXECUTE_READWRITE, &dwOldProtect);
        *(BYTE*)dwFrom = 0xE9;
        dwFrom += 1;
        *(DWORD*)dwFrom = (DWORD)dwTo - (dwFrom + 4);
        CloseHandle(Handle);
}

BOOL WINAPI MyHeapFree(HANDLE HeapHandle, ULONG Flags, PVOID Address) {

        if (0 != IsBadReadPtr((PVOID)((DWORD)Address - 8), 8))
                return FALSE;
        return  RtlFreeHeap(HeapHandle, Flags, Address);

        /////////////////////SEH////////////////////////////////

        //__try {
        //        return RtlFreeHeap(HeapHandle, Flags, Address);
        //}
        //__except (1)
        //{
        //        return FALSE;
        //}

}

BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, PVOID pvReserved)
{
        if (dwReason == DLL_PROCESS_ATTACH)
        {
                Jmp(MyHeapFree, (DWORD)HeapFree);
        }
       
        return TRUE;
}
Release.zip (82.91 KB, 下载次数: 2)



作者: haishifu    时间: 2019-10-7 17:29
q78410326 发表于 2019-10-7 09:07
VirtualAlloc申请的内存堆释放是必崩的 -1肯定是空指针
程序传进程的指针就是个空指针 减1也是空指针   ...

你这杠精挺6  你拿我触发崩溃的代码的指针来-1 , 我去,你要笑死我。另外这个指针-1关你检测毛事? 你不知道window喜欢用各种掩码?脑c把。。     另外你的测试图一看就是测试无效指针的速度,拜托测试下有效指针的速度??难道你写的程序都是无效指针多,而有效指针少?
作者: haishifu    时间: 2019-10-7 17:34
q78410326 发表于 2019-10-7 09:07
VirtualAlloc申请的内存堆释放是必崩的 -1肯定是空指针
程序传进程的指针就是个空指针 减1也是空指针   ...

还代码一并给我。。。你这代码的hook为何仿照着我的代码呢?我倒是想知道你没看我代码会不会算这个偏移。 另外你不知道修改内存属性的进程句柄直接可以传-1吗? 还打开进程。
作者: haishifu    时间: 2019-10-7 17:48
q78410326 发表于 2019-10-7 09:07
VirtualAlloc申请的内存堆释放是必崩的 -1肯定是空指针
程序传进程的指针就是个空指针 减1也是空指针   ...


好好悟悟这张图,另外,你要减-1也好-8也好,我不知道你是什么想的,你别在我这喷啊,在论坛发个帖子出来给别人学习不是更好?另外为什么我写的检测在无效时那么慢,因为我使用了系统领空而不是直接返回代码处,因为我懒得写,再说我写那么完美给你们看干啥,再说了,还是那句话:难不成你无效的指针要比有效的指针多的多??最后就别回复了。

作者: haishifu    时间: 2019-10-7 18:18
q78410326 发表于 2019-10-7 09:07
VirtualAlloc申请的内存堆释放是必崩的 -1肯定是空指针
程序传进程的指针就是个空指针 减1也是空指针   ...

还有,VirtualAlloc申请的会不会崩就得看你申请内内存是不是处于界限了  问题是没有人会傻到VirtualAlloc申请的内存用HeapFree来释放把??都是用的VirtualFree把?   另外   VirtualFree我是没遇到过无效指针会崩的,至于内存为什么要用堆我就不多说了。还有还有,你要减1减8的你是没观察到过界限把,有时候申请的两块内存可能是会相连的。小心别把其他的内存给释放了。
作者: Dosnow    时间: 2019-10-7 18:21
haishifu 发表于 2019-10-7 17:34
还代码一并给我。。。你这代码的hook为何仿照着我的代码呢?我倒是想知道你没看我代码会不会算这个偏移。 ...

好吧  你牛逼  你牛逼  你牛逼   
作者: haishifu    时间: 2019-10-7 18:32
q78410326 发表于 2019-10-7 18:21
好吧  你牛逼  你牛逼  你牛逼

我不牛逼,我只是给程序的变量释放加了个补丁而已,像你说的检测-1   你相当于把那些用VirtualAlloc申请用HeapFree释放的那些人害了而已,   以为释放掉了却看看任务管理器内存一直涨。你要弄的完美不应该是单单检测-1把? 你得检测0再检测-1是不是界限来判断是虚拟内存还是堆内存  然后再用对应方式释放把? 当然这也是不可行的,因为不处于界限的虚拟内存-1也是有效的指针,然后你想用虚拟内存的api来检测,接着发现人家释放个堆内存性能却慢的慌?所以我一开始完全看不懂你在说什么,应该明白了你就是想用VirtualAlloc申请用HeapFree释放永远不会崩,可是那有意义么?你的内存并没有释放掉啊,而我的目的只是单纯的将堆释放无效指针会导致崩溃的问题给补丁了。
作者: cosset    时间: 2019-10-13 09:26
支持开源~!感谢分享
作者: 心智帅哥    时间: 2019-10-13 23:22
支持开源~!感谢分享
作者: 弱鸡第一步    时间: 2019-10-18 15:05
吵的挺凶的 那就来看看是什么东西把
作者: jiahui    时间: 2019-11-10 22:24
学习学习 谢谢楼主的分享
作者: EX飞哥    时间: 2019-11-16 10:19
666666666666666
作者: 就是那个秋    时间: 2019-11-23 21:19
        支持开源~!感谢分享
作者: 心智帅哥    时间: 2020-3-8 20:27
支持开源,感谢分享~!
作者: 落寞23333    时间: 2020-3-9 22:59
多谢大佬解决了我困扰多年的问题
作者: 心智帅哥    时间: 2020-3-17 23:05
支持开源,感谢分享~!
作者: 心智帅哥    时间: 2020-3-22 21:01
支持开源,感谢分享~!
作者: 心智帅哥    时间: 2020-3-23 21:29
支持开源,感谢分享~!
作者: gaoqing    时间: 2020-3-24 18:22
正好需要谢谢
作者: zch41022022    时间: 2020-3-26 13:55
        新技能已get√
作者: 646hjhj    时间: 2020-4-9 21:15
感谢楼主分享,支持一下!
作者: 70805    时间: 2020-4-14 11:59
正好需要谢谢分享
作者: 前端    时间: 2020-6-7 19:33
感谢分享,支持一个
作者: xiaogui888    时间: 2020-7-12 11:55
看看能不鞥加速电脑速度吧!
作者: q3406248    时间: 2020-7-18 21:12
谢谢分享,学习一下
作者: Krust    时间: 2020-7-24 09:45
新技能get,感谢分享!
作者: 涛哥在此    时间: 2020-8-31 15:40
6666666666
作者: xujianc    时间: 2021-7-5 12:28
66666666666666666
作者: 杰西卡技术传媒    时间: 2021-8-13 10:51
感谢发布原创作品,精易因你更精彩!
作者: yuxuanju    时间: 2021-9-26 18:25
已下载,winxp中测试。




欢迎光临 精易论坛 (https://125.confly.eu.org/) Powered by Discuz! X3.4