[摘要](内存低址) 再单步执行, 返回到调用main函数的函数 (gdb) si 0x400349cb in __libc_start_main (main=0x804842c <main>,...
(内存低址)
再单步执行, 返回到调用main函数的函数
(gdb) si
0x400349cb in __libc_start_main (main=0x804842c <main>, argc=2, argv=0xbffff704, init=0x80482c0 <_init>,
fini=0x804848c <_fini>, rtld_fini=0x4000ae60 <_dl_fini>, stack_end=0xbffff6fc)
at ../sysdeps/generic/libc-start.c:92
92 ../sysdeps/generic/libc-start.c: No such file or directory.
原来是 __libc_start_main 函数调用了我们的main函数, 看来和概述里说的有些出入,
但这对于我们来讲不是很重要. 如果想看源码, 请到../sysdeps/generic/libc-start.c
文件中找.
(gdb) x/16x $esp
0xbffff6c0: 0x00000002 0xbffff704 0xbffff710 0x40013868
0xbffff6d0: 0x00000002 0x08048350 0x00000000 0x08048371
0xbffff6e0: 0x0804842c 0x00000002 0xbffff704 0x080482c0
0xbffff6f0: 0x0804848c 0x4000ae60 0xbffff6fc 0x40013e90
从上面可以看到, stack_end=0xbffff6fc, 也就是说我们的进程的栈底地址为0xbffff6fc,
在调用__libc_start_main函数前依次推了如下七个参数入栈:
0xbffff6fc -> 进程的栈底
0x4000ae60 -> _dl_fini函数的入口地址.
0x0804848c -> _fini函数的入口地址
0x080482c0 -> _init函数的入口地址
0xbffff704 -> argv命令行参数地址的地址
0x00000002 -> argc命令行参数个数值
0x0804842c -> 我们的main函数入口
从上面的分析可推出, 在内存地址0xbffff6dc的内容0x08048371就是__libc_start_main函数
的返回地址了.
我们来看看是什么函数调用了__libc_start_main.
(gdb) disas 0x08048371
Dump of assembler code for function _start:
0x8048350 <_start>: xor %ebp,%ebp
0x8048352 <_start+2>: pop %esi
0x8048353 <_start+3>: mov %esp,%ecx
0x8048355 <_start+5>: and $0xfffffff8,%esp
0x8048358 <_start+8>: push %eax
0x8048359 <_start+9>: push %esp
0x804835a <_start+10>: push %edx
0x804835b <_start+11>: push $0x804848c
0x8048360 <_start+16>: push $0x80482c0
0x8048365 <_start+21>: push %ecx
0x8048366 <_start+22>: push %esi
0x8048367 <_start+23>: push $0x804842c
0x804836c <_start+28>: call 0x8048320 <__libc_start_main>
0x8048371 <_start+33>: hlt
0x8048372 <_start+34>: nop
0x8048373 <_start+35>: nop
(省略以下的nop)
End of assembler dump.
原来是_start函数调用了__libc_start_main函数.
至于_start函数调用__libc_start_main函数后, 接是如何调用_init函数和_dl_runtime_resove
函数来调用共享库函数和我们的main函数然后退出的, 已经远远脱离了本文的主题, 这里不再继
续介绍.
(gdb) x/1024x 0xbffff6f0
0xbffff6f0: 0x0804848c 0x4000ae60 0xbffff6fc 0x40013e90
0xbffff700: 0x00000002 0xbffff83e 0xbffff856 0x00000000
0xbffff710: 0xbffff85f 0xbffff881 0xbffff88f 0xbffff89e
0xbffff720: 0xbffff8c4 0xbffff8d2 0xbffff900 0xbffff91a
0xbffff730: 0xbffff932 0xbffff94d 0xbffff9a8 0xbffff9df
0xbffff740: 0xbffffaf3 0xbffffb06 0xbffffb11 0xbffffb31
0xbffff750: 0xbffffb5a 0xbffffb68 0xbffffc72 0xbffffc7e
0xbffff760: 0xbffffc8f 0xbffffca4 0xbffffcb4 0xbffffcbf
0xbffff770: 0xbffffcd7 0xbffffcf5 0xbffffd0e 0xbffffd19
0xbffff780: 0xbffffd23 0xbffffd6c 0xbffffd79 0xbffffda0
0xbffff790: 0xbffffdb2 0xbffffdc1 0xbffffde6 0xbffffe08
0xbffff7a0: 0xbffffe10 0xbfffffd3 0x00000000 0x00000003
0xbffff7b0: 0x08048034 0x00000004 0x00000020 0x00000005
0xbffff7c0: 0x00000006 0x00000006 0x00001000 0x00000007
0xbffff7d0: 0x40000000 0x00000008 0x00000000 0x00000009
0xbffff7e0: 0x08048350 0x0000000b 0x000001f5 0x0000000c
0xbffff7f0: 0x000001f5 0x0000000d 0x00000004 0x0000000e
0xbffff800: 0x00000004 0x00000010 0x008001bf 0x0000000f
0xbffff810: 0xbffff839 0x00000000 0x00000000 0x00000000
0xbffff820: 0x00000000 0x00000000 0x00000000 0x00000000
0xbffff830: 0x00000000 0x00000000 0x38356900 0x682f0036
0xbffff840: 0x2f656d6f 0x65776f74 0x74742f72 0x2f737775
0xbffff850: 0x2f6c6469 0x41410070 0x41414141 0x4c004141
0xbffff860: 0x4f535345 0x3d4e4550 0x73752f7c 0x69622f72
...
(省略)
...
0xbfffffd0: 0x54003a35 0x75413d5a 0x61727473 0x2f61696c
0xbfffffe0: 0x0057534e 0x6d6f682f 0x6f742f65 0x2f726577
0xbffffff0: 0x77757474 0x64692f73 0x00702f6c 0x00000000
0xc0000000: Cannot access memory at address 0xc0000000
我们知道内存单元0xbffff704放的是指argv[0]的地址, 那么0xbffff708放的就是argv[1]
的地址了. 0xbffff700里放的是argc的值.
那么0xbffff710里放的是什么呢? 看样子象是指向字符串的地址, 让我们来看看.
(gdb) x/1s 0xbffff85f
0xbffff85f: "LESSOPEN=
关键词:编写自己的缓冲区溢出运用程序