pwnable.kr one
OK, 題目說讓我們 ssh 遠程服務(wù)器,那么咱們 ssh 連接一下。友情提示:現(xiàn)在的 pwn 一般都是基于 Linux 的哦。所以大家在開始玩這么一個游戲的時候建議先安裝一個基于 Linux 內(nèi)核的虛擬機关贵,如 WSL。
```shell
$?ssh?fd@pwnable.kr?-p2222
fd@pwnable.kr's?password:?guest????#?這個密碼是不可見的
```
下面我使用的是 WSL for kali 遠程登錄的結(jié)果:
好了卖毁,相信大家都會基本的 Linux 命令揖曾。我們查看一下目錄文件:
```shell
$?ls
fd??fd.c??flag
```
發(fā)現(xiàn)目錄下有三個文件落萎。然后三個文件的類型可以使用‘file filename’查看。
```$?file?fd?fd.c?flag
fd:???setuid?ELF?32-bit?LSB?executable,?Intel?80386,?version?1?(SYSV),?dynamically?linked,?interpreter?/lib/ld-linux.so.2,?for?GNU/Linux?2.6.24,?BuildID[sha1]=c5ecc1690866b3bb085d59e87aad26a1e386aaeb,?not?strippedfd.c:?C?source,?ASCII?text
flag:?regular?file,?no?read?permission
我們發(fā)現(xiàn) flag 是沒有讀權(quán)限的炭剪,顯然咱們不能直接使用 cat 命令查看练链。所以咱們還是老老實實的做題吧。
既然題目提供了源代碼奴拦,我們當然是先分析源代碼:
$?cat?fd.c
fd.c 文件內(nèi)容如下:
#include?
#include?
#include?
char?buf[32];
int?main(int?argc,?char*?argv[],?char*?envp[]){
if(argc<2){
printf("pass?argv[1]?a?number\n");
return?0;
}
int?fd?=?atoi(?argv[1]?)?-?0x1234;
int?len?=?0;
len?=?read(fd,?buf,?32);
if(!strcmp("LETMEWIN\n",?buf)){
printf("good?job?:)\n");
system("/bin/cat?flag");
exit(0);
}
printf("learn?about?Linux?file?IO\n");
return?0;
}
分析一下媒鼓,程序大概的意思就是讓我們提供一個參數(shù)(從 atoi 還可以看出,參數(shù)還必須是一個整數(shù))給程序错妖,然后程序?qū)?buf 里面的內(nèi)容與字符串“LETMEWIN\n”開始比較绿鸣,if 語句里面緊接著就跟了咱們想要的 flag 。于是咱們開始分析一下判斷條件暂氯,發(fā)現(xiàn) buf 只在
len?=?read(fd,?buf,?32);
中出現(xiàn)潮模。于是乎我們開始查詢“Linux中read函數(shù)的用法”……查到一個 Linux 常用函數(shù)手冊,但是他個雞兒的亂碼了(查看源碼發(fā)現(xiàn)網(wǎng)頁采用的是big5編碼)株旷,于是乎在chrome中下載了一個轉(zhuǎn)碼插件隨后順利解決了亂碼問題再登。
read(由已打開的文件讀取數(shù)據(jù))
相關(guān)函數(shù)readdir,write晾剖,fcntl,close梯嗽,lseek齿尽,readlink,fread
表頭文件#include
定義函數(shù)ssize_t read(int fd,void * buf ,size_t count);
函數(shù)說明read()會把參數(shù)fd 所指的文件傳送count個字節(jié)到buf指針所指的內(nèi)存中灯节。若參數(shù)count為0循头,則read()不會有作用並返回0。返回值為實際讀取到的字節(jié)數(shù)炎疆,如果返回0卡骂,表示已到達文件尾或是無可讀取的數(shù)據(jù),此外文件讀寫位置會隨讀取到的字節(jié)移動形入。
附加說明如果順利read()會返回實際讀到的字節(jié)數(shù)全跨,最好能將返回值與參數(shù)count 作比較,若返回的字節(jié)數(shù)比要求讀取的字節(jié)數(shù)少亿遂,則有可能讀到了文件尾浓若、從管道(pipe)或終端機讀取,或者是read()被信號中斷了讀取動作蛇数。當有錯誤發(fā)生時則返回-1挪钓,錯誤代碼存入errno中,而文件讀寫位置則無法預(yù)期耳舅。
錯誤代碼EINTR 此調(diào)用被信號所中斷碌上。
EAGAIN 當使用不可阻斷I/O 時(O_NONBLOCK),若無數(shù)據(jù)可讀取則返回此值。
EBADF 參數(shù)fd 非有效的文件描述詞馏予,或該文件已關(guān)閉天梧。
範例參考open()。
當然吗蚌,如果你完全信任自己的英語水平的話可以在 Linux 中使用下面的命令查看 read 函數(shù)的幫助腿倚。
$?man?read
READ(2)??????????????????????????????????????????????????????????????Linux?Programmer's?Manual??????????????????????????????????????????????????????????????READ(2)
NAME
read?-?read?from?a?file?descriptor
SYNOPSIS
#include?
ssize_t?read(int?fd,?void?*buf,?size_t?count);
DESCRIPTION
read()?attempts?to?read?up?to?count?bytes?from?file?descriptor?fd?into?the?buffer?starting?at?buf.
On??files?that?support?seeking,?the?read?operation?commences?at?the?current?file?offset,?and?the?file?offset?is?incremented?by?the?number?of?bytes?read.??If
the?current?file?offset?is?at?or?past?the?end?of?file,?no?bytes?are?read,?and?read()?returns?zero.
If?count?is?zero,?read()?may?detect?the?errors?described?below.??In?the?absence?of?any?errors,?or?if?read()?does?not?check?for?errors,?a?read()?with?a?count
of?0?returns?zero?and?has?no?other?effects.
If?count?is?greater?than?SSIZE_MAX,?the?result?is?unspecified.
RETURN?VALUE
On?success,?the?number?of?bytes?read?is?returned?(zero?indicates?end?of?file),?and?the?file?position?is?advanced?by?this?number.??It?is?not?an?error?if?this
number?is?smaller?than?the?number?of?bytes?requested;?this?may?happen?for?example?because?fewer?bytes?are?actually?available?right??now??(maybe??because??we
were?close?to?end-of-file,?or?because?we?are?reading?from?a?pipe,?or?from?a?terminal),?or?because?read()?was?interrupted?by?a?signal.??See?also?NOTES.
On?error,?-1?is?returned,?and?errno?is?set?appropriately.??In?this?case,?it?is?left?unspecified?whether?the?file?position?(if?any)?changes.
……(此處省略一萬個單詞)
因為這里 fd 參數(shù)才是我們可以控制的,所以我們要知道的是 read 函數(shù)中 fd 參數(shù)代表的是什么蚯妇。由 reference 我們知道敷燎,int fd 實際上是一個文件描述符。繼續(xù)搜索“read 函數(shù)中的 fd”在百度貼吧中得到了完美的解釋箩言。
open打開一個文件硬贯,并返回一個整數(shù)值,這個整數(shù)叫做文件描述符陨收,默認的標準輸入是 0饭豹, 標準輸出是1,標準出錯是2(這些可以在unistd.h中找到)务漩,所以你再open一個文件的時候返回的是3拄衰,如果在你關(guān)閉這個文件之前,再open一個文件饵骨,那返回的就是4翘悉,以前類推。
至于讀函數(shù)出錯居触,你可以包含errno.h頭文件妖混,并打印錯誤信息,printf( "%d,%s", errno,(char*)strerror(errno) );來顯示錯誤信息
--https://zhidao.baidu.com/question/1430510337268766779.html(來來轮洋,給這個完美的解釋一個贊V剖小)
Perfect~,我們已經(jīng)知道要干嘛了弊予,就是使 fd 的值為 0(其實我測試了一下祥楣,0,1,2 都是可以的),然后使 read 接收我們的輸入块促。
0x1234 = 4660
最終解題:
fd@ubuntu:~$?./fd?4660
LETMEWIN
good?job?:)
mommy!?I?think?I?know?what?a?file?descriptor?is!!
fd@ubuntu:~$
Flag:??mommy! I think I know what a file descriptor is!!