作者:重楼
给一个CALL传入适当的参数,是要看CALL内部调用了什么参数,而不是看CALL前面压入了什么.CALL前面压入的只是一个参考.
图中便是F8的喊话模拟器.很多初学者朋友都不是很清楚,为啥只要写一个CALL就可以调用喊话.
我们都知道最后那个CALL是调用喊话的核心CALL.我在文章前面说过,要给一个CALL传入适当的参数是要看CALL内部调用了那些参数.我们进入到CALL内部看看
这里是喊话CALL内部的头部部分.这里我们可以看出CALL的内部调用了4个参数.([EBP+*]或者[ESP+*]是指向参数部分具体请看之前的文章)
我们分别来看看这里的4个参数到底读取了什么.
按照顺序来看,首先是 [EBP+14] 喊话内容 [EBP+10] 喊话方式 [EBP+C] 喊话对象 [EBP+8]喊话基址.
从这个CALL的内部我们可以看出 CALL只需要4个参数.
断在程序调用CALL的地方,我们从堆栈里可以看到这里压入了4个参数跟CALL内部是对应的.所以我们这里只需要压入4个参数即可.不需要写上面的那几个CALL
例2
图中是游戏CALL实例ONE中的吃血的CALL 写成代码就是
从图中可以看出这里只赋值给一个EDX,为何要把EAX也赋值呢?我们来看看CALL的内部
如何看CALL需要的寄存器?这里首先我们看看CALL调用了哪些寄存器.
首先是PUSH EBP 然后是PUSH EBX 还有一个 MOV EBX,EAX MOV [ESP-4],EDX
这里的PUSH EBP 和PUSH EBX 其实是 环境保护.因为下面的代码需要用到EBP 和EBX这2个寄存器,但如果直接赋值就会丢失原有的数据?所以为了不丢失原有的数据,只好将他放在某个地方等EBP用完以后再弄回去.而下面的2句 POP ECX 相当于变相的内部堆栈平衡,平衡头部开辟出来的2个堆栈空间
这个代码就是将寄存器保存在 堆栈里.用完后取出. 所以看是不是环境保护的寄存器可以看结尾是否有对应的POP 指令
这里EBP EBX就可以排除了. 下面是 MOV [ESP-4],EDX 结尾没有这个指令,所以这个PUSH EBX 是供给下面那个CALL使用的. 还有一个就是MOV EBX,EAX 在上面并没有给EAX赋值, 而寄存器中的值本身就是空的或者是上个CALL遗留下来的残留数据.这个时候如果被传入了残留数据,那么就会导致指针读取不可读的内存区域导致程序出错.
给一个CALL传入适当的参数
最新推荐文章于 2024-04-22 16:31:53 发布