通过调用栈对软件爆破,以后不用总是搜索字符串了
基础知识栈
栈是操作系统在运行时自动初始化的一块区域,是数据暂时存储的的动态内存区域。它的大小在Windows操作系统下由PE文件结构中PE文件头中IMAGE_OPTIONAL_HEADER结构中SizeOfStackReserve字段所定义。在OD中,要想顺利分析软件的功能,在单步需要关注的便是寄存器和栈空间。下面,我们来看一下软件是怎么利用栈的。 函数的调用过程
我们用一个充满函数的小软件来研究函数的调用,源代码如下: 复制代码 隐藏代码 #include #include #include #include using namespace std; int function(int a,int b);//这是第一个函数,揭示控制台应用程序函数调用过程 int WINAPI winfunction(int a,int b);//winapi调用方式 int _cdecl cfunction(int a,int b);//c函数方式 int _stdcall cppfunction(int a,int b);//c++函数方式 int _fastcall ffunction(int a,int b);//寄存器函数方式 int _stdcall stdfunction(int a,int b);//其实就是WINAPI调用方式 int myfunction(int a,int b);//递归调用演示 int main(){ int a;int b; printf("定位汇编代码"); scanf("%d",&a); scanf("%d",&b);//scanf方便找汇编代码 winfunction(a,b); cfunction(a,b); cppfunction(a,b); ffunction(a,b); stdfunction(a,b); myfunction(a,b); return 0; } int function(int a,int b){ int c = a + b;//加法运算最简单 return c; } int WINAPI winfunction(int a,int b){ int c = a + b;//加法运算最简单 return c; } int _cdecl cfunction(int a,int b){ int c = a + b;//加法运算最简单 return c; } int _stdcall cppfunction(int a,int b){ int c = a + b;//加法运算最简单 return c; } int _fastcall ffunction(int a,int b){ int c = a + b;//加法运算最简单 return c; } int _stdcall stdfunction(int a,int b){ int c = a + b;//加法运算最简单 return c; } int myfunction(int a,int b){ a++; b++; myfunction(a,b); }
将编译出的软件用OD载入,通过API定位至调用语段:
简单分析一下,易得: 复制代码 隐藏代码 0040159A 8B55 F0 mov edx,dword ptr ss:[ebp-0x10] ; 将scanf的结果放入EDX(b) 0040159D 8B45 F4 mov eax,dword ptr ss:[ebp-0xC] ; 将scanf的结果放入EAX(a) 004015A0 895424 04 mov dword ptr ss:[esp+0x4],edx ; 将EDX内容压入栈,就是我输入的b(=2) 004015A4 890424 mov dword ptr ss:[esp],eax ; 将EAX内容压入栈,就是我输入的a(=1) 004015A7 E8 81000000 call 未命名1.0040162D ; WINAPI调用方式 004015AC 83EC 08 sub esp,0x8 ; 恢复堆栈 004015AF 8B55 F0 mov edx,dword ptr ss:[ebp-0x10] ; 将scanf的结果放入EDX(b) 004015B2 8B45 F4 mov eax,dword ptr ss:[ebp-0xC] ; 将scanf的结果放入EAX(a) 004015B5 895424 04 mov dword ptr ss:[esp+0x4],edx ; 将EDX内容压入栈,就是我输入的b(=2) 004015B9 890424 mov dword ptr ss:[esp],eax ; 将EAX内容压入栈,就是我输入的a(=1) 004015BC E8 84000000 call 未命名1.00401645 ; c函数方式 004015C1 8B55 F0 mov edx,dword ptr ss:[ebp-0x10] ; 将scanf的结果放入EDX(b) 004015C4 8B45 F4 mov eax,dword ptr ss:[ebp-0xC] ; 将scanf的结果放入EAX(a) 004015C7 895424 04 mov dword ptr ss:[esp+0x4],edx ; 将EDX内容压入栈,就是我输入的b(=2) 004015CB 890424 mov dword ptr ss:[esp],eax ; 将EAX内容压入栈,就是我输入的a(=1) 004015CE E8 88000000 call 未命名1.0040165B ; c++函数方式 004015D3 83EC 08 sub esp,0x8 ; 恢复堆栈 004015D6 8B55 F0 mov edx,dword ptr ss:[ebp-0x10] ; 将scanf的结果放入EDX(b) 004015D9 8B45 F4 mov eax,dword ptr ss:[ebp-0xC] ; 将scanf的结果放入EAX(a) 004015DC 89C1 mov ecx,eax ; 将EAX寄存器的值放入ECX 004015DE E8 90000000 call 未命名1.00401673 ; 寄存器方式 004015E3 8B55 F0 mov edx,dword ptr ss:[ebp-0x10] ; 将scanf的结果放入EDX(b) 004015E6 8B45 F4 mov eax,dword ptr ss:[ebp-0xC] ; 将scanf的结果放入EAX(a) 004015E9 895424 04 mov dword ptr ss:[esp+0x4],edx ; 将EDX内容压入栈,就是我输入的b(=2) 004015ED 890424 mov dword ptr ss:[esp],eax ; 将EAX内容压入栈,就是我输入的a(=1) 004015F0 E8 9A000000 call 未命名1.0040168F ; stdcall调用方式 004015F5 83EC 08 sub esp,0x8 ; 恢复堆栈 004015F8 8B55 F0 mov edx,dword ptr ss:[ebp-0x10] ; 将scanf的结果放入EDX(b) 004015FB 8B45 F4 mov eax,dword ptr ss:[ebp-0xC] ; 将scanf的结果放入EAX(a) 004015FE 895424 04 mov dword ptr ss:[esp+0x4],edx ; 将EDX内容压入栈,就是我输入的b(=2) 00401602 890424 mov dword ptr ss:[esp],eax ; 将EAX内容压入栈,就是我输入的a(=1) 00401605 E8 9D000000 call 未命名1.004016A7 ; 递归调用
然后我们随意跟进一个函数,如图(我选择的是C函数方式)
简单分析,易得: 复制代码 隐藏代码 00401645 55 push ebp ; ebp入栈保护现场 00401646 89E5 mov ebp,esp ; 保存栈指针 00401648 83EC 10 sub esp,0x10 ; 设置栈指针 0040164B 8B55 08 mov edx,dword ptr ss:[ebp+0x8] ; 从栈中读入edx(a) 0040164E 8B45 0C mov eax,dword ptr ss:[ebp+0xC] ; 从栈中读入eax(b) 00401651 01D0 add eax,edx ; 将eax和ebx相加,读入eax 00401653 8945 FC mov dword ptr ss:[ebp-0x4],eax ; 保存eax的值入栈准备引用(c) 00401656 8B45 FC mov eax,dword ptr ss:[ebp-0x4] ; 将c作为返回值放入eax 00401659 C9 leave ; 恢复栈 0040165A C3 retn ; 函数返回
综上所述,我们可以得到以下几点:
1.大多数调用协定都将栈作为参数传递的途径
2.在进入一个函数时执行call指令就是做了两步:
(1)将下一行指令地址压入栈
(2)跳转到call后的地址
3.将eax作为返回值
4.return指令实际做的事:
(1)跳转到栈顶的那个地址
(2)栈顶中的地址出栈
所以,函数为了返回必定要用栈,分析栈也就可以知道函数是从哪调用的。 正式开始调用栈
栈不止可以用于函数调用,临时数据的存储都是用栈,但是,栈中为了函数调用的部分称为调用栈,用调用栈可以分析函数是从哪里调用的。 OD对调用栈的支持
快捷键(Alt+K)
如图便是OD的调用栈窗口
第一行是Main函数里的函数
第二行是Main函数 调用栈找地址法原理
通过调用栈,我们可以知道函数是从哪里调用的,便可以知道是哪里触发了函数,便可轻易找到是哪里判断了注册码是正确还是错误的。 实战调用栈法
我又写了一个小程序,源码如下(验证部分和我上次发帖的一样): 复制代码 隐藏代码 #include #include #include #include #include using namespace std; int check(string username,string sn);//检测注册码正确性 int registe();//注册界面 int help();//帮助界面 int main(){ cout<<"1.注册"<>choose; if(choose==1){ registe(); } else if(choose==2){ help(); } else{ cout<<"没有这个选项!"<>username; cout<<"请输入序列号:"<>sn; check(username,sn); system("pause"); return 0; } int check(string user,string sn){ for(int i=0;i
零食一哥良品铺子失宠了?被资本和消费者双抛弃编者按你上次踏进良品铺子的门店,是什么时候?最近,一向以高端定位在零食界闻名的良品铺子,迎来了被资本抛弃的噩耗。是资本变心了,还是市场赛道变了?推荐你看这篇文章,看良品铺子如何从零
恒大教训不基于核心竞争力的扩张就是作死01hr恒大价值2万亿的教训最近皮带哥的日子不太好过,甚至还有没有多少日子都不好说了。昨天一天下来,先是广州越秀公安微博一石激起千层浪然后就是跳了吧,没跳,跳了,没跳的反转再反转。
我是个妈妈,我需要铂金包纽约上东区妈妈圈的焦虑与竞争前言当妈妈对于女性来说,是人生的一次重要转折,很多女性在生完孩子之后,既体会了为人母的幸福,也遇到了各种各样的焦虑,像是,重新回归工作会不会有困难?跟老公的分工合作会不会产生矛盾?
11月份我国电商物流指数为106。6点,总业务量小幅回升12月3日,中国物流与采购联合会和京东集团联合调查的2022年11月中国电商物流指数为106。6点,比上月回落0。3个点。从9个分项指数看,总业务量指数农村业务量指数满意率指数和成
诺淇奢品洗护丨那件被你洗坏的Moncler羽绒服,后来怎么样了?你今天出门被虐了吗?全国各地陆续开启了降温模式,气温随着雪花急速下降,街头上也开始出现一波波冬日虐狗的景象。不是变着花样的情侣羽绒服LOOK,就是像杜江和霍思燕那样的互相取暖现场,
Dart知识点混入Mixin头条创作挑战赛本文同步本人掘金平台的文章httpsjuejin。cnpost7128957843314573349推荐使用线上编辑器dartpad。cn进行学习,测试什么是混入Mi
退休养老好去处建水常看到有人讨论哪里最适合退休后养老,要我说,退休后就去云南的建水古城去养老。去年五月我去云南旅游,也到建水游玩了一下,对它留下了深刻的印象。建水地处云南,那里气候宜人,风景秀丽,四
2022GV最新GoogleVoice转移教程大家好,今天来更新一下关于2022GV最新GoogleVoice转移教程,相信很多小伙伴都玩过GoogleVoice,但是很多人都不会转移到自己的帐号上,但是现在更新了最新的政策,
魅族太猛了骁龙870OLED直屏Flyme9,跌至1449元魅族的成立时间比小米早,但是却被后来居上,有网友归咎于魅族一直扶持联发科导致体验受到质疑,直到魅族Pro7之后,就彻底爆发,被网友嫌弃了,发布价2880元的魅族Pro7,最终以12
今年第1000亿件快递已送达作者丨费心懿编辑丨林曦图源丨新华社大浪淘沙,多重挑战下的2022年,快递业再次坚韧地走进千亿件时代。国家邮政局快递大数据平台实时监测数据显示,2022年12月1日,今年我国快递业务
四川攀枝花风景名胜区1。二滩国家森林公园4A二滩国家森林公园地处成都峨眉山西昌昆明这条旅游热线上,既有美丽的自然风光,如高山峡谷湖泊森林,也有壮观的人工建筑,二滩水电站。景区内为高山峡谷地貌,交通不是