本篇文章我们主要讲述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.大概就是这样一个流程.
