原題:
Bad idea to use predictable stuff.
source code:
/*
* gcc ch21.c -lcrypt -o ch21
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <crypt.h>
#include <sys/types.h>
#include <unistd.h>
int main (int argc, char *argv[]) {
? ? char pid[16];
? ? char *args[] = { "/bin/bash", "-p", 0 };
? ? snprintf(pid, sizeof(pid), "%i", getpid());
? ? if (argc != 2)
? ? ? ? return 0;
? ? printf("%s=%s",argv[1], crypt(pid, "$1$awesome"));
? ? if (strcmp(argv[1], crypt(pid, "$1$awesome")) == 0) {
? ? ? ? printf("WIN!\n");
execve(args[0], &args[0], NULL);
? ? } else {
? ? ? ? printf("Fail... :/\n");
? ? }
? ? return 0;
}
Challenge connection informations?:
Hostchallenge01.root-me.org
ProtocolSSH
Port2221
SSH access:?ssh -p 2221 cryptanalyse-ch21@challenge01.root-me.org
Usernamecryptanalyse-ch21
Passwordcryptanalyse-ch21
打開ssh的鏈接,用ls -a我們可以看到當前目錄:
ch21是可執行文件,執行效果在下一行代碼中。ch21.c是源碼,和題干中的源碼一樣。.passwd是隱藏文件,以現在的權限不能讀取。
查看源碼之后可以發現我們要輸入一個和等號后面一樣的字符串就可以得到一個shell。那個字符串是由程序的PID加密得到的。
因為PID是有限的,如果用完了PID就會循環從0開始。題目中的ELF32可以看到這個系統是32位的,所以PID最大為32768。我寫了一個循環來使PID重用,從而利用之前程序返回的字符串可以使程序的判斷為真:
for i in `seq 1 32768`; do ./ch21 '$1$awesome$taBoXpC0SSn8X3yE3WgJd1'; done
?運行結果如下:
得到shell之后查看隱藏文件.passwd就可以得到flag。
提交flag后看到別人的solution,看到有人一行代碼就可以實現。。。
./ch21 $(python -c 'import os,crypt; print crypt.crypt(str(os.getpid() + 1), "$1$awesome")')
原來crypt.h是unix標準庫里的,我之前以為這個頭文件是他們自己寫的。。。
既然是標準的加密函數,我們就可以預測出PID然后輸入到這個函數中得到結果。