PWN入门笔记-从创建进程到进入main函数,发生了什么?

admin 2026-01-23 11:07:27 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文章以helloworld为例,用objdump与glibc源码对照,逐段拆解ELF在_start、__libc_start_main、__libc_csu_init、_init、main、_fini及crt1.o、crti.o、crtn.o中的运行轨迹,阐明动态链接、构造析钩、__cxa_atexit注册与.init/.fini段拼装机制,给出可复现实验代码,帮助初学者建立从进程创建到main的完整PWN调试视图。 综合评分: 78 文章分类: 二进制安全,漏洞分析,安全开发,WEB安全,CTF


cover_image

PWN入门笔记-从创建进程到进入main函数,发生了什么?

原创

gary_ygl gary_ygl

绿洲安全

2026年1月22日 08:00 北京

免责声明

由于传播、利用本公众号绿洲安全所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,公众号绿洲安全及作者不为此承担任何责任,一旦造成后果请自行承担!如有侵权烦请告知,我们会立即删除并致歉。谢谢

参考链接:

https://blog.csdn.net/gary_ygl/article/details/8506007

https://zhuanlan.zhihu.com/p/272174191

1最简单的程序

1)编辑helloworld程序,$vim helloworld.c

&nbsp;#include&nbsp;<stdio.h>&nbsp;&nbsp;int&nbsp;main&nbsp;(int&nbsp;argc,&nbsp;char&nbsp;*argv[])&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf("Hello world!\n");&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return&nbsp;0;&nbsp;}
编译,$&nbsp;gcc helloworld.c -o helloworld

运行,$./helloworld

Hello world!

2 最简单的程序其实不简单

上面这个helloword程序已经再简单不过了,先来看一看它的反汇编代码:

$&nbsp;objdump&nbsp;-d&nbsp;helloworld
helloworld: &nbsp; &nbsp; file format elf32-i386

Disassembly of section .init:
080482b0 <_init>:&nbsp;80482b0:    53&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebx&nbsp;80482b1:  83&nbsp;ec&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x8,%esp&nbsp;80482b4:   e8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp;&nbsp;80482b9 <_init+0x9>&nbsp;80482b9:  5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;80482ba: 81&nbsp;c3&nbsp;3b&nbsp;1d&nbsp;00&nbsp;00&nbsp; &nbsp;     add &nbsp; &nbsp;$0x1d3b,%ebx&nbsp;80482c0:    8b&nbsp;83&nbsp;fc&nbsp;ff ff ff &nbsp; &nbsp;  mov &nbsp; &nbsp;-0x4(%ebx),%eax&nbsp;80482c6:  85&nbsp;c0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  test &nbsp; %eax,%eax&nbsp;80482c8: 74&nbsp;05&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   je &nbsp; &nbsp;&nbsp;80482cf <_init+0x1f>&nbsp;80482ca:    e8&nbsp;31&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp;&nbsp;8048300&nbsp;<__gmon_start__@plt>&nbsp;80482cf:    e8 dc&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;    call &nbsp;&nbsp;80483b0 <frame_dummy>&nbsp;80482d4:    e8&nbsp;97&nbsp;01&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp;&nbsp;8048470&nbsp;<__do_global_ctors_aux>&nbsp;80482d9: 83&nbsp;c4&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  add &nbsp; &nbsp;$0x8,%esp&nbsp;80482dc:   5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;80482dd: c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret
Disassembly of section .plt:
080482e0 <puts@plt-0x10>:&nbsp;80482e0:    ff&nbsp;35&nbsp;f8&nbsp;9f&nbsp;04&nbsp;08&nbsp; &nbsp;     pushl &nbsp;0x8049ff8&nbsp;80482e6: ff&nbsp;25&nbsp;fc&nbsp;9f&nbsp;04&nbsp;08&nbsp; &nbsp;     jmp &nbsp; &nbsp;*0x8049ffc&nbsp;80482ec:   00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   add &nbsp; &nbsp;%al,(%eax) ...
080482f0 <puts@plt>:&nbsp;80482f0:    ff&nbsp;25&nbsp;00&nbsp;a0&nbsp;04&nbsp;08&nbsp; &nbsp;     jmp &nbsp; &nbsp;*0x804a000&nbsp;80482f6:   68&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   push &nbsp;&nbsp;$0x0&nbsp;80482fb:    e9 e0 ff ff ff &nbsp; &nbsp; &nbsp;     jmp &nbsp; &nbsp;80482e0 <_init+0x30>
08048300&nbsp;<__gmon_start__@plt>:&nbsp;8048300:    ff&nbsp;25&nbsp;04&nbsp;a0&nbsp;04&nbsp;08&nbsp; &nbsp;     jmp &nbsp; &nbsp;*0x804a004&nbsp;8048306:   68&nbsp;08&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   push &nbsp;&nbsp;$0x8&nbsp;804830b:    e9 d0 ff ff ff &nbsp; &nbsp; &nbsp;     jmp &nbsp; &nbsp;80482e0 <_init+0x30>
08048310&nbsp;<__libc_start_main@plt>:&nbsp;8048310:    ff&nbsp;25&nbsp;08&nbsp;a0&nbsp;04&nbsp;08&nbsp; &nbsp;     jmp &nbsp; &nbsp;*0x804a008&nbsp;8048316:   68&nbsp;10&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   push &nbsp;&nbsp;$0x10&nbsp;804831b:   e9 c0 ff ff ff &nbsp; &nbsp; &nbsp;     jmp &nbsp; &nbsp;80482e0 <_init+0x30>
Disassembly of section .text:
08048320&nbsp;<_start>:&nbsp;8048320:    31&nbsp;ed &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  xor &nbsp; &nbsp;%ebp,%ebp&nbsp;8048322:    5e &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%esi&nbsp;8048323: 89&nbsp;e1 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  mov &nbsp; &nbsp;%esp,%ecx&nbsp;8048325:    83&nbsp;e4 f0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;     and &nbsp; &nbsp;$0xfffffff0,%esp&nbsp;8048328:    50&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %eax&nbsp;8048329:  54&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %esp&nbsp;804832a:  52&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %edx&nbsp;804832b:  68&nbsp;60&nbsp;84&nbsp;04&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp;   push &nbsp;&nbsp;$0x8048460&nbsp;8048330:  68&nbsp;f0&nbsp;83&nbsp;04&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp;   push &nbsp;&nbsp;$0x80483f0&nbsp;8048335:  51&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ecx&nbsp;8048336:  56&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %esi&nbsp;8048337:  68&nbsp;d4&nbsp;83&nbsp;04&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp;   push &nbsp;&nbsp;$0x80483d4&nbsp;804833c:  e8 cf ff ff ff &nbsp; &nbsp; &nbsp;     call &nbsp;&nbsp;8048310&nbsp;<__libc_start_main@plt>&nbsp;8048341: f4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   hlt &nbsp; &nbsp;&nbsp;8048342: 90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048343:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048344:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048345:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048346:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048347:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048348:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048349:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804834a:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804834b:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804834c:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804834d:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804834e:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804834f:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop
08048350&nbsp;<__do_global_dtors_aux>:&nbsp;8048350:    55&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebp&nbsp;8048351:  89&nbsp;e5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  mov &nbsp; &nbsp;%esp,%ebp&nbsp;8048353:    53&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebx&nbsp;8048354:  83&nbsp;ec&nbsp;04&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x4,%esp&nbsp;8048357:   80&nbsp;3d&nbsp;14&nbsp;a0&nbsp;04&nbsp;08&nbsp;00&nbsp;    cmpb &nbsp;&nbsp;$0x0,0x804a014&nbsp;804835e:  75&nbsp;3f &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  jne &nbsp; &nbsp;804839f <__do_global_dtors_aux+0x4f>&nbsp;8048360: a1&nbsp;18&nbsp;a0&nbsp;04&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp;   mov &nbsp; &nbsp;0x804a018,%eax&nbsp;8048365:   bb&nbsp;20&nbsp;9f&nbsp;04&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp;   mov &nbsp; &nbsp;$0x8049f20,%ebx&nbsp;804836a: 81&nbsp;eb&nbsp;1c&nbsp;9f&nbsp;04&nbsp;08&nbsp; &nbsp;     sub &nbsp; &nbsp;$0x8049f1c,%ebx&nbsp;8048370: c1 fb&nbsp;02&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   sar &nbsp; &nbsp;$0x2,%ebx&nbsp;8048373:   83&nbsp;eb&nbsp;01&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x1,%ebx&nbsp;8048376:   39&nbsp;d8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  cmp &nbsp; &nbsp;%ebx,%eax&nbsp;8048378:    73&nbsp;1e &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  jae &nbsp; &nbsp;8048398&nbsp;<__do_global_dtors_aux+0x48>&nbsp;804837a:    8d b6&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp;  lea &nbsp; &nbsp;0x0(%esi),%esi&nbsp;8048380:   83&nbsp;c0&nbsp;01&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  add &nbsp; &nbsp;$0x1,%eax&nbsp;8048383:   a3&nbsp;18&nbsp;a0&nbsp;04&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp;   mov &nbsp; &nbsp;%eax,0x804a018&nbsp;8048388:   ff&nbsp;14&nbsp;85&nbsp;1c&nbsp;9f&nbsp;04&nbsp;08&nbsp;    call &nbsp; *0x8049f1c(,%eax,4)&nbsp;804838f:   a1&nbsp;18&nbsp;a0&nbsp;04&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp;   mov &nbsp; &nbsp;0x804a018,%eax&nbsp;8048394:   39&nbsp;d8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  cmp &nbsp; &nbsp;%ebx,%eax&nbsp;8048396:    72&nbsp;e8 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  jb &nbsp; &nbsp;&nbsp;8048380&nbsp;<__do_global_dtors_aux+0x30>&nbsp;8048398:   c6&nbsp;05&nbsp;14&nbsp;a0&nbsp;04&nbsp;08&nbsp;01&nbsp;    movb &nbsp;&nbsp;$0x1,0x804a014&nbsp;804839f:  83&nbsp;c4&nbsp;04&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  add &nbsp; &nbsp;$0x4,%esp&nbsp;80483a2:   5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;80483a3: 5d &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebp&nbsp;80483a4: c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret &nbsp; &nbsp;&nbsp;80483a5: 8d&nbsp;74&nbsp;26&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;    lea &nbsp; &nbsp;0x0(%esi,%eiz,1),%esi&nbsp;80483a9:    8d bc&nbsp;27&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp; lea &nbsp; &nbsp;0x0(%edi,%eiz,1),%edi
080483b0 <frame_dummy>:&nbsp;80483b0:    55&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebp&nbsp;80483b1:  89&nbsp;e5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  mov &nbsp; &nbsp;%esp,%ebp&nbsp;80483b3:    83&nbsp;ec&nbsp;18&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x18,%esp&nbsp;80483b6:  a1&nbsp;24&nbsp;9f&nbsp;04&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp;   mov &nbsp; &nbsp;0x8049f24,%eax&nbsp;80483bb:   85&nbsp;c0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  test &nbsp; %eax,%eax&nbsp;80483bd: 74&nbsp;12&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   je &nbsp; &nbsp;&nbsp;80483d1 <frame_dummy+0x21>&nbsp;80483bf:  b8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   mov &nbsp; &nbsp;$0x0,%eax&nbsp;80483c4:   85&nbsp;c0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  test &nbsp; %eax,%eax&nbsp;80483c6: 74&nbsp;09&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   je &nbsp; &nbsp;&nbsp;80483d1 <frame_dummy+0x21>&nbsp;80483c8:  c7&nbsp;04&nbsp;24&nbsp;24&nbsp;9f&nbsp;04&nbsp;08&nbsp;    movl &nbsp;&nbsp;$0x8049f24,(%esp)&nbsp;80483cf:   ff d0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp; *%eax&nbsp;80483d1: c9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   leave &nbsp;&nbsp;80483d2:  c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret &nbsp; &nbsp;&nbsp;80483d3: 90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop
080483d4 <main>:&nbsp;80483d4:    55&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebp&nbsp;80483d5:  89&nbsp;e5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  mov &nbsp; &nbsp;%esp,%ebp&nbsp;80483d7:    83&nbsp;e4 f0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;     and &nbsp; &nbsp;$0xfffffff0,%esp&nbsp;80483da:    83&nbsp;ec&nbsp;10&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x10,%esp&nbsp;80483dd:  c7&nbsp;04&nbsp;24&nbsp;c0&nbsp;84&nbsp;04&nbsp;08&nbsp;    movl &nbsp;&nbsp;$0x80484c0,(%esp)&nbsp;80483e4:   e8&nbsp;07&nbsp;ff ff ff &nbsp; &nbsp; &nbsp;   call &nbsp;&nbsp;80482f0 <puts@plt>&nbsp;80483e9:   b8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   mov &nbsp; &nbsp;$0x0,%eax&nbsp;80483ee:   c9 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   leave &nbsp;&nbsp;80483ef:  c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret
080483f0 <__libc_csu_init>:&nbsp;80483f0:    55&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebp&nbsp;80483f1:  57&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %edi&nbsp;80483f2:  56&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %esi&nbsp;80483f3:  53&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebx&nbsp;80483f4:  e8&nbsp;69&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp;&nbsp;8048462&nbsp;<__i686.get_pc_thunk.bx>&nbsp;80483f9:    81&nbsp;c3 fb&nbsp;1b&nbsp;00&nbsp;00&nbsp; &nbsp;  add &nbsp; &nbsp;$0x1bfb,%ebx&nbsp;80483ff:    83&nbsp;ec&nbsp;1c &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;    sub &nbsp; &nbsp;$0x1c,%esp&nbsp;8048402:  8b&nbsp;6c&nbsp;24&nbsp;30&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;    mov &nbsp; &nbsp;0x30(%esp),%ebp&nbsp;8048406:  8d bb&nbsp;20&nbsp;ff ff ff &nbsp; &nbsp;   lea &nbsp; &nbsp;-0xe0(%ebx),%edi&nbsp;804840c: e8&nbsp;9f fe ff ff &nbsp; &nbsp; &nbsp;    call &nbsp;&nbsp;80482b0 <_init>&nbsp;8048411:  8d&nbsp;83&nbsp;20&nbsp;ff ff ff &nbsp; &nbsp;  lea &nbsp; &nbsp;-0xe0(%ebx),%eax&nbsp;8048417: 29&nbsp;c7 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;%eax,%edi&nbsp;8048419:    c1 ff&nbsp;02&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   sar &nbsp; &nbsp;$0x2,%edi&nbsp;804841c:   85&nbsp;ff &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  test &nbsp; %edi,%edi&nbsp;804841e: 74&nbsp;29&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   je &nbsp; &nbsp;&nbsp;8048449&nbsp;<__libc_csu_init+0x59>&nbsp;8048420: 31&nbsp;f6 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  xor &nbsp; &nbsp;%esi,%esi&nbsp;8048422:    8d b6&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp;  lea &nbsp; &nbsp;0x0(%esi),%esi&nbsp;8048428:   8b&nbsp;44&nbsp;24&nbsp;38&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;    mov &nbsp; &nbsp;0x38(%esp),%eax&nbsp;804842c:  89&nbsp;2c&nbsp;24&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  mov &nbsp; &nbsp;%ebp,(%esp)&nbsp;804842f:  89&nbsp;44&nbsp;24&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;    mov &nbsp; &nbsp;%eax,0x8(%esp)&nbsp;8048433:   8b&nbsp;44&nbsp;24&nbsp;34&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;    mov &nbsp; &nbsp;0x34(%esp),%eax&nbsp;8048437:  89&nbsp;44&nbsp;24&nbsp;04&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;    mov &nbsp; &nbsp;%eax,0x4(%esp)&nbsp;804843b:   ff&nbsp;94&nbsp;b3&nbsp;20&nbsp;ff ff ff    call &nbsp; *-0xe0(%ebx,%esi,4)&nbsp;8048442:   83&nbsp;c6&nbsp;01&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  add &nbsp; &nbsp;$0x1,%esi&nbsp;8048445:   39&nbsp;fe &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  cmp &nbsp; &nbsp;%edi,%esi&nbsp;8048447:    75&nbsp;df &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  jne &nbsp; &nbsp;8048428&nbsp;<__libc_csu_init+0x38>&nbsp;8048449:  83&nbsp;c4&nbsp;1c &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;    add &nbsp; &nbsp;$0x1c,%esp&nbsp;804844c:  5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;804844d: 5e &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%esi&nbsp;804844e: 5f &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%edi&nbsp;804844f: 5d &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebp&nbsp;8048450: c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret &nbsp; &nbsp;&nbsp;8048451: eb&nbsp;0d &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  jmp &nbsp; &nbsp;8048460&nbsp;<__libc_csu_fini>&nbsp;8048453:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048454:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048455:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048456:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048457:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048458:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048459:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804845a:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804845b:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804845c:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804845d:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804845e:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804845f:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop
08048460&nbsp;<__libc_csu_fini>:&nbsp;8048460:    f3 c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   repz ret
08048462&nbsp;<__i686.get_pc_thunk.bx>:&nbsp;8048462:    8b&nbsp;1c&nbsp;24&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  mov &nbsp; &nbsp;(%esp),%ebx&nbsp;8048465:  c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret &nbsp; &nbsp;&nbsp;8048466: 90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048467:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048468:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;8048469:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804846a:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804846b:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804846c:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804846d:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804846e:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804846f:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop
08048470&nbsp;<__do_global_ctors_aux>:&nbsp;8048470:    55&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebp&nbsp;8048471:  89&nbsp;e5 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  mov &nbsp; &nbsp;%esp,%ebp&nbsp;8048473:    53&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebx&nbsp;8048474:  83&nbsp;ec&nbsp;04&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x4,%esp&nbsp;8048477:   a1&nbsp;14&nbsp;9f&nbsp;04&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp;   mov &nbsp; &nbsp;0x8049f14,%eax&nbsp;804847c:   83&nbsp;f8 ff &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;     cmp &nbsp; &nbsp;$0xffffffff,%eax&nbsp;804847f:    74&nbsp;13&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   je &nbsp; &nbsp;&nbsp;8048494&nbsp;<__do_global_ctors_aux+0x24>&nbsp;8048481:   bb&nbsp;14&nbsp;9f&nbsp;04&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp;   mov &nbsp; &nbsp;$0x8049f14,%ebx&nbsp;8048486: 66&nbsp;90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   xchg &nbsp; %ax,%ax&nbsp;8048488:   83&nbsp;eb&nbsp;04&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x4,%ebx&nbsp;804848b:   ff d0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp; *%eax&nbsp;804848d: 8b&nbsp;03&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   mov &nbsp; &nbsp;(%ebx),%eax&nbsp;804848f:  83&nbsp;f8 ff &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;     cmp &nbsp; &nbsp;$0xffffffff,%eax&nbsp;8048492:    75&nbsp;f4 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  jne &nbsp; &nbsp;8048488&nbsp;<__do_global_ctors_aux+0x18>&nbsp;8048494:    83&nbsp;c4&nbsp;04&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  add &nbsp; &nbsp;$0x4,%esp&nbsp;8048497:   5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;8048498: 5d &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebp&nbsp;8048499: c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret &nbsp; &nbsp;&nbsp;804849a: 90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop&nbsp;804849b:   90&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nop
Disassembly of section .fini:
0804849c <_fini>:&nbsp;804849c:    53&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebx&nbsp;804849d:  83&nbsp;ec&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x8,%esp&nbsp;80484a0:   e8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp;&nbsp;80484a5 <_fini+0x9>&nbsp;80484a5:  5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;80484a6: 81&nbsp;c3&nbsp;4f&nbsp;1b&nbsp;00&nbsp;00&nbsp; &nbsp;     add &nbsp; &nbsp;$0x1b4f,%ebx&nbsp;80484ac:    e8&nbsp;9f fe ff ff &nbsp; &nbsp; &nbsp;    call &nbsp;&nbsp;8048350&nbsp;<__do_global_dtors_aux>&nbsp;80484b1: 83&nbsp;c4&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  add &nbsp; &nbsp;$0x8,%esp&nbsp;80484b4:   5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;80484b5: c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret

从反汇编结果来看,helloworld可执行文件并不只是main函数,除main外,还有几个重要的函数,_init,_fini,_start,__libc_start_main,__libc_csu_init,__libc_csu_fini等。

除main函数外,其它函数从哪来的?分析一下编译好的可执行文件helloworld的库依赖关系如下:

$ ldd helloworld    linux-gate.so.1 => &nbsp;(0x00876000)   libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000) /lib/ld-linux.so.2 (0x006a3000)

linux-gate.so.1为系统调用相关的动态库,ld-linux.so.2为动态链接库,libc.so.6为GNU C库。

从反汇编出来的相关函数名称(__libc_start_main)来看,我们把目标锁定在GNU C库,即glibc,也是GNU开源项目,可以从GNU 源码ftp站点( http://ftp.gnu.org/gnu/libc/)上找到。

__libc_start_main函数可以在glibc源码的csu/libc-start.c中找到:

STATIC&nbsp;int&nbsp;LIBC_START_MAIN (int&nbsp;(*main) (int,&nbsp;char&nbsp;**,&nbsp;char&nbsp;**                     MAIN_AUXVEC_DECL),          &nbsp; &nbsp;int&nbsp;argc,             &nbsp; &nbsp;char&nbsp;*__unbounded *__unbounded ubp_av,#ifdef&nbsp;LIBC_START_MAIN_AUXVEC_ARG          &nbsp; &nbsp;ElfW(auxv_t) *__unbounded auxvec,#endif            &nbsp; &nbsp;__typeof&nbsp;(main) init,             &nbsp; &nbsp;void&nbsp;(*fini) (void),          &nbsp; &nbsp;void&nbsp;(*rtld_fini) (void),             &nbsp; &nbsp;void&nbsp;*__unbounded stack_end)&nbsp; &nbsp; &nbsp;__attribute__ ((noreturn));

__libc_csu_init,__libc_csu_fini函数可以在glibc源码的csu/elf-init.c中找到:

void__libc_csu_init (int&nbsp;argc,&nbsp;char&nbsp;**argv,&nbsp;char&nbsp;**envp){&nbsp;&nbsp;/* For dynamically linked executables the preinit array is executed by&nbsp; &nbsp; &nbsp;the dynamic linker (before initializing any shared object. &nbsp;*/
#ifndef&nbsp;LIBC_NONSHARED&nbsp;&nbsp;/* For static executables, preinit happens right before init. &nbsp;*/&nbsp; {&nbsp; &nbsp;&nbsp;const&nbsp;size_t&nbsp;size = __preinit_array_end - __preinit_array_start;&nbsp; &nbsp;&nbsp;size_t&nbsp;i;&nbsp; &nbsp;&nbsp;for&nbsp;(i =&nbsp;0; i < size; i++)&nbsp; &nbsp; &nbsp; (*__preinit_array_start [i]) (argc, argv, envp);&nbsp; }#endif
&nbsp; _init ();
&nbsp;&nbsp;const&nbsp;size_t&nbsp;size = __init_array_end - __init_array_start;&nbsp;&nbsp;for&nbsp;(size_t&nbsp;i =&nbsp;0; i < size; i++)&nbsp; &nbsp; &nbsp; (*__init_array_start [i]) (argc, argv, envp);}
/* This function should not be used anymore. &nbsp;We run the executable's&nbsp; &nbsp;destructor now just like any other. &nbsp;We cannot remove the function,&nbsp; &nbsp;though. &nbsp;*/void__libc_csu_fini (void){#ifndef&nbsp;LIBC_NONSHARED&nbsp;&nbsp;size_t&nbsp;i = __fini_array_end - __fini_array_start;&nbsp;&nbsp;while&nbsp;(i-- >&nbsp;0)&nbsp; &nbsp; (*__fini_array_start [i]) ();
&nbsp; _fini ();#endif}

_start函数可以在glibc源码的sysdeps/i386/elf/start.S中找到:

#include&nbsp;"bp-sym.h"
    .text   .globl _start   .type _start,@function_start:/* Clear the frame pointer. &nbsp;The ABI suggests this be done, to mark    &nbsp; the outermost frame obviously. &nbsp;*/ xorl&nbsp;%ebp,&nbsp;%ebp
/* Extract the arguments as encoded on the stack and set up     &nbsp; the arguments for `main': argc, argv. &nbsp;envp will be determined  &nbsp; later in __libc_start_main. &nbsp;*/    popl&nbsp;%esi      /* Pop the argument count. &nbsp;*/ movl&nbsp;%esp,&nbsp;%ecx       /* argv starts just at the current stack top.*/
/* Before pushing the arguments align the stack to a 16-byte    (SSE needs 16-byte alignment) boundary to avoid penalties from  misaligned accesses. &nbsp;Thanks to Edward Seidl <[email protected]> for pointing this out. &nbsp;*/ andl&nbsp;$0xfffffff0,&nbsp;%esp   pushl&nbsp;%eax     /* Push garbage because we allocate              &nbsp; 28 more bytes. &nbsp;*/
/* Provide the highest stack address to the user code (for stacks     &nbsp; which grow downwards). &nbsp;*/ pushl&nbsp;%esp
    pushl&nbsp;%edx     /* Push address of the shared library                &nbsp; termination function. &nbsp;*/
#ifdef&nbsp;SHARED/* Load PIC register. &nbsp;*/    call 1f addl&nbsp;$_GLOBAL_OFFSET_TABLE_,&nbsp;%ebx
/* Push address of our own entry points to .fini and .init. &nbsp;*/    leal __libc_csu_fini@GOTOFF(%ebx),&nbsp;%eax    pushl&nbsp;%eax leal __libc_csu_init@GOTOFF(%ebx),&nbsp;%eax    pushl&nbsp;%eax
    pushl&nbsp;%ecx     /* Push second argument: argv. &nbsp;*/ pushl&nbsp;%esi     /* Push first argument: argc. &nbsp;*/
    pushl&nbsp;BP_SYM&nbsp;(main)@GOT(%ebx)
/* Call the user's main function, and exit with its value.     &nbsp; But let the libc call main. &nbsp; &nbsp;*/ call&nbsp;BP_SYM&nbsp;(__libc_start_main)@PLT#else/* Push address of our own entry points to .fini and .init. &nbsp;*/  pushl&nbsp;$__libc_csu_fini    pushl&nbsp;$__libc_csu_init
    pushl&nbsp;%ecx     /* Push second argument: argv. &nbsp;*/ pushl&nbsp;%esi     /* Push first argument: argc. &nbsp;*/
    pushl&nbsp;$BP_SYM&nbsp;(main)
/* Call the user's main function, and exit with its value.     &nbsp; But let the libc call main. &nbsp; &nbsp;*/ call&nbsp;BP_SYM&nbsp;(__libc_start_main)#endif
    hlt         /* Crash if somehow `exit' does return. &nbsp;*/

_init,_fini函数可以在glibc源码的sysdeps/generic/initfini.c中找到:

/* The beginning of _init: &nbsp;*/asm&nbsp;("\n/*@_init_PROLOG_BEGINS*/");
static&nbsp;voidcall_gmon_start(void){&nbsp;&nbsp;extern&nbsp;void&nbsp;__gmon_start__ (void) __attribute__ ((weak));&nbsp;/*weak_extern (__gmon_start__);*/&nbsp;&nbsp;void&nbsp;(*gmon_start) (void) = __gmon_start__;
&nbsp;&nbsp;if&nbsp;(gmon_start)&nbsp; &nbsp; gmon_start ();}
SECTION (".init");extern&nbsp;void&nbsp;__attribute__ ((section (".init"))) _init (void);void_init (void){&nbsp;&nbsp;/* We cannot use the normal constructor mechanism in gcrt1.o because it&nbsp; &nbsp; &nbsp;appears before crtbegin.o in the link, so the header elt of .ctors&nbsp; &nbsp; &nbsp;would come after the elt for __gmon_start__. &nbsp;One approach is for&nbsp; &nbsp; &nbsp;gcrt1.o to reference a symbol which would be defined by some library&nbsp; &nbsp; &nbsp;module which has a constructor; but then user code's constructors&nbsp; &nbsp; &nbsp;would come first, and not be profiled. &nbsp;*/&nbsp; call_gmon_start ();
&nbsp;&nbsp;asm&nbsp;("ALIGN");&nbsp;&nbsp;asm("END_INIT");&nbsp;&nbsp;/* Now the epilog. */&nbsp;&nbsp;asm&nbsp;("\n/*@_init_PROLOG_ENDS*/");&nbsp;&nbsp;asm&nbsp;("\n/*@_init_EPILOG_BEGINS*/");&nbsp; SECTION(".init");}asm&nbsp;("END_INIT");
/* End of the _init epilog, beginning of the _fini prolog. */asm&nbsp;("\n/*@_init_EPILOG_ENDS*/");asm&nbsp;("\n/*@_fini_PROLOG_BEGINS*/");
SECTION (".fini");extern&nbsp;void&nbsp;__attribute__ ((section (".fini"))) _fini (void);void_fini (void){
&nbsp;&nbsp;/* End of the _fini prolog. */&nbsp;&nbsp;asm&nbsp;("ALIGN");&nbsp;&nbsp;asm&nbsp;("END_FINI");&nbsp;&nbsp;asm&nbsp;("\n/*@_fini_PROLOG_ENDS*/");
&nbsp; {&nbsp; &nbsp;&nbsp;/* Let GCC know that _fini is not a leaf function by having a dummy&nbsp; &nbsp; &nbsp; &nbsp;function call here. &nbsp;We arrange for this call to be omitted from&nbsp; &nbsp; &nbsp; &nbsp;either crt file. &nbsp;*/&nbsp; &nbsp;&nbsp;extern&nbsp;void&nbsp;i_am_not_a_leaf (void);&nbsp; &nbsp; i_am_not_a_leaf ();&nbsp; }
&nbsp;&nbsp;/* Beginning of the _fini epilog. */&nbsp;&nbsp;asm&nbsp;("\n/*@_fini_EPILOG_BEGINS*/");&nbsp; SECTION (".fini");}asm&nbsp;("END_FINI");
/* End of the _fini epilog. &nbsp;Any further generated assembly (e.g. .ident)&nbsp; &nbsp;is shared between both crt files. */asm&nbsp;("\n/*@_fini_EPILOG_ENDS*/");asm&nbsp;("\n/*@TRAILER_BEGINS*/");

但是为什么不能在libc.so.6中找到_start,_init,_fini这三个函数呢?

是因为GNU把这三个作为了程序启动和结束的最基本运行库函数,分别放在crt1.o,crti.o,crtn.o这三个object文件中供程序链接时使用。

从glibc的源码sysdeps/generic/initfini.c相关注释也可以看出:

/* This file is compiled into assembly code which is then munged by a sedscript into two files: crti.s and crtn.s.* crti.s puts a function prologue at the beginning of the.init and .fini sections and defines global symbols forthose addresses, so they can be called as functions.* crtn.s puts the corresponding function epiloguesin the .init and .fini sections. */

从上面注释来看crti.o,crtn.o分别包含.init和.fini段的开头和结束部分,分析它们的反汇编代码也可以看出:

$ objdump -d /usr/lib/i386-linux-gnu/crti.o&nbsp;/usr/lib/i386-linux-gnu/crti.o: &nbsp; &nbsp; file format elf32-i386

Disassembly of section .init:
00000000 <_init>:&nbsp; &nbsp;0:    53 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   push &nbsp; %ebx&nbsp; &nbsp;1: 83 ec 08 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x8,%esp&nbsp; &nbsp;4:  e8 00 00 00 00 &nbsp; &nbsp; &nbsp;     call &nbsp; 9 <_init+0x9>&nbsp; &nbsp;9:    5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp; &nbsp;a:    81 c3 03 00 00 00 &nbsp; &nbsp; add &nbsp; &nbsp;$0x3,%ebx&nbsp; 10:   8b 83 00 00 00 00 &nbsp; &nbsp; mov &nbsp; &nbsp;0x0(%ebx),%eax&nbsp; 16:   85 c0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   test&nbsp; &nbsp;%eax,%eax&nbsp; 18:    74 05 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   je &nbsp; &nbsp; 1f <_init+0x1f>&nbsp; 1a:  e8&nbsp;fc&nbsp;ff ff ff &nbsp; &nbsp; &nbsp;   call &nbsp; 1b <_init+0x1b>
Disassembly of section .fini:
00000000 <_fini>:&nbsp; &nbsp;0:    53 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   push &nbsp; %ebx&nbsp; &nbsp;1: 83 ec 08 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x8,%esp&nbsp; &nbsp;4:  e8 00 00 00 00 &nbsp; &nbsp; &nbsp;     call &nbsp; 9 <_fini+0x9>&nbsp; &nbsp;9:    5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp; &nbsp;a:    81 c3 03 00 00 00 &nbsp; &nbsp; add &nbsp; &nbsp;$0x3,%ebx
$ objdump -d /usr/lib/i386-linux-gnu/crtn.o
/usr/lib/i386-linux-gnu/crtn.o: &nbsp; &nbsp; file&nbsp;format&nbsp;elf32-i386

Disassembly of section .init:
00000000&nbsp;<.init>:&nbsp; &nbsp;0:    83&nbsp;c4 08 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;     add &nbsp; &nbsp;$0x8,%esp&nbsp; &nbsp;3:  5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop&nbsp; &nbsp;&nbsp;%ebx&nbsp; &nbsp;4:   c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret
Disassembly of section .fini:
00000000&nbsp;<.fini>:&nbsp; &nbsp;0:    83&nbsp;c4 08 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;     add &nbsp; &nbsp;$0x8,%esp&nbsp; &nbsp;3:  5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop&nbsp; &nbsp;&nbsp;%ebx&nbsp; &nbsp;4:   c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret

回过头来看看helloworld程序反汇编代码中的_init,_fini函数的组成:

080482b0&nbsp;<_init>:&nbsp;80482b0:    53&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebx&nbsp;80482b1:  83&nbsp;ec&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x8,%esp&nbsp;80482b4:   e8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp;&nbsp;80482b9 <_init+0x9>&nbsp;80482b9:  5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;80482ba: 81&nbsp;c3&nbsp;3b&nbsp;1d&nbsp;00&nbsp;00&nbsp; &nbsp;     add &nbsp; &nbsp;$0x1d3b,%ebx&nbsp;80482c0:    8b&nbsp;83&nbsp;fc ff ff ff &nbsp; &nbsp;   mov &nbsp; &nbsp;-0x4(%ebx),%eax&nbsp;80482c6:  85&nbsp;c0 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  test &nbsp; %eax,%eax&nbsp;80482c8: 74&nbsp;05&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   je &nbsp; &nbsp;&nbsp;80482cf <_init+0x1f>
&nbsp;80482ca:    e8&nbsp;31&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp;&nbsp;8048300&nbsp;<__gmon_start__@plt>&nbsp;80482cf:    e8 dc&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;    call &nbsp;&nbsp;80483b0 <frame_dummy>&nbsp;80482d4:    e8&nbsp;97&nbsp;01&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp;&nbsp;8048470&nbsp;<__do_global_ctors_aux>
&nbsp;80482d9:    83&nbsp;c4&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  add &nbsp; &nbsp;$0x8,%esp&nbsp;80482dc:   5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;80482dd: c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret
0804849c&nbsp;<_fini>:&nbsp;804849c:    53&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; push &nbsp; %ebx&nbsp;804849d:  83&nbsp;ec&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  sub &nbsp; &nbsp;$0x8,%esp&nbsp;80484a0:   e8&nbsp;00&nbsp;00&nbsp;00&nbsp;00&nbsp; &nbsp; &nbsp; &nbsp;   call &nbsp;&nbsp;80484a5 <_fini+0x9>&nbsp;80484a5:  5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;80484a6: 81&nbsp;c3&nbsp;4f&nbsp;1b&nbsp;00&nbsp;00&nbsp; &nbsp;     add &nbsp; &nbsp;$0x1b4f,%ebx
&nbsp;80484ac:    e8&nbsp;9f fe ff ff &nbsp; &nbsp; &nbsp;    call &nbsp;&nbsp;8048350&nbsp;<__do_global_dtors_aux>
&nbsp;80484b1:    83&nbsp;c4&nbsp;08&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;  add &nbsp; &nbsp;$0x8,%esp&nbsp;80484b4:   5b &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   pop &nbsp; &nbsp;%ebx&nbsp;80484b5: c3 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;   ret

helloworld程序反汇编代码中的_init,_fini函数中间多出来的部分是其它库或用户自定义的.init和.fini段代码。

从上面helloworld程序反汇编来看,程序启动的过程应该:

_start -> __libc_start_main -> main. 具体一点就是:

_start -> __libc_start_main -> __libc_csu_init -> main. 再具体一点就是:

_start -> __libc_start_main -> __libc_csu_init -> _init -> main -> _fini.

可以通过分析__libc_start_main函数进一步了解,下面的__libc_start_main函数是我精简后的伪代码:

/* Note: the fini parameter is ignored here for shared library. &nbsp;It&nbsp; &nbsp;is registered with __cxa_atexit. &nbsp;This had the disadvantage that&nbsp; &nbsp;finalizers were called in more than one place. &nbsp;*/STATIC&nbsp;intLIBC_START_MAIN (int&nbsp;(*main) (int,&nbsp;char&nbsp;**,&nbsp;char&nbsp;** MAIN_AUXVEC_DECL),        &nbsp;int&nbsp;argc,&nbsp;char&nbsp;*__unbounded *__unbounded ubp_av,#ifdef&nbsp;LIBC_START_MAIN_AUXVEC_ARG      ElfW(auxv_t) *__unbounded auxvec,#endif         __typeof&nbsp;(main) init,     &nbsp;void&nbsp;(*fini) (void),     &nbsp;void&nbsp;(*rtld_fini) (void),&nbsp;void&nbsp;*__unbounded stack_end){&nbsp; ...&nbsp;&nbsp;/* Register the destructor of the dynamic linker if there is any. &nbsp;*/&nbsp;&nbsp;if&nbsp;(__builtin_expect (rtld_fini !=&nbsp;NULL,&nbsp;1))&nbsp; &nbsp; __cxa_atexit ((void&nbsp;(*) (void&nbsp;*)) rtld_fini,&nbsp;NULL,&nbsp;NULL);
&nbsp;&nbsp;/* Call the initializer of the libc. &nbsp;This is only needed here if we&nbsp; &nbsp; &nbsp;are compiling for the static library in which case we haven't&nbsp; &nbsp; &nbsp;run the constructors in `_dl_start_user'. &nbsp;*/&nbsp; __libc_init_first (argc, argv, __environ);
&nbsp;&nbsp;/* Register the destructor of the program, if any. &nbsp;*/&nbsp;&nbsp;if&nbsp;(fini)&nbsp; &nbsp; __cxa_atexit ((void&nbsp;(*) (void&nbsp;*)) fini,&nbsp;NULL,&nbsp;NULL);
&nbsp;&nbsp;/* Call the initializer of the program, if any. &nbsp;*/&nbsp;&nbsp;if&nbsp;(init)&nbsp; &nbsp; (*init) (argc, argv, __environ MAIN_AUXVEC_PARAM);
&nbsp;&nbsp;/* Nothing fancy, just call the function. &nbsp;*/&nbsp; result = main (argc, argv, __environ MAIN_AUXVEC_PARAM);
&nbsp; exit (result);}

__libc_start_main函数的参数main, argc, ubp_av, init, fini, rtld_fini都是通过_start入栈得到。

其中argc, ubp_av为传递给main函数的参数argc, argv。init为__libc_csu_init函数指针,fini为__libc_csu_fini函数指针,rtld_fini为运行库加载收尾函数指针。

从__libc_start_main函数可以看出在call init之前还通过__cxa_atexit向exit函数注册了rtlf_fini和fini函数,目的是为了在main结束后call exit自动完成一些收尾工作。

这里的_init, _fini函数功能还主要负责完成C++程序全局/静态对象的构造与析构,有兴趣的可以深入一下。

__cxa_atexit函数用于注册main结束后程序退出时调用的函数,例如:1

&nbsp;#include&nbsp;<stdio.h>
#include&nbsp;<stdlib.h>&nbsp;&nbsp;void&nbsp;pre_exit&nbsp;(void){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf("Will be exit!\n");&nbsp;}&nbsp;&nbsp;int&nbsp;main&nbsp;(int&nbsp;argc,&nbsp;char&nbsp;*argv[]){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;__cxa_atexit(pre_exit,&nbsp;NULL,&nbsp;NULL);&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf("Hello world!\n");&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return&nbsp;0;}$ gcc helloworld2.c -o helloworld2$ ./helloworld2Hello world!Will be exit!

可以看到pre_exit函数并不是靠main来执行的,而是靠__libc_start_main函数里面的exit函数来调用完成。

为了更进一步理解_init函数的作用,我们再改写一下代码:

因为链接器会自动把.init段粘贴到一起组成_init函数,所以为了不使_init函数半途返回退出,我们只能用下面汇编的方法定义哪些程序块是需要被链接到_init函数,且该程序块不能有函数的返回指令,这样我们必须在该程序块结束的地方加入汇编指令告诉编译器后面的程序不属于.init段,因此就有了下面这个测试函数pre_init,它会被link到两个section,即.init和.text段。

#include&nbsp;<stdio.h>&nbsp;&nbsp;#include&nbsp;<stdlib.h>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void&nbsp;__attribute__((used))&nbsp;pre_init&nbsp;(void) &nbsp;&nbsp; { &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;asm&nbsp;(".section .init"); &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("pre-init section .init part\n"); &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("Call pre_init before main\n"); &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;asm&nbsp;(".section .text"); &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("pre-init section .text part\n"); &nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("call pre_init in main\n"); &nbsp;&nbsp;} &nbsp;&nbsp; &nbsp;&nbsp;void&nbsp;pre_exit&nbsp;(void)&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf("Call pre_exit after main!\n"); &nbsp;&nbsp;} &nbsp;&nbsp; &nbsp;&nbsp;int&nbsp;main&nbsp;(int&nbsp;argc,&nbsp;char&nbsp;*argv[])&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf("Enter main\n"); &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;__cxa_atexit(pre_exit,&nbsp;NULL,&nbsp;NULL); &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf("Hello world!\n"); &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;pre_init(); &nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("Exit main\n"); &nbsp;&nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return&nbsp;0; &nbsp;&nbsp;}
$ gcc helloworld3.c -o helloworld3 &nbsp;$ ./helloworld3 &nbsp;pre-init section .init part &nbsp;Call pre_init before main &nbsp;Enter main &nbsp;Hello world! &nbsp;pre-init section .text part &nbsp;call pre_init in main &nbsp;Exit main &nbsp;Call pre_exit after main!

从helloworld3程序的运行结果也可以看出该程序函数的调用过程:

pre_init (.init段部分 代码) -> main -> pre_init (.text段部分 代码) -> pre_exit.

同样我们也可以添加.fini段代码,链接器会把.fini段代码部分链接进_fini函数,这样_fini函数就会帮我们在main函数退出后自动执行这段代码:

&nbsp;void&nbsp;__attribute__((used)) pre_fini (void)&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; asm (".section .fini");&nbsp; &nbsp; &nbsp; &nbsp; printf("pre-fini section .fini part\n");&nbsp; &nbsp; &nbsp; &nbsp; printf("Call pre_fini after main\n");&nbsp; &nbsp; &nbsp; &nbsp; asm (".section .text");&nbsp;}$ gcc helloworld4.c -o helloworld4$ ./helloworld4pre-init&nbsp;section .init&nbsp;partCall pre_init before mainEnter mainHello world!pre-init&nbsp;section .text partcall pre_init&nbsp;in&nbsp;mainExit mainCall pre_exit after main!pre-fini section .fini partCall pre_fini after main

从以上运行结果可知pre_fini函数是在main函数退出后才被调用的,但是为什么pre_fini打印的内容比pre_exit打印的内容要晚出来呢?这是因为pre_exit函数注册比pre_fini要晚,而通过__cxa_atexit注册的过程其实就是建立一个exit函数指针链表栈,按栈的规则是后进先出,因此pre_exit比pre_fini要先被调用。

从helloworld4程序的运行结果也可以看出该程序函数的调用过程:

pre_init (.init段部分 代码) -> main -> pre_init (.text段部分 代码) -> pre_exit -> pre_fini (.fini段部分 代码).

为了让程序正常运行和结束,链接器ld帮我们做了好多事情,可以用下面来表示:

ld crt1.o crti.o [usr object] [lib] crtn.o

最后总结一下,程序启动和结束的过程可以描述为:

_start -> __libc_start_main -> init -> main -> exit.


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:绿洲安全 garyygl garyygl《PWN入门笔记-从创建进程到进入main函数,发生了什么?》

评论:0   参与:  0