本篇文章我们主要讲述helloworld程序的执行,这一次我们不从main函数开始,我们从更原始的起点开始跟踪程序的执行,让大家看到一些不应该看到的东西。
首先给出最简单helloworld源代码,如下所示:
#includestdio.h intmain() { printf(HelloWorld!!!\n); return(0); }
通常我们编写程序的时候,不管书里或者教授之人,都会告诉我们程序是从main函数开始执行的,main()是程序的开始,但是真的是这样吗,main是如何开始的呢?我们使用GCC进行编译,如下:gcchello\world.c-otest我们已经得到了我们编译后的ELF可执行文件,结果就是打印一个”helloworld!”字符串。我们如何开始进行分析呢,这里我们使用IDA进行分析,我们打开IDA载入ELF目标文件,我们可以看到IDA对程序进行了自动分析,并进行了绘图,如下所示:
我们看到根为_start,我们textview反汇编代码,代码如下:
.text:08048310 .text:08048310_start .text:08048310 .text:08048312 .text:08048313 .text:08048315 .text:08048318 .text:08048319 .text:0804831A .text:0804831B .text:08048320 .text:08048325 .text:08048326 .text:08048327 .text:0804832C .text:08048331 .text:08048331_start public_start procnear xor ebp,ebp pop esi mov ecx,esp and esp,0FFFFFFF0h push push push push push push push push call hlt eax esp edx offset__libc_csu_fini offset__libc_csu_init ecx esi offsetmain ___libc_start_main endp
我们通过对这段代码进行分析,可以发现,这个地方最后调用了__libc_start_main。这里共传入了七个参数,第一个函数是main的地址,第二个参数esi为argc,第三个参数为argv的地址,第四个地址为_init地址,第五个参数为_finit地址,第六个参数为finit,第七个为esp顶。我们可以看到_start的第一行为xorebpebp,设置ebp,这里才是一个程序最外层的函数。那么这段_start是如何进入我们的helloworld的呢,是由GCC编译的时候链接的,我们在glibc里可以找到_start的源代码,代码如下:
057#includebp-sym.h 058 059 060 .text .globl_start 99 061 .type_start,@function 062_start: /**Cleartheframepointer.TheABIsuggeststhisbedone,tomark 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 theoutermostframeobviously.*/ xorl%ebp,%ebp /**Extracttheargumentsasencodedonthestackandsetup theargumentsfor`main:argc,argv.envpwillbedetermined laterin__libc_start_main.*/ popl%esi /**Poptheargumentcount.*/ movl%esp,%ecx /**argvstartsjustatthecurrentstacktop.*/ /**Beforepushingtheargumentsalignthestacktoa16-byte (SSEneeds16-bytealignment)boundarytoavoidpenaltiesfrom misalignedaccesses.ThankstoEdwardSeidlseidl@janed.com forpointingthisout.*/ andl$0xfffffff0,%esp pushl%eax /**Pushgarbagebecauseweallocate 28morebytes.*/ /**Providethehigheststackaddresstotheusercode(forstacks whichgrowdownwards).*/ pushl%esp pushl%edx /**Pushaddressofthesharedlibrary terminationfunction.*/ 088#ifdefSHARED /**LoadPICregister.*/ call1f 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 addl$_GLOBAL_OFFSET_TABLE_,%ebx /**Pushaddressofourownentrypointsto.finiand.init.*/ leal__libc_csu_fini@GOTOFF(%ebx),%eax pushl%eax leal__libc_csu_init@GOTOFF(%ebx),%eax pushl%eax pushl%ecx pushl%esi /**Pushsecondargument:argv.*/ /**Pushfirstargument:argc.*/ pushlBP_SYM(main)@GOT(%ebx) /**Calltheusersmainfunction,andexitwithitsvalue. Butletthelibccallmain. callBP_SYM(__libc_start_main)@PLT 107#else */ 108 109 /**Pushaddressofourownentrypointsto.finiand.init.*/ pushl$__libc_csu_fini 100 110 111 112 113 114 115 116 117 118 119 pushl$__libc_csu_init pushl%ecx pushl%esi /**Pushsecondargument:argv.*/ /**Pushfirstargument:argc.*/ pushl$BP_SYM(main) /**Calltheusersmainfunction,andexitwithitsvalue. Butletthelibccallmain. */ callBP_SYM(__libc_start_main) 120#endif 121 122 hlt /**Crashifsomehow`exitdoesreturn.*/ 123 124#ifdefSHARED 1251:movl (%esp),%ebx 126 ret 127#endif 128 129/**TofulfilltheSystemV/i386ABIweneedthissymbol.Yuck,itsso 130 131 132 meaninglesssincewedontsupportmachines80386.*/ .section.rodata .globl_fp_hw 133_fp_hw:.long3 134 135 136 .size_fp_hw,4 .type_fp_hw,@object 137/**Defineasymbolforthefirstpieceofinitializeddata.*/ 138 139 .data .globl__data_start 140__data_start: 141 142 143 .long0 .weakdata_start data_start=__data_start
下面我们大概清楚了_start为程序的最外部函数,现在我们开始研究_start中call__libc_start_main,这个是什么函数,都作了什么。我们可以textview,看下其反编译代码,我们可以看到在IDA中是无法看到他的,指向了.plt表,如下表所示:
.plt:080482E4 .plt:080482E4___libc_start_mainprocnear p ;CODEXREF:_start+1C .plt:080482E4 jmp ds:off_804A004 .plt:080482E4___libc_start_mainendp .plt:080482E4
我们可以gdb动态调试或IDA动态调试再disas__libc_strat_main,代码如下所示:
(gdb)disassemble__libc_start_main Dumpofassemblercodeforfunction__libc_start_main: 0xb7e11690__libc_start_main+0:push%ebp 0xb7e11691__libc_start_main+1:xor 0xb7e11693__libc_start_main+3:mov %edx,%edx %esp,%ebp 0xb7e11695__libc_start_main+5:push%edi 0xb7e11696__libc_start_main+6:push%esi 0xb7e11697__libc_start_main+7:push%ebx 0xb7e11698__libc_start_main+8:call _Unwind_Find_FDE@plt+111 0xb7e115af 0xb7e1169d__libc_start_main+13:add 0xb7e116a3__libc_start_main+19:sub 0xb7e116a6__libc_start_main+22:mov 0xb7e116a9__libc_start_main+25:mov 0xb7e116ac__libc_start_main+28:mov $0x148957,%ebx $0x4c,%esp 0x14(%ebp),%esi 0x1c(%ebp),%ecx -0x100(%ebx),%eax 0xb7e116b2__libc_start_main+34:test%eax,%eax 0xb7e116b4__libc_start_main+36:jne __libc_start_main+237 0xb7e1177d 0xb7e116ba__libc_start_main+42:mov -0x3c(%ebx),%eax 0xb7e116c0__libc_start_main+48:test%ecx,%ecx 0xb7e116c2__libc_start_main+50:mov 0xb7e116c4__libc_start_main+52:je %edx,(%eax) 0xb7e116de__libc_start_main+78 0xb7e116c6__libc_start_main+54:movl$0x0,0x8(%esp) ---Typereturntocontinue,orqreturntoquit--- 0xb7e116ce__libc_start_main+62:movl$0x0,0x4(%esp) 0xb7e116d6__libc_start_main+70:mov 0xb7e116d9__libc_start_main+73:call0xb7e29e10__cxa_atexit 0xb7e116de__libc_start_main+78:mov %ecx,(%esp) -0xc4(%ebx),%edx 0xb7e116e4__libc_start_main+84:testb$0x2,(%edx) 0xb7e116e7__libc_start_main+87:jne __libc_start_main+414 0xb7e1182e 0xb7e1170c 0xb7e116ed__libc_start_main+93:test%esi,%esi 0xb7e116ef__libc_start_main+95:je __libc_start_main+124 0xb7e116f1__libc_start_main+97:mov 0xb7e116f7__libc_start_main+103:mov 0xb7e116fa__libc_start_main+106:mov 0xb7e116fc__libc_start_main+108:mov 0xb7e116ff__libc_start_main+111:mov 0xb7e11703__libc_start_main+115:mov 0xb7e11706__libc_start_main+118:mov -0x58(%ebx),%eax 0xc(%ebp),%edx (%eax),%eax %edx,(%esp) %eax,0x8(%esp) 0x10(%ebp),%eax %eax,0x4(%esp) 0xb7e1170a__libc_start_main+122:call*%esi 0xb7e1170c__libc_start_main+124:mov -0xc4(%ebx),%ecx 102 0xb7e11712__libc_start_main+130:mov 0x1c0(%ecx),%edx 0xb7e11718__libc_start_main+136:test%edx,%edx 0xb7e1171a__libc_start_main+138:jne __libc_start_main+341 0xb7e117e5 0xb7e117c8 ---Typereturntocontinue,orqreturntoquit--- 0xb7e11720__libc_start_main+144:mov 0xb7e11726__libc_start_main+150:testb$0x2,(%edx) 0xb7e11729__libc_start_main+153:jne __libc_start_main+312 -0xc4(%ebx),%edx 0xb7e1172f__libc_start_main+159:lea 0xb7e11732__libc_start_main+162:mov -0x38(%ebp),%eax %eax,(%esp) 0xb7e11735__libc_start_main+165:call0xb7e26470_setjmp 0xb7e1173a__libc_start_main+170:test%eax,%eax 0xb7e1173c__libc_start_main+172:jne 0xb7e1178a __libc_start_main+250 0xb7e1173e__libc_start_main+174:mov 0xb7e11744__libc_start_main+180:mov 0xb7e11747__libc_start_main+183:mov 0xb7e1174d__libc_start_main+189:mov 0xb7e11750__libc_start_main+192:lea 0xb7e11753__libc_start_main+195:mov 0xb7e11759__libc_start_main+201:mov 0xb7e1175f__libc_start_main+207:mov 0xb7e11762__libc_start_main+210:mov 0xb7e11764__libc_start_main+212:mov 0xb7e11767__libc_start_main+215:mov 0xb7e1176b__libc_start_main+219:mov 0xb7e1176e__libc_start_main+222:mov %gs:0x60,%eax %eax,-0x1c(%ebp) %gs:0x5c,%eax %eax,-0x18(%ebp) -0x38(%ebp),%eax %eax,%gs:0x60 -0x58(%ebx),%eax 0xc(%ebp),%edx (%eax),%eax %edx,(%esp) %eax,0x8(%esp) 0x10(%ebp),%eax %eax,0x4(%esp) ---Typereturntocontinue,orqreturntoquit--- 0xb7e11772__libc_start_main+226:call*0x8(%ebp) 0xb7e11775__libc_start_main+229:mov 0xb7e11778__libc_start_main+232:call0xb7e29b30exit 0xb7e1177d__libc_start_main+237:xor %eax,(%esp) %edx,%edx 0xb7e1177f__libc_start_main+239:cmpl$0x0,(%eax) 0xb7e11782__libc_start_main+242:sete%dl 0xb7e11785__libc_start_main+245:jmp 0xb7e1178a__libc_start_main+250:mov 0xb7e11790__libc_start_main+256:ror 0xb7e11793__libc_start_main+259:xor 0xb7e116ba__libc_start_main+42 0x34f4(%ebx),%eax $0x9,%eax %gs:0x18,%eax 0xb7e1179a__libc_start_main+266:call*%eax 0xb7e1179c__libc_start_main+268:mov 0xb7e117a2__libc_start_main+274:ror 0xb7e117a5libcstartmain+277:xor 0x34ec(%ebx),%eax $0x9,%eax %gs:0x18,%eax 103 0xb7e117ac__libc_start_main+284:lockdecl(%eax) 0xb7e117af__libc_start_main+287:sete%dl 0xb7e117b2__libc_start_main+290:xor %eax,%eax 0xb7e117b4__libc_start_main+292:test%dl,%dl 0xb7e117b6__libc_start_main+294:jne 0xb7e11775 0xb7e1172f 0xb7e1181f 0xb7e11800 __libc_start_main+229 0xb7e117b8__libc_start_main+296:movl$0x0,(%esp) 0xb7e117bf__libc_start_main+303:call0xb7ecd670 ---Typereturntocontinue,orqreturntoquit--- 0xb7e117c4__libc_start_main+308:lea 0xb7e117c8__libc_start_main+312:mov 0xb7e117cb__libc_start_main+315:mov 0xb7e117cd__libc_start_main+317:mov 0xb7e117d1__libc_start_main+321:lea 0xb7e117d7__libc_start_main+327:mov 0x0(%esi,%eiz,1),%esi 0x10(%ebp),%ecx (%ecx),%eax %eax,0x4(%esp) -0x1f39e(%ebx),%eax %eax,(%esp) 0xb7e117da__libc_start_main+330:call*0x194(%edx) 0xb7e117e0__libc_start_main+336:jmp __libc_start_main+159 0xb7e117e5__libc_start_main+341:mov 0xb7e117eb__libc_start_main+347:xor 0xb7e117ed__libc_start_main+349:mov 0xb7e117f3__libc_start_main+355:mov 0xb7e117f6__libc_start_main+358:mov 0xb7e117f8__libc_start_main+360:mov 0xb7e117fb__libc_start_main+363:nop 0xb7e117fc__libc_start_main+364:lea 0xb7e11800__libc_start_main+368:mov -0x34(%ebx),%eax %esi,%esi 0x1bc(%ecx),%edi %ecx,-0x44(%ebp) (%eax),%eax %eax,-0x40(%ebp) 0x0(%esi,%eiz,1),%esi 0xc(%edi),%ecx 0xb7e11803__libc_start_main+371:test%ecx,%ecx 0xb7e11805__libc_start_main+373:je __libc_start_main+399 0xb7e11807__libc_start_main+375:mov 0xb7e1180a__libc_start_main+378:lea -0x40(%ebp),%edx 0x254(%edx,%esi,8),%eax ---Typereturntocontinue,orqreturntoquit--- 0xb7e11811__libc_start_main+385:mov 0xb7e11814__libc_start_main+388:call*%ecx %eax,(%esp) 0xb7e11816__libc_start_main+390:mov 0xb7e11819__libc_start_main+393:mov 0xb7e1181f__libc_start_main+399:add 0xb7e11822__libc_start_main+402:mov 0xb7e11825__libc_start_main+405:cmp 0xb7e11827__libc_start_main+407:jb __libc_start_main+368 -0x44(%ebp),%ecx 0x1c0(%ecx),%edx $0x1,%esi 0x20(%edi),%edi %edx,%esi 0xb7e11829__libc_start_main+409:jmp 0xb7e11720 __libc_start_main+144 0xb7e1182e__libc_start_main+414:mov 0xb7e11831__libc_start_main+417:mov 0xb7e11833__libc_start_main+419:mov 0xb7e11837__libc_start_main+423:lea 0xb7e1183d__libc_start_main+429:mov 0x10(%ebp),%ecx (%ecx),%eax %eax,0x4(%esp) -0x1f3b8(%ebx),%eax %eax,(%esp) 0xb7e11840__libc_start_main+432:call*0x194(%edx) 0xb7e11846__libc_start_main+438:jmp Endofassemblerdump. 0xb7e116ed__libc_start_main+93
省略了很多,代码太多,去研究比较麻烦,但毕竟这是在LINUX下,我们可以找下glibc的源代码,__libc_start_main位于glibc库csu目录下libc_start.c文件,我们看一下代码,如下所示:
019#includestdlib.h 020#includestdio.h 021#includeunistd.h 022#includeldsodefs.h 023#includebp-start.h 024#includebp-sym.h 025 026externvoid__libc_init_first(intargc,char**argv,char**envp); 027 028externint__libc_multiple_libcs; 029 030#includetls.h 031#ifndefSHARED 032#includedl-osinfo.h 033externvoid__pthread_initialize_minimal(void); 034#ifndefTHREAD_SET_STACK_GUARD 035/**Onlyexportedforarchitecturesthatdontstorethestackguardcanary 036 inthreadlocalarea.*/ 037uintptr_t__stack_chk_guardattribute_relro; 038#endif 039#endif 040 041#ifdefHAVE_PTR_NTHREADS 042/**Weneedatomicoperations.*/ 043#includeatomic.h 044#endif 045046 047#ifdefLIBC_START_MAIN 048#ifdefLIBC_START_DISABLE_INLINE 049#defineSTATICstatic 050#else 051#defineSTATICstaticinline__attribute__((always_inline)) 052#endif 053#else 054#defineSTATIC 055#defineLIBC_START_MAINBP_SYM(__libc_start_main) 056#endif 057 058#ifdefMAIN_AUXVEC_ARG 059/**maingetspassedapointertotheauxiliary.*/ 060#defineMAIN_AUXVEC_DECL,void* 061#defineMAIN_AUXVEC_PARAM,auxvec 062#else 063#defineMAIN_AUXVEC_DECL 064#defineMAIN_AUXVEC_PARAM 065#endif 066 067STATICintLIBC_START_MAIN(int(*main)(int,char**,char** 068 069 070 MAIN_AUXVEC_DECL), intargc, char*__unbounded*__unboundedubp_av, 071#ifdefLIBC_START_MAIN_AUXVEC_ARG 072 ElfW(auxv_t)*__unboundedauxvec, 073#endif 074 __typeof(main)init, 075 void(*fini)(void), 076 void(*rtld_fini)(void), void*__unboundedstack_end) 077 078 079 080 __attribute__((noreturn)); 081/**Note:thefiniparameterisignoredhereforsharedlibrary.It 082 083 isregisteredwith__cxa_atexit.Thishadthedisadvantagethat finalizerswerecalledinmorethanoneplace.*/ 084STATICint 085LIBC_START_MAIN(int(*main)(int,char**,char**MAIN_AUXVEC_DECL), 086 intargc,char*__unbounded*__unboundedubp_av, 087#ifdefLIBC_START_MAIN_AUXVEC_ARG 088 ElfW(auxv_t)*__unboundedauxvec, 089#endif 090 __typeof(main)init, 091 void(*fini)(void), 092 void(*rtld_fini)(void),void*__unboundedstack_end) 093{ 094#if__BOUNDED_POINTERS__ 095char**argv; 096#else 097#defineargvubp_av 098#endif 099 100/**Resultofthemainfunction.*/ 101intresult; 102 103__libc_multiple_libcs=_dl_starting_up!_dl_starting_up; 104 105#ifndefSHARED 106char*__unbounded*__unboundedubp_ev=ubp_av[argc+1]; 107 108INIT_ARGV_and_ENVIRON; 109 110/**Storetheloweststackaddress.Thisisdoneinld.soifthisis 111 thecodefortheDSO.*/ 112__libc_stack_end=stack_end; 113 114#ifdefHAVE_AUX_VECTOR 115/**Firstprocesstheauxiliaryvectorsinceweneedtofindthe 116 programheadertolocateaneventuallypresentPT_TLSentry.*/ 117#ifndefLIBC_START_MAIN_AUXVEC_ARG 118ElfW(auxv_t)*__unboundedauxvec; 119{ 120 char*__unbounded*__unboundedevp=ubp_ev; while(*evp++!=NULL) 121 122 ; 123 auxvec=(ElfW(auxv_t)*__unbounded)evp; 124} 125#endif 126_dl_aux_init(auxvec); 127#endif 128#ifdefDL_SYSDEP_OSCHECK 129if(!__libc_multiple_libcs) 130 131 132 133 134 { /**Thisneedstoruntoinitiliaze_dl_osversionbeforeTLS setupmightcheckit.*/ DL_SYSDEP_OSCHECK(__libc_fatal); } 135#endif 136 137/**Initializethethreadlibraryatleastabitsincethelibgcc 138 139 functionsareusingthreadfunctionsiftheseareavailableand weneedtosetuperrno.*/ 140__pthread_initialize_minimal(); 141 142/**Setupthestackcheckerscanary.*/ 143uintptr_tstack_chk_guard=_dl_setup_stack_chk_guard(); 144#ifdefTHREAD_SET_STACK_GUARD 145THREAD_SET_STACK_GUARD(stack_chk_guard); 146#else 147__stack_chk_guard=stack_chk_guard; 148#endif 149#endif 150 151/**Registerthedestructorofthedynamiclinkerifthereisany.*/ 152if(__builtin_expect(rtld_fini!=NULL,1)) 153 154 __cxa_atexit((void(*)(void*))rtld_fini,NULL,NULL); 155#ifndefSHARED 156/**Calltheinitializerofthelibc.Thisisonlyneededhereifwe 157 158 arecompilingforthestaticlibraryinwhichcasewehavent runtheconstructorsin`_dl_start_user.*/ 159__libc_init_first(argc,argv,__environ); 160 161/**Registerthedestructoroftheprogram,ifany.*/ 162if(fini) 163 164 __cxa_atexit((void(*)(void*))fini,NULL,NULL); 165/**Somesecurityatthispoint.PreventstartingaSUIDbinarywhere 166 167 168 thestandardfiledescriptorsarenotopened.Wehavetodothis onlyforstaticallylinkedapplicationssinceotherwisethedynamic loaderdidtheworkalready.*/ 169if(__builtin_expect(__libc_enable_secure,0)) 170__libc_check_standard_fds(); 171#endif 172 173/**Calltheinitializeroftheprogram,ifany.*/ 174#ifdefSHARED 175if(__builtin_expect(GLRO(dl_debug_mask)DL_DEBUG_IMPCALLS,0)) 176 GLRO(dl_debug_printf)(\ninitializeprogram:%s\n\n,argv[0]); 177#endif 178if(init) 179 (*init)(argc,argv,__environMAIN_AUXVEC_PARAM); 180 181#ifdefSHARED 182/**Auditingcheckpoint:wehaveanewobject.*/ 183if(__builtin_expect(GLRO(dl_naudit)0,0)) 184 185 186 187 188 189 { structaudit_ifaces*afct=GLRO(dl_audit); structlink_map*head=GL(dl_ns)[LM_ID_BASE]._ns_loaded; for(unsignedintcnt=0;cntGLRO(dl_naudit);++cnt) { if(afct-preinit!=NULL) 108 190 191 192 193 194 afct-preinit(head-l_audit[cnt].cookie); afct=afct-next; } } 195#endif 196 197#ifdefSHARED 198if(__builtin_expect(GLRO(dl_debug_mask)DL_DEBUG_IMPCALLS,0)) 199 GLRO(dl_debug_printf)(\ntransferringcontrol:%s\n\n,argv[0]); 200#endif 201 202#ifdefHAVE_CLEANUP_JMP_BUF 203/**Memoryforthecancellationbuffer.*/ 204structpthread_unwind_bufunwind_buf; 205 206intnot_first_call; 207not_first_call = setjmp ((struct __jmp_buf_tag *) unwind_buf.cancel_jmp_buf); 208if(__builtin_expect(!not_first_call,1)) 209 210 211 212 213 214 215 216 217 218 219 220 221 { structpthread*self=THREAD_SELF; /**Storeoldinfo.*/ unwind_buf.priv.data.prev=THREAD_GETMEM(self,cleanup_jmp_buf); unwind_buf.priv.data.cleanup=THREAD_GETMEM(self,cleanup); /**Storethenewcleanuphandlerinfo.*/ THREAD_SETMEM(self,cleanup_jmp_buf,unwind_buf); /**Runtheprogram.*/ result=main(argc,argv,__environMAIN_AUXVEC_PARAM); } 222else 223 224 { /**Removethethread-localdata.*/ 225#ifdefSHARED 226 PTHFCT_CALL(ptr__nptl_deallocate_tsd,()); 227#else 228 externvoid__nptl_deallocate_tsd(void)__attribute((weak)); __nptl_deallocate_tsd(); 229 230#endif 231 232 233 234 /**Onelessthread.Decrementthecounter.Ifitiszerowe terminatetheentireprocess.*/ result=0; 235#ifdefSHARED 236 237 unsignedint*ptr=__libc_pthread_functions.ptr_nthreads; PTR_DEMANGLE(ptr); 238#else 239 externunsignedint__nptl_nthreads__attribute((weak)); unsignedint*constptr=__nptl_nthreads; 240 241#endif 242 243 244 245 246 if(!atomic_decrement_and_test(ptr)) /**Notmuchlefttodobuttoexitthethread,nottheprocess.*/ __exit_thread(0); } 247#else 248/**Nothingfancy,justcallthefunction.*/ 249result=main(argc,argv,__environMAIN_AUXVEC_PARAM); 250#endif 251 252exit(result); 253}
多个输入参数,然后开始对程序进行初始化工作,如初始化线程、安装SSP防护、注册析构函数等,包括对程序结束的撤销系统资源等等。那么现在我们可以解答文件开始的问题,main是从__libc_satart_main函数调用的。
我们看到__libc_start_main传入了7个参数,其中有init和finit,在IDA反汇编时时__libc_csu_init和__libc_csu_finit.这两个函数一个是函数开始处理和一个是函数退出处理,就是在main前后,我们可以看一下这两个函数都作了什么,首先我们看一下__libc_csu_initIDA反汇编;
.text:08048400 .text:08048400;Attributes:bp-basedframe .text:08048400 .text:08048400 public__libc_csu_init .text:08048400__libc_csu_initprocnear ;DATAXREF:_start+10 o .text:08048400 .text:08048400arg_0 .text:08048400arg_4 .text:08048400arg_8 .text:08048400 .text:08048400 .text:08048401 .text:08048403 .text:08048404 .text:08048405 .text:08048406 .text:0804840B .text:08048411 .text:08048414 .text:08048419 .text:0804841F .text:08048425 =dwordptr8 =dwordptr0Ch =dwordptr10h push mov ebp ebp,esp edi push push push call add esi ebx __i686_get_pc_thunk_bx ebx,1BE9h sub esp,0Ch call lea _init_proc edi,(__CTOR_LIST__-8049FF4h)[ebx] eax,(__CTOR_LIST__-8049FF4h)[ebx] edi,eax lea sub .text:08048427 sar test jz edi,2 .text:0804842A edi,edi .text:0804842C shortloc_8048452 esi,esi .text:0804842E xor .text:08048430 .text:08048430loc_8048430: __libc_csu_init+50j .text:08048430 ;CODEXREF: mov mov mov mov mov mov eax,[ebp+arg_8] [esp+8],eax eax,[ebp+arg_4] [esp+4],eax eax,[ebp+arg_0] [esp],eax .text:08048433 .text:08048437 .text:0804843A .text:0804843E .text:08048441 .text:08048444 call ds:(__CTOR_LIST__- 8049FF4h)[ebx+esi*4] .text:0804844B add cmp jb esi,1 .text:0804844E esi,edi .text:08048450 shortloc_8048430 .text:08048452 .text:08048452loc_8048452: __libc_csu_init+2Cj .text:08048452 ;CODEXREF: add pop pop pop pop retn esp,0Ch ebx .text:08048455 .text:08048456 esi .text:08048457 edi .text:08048458 ebp .text:08048459 .text:08048459__libc_csu_initendp 我们对比看一下glibc源代码中__libc_cus_init,如下所示: 63void 64__libc_csu_init(intargc,char**argv,char**envp) 65{ 66 67 68 /**Fordynamicallylinkedexecutablesthepreinitarrayisexecutedby thedynamiclinker(beforeinitializinganysharedobject.*/ 69#ifndefLIBC_NONSHARED 70 71 72 73 74 75 76 /**Forstaticexecutables,preinithappensrightsbeforeinit.*/ { constsize_tsize=__preinit_array_end-__preinit_array_start; size_ti; for(i=0;isize;i++) (*__preinit_array_start[i])(argc,argv,envp); } 77#endif 78 79 _init(); 80 81 82 constsize_tsize=__init_array_end-__init_array_start; for(size_ti=0;isize;i++) 83 (*__init_array_start[i])(argc,argv,envp); 84}
我们可以看到它最后调用了init这个函数,这个init也就是我们ida图中.init_proc,如下
.init:08048294;Attributes:bp-basedframe .init:08048294 .init:08048294 public_init_proc procnear .init:08048294_init_proc __libc_csu_init+14p .init:08048294 ;CODEXREF: push ebp ;_init .init:08048295 mov ebp,esp ebx .init:08048297 push sub .init:08048298 esp,4 $+5 .init:0804829B call pop .init:080482A0 ebx .init:080482A1 add ebx,1D54h .init:080482A7 mov edx,ds:(__gmon_start___ptr- 8049FF4h)[ebx] .init:080482AD test jz edx,edx .init:080482AF shortloc_80482B6 ___gmon_start__ .init:080482B1 call .init:080482B6 .init:080482B6loc_80482B6: _init_proc+1Bj .init:080482B6 ;CODEXREF: call call pop frame_dummy .init:080482BB __do_global_ctors_aux .init:080482C0 eax ebx .init:080482C1 pop .init:080482C2 leave retn endp .init:080482C3 .init:080482C3_init_proc
我们看到它又调用了.___gmon_start、frame_dummy、__do_global_ctors_aux.这三个函数的作用中,一个是gpronf检查函数会用的到,我们编译的时候加-pg即可设置,然后运行会自动生成gmou.a文件,对函数的调用次数时间等进行记录。Frame主要是最后调用call__register_frame_info_base,传入elf中.eh_frame和.bss,对它们进行注册。最后我们了解下__do_global_ctors_aux,它的作用是分发构造函数。这部分大家可以通过阅读glibc源代码cus下进行深入理解。
我们知道elf结构中有.init和.finit两个节,和__libc_cus_init、__libc_cus_finit基本是对应的,存放主函数前后执行初始化等。
然后main函数我们就不讲了,具体里面printf是如何执行等,这些都属于基本的,用户调用glibc,系统调用等等。
我们整理下我们大概整理的函数执行流程,从_start到__libc_start_main,__libc_start_main调用__libc_csu_init、main、__libc_csu_finit,__libc_csu_init调用___gmon_start、frame_dummy、__do_global_ctors_aux.大概就是这样一个流程.