最近才对call 的堆栈平衡有点小小领悟,别笑话俺。
学习各种外挂制作技术,马上去百度搜索 "魔鬼作坊" 点击第一个站 去那里学习喽。
当你对游戏某项功能实现的时候需要调用call  ,call 前面往往有一些入栈操作
例如        push  a
push b
push c
push d
call  游戏功能子程序
调用子程序的例子
游戏功能子程序:
push esi
push ebx
.
........
add  esp ,4 /sub esp ,8
.........
pop  ebx
pop  esi
ret 
简单解释: 
子程序中 不管对堆栈如何操作(像上例中的add esp ,4 或者sub esp ,8) 不管游戏子程序开始对应的push /pop 乱起八糟的有多少,只要到子程序末尾的 ret  ,那此时堆栈一定退回到 call 刚入栈的状态,esp的值 = eip的值(即call调用子程序结束后,需要执行的下个语句的地址)
简单分类:
1 .  “游戏子程序”末尾是  ret 
这个需要call调用返回后,用户自己对堆栈进行平衡,像上面的例子 ,调用前压入了4个参数 ,返回后,4个参数还在栈中,占用了堆栈的十六进制的4*4=10
的栈空间 ,那自己注入写的代码 需要 在call 后面加add esp ,10 
如果您的程序接下来的执行,需要压入的参数,那您可以不用 平衡,平衡交给后面执行的程序。
但我们见的99%的需要马上平衡,后面程序不需要上面压入的参数,那自己注入代码 需要 在call 后面加add esp ,10 ,来进行堆栈的平衡操作。
2.”游戏子程序”末尾是  ret  N
这个是您调用的call 子程序 ,自己对堆栈平衡做了操作,这样的一般来说就不用我们对注入的代码进行 add esp 参数个数*4 的操作了
ret N    就是程序运行到这句时  ,先执行 ret  ,同时让 add  esp ,n 操作。 ret是返回调用程序 ,add esp ,n 是对被调用程序压入的参数操作,以使堆栈平衡 
ps:当自己嵌入汇编代码到其他高级语言的时候 ,注意您自己的参数是否正确,否则程序要么提示**内存不可读,要么直接挂掉退出。
比如 上面例子 push a  a 是一个地址  ,您却把此地址的值压入了栈,当执行call程序的时候,访问虚拟内存这个地址的时候,是不会到的,因为您传入的是一个值,而非地址。
俺以前经常犯这样的错误,总认为很对,结果。。。
学习各种外挂制作技术,马上去百度搜索 "魔鬼作坊" 点击第一个站 去那里学习喽。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。