20190916pwnable上的第一題[fd]詳解writeup

首先我們先在pwnable.kr上選擇這道fd題目,應(yīng)該是第一道,也是我第一次做pwn。

這里我們通過(guò)ssh工具來(lái)進(jìn)行連接,我使用的是MobaXterm

在這里設(shè)置主機(jī)名:pwnable.kr ,端口為2222,賬號(hào)為fd,密碼為guest。


我這里因?yàn)楣ぞ叩脑?,不需要?zhí)行l(wèi)s來(lái)看有哪些文件,從左側(cè)可以看出有三個(gè)文件,其中flag文件是我們需要的,可惜我們沒(méi)有權(quán)限去read。這里還是算比較友好的,是開(kāi)源的,我們可以直接cat fd.c來(lái)查看該文件的源碼。


這里我第一天題目做出來(lái)只是有很淺薄的認(rèn)識(shí),知其然不知其所以然。后面Johnny老哥討論的時(shí)候,他問(wèn)了我?guī)讉€(gè)問(wèn)題給我問(wèn)倒了,隨后我又進(jìn)行一行一行的查詢理解總算是把這道題吃透了。

前面三行#include學(xué)過(guò)編程的應(yīng)該都知道,這是要引用頭文件,類似java、python調(diào)用庫(kù)。

char buf[32];這里意味著聲明一個(gè)大小為32的字符型數(shù)組buf。

int main(int argc, char* argv[], char* envp[])這里意味著定義一個(gè)main函數(shù),第一個(gè)參數(shù)argc的值表示程序運(yùn)行時(shí),命令行參數(shù)的個(gè)數(shù)。第二個(gè)參數(shù)*argv[]的值表示指向字符串?dāng)?shù)組的指針,每個(gè)字符串對(duì)應(yīng)一個(gè)參數(shù)。第三個(gè)參數(shù)是用來(lái)取得系統(tǒng)的環(huán)境變量,如:在DOS下,有一個(gè)PATH變量。當(dāng)你在DOS提示符下輸入一個(gè)命令的時(shí)候,DOS會(huì)首先在當(dāng)前目錄下找這個(gè)命令的執(zhí)行文件。如果找不到,則到PATH定義的路徑下去找,找到則執(zhí)行,找不到返回Bad?? command?? or?? file?? name?。在DOS命令提示符下鍵入set可查看系統(tǒng)的環(huán)境變量。

if(argc<2){

? ? ? ? ? ? ? ? printf("pass argv[1] a number\n");

? ? ? ? ? ? ? ? return 0;

? ? ? ? }

這里的意思是,如果argc<2的話,輸出pass argv[1] a number。argc用來(lái)統(tǒng)計(jì)參數(shù)的個(gè)數(shù),因?yàn)槁窂綖槟J(rèn)的參數(shù),所以argc至少為1,所以這里一定要至少有一個(gè)數(shù)字輸入。

int fd = atoi( argv[1] ) - 0x1234;這里申明一個(gè)整型變量fd(fd應(yīng)該是filedes的意思P.S.如果說(shuō)錯(cuò)了希望能私信我指出),atoi (表示 ascii to integer)是把字符串轉(zhuǎn)換成整型數(shù)的一個(gè)函數(shù),就是把a(bǔ)rgv[1]的輸入強(qiáng)制轉(zhuǎn)換為整型數(shù),這里的argv[1]就是我們的第一個(gè)輸入。argv[0]是輸入的路徑,argv[1]、argv[2]......就是我們的第一個(gè)、第二個(gè)....個(gè)輸入。這里把我們的輸入進(jìn)行了減法操作,把我們的輸入-0x1234后賦值給fd。

int len = 0;這里申明len=0。

len = read(fd, buf, 32);? 這里是一個(gè)read函數(shù),fd的值分三種情況,①fd=0:代表stdin(標(biāo)準(zhǔn)輸入)fd=1:代表 stdout(標(biāo)準(zhǔn)輸出)fd=2:代表 stderr(標(biāo)準(zhǔn)錯(cuò)誤)。后面意味著從fd處讀取32個(gè)字符作為buf。

strcmp("LETMEWIN\n", buf)這里我們一層層來(lái)看,這里的strcmp(string compare)是用來(lái)對(duì)比字符串的,這里要做一個(gè)LETMEWIN和buf內(nèi)我們輸入的進(jìn)行對(duì)比,如果兩個(gè)一樣則為0,兩個(gè)不一樣則為1。

if(!strcmp("LETMEWIN\n", buf)),這里在前面的基礎(chǔ)上加上了一個(gè)!意味著取反,如果兩個(gè)一樣就為1,兩個(gè)不一樣就為0。在if函數(shù)里,輸入為1則為真,輸入為0則為假,所以要將此處strcmp的結(jié)果進(jìn)行取反來(lái)達(dá)到驗(yàn)證的目的。

后面的代碼就是簡(jiǎn)單的輸出和調(diào)用system來(lái)執(zhí)行cat flag的命令了,這里就不再解釋了。


繼續(xù)解題,我們可以看到這里fd是需要減去一個(gè)0x1234的,0x1234是十六進(jìn)制下的1234,所對(duì)應(yīng)的十進(jìn)制數(shù)是4660,比較快速的方法就是用程序員計(jì)算器。這里fd減去一個(gè)0x1234我第一反應(yīng)就是在這里構(gòu)造一個(gè)fd=0,上面提到了fd=0是標(biāo)準(zhǔn)輸入。

這里我輸入了4660,這時(shí)候就跳到下一步了,輸入一串字符串,這里要和LETMEWIN做一個(gè)比對(duì),要完全一致,所以我們?cè)谶@里輸入一個(gè)LETMEWIN,注意:要完全一致!

這里就按照程序順序執(zhí)行下去了,good job是打印的成功信息,mommy! I think I know what a file descriptor is!!這里加粗的就是這道題的flag。題目到這里是做完了,提交過(guò)后便算過(guò)關(guān)了,但是秉著學(xué)習(xí)的態(tài)度,我做了一下fd不為0的測(cè)試。

當(dāng)我輸入4661,令fd=1,可以成功cat flag。

當(dāng)我輸入4662,令fd=2同樣可以。這里可能是作者為了對(duì)新手友好一點(diǎn)的表現(xiàn)吧,畢竟是入門第一道題目,只要這里的fd=0、1/2都可以成功獲取flag,fd=0、1、2均是合法輸入,均會(huì)順序執(zhí)行下去。題目就到這里結(jié)束了,如有不對(duì)的地方,望大家指出,謝謝!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 大綱 一.Socket簡(jiǎn)介 二.BSD Socket編程準(zhǔn)備 1.地址 2.端口 3.網(wǎng)絡(luò)字節(jié)序 4.半相關(guān)與全相...
    VD2012閱讀 2,700評(píng)論 0 5
  • 先小小提一下下面涉及到的一些東西,玩Linux很溜的可以無(wú)視。主要照顧一些現(xiàn)在只接觸過(guò)Windows的同學(xué): ls...
    Reverse的舔狗閱讀 866評(píng)論 0 0
  • 下面為Daytime這個(gè)服務(wù)的源代碼例子,同時(shí)兼容IPV6和IPV4的地址,最后部分有更多說(shuō)明。 單播模式下的Se...
    天楚銳齒閱讀 6,037評(píng)論 0 2
  • 串口操作 串口操作需要的頭文件 #include /*標(biāo)準(zhǔn)輸入輸出定義*/ #include /*標(biāo)準(zhǔn)函數(shù)庫(kù)定...
    旅行家John閱讀 1,469評(píng)論 0 3
  • 推脫不掉的廉價(jià)勞動(dòng)力 很累,但是走不了 哎 最缺錢的時(shí)候
    monsterF閱讀 124評(píng)論 0 0

友情鏈接更多精彩內(nèi)容