# VolgaCTF 2019 "warm [PWN 100]" writeup
![問題](./001.png)
このぐらいのレベルが楽しく解けてちょうど良い。
## 解法
stringsで見てみるとstrcpyとかgetsとかあるしバッファオーバフロー系かなと思う。
が、checksecで見るとフルでプロテクトかかってる。これは苦労しそうだなと。さらにfileコマンドで見てみると↓ARMかよ．．．ARMのgdb環境は整えてないので少し萎える。
```bash-statementsaru@lucifen:~/wani-writeup/2019/03-volga/pwn-warm$ file warm
warm: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-, for GNU/Linux 3.2.0, BuildID[sha1]=c549628c0b3841a5fd9a23f0faaf6b51eb858e94, stripped
saru@lucifen:~/wani-writeup/2019/03-volga/pwn-warm$```
とりあえず繋いでみると、パスワードを聞かれる。適当に長いやつ入れてみたけど簡単にはsegmentation faultは起きない。
![繋いでみた](./002.png)
そんな中でghidraにかけてみた。なんだこれは簡単そうじゃないか．．．一文字目は0x76、後はXORをひたすらかけてる。
```C:ghidra_001.cundefined4 FUN_00010788(byte *pbParm1){  size_t sVar1;  undefined4 uVar2;   sVar1 = strlen((char *)pbParm1);  if (sVar1 < 0x10) {    uVar2 = 1;  }else {    if (((((*pbParm1 == 0x76) && ((pbParm1[1] ^ *pbParm1) == 0x4e)) &&	  ((pbParm1[2] ^ pbParm1[1]) == 0x1e)) &&	 ((((pbParm1[3] ^ pbParm1[2]) == 0x15 && ((pbParm1[4] ^ pbParm1[3]) == 0x5e)) &&	   (((pbParm1[5] ^ pbParm1[4]) == 0x1c &&	     (((pbParm1[6] ^ pbParm1[5]) == 0x21 && ((pbParm1[7] ^ pbParm1[6]) == 1)))))))) &&	(((pbParm1[8] ^ pbParm1[7]) == 0x34 &&	  ((((((pbParm1[9] ^ pbParm1[8]) == 7 && ((pbParm1[10] ^ pbParm1[9]) == 0x35)) &&	      ((pbParm1[0xb] ^ pbParm1[10]) == 0x11)) &&	     (((pbParm1[0xc] ^ pbParm1[0xb]) == 0x37 && ((pbParm1[0xd] ^ pbParm1[0xc]) == 0x3c))))&&	    (((pbParm1[0xe] ^ pbParm1[0xd]) == 0x72 && ((pbParm1[0xf] ^ pbParm1[0xe]) ==0x47)))))))) {      uVar2 = 0;    } else {      uVar2 = 2;    }  }  return uVar2;}```
というわけでデコードプログラムを書く。
```c:krack_pass.c#include <stdio.h>#include <ctype.h>
int main(){  uint8_t c, tmp;  c = 0x76;   putchar(c);    tmp = 0x4e;  c = c ^ tmp;   putchar(c);  tmp = 0x1e;  c = c ^ tmp;
  putchar(c);    tmp = 0x15;  c = c ^ tmp;
  putchar(c);    tmp = 0x5e;  c = c ^ tmp;
  putchar(c);    tmp = 0x1c;  c = c ^ tmp;
  putchar(c);    tmp = 0x21;  c = c ^ tmp;
  putchar(c);    tmp = 0x01;  c = c ^ tmp;
  putchar(c);    tmp = 0x34;  c = c ^ tmp;
  putchar(c);    tmp = 0x07;  c = c ^ tmp;
  putchar(c);    tmp = 0x35;  c = c ^ tmp;
  putchar(c);    tmp = 0x11;  c = c ^ tmp;
  putchar(c);    tmp = 0x37;  c = c ^ tmp;
  putchar(c);    tmp = 0x3c;  c = c ^ tmp;
  putchar(c);    tmp = 0x72;  c = c ^ tmp;
  putchar(c);    tmp = 0x47;  c = c ^ tmp;
  putchar(c);}```
実行結果は
![実行結果](./003.png)
パスワードをサーバに入力してみると合ってはいるのだけど何かがおかしい。
![パスワード入力](./004.png)
もっかいghidraの結果を眺めてみる。ファイルの入出力のところの処理を追ってみるとパスワード「```acStack220[100]```」があってた場合ファイル「```acStack120[100]```」を開いてその中身を表示させている。
```c:ghidra_002.cundefined4 FUN_000109ec(void){  int __c;  FILE *__stream;  char acStack220 [100];  char acStack120 [100];  int local_14;  local_14 = __stack_chk_guard;  setvbuf(stdout,(char *)0x0,2,0);  while( true ) {    while( true ) {      FUN_000108f0(acStack120);      puts("Hi there! I\'ve been waiting for your password!");      gets(acStack220);      __c = FUN_00010788(acStack220);      if (__c == 0){	break;      }      FUN_00010978(1,0);    }    __stream = fopen(acStack120,"rb");    if (__stream != (FILE *)0x0){      break;    }    FUN_00010978(2,acStack120);  }   while (__c = _IO_getc((_IO_FILE *)__stream), __c != -1) {    putchar(__c);  }  fclose(__stream);  if (local_14 == __stack_chk_guard) {    return 0;  }  /* WARNING: Subroutine does not return */  __stack_chk_fail();}```
じゃファイル名書き換えられるんじゃね？ということでパスワードの後に適当に```A * 100```をつけて送ってみた。見事ファイルを書き換えられた！
![書き換えは成功](./005.png)
たぶん```flag.txt```だろうと思ってやってみたが駄目。flagをやってみたら```Seek file with something more sacred!```と出る。sacredをscaredと間違えてvirusとか入れてみたけど駄目。で、少し考えてみてsacredを入力したらゲットできた。
![flag奪取](./006.png)