之前介绍了几种让IDA F5无法得知函数参数的技巧
本文介绍一种让IDA F5正常显示函数参数,但却并不是函数实际参数的技巧
比如显示是puts("7777")
,但实际上运行时是puts("4396")
源码、编译
代码如下:
#include<stdio.h>
#include<stdlib.h>
int func(int a,int b){
printf("%d %d\n",a,b);
return a+b;
}
int main(int argc,char**argv){
func(12345678,12345678);
func(12345678,12345678);
func(12345678,12345678);
func(12345678,12345678);
return 0;
}
//gcc -m32 main.c -o test
IDA打开,惯例先patch掉一些东西
最初的main函数
我们把0x0804846C
到0x0804847E
全部nop
掉
patch
我们主要利用在参数压栈过程中,使某段时间esp并不以4字节对齐的技巧,来欺骗IDA的参数识别
patch如下,main函数被显示栈不平衡,虽然不知道为什么,但这没有什么关系,我们还可以F5
其中0x0BC614E
就是十进制12345678
因为栈是从高向低生长的,我们先多让esp
减去一,再push
参数
这将导致其实只让3个字节进入函数参数范围,最后的一个字节其实没有用
然后再inc esp
消去影响
看起来IDA应该能很轻松发现这里参数有问题,但实际上...
main函数里是有一点差别
点进sub_8048474((int)&savedregs)
仍然显示的是func(12345678,12345678)
对于像我这样不喜欢动态调试只会F5的人...可以说是灾难了
动态调试
在gdb里调试一下看看参数具体状况
在esp
仍然以四字节对齐时,gdb-peda
给了很多有用的栈上内容信息
再跟进一步,信息全乱了
在我们call func()
前,栈上内容如图
参数分别是0xbc61
和0xbc614e
,并不像IDA识别的那样
而实际运行结果如下
尝试精确控制参数值
其实是可以精确控制成我们要的参数的值的,尝试控制第一个压栈的参数
patch形如这样
假装0x0ABCD6789
是参数,但后面三条指令对它进行了修改
动态调试一波
伪装的参数刚压栈
断在两条指令后
注意栈上内容,0x55556666
改变了两字节
这样我们确实可以精确的控制参数...
遗憾的是这个被F5识别出了意图:(
效果较好的一次
patch如图
F5结果
调试:
限于篇幅这段调试过程比较难说明,我自己调试时也想了很久,有兴趣的师傅们可以上手调试一下
结果就是,我们不仅可以欺骗IDA,还可以把
0x89674523
精确的控制成0xbc618967
运行结果:
总结
最后的一次控制参数比较烧脑,也可能是我还tcl...
欺骗IDA真是一种乐趣...