__declspec(naked)和__asm编写实践总结

__cdecl 和 __stdcall 压栈参数顺序是一致的,但平衡堆栈方式不一样。

__cdecl调用函数方式是调用者,即函数外部平衡堆栈,一般是在函数外部调用add esp, xxxx,函数内部只需要ret返回就行

__stdcall调用函数方式是被调用,即函数内部平衡堆栈,一般在函数内部结束的时候调用ret xxx或者add esp,xxxx ; ret

在vs2005里面C++工程默认都是__cdecl,所以需要外部平衡堆栈

 

看一个实例,本来__asm里面本来原意会去取函数参数,并打印出来

 

    

但经过编译过后,汇编代码如下:

Release版本

 

00401000 > .  56              push esi                                                            ; {
00401001   .  8B35 A4204000   mov esi,dword ptr ds:[<&MSVCR80.printf>]  
00401007   .  68 F4204000     push huibianT.004020F4
0040100C   .  FFD6            call esi
0040100E   .  83C4 04         add esp,4
00401011   .  50              push eax
00401012   .  8B4424 04       mov eax,dword ptr ss:[esp+4]
00401016   .  A3 7C334000     mov dword ptr ds:[__native_startup_lockonement],eax
0040101B   .  8B4424 08       mov eax,dword ptr ss:[esp+8]
0040101F   .  A3 78334000     mov dword ptr ds:[__native_startup_stateeement],eax
00401024   .  8B4424 0C       mov eax,dword ptr ss:[esp+C]
00401028   .  A3 74334000     mov dword ptr ds:[_adjust_fdivlestatussonement],eax
0040102D   .  58              pop eax
0040102E   .  A1 74334000     mov eax,dword ptr ds:[_adjust_fdivlestatussonement]
00401033   .  8B0D 78334000   mov ecx,dword ptr ds:[__native_startup_stateeement]
00401039   .  8B15 7C334000   mov edx,dword ptr ds:[__native_startup_lockonement]
0040103F   .  50              push eax
00401040   .  51              push ecx
00401041   .  52              push edx
00401042   .  68 F8204000     push huibianT.004020F8
00401047   .  FFD6            call esi
00401049   .  68 10214000     push huibianT.00402110

0040104E   .  FF15 9C204000   call dword ptr ds:[<&MSVCR80.system>]
00401054   .  83C4 14         add esp,14
00401057   .  33C0            xor eax,eax 

00401059 > .  5E              pop esi 

0040105A   .  C3              retn

 

Release版本优化过后函数参数不知去向。

而Debug版本的TestMy函数内部的esp已经早就破坏了,[esp+0x08]已经不再表示第一个参数。


00411449    53                push ebx
0041144A    56                push esi
0041144B    57                push edi
0041144C    8DBD 40FFFFFF     lea edi,dword ptr ss:[ebp-C0]
00411452    B9 30000000       mov ecx,30
00411457    B8 CCCCCCCC       mov eax,CCCCCCCC
0041145C    F3:AB             rep stos dword ptr es:[edi]
0041145E    8BF4              mov esi,esp
00411460    68 40574100       push huibianT.00415740
00411465    FF15 C8824100     call dword ptr ds:[<&MSVCR80D.printf>]
0041146B    83C4 04           add esp,4
0041146E    3BF4              cmp esi,esp
00411470    E8 DAFCFFFF       call huibianT.0041114F
00411475    50                push eax
00411476    8B4424 04         mov eax,dword ptr ss:[esp+4]
0041147A    A3 EC744100       mov dword ptr ds:[vEsp2ggerListeningIPTORWe>::NativeDll::ProcessVer>
0041147F    8B4424 08         mov eax,dword ptr ss:[esp+8]
00411483    A3 E8744100       mov dword ptr ds:[argc1ggerListeningIPTORWe>::NativeDll::ProcessVer>
00411488    8B4424 0C         mov eax,dword ptr ss:[esp+C]                                       
0041148C    A3 E4744100       mov dword ptr ds:[argc2ggerListeningIPTORWe>::NativeDll::ProcessVer>
00411491    58                pop eax
00411492    8BF4              mov esi,esp
00411494    A1 E4744100       mov eax,dword ptr ds:[argc2ggerListeningIPTORWe>::NativeDll::Proces>
00411499    50                push eax
0041149A    8B0D E8744100     mov ecx,dword ptr ds:[argc1ggerListeningIPTORWe>::NativeDll::Proces>
04114A0    51                push ecx
004114A1    8B15 EC744100     mov edx,dword ptr ds:[vEsp2ggerListeningIPTORWe>::NativeDll::Proces>
004114A7    52                push edx
004114A8    68 A8574100       push huibianT.004157A8
004114AD    FF15 C8824100     call dword ptr ds:[<&MSVCR80D.printf>]
004114B3    83C4 10           add esp,10
004114B6    3BF4              cmp esi,esp
004114B8    E8 92FCFFFF       call huibianT.0041114F
004114BD    5F                pop edi
004114BE    5E                pop esi
004114BF    5B                pop ebx
004114C0    81C4 C0000000     add esp,0C0
004114C6    3BEC              cmp ebp,esp
004114C8    E8 82FCFFFF       call huibianT.0041114F
004114CD    8BE5              mov esp,ebp
004114CF    5D                pop ebp
004114D0    C3                retn

 

 当使用__declspec(naked)调用约定的时候,如下面

 

 

需要注意的是使用这样约定调用的时候,函数内部不会帮你处理堆栈,需要你自己来处理,也就是说不会帮你ret,需要你自己来操作。但可以内部调用其他函数,而且会帮你的其他函数平衡好堆栈,即ebp和esp不会因为操作这些函数而改变,只有当你用__asm里面进行对其进行操作,才会改变。因为默认是__cdecl,所以我处理返回是ret。 另外我这里故意将内部临时变量从static int 变为 int,发现ebp和esp也并没有做改变。汇编代码如下:

Debug版本

 

00411440 >  8BF4              mov esi,esp                                        ; {
00411442    68 40574100       push huibianT.00415740
00411447    FF15 C8824100     call dword ptr ds:[<&MSVCR80D.printf>]
0041144D    83C4 04           add esp,4
00411450    3BF4              cmp esi,esp
00411452    E8 F8FCFFFF       call huibianT.0041114F
00411457    50                push eax                                                            ; push eax
00411458    8B4424 04         mov eax,dword ptr ss:[esp+4]                     ; mov eax, [esp + 0x04]
0041145C    8945 F8           mov dword ptr ss:[ebp-8],eax                       ; mov vEsp, eax
0041145F    8B4424 08         mov eax,dword ptr ss:[esp+8]                      ; mov eax, [esp + 0x08]
00411463    8945 EC           mov dword ptr ss:[ebp-14],eax                      ; mov argc1, eax
00411466    8B4424 0C         mov eax,dword ptr ss:[esp+C]                      ; mov eax,[esp + 0x0C]
0041146A    8945 E0           mov dword ptr ss:[ebp-20],eax                      ; mov argc2, eax
0041146D    58                pop eax                                                               ; pop eax
0041146E    8BF4              mov esi,esp                                                 
00411470    8B45 E0           mov eax,dword ptr ss:[ebp-20]
00411473    50                push eax
00411474    8B4D EC           mov ecx,dword ptr ss:[ebp-14]
00411477    51                push ecx
00411478    8B55 F8           mov edx,dword ptr ss:[ebp-8]
0041147B    52                push edx
0041147C    68 A8574100       push huibianT.004157A8
00411481    FF15 C8824100     call dword ptr ds:[<&MSVCR80D.printf>]
00411487    83C4 10           add esp,10
0041148A    3BF4              cmp esi,esp
0041148C    E8 BEFCFFFF       call huibianT.0041114F
00411491    C3                retn                                               

 

当我想对函数内部的int变量赋值的时候,发现会报错,看来这种调用约定是严格保护了ebp和esp的。

那么Release版本优化会不会改变ebp和esp的值呢

 

00401000 >/$  8B35 A4204000   mov esi,dword ptr ds:[<&MSVCR80.printf>]                            
00401006  |.  68 F4204000     push huibianT.004020F4
0040100B  |.  FFD6            call esi
0040100D  |.  83C4 04         add esp,4
00401010  |.  50              push eax                                                                   ; push eax
00401011  |.  8B4424 04       mov eax,dword ptr ss:[esp+4]                                        ; mov eax, [esp + 0x04]
00401015  |.  8945 F8         mov [local.2],eax                                                   ; mov vEsp, eax
00401018  |.  8B4424 08       mov eax,dword ptr ss:[esp+8]                                        ; mov eax, [esp + 0x08]
0040101C  |.  8945 FC         mov [local.1],eax                                                   ; mov argc1, eax
0040101F  |.  8B4424 0C       mov eax,dword ptr ss:[esp+C]                                        ; mov eax,[esp + 0x0C]
00401023  |.  8945 F4         mov [local.3],eax                                                   ; mov argc2, eax
00401026  |.  58              pop eax                                                                     ; pop eax
00401027  |.  8B45 F4         mov eax,[local.3]                                                   ; printf("%x  --   %d  --  %d /n",vEsp, argc1, argc2);
0040102A  |.  8B4D FC         mov ecx,[local.1]
0040102D  |.  8B55 F8         mov edx,[local.2]
00401030  |.  50              push eax
00401031  |.  51              push ecx
00401032  |.  52              push edx
00401033  |.  68 F8204000     push huibianT.004020F8
00401038  |.  FFD6            call esi
0040103A  |.  83C4 10         add esp,10
0040103D  /.  C3              retn                                                                

 

可以看到ebp和esp都保护得相当完美。

 

现在基本可以得到结论:

在没有__declspec(naked)调用约定的函数内部操作esp和ebp是不安全的。

而在有__declspec(naked)需要自己维护堆栈,但调用其他自己的函数,堆栈不会受影响

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/499645.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

逆向调试雷电思路总结

1.首先根据内存变化&#xff0c;能迅速找到飞机的生命&#xff0c;炸弹&#xff0c;分数&#xff0c;能够基本确认飞机结构。 2.找飞机位置有点困难&#xff0c;但可以查找飞机结构属性周围的内存变化找到飞机变化的坐标&#xff0c;这里有个小技巧&#xff0c;可以将内存十六进…

共享内存实践总结

经过实验得之&#xff0c;共享内存只有在两个进程同时存在的情况下映射才会成功 。 当共享内存在一个进程映射的情况下&#xff0c;此进程一旦销毁&#xff0c;共享内存即刻销毁,当第二个进程创建共享内存&#xff0c;会有新的共享内存空间。 另外console进程&#xff0c;在mai…

调试总结

1.调试程序之前不要放过每个细节&#xff0c;包括资源配置文件的所有东西都必须过一道两道或者三道&#xff0c;在这里发现的线索往往能让你调试事半功倍。 2.解析收包发包是基础&#xff0c;往往能跟到比较有价值的线索。 3.找结构体指针地址&#xff0c;想通过内存搜索来找…

sizeof

对于new出来的array sizeof()得到的只是指针大小 对于直接赋值的array sizeof()得到的就是整个数组的大小 memcpy的时候特别注意

关于栈实践总结

今天发了个帖&#xff0c;问栈位于进程空间的哪个位置&#xff0c;居然很多人都不清楚。本人用OD看了下就一目了然 进程结构示意图&#xff1a; 主线程堆栈 --临时变量都在里面主线程pe --GetModuleHandle(NULL)通过API得到的进程首地址在这个位置&#xff…

中文路径

混合编码编译选项不能读中文路径 需要设置为unicode编译选项wifstream ifs; ifs.read(参数1&#xff0c;参数2) 参数2传的是个数&#xff0c;跟Unnicode无关将参数1转化成ansic过后得到的string.size()跟参数2不一样。 所以取读取的长度还是用参数2PS: string.size()跟string.l…

通过VirtualQuery获取当前模块的句柄

HMODULE ModuleFromAddress( PVOID pv ){MEMORY_BASIC_INFORMATION mbi;if(::VirtualQuery(pv, &mbi, sizeof(mbi)) ! 0){return (HMODULE)mbi.AllocationBase;}else{return NULL;}} 得到的模块基地址HMOUDULE handle ModuleFromAddress((PBYTE)ModuleFromAddress)就是模块…

D3DLOCK写纹理遇到的问题

现象&#xff1a;以D3D_DISCARD方式来LockRect写入的显存数据在UnLock过后拷贝出来就崩溃&#xff0c;在一些机器出现而在某些机器就不会出现。 解决&#xff1a;判断游戏写纹理数据LockRect方式是D3D_DISCARD的话&#xff0c;在UnLockRect写完数据过后&#xff0c;就不对原来显…

去除ring3层的Debug标志

_asm{mov eax, fs:[0x18]mov eax, [eax0x30]mov dword ptr ds:[eax],0}

2011工作总结

1、编码能力 代码实践中&#xff0c;开始注重模型的概念。所谓模型打个比方&#xff1a;要做一台电视机&#xff0c;首先搞清楚你想怎么使用它&#xff0c;目的是让它看起来更方便易用。根据常规经验判断&#xff0c;电器需要电源、需要信号&#xff0c;这两点是必不可少。OK&a…

逆向调试完成端口回包实践总结

大概描述下完成端口的原理 一个套接字可以对应多个overlapped, 每个overlapped都由相应的一个线程来处理。而WSARecv绑定好了一个OVERLAPPED&#xff0c;WSARecv的调用会通知数据即将到来&#xff0c;同时将会触发某线程中的GetQueuedCompletionStatus函数调用完成&#xff0c;…

编码问题

从XML读进来的UTF8编码需要转一次到宽字符&#xff0c;宽字符再转化成窄字符。 在中文系统下面读中文&#xff0c;没问题。 但读韩文的时候&#xff0c;第二步就会出现丢失现象。 所以在国际化中&#xff0c;最好都统一用宽字符编码

zeromq

使用zeromq注意context是多个socket的集合。 频繁删除创建context会产生异常&#xff0c;估计是zeromq的bug&#xff0c;待分析

静态添加DLL

LordPE 这个工具能够直接静态添加DLL,这下更方便了具体步骤&#xff1a;1. 点击PE编辑器&#xff0c;打开要添加的exe2. 进入目录表&#xff0c;选择输入表一项&#xff0c;点击省略号3..进入添加DLL界面。选择要添加的DLL。dll必须有一个导出函数添加即可,最后保存

区块链读书笔记一

区块链的本质就是交易各方信任机制建设的一个完美方案。 为什么是完美方案&#xff0c;原因 其一&#xff1a;是用纯数学方法来解决信任机制。 其二&#xff1a;不需要借助任何第三方结构。 其三&#xff1a;建立信任关系的成本几乎降到了零。 关于区块链问题&#xff0c;这…

区块链读书笔记二

“双花”问题&#xff0c;在区块链加密技术出现之前&#xff0c;加密数字资产和其他数字一样&#xff0c;具有无限复制性&#xff0c;如果没有一个中心化的机构&#xff0c;则我们没有办法确认一笔数字现金是否已经被花掉。在交易中一个可以信赖的第三方会保留甲乙总账从而保证…

区块链读书笔记三

区块链货币未来的完善分三个层面&#xff1a; 用户层面&#xff1a;区块链加密技术需要用户都要保存好自己的私钥&#xff0c;这涉及一个问题&#xff0c;若私钥丢失了&#xff0c;那意味着你的比特币也丢失了。这时候并没有第三方机构来为你进行密码恢复或找回私钥。 商户层面…

区块链读书笔记四

区块链对大规模协作产生的影响 对区块链未来的前景的兴奋点在于&#xff0c;极高的生产力会将这个星球上所有的人和机器都连入一个全新的网络&#xff0c;也许到了21世纪下半夜&#xff0c;资本主义走向没落&#xff0c;区块链去中心化协同共享将取而代之&#xff0c;每个人都有…

模拟网页行为之工具篇

模拟网页行为最常见的包含模拟网页登陆&#xff0c;模拟提交表单&#xff0c;甚至可以拒绝网页第三方安全软件的加载等一些更酷的行为&#xff0c;这种行为不仅仅是减少了一些非常枯燥重复的过程&#xff0c;更重要的是提升了商业行为中的效率&#xff0c;甚至会给你直接带来金…

模拟网页行为之工具篇二

先说360浏览器&#xff0c;打开开发者选项&#xff0c;可以看到界面提供了几个功能选项&#xff0c;如图&#xff1a; 这个图片的第一个搜索图标点中过后&#xff0c;再去选中网页你感兴趣的部分就可以在Element选项中跳转到你感兴趣的代码。也可以直接ctrlF2搜寻你感兴趣网页元…