好友
阅读权限10
听众
最后登录1970-1-1
|
|
自己开了几百个记事本测试 没有问题
看了老师(链接:https://www.52pojie.cn/thread-2109207-1-1.html)的帖子
自己正好学到内存这块 自己也要经常用winhex 突发奇想想尝试处理下
这次主要研究的是 WinHex 进程列表数量上限 的问题。
默认情况下,WinHex 在枚举进程时最多只能显示一部分进程,我的目标是把这个数量上限扩大,让它能够显示更多进程。一、分析目标目标很明确:把 WinHex 原本的进程枚举上限从大约 255 个进程 提高到 600 个进程左右。核心思路是:- 找到调用 EnumProcesses 的位置。
- 找到保存进程 PID 数组的缓冲区。
- 修改缓冲区大小参数。
- 修改读取 PID 数组的位置。
- 必要时新增节,放一个更大的缓冲区。
二、32 位版本分析过程32 位版本里,最开始看到的关键点是 EnumProcesses 附近的参数。原本代码里使用的是栈上的缓冲区,大概类似:
lea eax, [esp+4C8]
mov edx, 3FC
push 3FC这里的 3FC 就是传给 EnumProcesses 的缓冲区大小。0x3FC = 1020 字节。因为一个 PID 是 4 字节,所以:
1020 / 4 = 255也就是说,原本最多只能保存 255 个 PID。 三、第一次修改:把 3FC 改成 960为了提高进程数量,我把 3FC 改成了 960。
0x960 = 2400 字节
2400 / 4 = 600也就是理论上可以保存 600 个进程 PID。相关位置主要有:
004F46F7 mov edx, 3FC
0042D299 push 3FC修改为:
mov edx, 960
push 960但是只改这里还不够,因为原来的缓冲区是在栈上,空间不一定够,容易覆盖其他数据。 四、新增节 .ndata 放更大的缓冲区为了解决栈空间不够的问题,我新增了一个节:
节名:.ndata
VA:00305000
实际运行地址:00705000
大小:0x4000然后把原来指向栈缓冲区的地方改成指向新节。原本:
lea eax, [esp+4C8]改成:
mov eax, 00705000对应修改位置:
004F46F0 / 004F4701同时,后面读取 PID 数组的位置也要改。原本:
004F4719 lea ebx, [esp+4C8]改成:
mov ebx, 00705000这里很关键。一开始我只改了 EnumProcesses 的缓冲区地址和大小,结果 EnumProcesses 成功了,但是列表还是空的。后来继续追踪发现,程序后面读取 PID 的时候,还是从原来的 [esp+4C8] 读取,所以必须把读取点也一起改掉。 五、32 位最终关键修改点整理一下 32 位版本最终关键补丁点:
004F46F0 / 004F4701
lea eax, [esp+4C8]
改成:
mov eax, 00705000
004F46F7
mov edx, 3FC
改成:
mov edx, 960
0042D299
push 3FC
改成:
push 960
004F4719
lea ebx, [esp+4C8]
改成:
mov ebx, 00705000新增节:
.ndata
VA:00305000
运行地址:00705000
大小:0x4000最终 32 位版本可以正常显示超过 255 个进程。 六、64 位版本分析64 位版本思路和 32 位差不多,也是围绕 EnumProcesses 的缓冲区和大小参数改。64 位版本里我换的新节地址是:
00000000007FC000关键点同样是:
mov edx, 960也就是把传给 EnumProcesses 的大小改成 0x960,理论上支持 600 个 PID。不过 64 位版本比 32 位麻烦一点,因为指令长度、寄存器使用、地址写法都和 32 位不一样,不能简单照搬 32 位的 patch。64 位里重点是:- 找到 EnumProcesses 调用点。
- 找到原本传入的 PID 缓冲区。
- 把缓冲区地址替换成新节地址 00000000007FC000。
- 把大小参数改成 960。
- 后续读取 PID 的位置也要同步修正,否则枚举成功但显示不出来。
七、踩坑记录这次踩坑最多的地方不是 EnumProcesses 本身,而是后续读取逻辑。一开始以为只要把:
push 3FC或者:
mov edx, 3FC改成 960 就行。但实际测试发现不够。因为程序流程大概是:
准备缓冲区
调用 EnumProcesses
返回 PID 数组
根据返回字节数计算数量
再从缓冲区读取 PID
显示到列表如果只改了枚举时的缓冲区地址,但是后面读取还是读原来的栈地址,就会出现:
EnumProcesses 调用成功
但是列表为空或者显示异常所以真正完整的修改一定是两部分:
写入 PID 的地址要改
读取 PID 的地址也要改 八、最终效果最后的效果是:WinHex 原本只能显示大约 255 个进程,修改后可以显示超过 255 个进程,目标上限提升到大约 600 个。这次最大的收获是:逆向 patch 不能只看一个 API 调用点,还要顺着数据流继续往后看。尤其是这种缓冲区修改,必须确认:
谁写入这个缓冲区
谁读取这个缓冲区
读取地址有没有同步修改
缓冲区大小有没有同步修改否则很容易出现“API 调用成功,但程序功能没效果”的情况。 九、总结这次 WinHex 进程上限修改的核心就是:
原缓冲区大小:0x3FC
原最大 PID 数量:255
修改后大小:0x960
修改后理论 PID 数量:60032 位版本通过新增 .ndata 节,把 PID 缓冲区从栈迁移到新节中,再同步修改 EnumProcesses 参数和后续读取地址,最终成功突破原来的显示限制。这次也算是比较典型的一次补丁练习:
API 参数分析
栈缓冲区定位
新增节利用
数据流追踪
读取点修正比单纯改一个判断跳转更有意思,也更接近实际逆向里经常遇到的问题。 32位64位的都改好了 我放云盘里了 https://wwbrv.lanzn.com/ib5vS3rm608h |
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|
|