探索黑客技术攻防,实战研究与安全创新

导航菜单

深入跟踪HelloWorld执行

本篇文章我们主要讲述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对程序进行了自动分析,并进行了绘图,如下所示:

图片1.png

我们看到根为_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.大概就是这样一个流程.