码迷,mamicode.com
首页 > 其他好文 > 详细

c程序的启动过程的反汇编分析

时间:2014-07-19 23:12:48      阅读:452      评论:0      收藏:0      [点我收藏+]

标签:局部变量   代码分析   编译器   控制台   c语言   

0x01  工具准备

1.最简c代码一只,

int main(){

return 0;}

2.ollydbg

3.VC++6.0

4.GCCmingw

0x02  代码分析

int main()

{

return 0;

}

gcc下,添加-nostdlib编译选项,即链接器不链接标准库,会提示以下错误信息:

 

D:\Backup\我的文档\src>gcc main.c -nostdlib-o main.exe

C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccmSU3wr.o:main.c:(.text+0x9): undefined re

ference to `__main‘

collect2.exe: error: ld returned 1 exit status

 

关于-nostdlib编译选项,只有命令行指定的项才传递给链接器。标准启动文件和库都不会传递给链接器。该选项隐式打开选项-nostartfiles -nodefaultlibs。该选项也可以写作--no-standard-libraries

gcc执行汇编之后,在链接部分,当只打开选项-nostartfiles时,结果正常,未出现错误信息。而在-nodefaultlibs选项中,提示很多错误信息。

bubuko.com,布布扣

说明main函数,依赖了一些系统标准库文件,在链接的时候,需要到了一些函数,例如pre_cpp_initcheck_managed_apppre_c_init_tmainCRTStartup_InterlockedCompareExchangePointerduplicate_ppstringsWinMainCRTStartupmainCRTStartup_mingw_prepare_except_fr_msvcr80_and_higher….

汇编里面的_main就是C语言里面的main,是因为汇编器和C编译器对符号的命名差一个下划线。

链接器会在系统标准库文件,类似于/lib/crt2.o的文件中,寻找_start符号,然后在_start中执行创建堆对象,栈,打开系统预先提供的设备,将argv,argc参数传入main函数,然后调用main函数。

0x03  vc main函数反汇编分析

1:    int main()

2:    {

00401010   push        ebp   //在堆栈上保存EBP

00401011   mov         ebp,esp //将堆栈当前位置给EBP,以在堆栈结构中存储值时的参考点

00401013   sub         esp,40h //分配空间

00401016   push        ebx  //保存数据段值

00401017   push        esi //源地址指针

00401018   push        edi //目的地址指针

00401019   lea         edi,[ebp-40h] //装入有效地址,用来得到局部变量和函数参数的指针。这里[ebp-40h]就是基地址再向下偏移40h,就是前面说的为本地变量留出的空间的起始地址;将这个值装载入edi寄存器,从而得到局部变量的地址

0040101C   mov         ecx,10h //ecx寄存器存储10h

00401021   mov         eax,0CCCCCCCCh

00401026   rep stos    dword ptr [edi] //初始化局部变量空间,ds:[edi]

3:        return 0;

00401028   xor         eax,eax

4:    }

0040102A   pop         edi //恢复所有寄存器的值

0040102B   pop         esi

0040102C   pop         ebx

0040102D   mov         esp,ebp //恢复堆栈

0040102F   pop         ebp

00401030   ret //返回到源EIP地址

 

Vc查看调用栈,可以看到在main函数之前,系统还启动了mainCRTStartup函数,这个函数是控制台环境下多字节编码的启动函数。在kernel32.dll中地址7c816fd7处调用了mainCRTStartup函数。

main() line 2

mainCRTStartup() line 206 + 25 bytes

KERNEL32! 7c816fd7()

0x04 ollydbg反汇编分析


Od载入,如图所示。

bubuko.com,布布扣


堆栈窗口如图所示。

bubuko.com,布布扣


通过堆栈,可以看到kelnel32调用了入口函数(mainCRTStartup),对于od来说,main函数并不是Entry point,而是mainCRTStartup函数。

一直单步,单步到00401146处,od分析为调用GetVersion函数,获取当前运行平台的版本号,因为是控制台程序,所以获取版本号为ms-dos的版本信息。

继续单步,单步到0040119E处,单步进入,可以看到有HeapCreate申请堆空间函数,大小由传递的参数决定,并且该call里有HeapDestroy销毁堆函数。因此0040119E为初始化堆空间,如图所示。

bubuko.com,布布扣


004011C0处,od分析为GetCommandLineA函数,获取命令行参数信息的首地址。

进入下面的那个call后,可以看到GetEnvironmentStringsWGetEnvironmentStrings函数,获取环境变量的首地址,如图所示。以Unicode编码形式返回到寄存器和堆栈中,最后采用WideCharToMultiByte函数将Unicode字符串到一个多字节字符串, 

bubuko.com,布布扣

并且后续有参数分析的一些函数,环境变量信息分析,从而得到main函数所需的参数,然后在00402D4B位置,将参数传到main函数中,从而执行main函数中的内容。

0x05 后记

最近在阅读《c++反汇编与逆向分析技术揭秘》,在阅读到第三章认识启动函数,找到用户入口时,得知main函数之前系统要做一些准备工作,再加上上学期学的C语言程序入口函数不是main函数,而是_start函数,这不禁引发了一些思考,到底编译器在编译和系统执行程序的时候发生了什么,因此想以实例进行一定的分析。在思考的过程中,有些涉及到了编译器的知识,包括它如何工作的,汇编之后又是如何链接的,这一部分内容不太熟悉,这一方面得掌握编译原理的知识,还得学习编译器的相关内容。那些东西还没学,因此不免有一些缺憾。了解反汇编的一些内容,可以更深层次的理解相对底层的一些东西,包括栈,堆和寄存器的数据交换。另外并未使用到神器IDA,利用IDA会更好地静态分析一些函数。


c程序的启动过程的反汇编分析

标签:局部变量   代码分析   编译器   控制台   c语言   

原文地址:http://blog.csdn.net/dubuqingfenggzy/article/details/37969351

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!