Main()函数的前世今生

这篇具有很好参考价值的文章主要介绍了Main()函数的前世今生。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        在开始分析程序之前,我们第一个要解决的问题,就是如何定位到main函数,想要从二进制逆向的角度分析出main函数,就必须要了解正向的代码下main函数的所有的细节和特

征。毕竟逆向的本质就是正向。

程序真正的入口

VS C++开发的程序在调试时总是从main或WinMain函数开始,这就让开发者误认为它们是程序的第一条指令执行处,这个认知其实是错误的。

main或WinMain函数需要有一个调用者,在它们被调用前,编译器其实已经做了很多事情,所以main或WinMain是“语法规定的用户入口”,而不是“应用程序入口”。

应用程序被操作系统加载时,操作系统会分析执行文件内的数据,并分配相关资源,读取执行文件中的代码和数据到合适的内存单元,然后才是执行入口代码,入 口 代 码 其 实 并 不 是 main 或 WinMain 函 数 , 通 常 是mainCRTStartup 、 wmainCRTStartup 、 WinMainCRTStartup 或wWinMainCRTStartup , 具体视编译选项而定 。

  • mainCRTStartup和wmainCRTStartup是控制台环境下多字节编码和 Unicode 编 码 的 启 动 函 数
  • WinMainCRTStartup 和wWinMainCRTStartup则是Windows环境下多字节编码和Unicode编码的启动函数。

VS2019的启动函数

VS C++ 在 控 制 台 和 多 字 节 编 码 环 境 下 的 启 动 函 数 为 mainCRTStartup , 由 系 统 库 KERNEL32.dll 负 责 调 用 , 在 mainCRTStartup中再调用main函数。使用VS2019进行调试时,入 口断点总是停留在main函数的首地址处。可以利用VS2019的栈回溯功能分析调用main函数的栈信息。

Main()函数的前世今生,C与汇编,c语言,c++

mainCRTSartup函数之前的高级源码无法查看

mainCRTSartup --  _scrt_common_main()  --  _scrt_common_main_seh()  --  invoke_main()  --  main()

main函数的识别

特征如下:

  • 有3个参数,分别是命令行参数个数、命令行参数信息和环境变量信息,而且main函数是启动函数中唯一具有3个参数的函数。同理,WinMain也是启动函数中唯一具有4个参数的函数。
  • main函数返回后需要调用exit函数,结束程序根据main函数调用的特征,找到入口代码第一次调用exit函数处,离exit最近的且有3个参数的函数通常就是main函数。

调用main()堆栈

样例代码

#include <stdio.h>


int main()
{
	printf("Hello World!");

	return 0;
}

通过VS2019查看main()函数调用的堆栈空间

Main()函数的前世今生,C与汇编,c语言,c++

转到mainCRTStartup()的反汇编,这是C++程序执行的第一个函数

Main()函数的前世今生,C与汇编,c语言,c++

Main()函数的前世今生,C与汇编,c语言,c++

mainCRTStartup先调用__scrt_common_main函数

Main()函数的前世今生,C与汇编,c语言,c++

转到__scrt_common_main()的反汇编

Main()函数的前世今生,C与汇编,c语言,c++

在反汇编代码中,__scrt_common_main第二个调用函数是__scrt_common_main_seh

之后__scrt_common_main_seh调用invoke_main()

Main()函数的前世今生,C与汇编,c语言,c++

转到invoke_main()的反汇编,发现调用 _main()函数

Main()函数的前世今生,C与汇编,c语言,c++

Main()函数的前世今生,C与汇编,c语言,c++

回到源代码

Main()函数的前世今生,C与汇编,c语言,c++

这就到main函数了,这里就到了main函数了,这里main函数有三个参数,分别是

  • __argc是参数个数
  • __argv是参数列表
  • 最后一个是环境指针
里面的每一个参数都是单独的一个函数

Main()函数的前世今生,C与汇编,c语言,c++

可以得出规律

  1. mainCRTStartup调用__scrt_common_main
  2. __scrt_common_main调用__scrt_common_main_seh,对应汇编是在第二个call上
  3. __scrt_common_main_seh调用invoke_main,对应在汇编的特征如下:
    1. int const main_result = invoke_main();源码是赋值给一个变量
    2. 这个函数参数是0个,后面会跟exit函数,exit函数的参数 是 invoke_main 的返回值
    3. call指令后面必有一个mov [ebp-0xXXX],eax
  4. invoke_main调用main

x64dbg定位main函数

进入程序入口,调用mainCRTStartup函数

Main()函数的前世今生,C与汇编,c语言,c++

调用__scrt_common_main函数

Main()函数的前世今生,C与汇编,c语言,c++

调用_scrt_common_main_seh

Main()函数的前世今生,C与汇编,c语言,c++

调用invoke_main比较复杂,先分析一下它的特征,在scrt_common_main_seh

会把invoke_main的返回值给main_result
int const main_result = invoke_main();


返回值会伴随一个exit 和 一个main_result,必然有一个ret
if (!__scrt_is_managed_app())
   exit(main_result);

return main_result;

定位invoke_main方法:

  1. 找到第一个ret
  2. 定位到call XXXX
  3. call指令后面必有一个mov [ebp-0xXXX],eax

定位ret

Main()函数的前世今生,C与汇编,c语言,c++

定位invoke_main()

Main()函数的前世今生,C与汇编,c语言,c++

在这里会看到四个函数调用,最后一个才是 main 函数

Main()函数的前世今生,C与汇编,c语言,c++

定位到main()函数

Main()函数的前世今生,C与汇编,c语言,c++文章来源地址https://www.toymoban.com/news/detail-701895.html

到了这里,关于Main()函数的前世今生的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • InfiniBand 的前世今生

    今年,以 ChatGPT 为代表的 AI 大模型强势崛起,而 ChatGPT 所使用的网络,正是 InfiniBand,这也让 InfiniBand 大火了起来。那么,到底什么是 InfiniBand 呢?下面,我们就来带你深入了解 InfiniBand。 InfiniBand(也称为“无限带宽”,缩写为 IB)是一个用于高性能计算的计算机网络通信标

    2024年02月06日
    浏览(34)
  • 小程序插件的前世今生

    首先,在开始之前,我们需要了解小程序插件的概念。小程序插件可以理解为小程序的扩展功能,类似于应用商店中的插件。通过引入插件,我们可以给小程序添加一些特定的功能模块,例如地图、支付、分享等。这样一来,开发者就可以更加灵活地为用户提供丰富的体验。

    2024年02月03日
    浏览(44)
  • Docker 的前世今生

    🌷🍁 博主 libin9iOak带您 Go to New World.✨🍁 🦄 个人主页——libin9iOak的博客🎐 🐳 《面试题大全》 文章图文并茂🦕生动形象🦖简单易学!欢迎大家来踩踩~🌺 🌊 《IDEA开发秘籍》学会IDEA常用操作,工作效率翻倍~💐 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬

    2024年02月16日
    浏览(45)
  • 1 Go的前世今生

    概述         Go语言正式发布于2009年11月,由Google主导开发。它是一种针对多处理器系统应用程序的编程语言,被设计成一种系统级语言,具有非常强大和有用的特性。Go语言的程序速度可以与C、C++相媲美,同时更加安全,支持并行进程。此外,Go语言也支持面向对象编程

    2024年02月08日
    浏览(37)
  • ChatGPT:GPT前世今生

            2018年,OpenAI研究员Alec Radford提出了GPT(Generative Pre-trained Transformer)模型。这是人工智能历史上的一个里程碑,因为它是第一个成功应用Transformer网络结构到语言模型任务上的工作。         GPT的核心创新在于利用Transformer的自注意力机制来建模语言的长程依赖关系。

    2024年02月16日
    浏览(48)
  • JavaScript 发展的前世今生

    专栏介绍 本专栏主要用作于开放性知识点分享学习,其主要知识点范围是 以围绕 原生 JavaScript 语法 从基础知识到高阶语法阶段的学习分享。 导语: 既然博主,计划将此专栏打造为 JavaScript 的知识点学习分享集结地。所以,本章节就为大家带来,有关 JavaScript 这门语言的一

    2024年02月07日
    浏览(55)
  • CADisplayLink前世今生

    本文字数: 19803 字 预计阅读时间: 50 分钟 用最通俗的语言,描述最难懂的技术 上周同事做 code review 的时候说到了 CADisplayLink 的一些变化,感触颇深,提到了接口的一些变动,现在就自己的一些理解加上网上文档的查阅对该对象进行以下的说明: 测试环境 编译环境:Xcod

    2024年02月09日
    浏览(50)
  • ChatGPT的前世今生

    作者🕵️‍♂️:让机器理解语言か 专栏🎇:NLP(自然语言处理) 描述🎨:让机器理解语言,让世界更加美好! 寄语💓:🐾没有白走的路,每一步都算数!🐾 ( 本文是chatGPT原理介绍,但没有任何数学公式,可以放心食用 ) 这几个月, chatGPT模型 真可谓称得上是狂拽

    2023年04月09日
    浏览(39)
  • 提示工程的前世今生

    原文链接:芝士AI吃鱼 通过提示进行情境学习 在生物学中,涌现是一种令人难以置信的特性,由于相互作用的结果,各个部分聚集在一起,表现出新的行为(称为涌现),这是你在较小的尺度上看不到的。更令人难以置信的是,即使较小比例的版本看起来与较大比例相似,但

    2024年02月13日
    浏览(45)
  • powerpc架构的前世今生

    PowerPC架构是一种基于精简指令集计算机(RISC)的处理器架构。它最初由IBM、Motorola和Apple共同开发,旨在为个人电脑、工作站和服务器提供高性能和可扩展性。 PowerPC架构在1991年首次推出,后来成为苹果Macintosh电脑的主要处理器架构。它在苹果电脑上使用的时间从1994年持续到

    2024年02月10日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包