pwnable.kr(2)

布教用兼確認の2記事目

http://pwnable.kr

col

2つ目の問題。

col@ubuntu:~$ ls -l
total 16
-r-sr-x--- 1 col_pwn col     7341 Jun 11  2014 col
-rw-r--r-- 1 root    root     555 Jun 12  2014 col.c
-r--r----- 1 col_pwn col_pwn   52 Jun 11  2014 flag

MD5って書いてあったから多分、ソースコードcol.cのlongのハッシュコードがMD5なんだと思う。16バイト(128ビット)だし。MD5アルゴリズムとは何にも関係なさそう。

ソースコードを見てみると、プログラムの引数に値を渡すタイプだって事がわかる。長さは20じゃないとダメ。

	if(strlen(argv[1]) != 20){
		printf("passcode length should be 20 bytes\n");
		return 0;
	}

長さが20でもcheck_passwordの戻り値と定数hashcodeが同じじゃないとダメ。
check_passwordは20バイトの文字列を先頭から4バイトずつリトルエンディアンの整数として5回足すというもの。

unsigned long check_password(const char* p){
	int* ip = (int*)p;
	int i;
	int res=0;
	for(i=0; i<5; i++){
		res += ip[i];
	}
	return res;
}

この戻り値をhashcodeに合わせれば良い。合わせるパターンはいくらでもあるけど、¥x00(ヌル文字)とかは文字列が終了して使えなかったり、アラームとかも使えないんじゃないかって思ったりするので、そういうところは気をつける。
今回は、hashcodeを5で割って最後のにオフセットをつける。hashcodeは0x21DD09ECっていうことを踏まえて、算出する。python3のインタプリターで。

>>> from struct import pack
>>> pack('i',0x21DD09EC//5)
b'\xc8\xce\xc5\x06'
>>> pack('i',0x21DD09EC//5+0x21DD09EC%5)
b'\xcc\xce\xc5\x06'

これで準備は整った。
ぶち込んでやるぜぇ。

col@ubuntu:~$ ./col `python -c 'print "\xc8\xce\xc5\x06"*4+"\xcc\xce\xc5\x06"'`

おしまい。