浮点指令之找main函数
环境
vs2019 编译选项x86(32位) debug版本
float指令练习
//c++源码
#include<stdio.h>
int main(int argc,char* argv)
{
float f = (float)argc;//将int类型转换为float
printf("%f",f);
argc = (int)f;//在将float类型转换为int
printf("%d",argc);
return 0;
}
编译运行后,在return 0;语句打一个断点,右键可以看到切到汇编代码
对应的汇编代码如下
00183E40 55 push ebp
00183E41 8B EC mov ebp,esp
00183E43 81 EC CC 00 00 00 sub esp,0CCh
00183E49 53 push ebx
00183E4A 56 push esi
00183E4B 57 push edi
00183E4C 8D 7D F4 lea edi,[ebp-0Ch]
00183E4F B9 03 00 00 00 mov ecx,3
00183E54 B8 CC CC CC CC mov eax,0CCCCCCCCh
00183E59 F3 AB rep stos dword ptr es:[edi]
00183E5B B9 03 C0 18 00 mov ecx,offset _78F0D3D6_helloworld@c (018C003h)
00183E60 E8 A2 D4 FF FF call @__CheckForDebuggerJustMyCode@4 (0181307h)
4: float f = (float)argc;
00183E65 F3 0F 2A 45 08 cvtsi2ss xmm0,dword ptr [argc] //[argc]对应是[ebp+8] cvsi2ss指令:将整数转换为单精度数int强制转为float
00183E6A F3 0F 11 45 F8 movss dword ptr [f],xmm0//[f] 对应的是[ebp-4] //movss指令:用来传送单精度数,用来转送float
5: printf("%f",f);
00183E6F F3 0F 5A 45 F8 cvtss2sd xmm0,dword ptr [f]
00183E74 83 EC 08 sub esp,8
00183E77 F2 0F 11 04 24 movsd mmword ptr [esp],xmm0//movsd指令:传送双精度数
00183E7C 68 CC 7B 18 00 push offset string "%f" (0187BCCh)
00183E81 E8 17 D5 FF FF call _printf (018139Dh)
00183E86 83 C4 0C add esp,0Ch //外平栈
6: argc = (int)f;
00183E89 F3 0F 2C 45 F8 cvttss2si eax,dword ptr [f]//cvttss2si将float类型转换为int类型
00183E8E 89 45 08 mov dword ptr [argc],eax
7: printf("%d",argc);
00183E91 8B 45 08 mov eax,dword ptr [argc]
00183E94 50 push eax
00183E95 68 D0 7B 18 00 push offset string "%d" (0187BD0h)
00183E9A E8 FE D4 FF FF call _printf (018139Dh)
00183E9F 83 C4 08 add esp,8
8: return 0;
00183EA2 33 C0 xor eax,eax
9: }
00183EA4 5F pop edi
00183EA5 5E pop esi
00183EA6 5B pop ebx
00183EA7 81 C4 CC 00 00 00 add esp,0CCh
00183EAD 3B EC cmp ebp,esp
00183EAF E8 7C D3 FF FF call __RTC_CheckEsp (0181230h)
00183EB4 8B E5 mov esp,ebp
00183EB6 5D pop ebp
00183EB7 C3 ret
上面的代码:浮点数与整数、整数与浮点数的相互转换,从上面可以看到float类型占4字节,但是使用浮点栈将以8字节方式进行处理(movsd),而使用媒体寄存器则以4字节处理。当浮点数作为参数时,并不能直接入栈,PUSH指令只能传入4字节数据到栈。这样会丢失4字节数据。这就是使用printf函数以整数方式输出浮点数时会产生错误的原因。printf以整数方式输出时,将对应参数作为4字节数据长度,按补码范式解释,而真正压入的参数为浮点类型时,却是8字节长度,需要按浮点编码范式解释。
如何找到main函数
在大学中我们老师都教授我们一个函数的入口函数是main,但是呢今天我们来看看到底是不是。拿出工具x32dbug来进行测试
第一步
第二步进来以后初始的状态
是一个ntdll.dll是重要的Windows NT内核级文件。描述了windows本地NTAPI的接口。当Windows启动时,ntdll.dll就驻留在内存中特定的写保护区域,使别的程序无法占用这个内存区域。
第三步 快捷按F9
我们可以看到是一个._mainCRTStartup>,那么我们在进去(F9)
第三步
.__scrt_common main>,我们再次进去(F9)
第四步
_scrt_common_main_seh>
第五步
其中包含了.main函数,那么我们就算找到了main
00183E4 | 55 | push ebp | helloworld.c:3
00183E4 | 8BEC | mov ebp,esp |
00183E4 | 81EC CC000000 | sub esp,CC |
00183E4 | 53 | push ebx |
00183E4 | 56 | push esi | esi:__enc$textbss$end+23
00183E4 | 57 | push edi | edi:__enc$textbss$end+23
00183E4 | 8D7D F4 | lea edi,dword ptr ss:[ebp-C] | edi:__enc$textbss$end+23
00183E4 | B9 03000000 | mov ecx,3 |
00183E5 | B8 CCCCCCCC | mov eax,CCCCCCCC | eax:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183E5 | F3:AB | rep stosd |
00183E5 | B9 03C01800 | mov ecx,<shujutype._78F0D3D6_helloworld@c> | helloworld.c:15732480
00183E6 | E8 A2D4FFFF | call shujutype.181307 |
00183E6 | F3:0F2A45 08 | cvtsi2ss xmm0,dword ptr ss:[ebp+8] | helloworld.c:4
00183E6 | F3:0F1145 F8 | movss dword ptr ss:[ebp-8],xmm0 | [ebp-8]:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183E6 | F3:0F5A45 F8 | cvtss2sd xmm0,dword ptr ss:[ebp-8] | helloworld.c:5, [ebp-8]:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183E7 | 83EC 08 | sub esp,8 |
00183E7 | F2:0F110424 | movsd qword ptr ss:[esp],xmm0 |
00183E7 | 68 CC7B1800 | push shujutype.187BCC |
00183E8 | E8 17D5FFFF | call shujutype.18139D |
00183E8 | 83C4 0C | add esp,C |
00183E8 | F3:0F2C45 F8 | cvttss2si eax,dword ptr ss:[ebp-8] | helloworld.c:6, [ebp-8]:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183E8 | 8945 08 | mov dword ptr ss:[ebp+8],eax |
00183E9 | 8B45 08 | mov eax,dword ptr ss:[ebp+8] | helloworld.c:7
00183E9 | 50 | push eax | eax:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183E9 | 68 D07B1800 | push shujutype.187BD0 |
00183E9 | E8 FED4FFFF | call shujutype.18139D |
00183E9 | 83C4 08 | add esp,8 |
00183EA | 33C0 | xor eax,eax | helloworld.c:8, eax:&"E:\\c++反汇编技术加密与解密\\shujutype\\Debug\\shujutype.exe"
00183EA | 5F | pop edi | helloworld.c:9, edi:__enc$textbss$end+23
00183EA | 5E | pop esi | esi:__enc$textbss$end+23
00183EA | 5B | pop ebx |
00183EA | 81C4 CC000000 | add esp,CC |
00183EA | 3BEC | cmp ebp,esp |
00183EA | E8 7CD3FFFF | call shujutype.181230 |
00183EB | 8BE5 | mov esp,ebp |
00183EB | 5D | pop ebp |
00183EB | C3 | ret |
与我们编译好的一摸一样,那么我们就可以确定是main函数
总结
main函数是语法规定的用户入口,而真正的入口函数是mainCRTStartup,mainCRTStarup再次调用main函数。
浮点指令之找main函数的更多相关文章
- 【逆向知识】VS程序反汇编找main函数
工具:OllyICE 调试快捷键说明: F2键:设置断点,只要在光标定位的位置 F4键:程序运行到光标处 F7键:单步步入.功能同单步步过(F8)类似,区别是遇到 CALL 等子程序时会进入其中,进入 ...
- exe怎么找main函数
先说DEBUG版本的命令行EXE main函数有两种,第一种是int main(),第二种是int main(int argc,char* argv[]) 不管哪种只要查找j___p___argc就能 ...
- 【逆向工具】IDA使用2-VS2015版本release查找main函数入口,局部变量
VS2015版本release查找main函数入口 vc++开发的程序main或WinMain函数是语法规定的用户入口,而不是应用程序入口.入口代码是mainCRTstartup.wmainCRTSt ...
- 06_传智播客iOS视频教程_源文件后缀名和main函数
OC与C语言的不同. 把OC程序运行起来,CPU只会找main函数.并且只会执行main函数当中的代码.当main函数的代码执行完毕之后这个程序就自动结束掉了. main函数的参数是可以让我们在运行程 ...
- 在有main函数的前提下 eclipse找不到主类
有时候在测试类的时候eclipse会莫名奇妙的提示找不到主类 接下来分别有几种解决办法 1.在项目上右击> Builder Path -> Configure Build Path - ...
- [汇编与C语言关系]2. main函数与启动例程
为什么汇编程序的入口是_start,而C程序的入口是main函数呢?以下就来解释这个问题 在<x86汇编程序基础(AT&T语法)>一文中我们汇编和链接的步骤是: $ as hell ...
- main函数和启动例程
为什么汇编程序的入口是_start,而C程序的入口是main函数呢?本节就来解释这个问题.在讲例 18.1 “最简单的汇编程序”时,我们的汇编和链接步骤是: $ as hello.s -o hello ...
- 为什么c程序里一定要写main函数
一. 学习过程 编写程序f.c: 对其进行编译,正常通过,再对其进行连接,出现错误: 显示的出错信息为: 翻译成中文是:在c0s模块没有定义符号’_main’. 那么这个错误信息可能与文件c0s.ob ...
- C语言编程漫谈——main函数
写在前面 促使我写这篇文章是因为我这几天找了几个一样是大三的同学,与我相同专业相同方向(物联网)的人,除了@小胡同的诗,基本没有什么其他人会现在看起来很简单的编程题目了.问了一下其他同学,他们大部分都 ...
- 通过启动函数定位main()函数
如下,通过vc6.0编写一个hello world程序.尝试结合汇编代码.分析启动函数找到main函数. 在printf(xxx)插入断点,调试执行.如下,在堆栈窗口中可见main()下的一个 ...
随机推荐
- javasec(五)URLDNS反序列化分析
这篇文章介绍 URLDNS 就是ysoserial中⼀个利⽤链的名字,但准确来说,这个其实不能称作"利⽤链".因为其参数不是⼀个可以"利⽤"的命令,⽽仅为⼀个U ...
- JUC同步工具CountDownLatch
CountDownLatch:允许一条或多条线程等待其它线程中的一组操作完成后再继续执行. 在探究CountDownLatch之前,我们知道Thread的join也有类似功能,先看thread的joi ...
- Vue的项目打包为移动端(安卓手机应用)app
现在基于vue全家桶技术体系,基本上可以开发各端的各种应用,pc端的应用,开发完成以后,直接运行打包命令 yarn build 即可打包,部署到服务器端上线即可.那么,今天我们来聊一聊,开发好的vue ...
- 学习笔记——树形dp
树形 dp 介绍 概念 树形 dp,顾名思义,就是在树上做 dp,将 dp 的思想建立在树状结构之上. 常见的树形 dp 有两种转移方向: 从叶节点向根节点转移,这种也是树形 dp 中较为常见的一种. ...
- VMware虚拟机---Ubuntu无法连接网络该怎么解决?
在学习使用Linux系统时,由于多数同学们的PC上多是Windows系统,故会选择使用VMware创建一个虚拟机来安装Linux系统进行学习. 安装完成之后,在使用时总是会遇到各种各样的问题.本片随笔 ...
- abp(net core)+easyui+efcore实现仓储管理系统——供应商管理升级之上(六十三)
abp(net core)+easyui+efcore实现仓储管理系统目录 abp(net core)+easyui+efcore实现仓储管理系统--ABP总体介绍(一) abp(net core)+ ...
- 【C#】图片上传并根据长宽大小进行正方形、长方形及等比缩放。
#region 正方型裁剪并缩放 /// <summary> /// 正方型裁剪 /// 以图片中心为轴心,截取正方型,然后等比缩放 /// 用于头像处理 /// </summary ...
- 2021-06-25:只由小写字母(a~z)组成的一批字符串,都放在字符类型的数组String[] arr中,如果其中某两个字符串所含有的字符种类完全一样,就将两个字符串算作一类,比如:baacbba
2021-06-25:只由小写字母(a~z)组成的一批字符串,都放在字符类型的数组String[] arr中,如果其中某两个字符串所含有的字符种类完全一样,就将两个字符串算作一类,比如:baacbba ...
- vue全家桶进阶之路18:Vue Router
Vue Router 是 Vue.js 的官方路由管理器,它可以帮助我们实现单页应用(Single Page Application,SPA)的前端路由. Vue Router 基于 Vue.js 的 ...
- Django admin管理工具的使用、定制及源码解析
admin组件使用 Django 提供了基于 web 的管理工具. Django 自动管理工具是 django.contrib 的一部分.你可以在项目的 settings.py 中的 INSTALLE ...