(writeup見ちゃいました)
調査
ロトをやらされます。
1~45の6つの乱数が生成されます。6つの番号(というか6つのbyte)を入力し、そのうち1つでも乱数と一致していればflagがもらえます。
play()関数について
void play(){
int i;
printf("Submit your 6 lotto bytes : ");
fflush(stdout);
int r;
r = read(0, submit, 6);
printf("Lotto Start!n");
//sleep(1);
// generate lotto numbers
int fd = open("/dev/urandom", O_RDONLY);
if(fd==-1){
printf("error. tell adminn");
exit(-1);
}
unsigned char lotto[6];
if(read(fd, lotto, 6) != 6){
printf("error2. tell adminn");
exit(-1);
}
for(i=0; i<6; i++){
lotto[i] = (lotto[i] % 45) + 1; // 1 ~ 45
}
close(fd);
// calculate lotto score
int match = 0, j = 0;
for(i=0; i<6; i++){
for(j=0; j<6; j++){
if(lotto[i] == submit[j]){
match++;
}
}
}
// win!
if(match == 6){
system("/bin/cat flag");
}
else{
printf("bad luck...n");
}
}
ロトはソースコードのplay関数で行われています。
「ロト6」は普通、6つの数字は重複してはいけません。じゃないと低い等数の当選が狙いやすくなってしまいます。
ですが、play関数ではどこも6つの数(というかbyte)の重複チェックをしていません。
解法
よって、6つの数を全部同じ数にすれば良いです。
次のシェルスクリプトで自動で繰り返します。
対話型のプログラムの相手をさせるならexpectが一番でしょうが、サーバに入ってないのでこれも使えない。
標準的な機能のみで対話型?プログラムの自動化をするのは、(vMasturbation: bashのみで対話的なtelnetを自動実行する)を参考にしました。
μ秒単位で寝てくれるusleepも無いので仕方なく秒単位で寝るsleepを使わざるを得ませんが試行回数が少ないので実用範囲内です。
#!/bin/bash
commandline()
{
sleep 1; echo "1"
sleep 1; echo "######3"
}
for i in `seq 0 30`
do
touch /tmp/tmpfile1
commandline | ./lotto > /tmp/tmpfile1
cat /tmp/tmpfile1 | grep "bad"
#badなんとかって文言がないとき==当選したとき
if [ $? = 1 ] ; then
#当選したときのログを表示して終了
cat /tmp/tmpfile1
rm -f /tmp/tmpfile1
break
fi
rm -f /tmp/tmpfile1
done
なんか最初の1行だけ端末に表示されちゃいますが、動きます。
コメント