SECCON Beginners CTF 2021 reversing 05 firmware を勉強した記録

# 問題
reversing 05 firmware
ctf4b networks社のページからファームウェアをダウンロードしてきました。
このファイルの中からパスワードを探してください。

# 青い空を見上げればいつもそこに白い猫

`ファイル・データ抽出`ボタン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/996d87af-8e7b-4c9d-2dfc-94d7afbf6cca.png)

算出サイズを無視してにチェック
検索除外対象のzlibのチェックを外す
`検索実行`ボタン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/70cdc385-4a17-6eb3-2a9e-82f0be7e7f44.png)

ELFを選択
算出サイズを下選択で修正 4MBを指定
`リスト選択項目を保存`ボタン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/dbb5a226-2d26-933b-1c2a-27b7a458a23f.png)

保存したELFをGhidraで開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/850f9e15-0612-ed65-9fe6-05eb161278e3.png)
ARMだ

strings
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/2298b44b-6916-b886-6b4d-b8c839fbb94c.png)
Input password
Incorrect password 
などの文字が見える

main関数の初期デコンパイル結果

```c:main
undefined8 main(void)
{
  int iVar1;
  size_t sVar2;
  socklen_t local_11e4;
  int local_11e0;
  int local_11dc;
  int local_11d8;
  FILE *local_11d4;
  size_t local_11d0;
  char *local_11cc;
  undefined local_11c8 [4];
  undefined4 local_11c4;
  sockaddr sStack4536;
  uint auStack4520 [61];
  undefined4 local_10b4;
  undefined4 uStack4272;
  undefined4 uStack4268;
  undefined4 uStack4264;
  undefined4 local_10a4;
  undefined local_10a0;
  undefined4 local_109c;
  undefined4 uStack4248;
  undefined4 uStack4244;
  undefined4 uStack4240;
  undefined4 local_108c;
  undefined4 uStack4232;
  undefined4 uStack4228;
  undefined4 uStack4224;
  undefined4 local_107c;
  undefined local_1078;
  char acStack4212 [96];
  byte abStack4116 [4096];
  int local_14;
  
  local_14 = __stack_chk_guard;
  local_11dc = socket(2,1,0);
  if (local_11dc < 0) {
    perror("Failed to set socket.");
  }
  else {
    local_11c8._0_2_ = 2;
    local_11c8._2_2_ = htons(0x1f90);
    local_11c4 = 0;
    iVar1 = bind(local_11dc,(sockaddr *)local_11c8,0x10);
    if (iVar1 == 0) {
      iVar1 = listen(local_11dc,5);
      if (iVar1 == 0) {
        while( true ) {
          local_11e4 = 0x10;
          local_11d8 = accept(local_11dc,&sStack4536,&local_11e4);
          local_11d4 = fopen("ascii.txt","r");
          if (local_11d4 == (FILE *)0x0) break;
          fseek(local_11d4,0,2);
          local_11d0 = ftell(local_11d4);
          fseek(local_11d4,0,0);
          local_11cc = (char *)calloc(local_11d0,1);
          if (local_11cc == (char *)0x0) {
            perror("Failed to read file.");
            close(local_11d8);
            goto LAB_00010cf4;
          }
          fread(local_11cc,1,local_11d0,local_11d4);
          fclose(local_11d4);
          sVar2 = strlen(local_11cc);
          send(local_11d8,local_11cc,sVar2,0);
          free(local_11cc);
          memcpy(acStack4212,
                 "This is a IoT device made by ctf4b networks. Password authentication is required to operate.\n"
                 ,0x5e);
          sVar2 = strlen(acStack4212);
          send(local_11d8,acStack4212,sVar2,0);
          local_109c = 0x75706e49;
          uStack4248 = 0x61702074;
          uStack4244 = 0x6f777373;
          uStack4240 = 0x28206472;
          local_108c = 0x73736170;
          uStack4232 = 0x64726f77;
          uStack4228 = 0x20736920;
          uStack4224 = 0x47414c46;
          local_107c = 0x203e2029;
          local_1078 = 0;
          sVar2 = strlen((char *)&local_109c);
          send(local_11d8,&local_109c,sVar2,0);
          memset(abStack4116,0,0x1000);
          recv(local_11d8,abStack4116,0x1000,0);
          printf("%s",abStack4116);
          memcpy(auStack4520,&DAT_00010ea4,0xf4);
          sVar2 = strlen((char *)abStack4116);
          if (sVar2 != 0x3d) {
            local_10b4 = 0x6f636e49;
            uStack4272 = 0x63657272;
            uStack4268 = 0x61702074;
            uStack4264 = 0x6f777373;
            local_10a4 = 0xa2e6472;
            local_10a0 = 0;
            sVar2 = strlen((char *)&local_10b4);
            send(local_11d8,&local_10b4,sVar2,0);
            close(local_11d8);
          }
          local_11e0 = 0;
          while (local_11e0 < 0x3d) {
            if ((uint)(abStack4116[local_11e0] ^ 0x53) != auStack4520[local_11e0]) {
              local_10b4 = 0x6f636e49;
              uStack4272 = 0x63657272;
              uStack4268 = 0x61702074;
              uStack4264 = 0x6f777373;
              local_10a4 = 0xa2e6472;
              local_10a0 = 0;
              sVar2 = strlen((char *)&local_10b4);
              send(local_11d8,&local_10b4,sVar2,0);
              close(local_11d8);
            }
            local_11e0 = local_11e0 + 1;
          }
          local_10b4 = 0x72726f43;
          uStack4272 = 0x20746365;
          uStack4268 = 0x73736170;
          uStack4264 = 0x64726f77;
          local_10a4 = 0xa212121;
          local_10a0 = 0;
          sVar2 = strlen((char *)&local_10b4);
          send(local_11d8,&local_10b4,sVar2,0);
          close(local_11d8);
        }
        perror("Failed to read file.");
        close(local_11d8);
      }
      else {
        perror("Failed to listen.");
      }
    }
    else {
      perror("Failed to bind.");
    }
  }
LAB_00010cf4:
  if (__stack_chk_guard != local_14) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 1;
}
```

```
            if ((uint)(abStack4116[local_11e0] ^ 0x53) != auStack4520[local_11e0]) {
              local_10b4 = 0x6f636e49;
              uStack4272 = 0x63657272;
              uStack4268 = 0x61702074;
              uStack4264 = 0x6f777373;
              local_10a4 = 0xa2e6472;
```

0x53 と xor して違ってたら Incorrect password と表示している。

変数名を変更してデコンパイル結果を見やすくする

|変更前  |変更後  |
|---|---|
|auStack4520  |enc_flag |
|local_11e0|i |
|abStack4116|input|
|sVar2|inputlength|

```c:main（修正後）
undefined8 main(void)

{
  int iVar1;
  size_t inputlength;
  socklen_t local_11e4;
  int i;
  int local_11dc;
  int local_11d8;
  FILE *local_11d4;
  size_t local_11d0;
  char *local_11cc;
  undefined local_11c8 [4];
  undefined4 local_11c4;
  sockaddr sStack4536;
  uint enc_flag [61];
  undefined4 local_10b4;
  undefined4 uStack4272;
  undefined4 uStack4268;
  undefined4 uStack4264;
  undefined4 local_10a4;
  undefined local_10a0;
  undefined4 local_109c;
  undefined4 uStack4248;
  undefined4 uStack4244;
  undefined4 uStack4240;
  undefined4 local_108c;
  undefined4 uStack4232;
  undefined4 uStack4228;
  undefined4 uStack4224;
  undefined4 local_107c;
  undefined local_1078;
  char acStack4212 [96];
  byte input [4096];
  int local_14;
  
  local_14 = __stack_chk_guard;
  local_11dc = socket(2,1,0);
  if (local_11dc < 0) {
    perror("Failed to set socket.");
  }
  else {
    local_11c8._0_2_ = 2;
    local_11c8._2_2_ = htons(0x1f90);
    local_11c4 = 0;
    iVar1 = bind(local_11dc,(sockaddr *)local_11c8,0x10);
    if (iVar1 == 0) {
      iVar1 = listen(local_11dc,5);
      if (iVar1 == 0) {
        while( true ) {
          local_11e4 = 0x10;
          local_11d8 = accept(local_11dc,&sStack4536,&local_11e4);
          local_11d4 = fopen("ascii.txt","r");
          if (local_11d4 == (FILE *)0x0) break;
          fseek(local_11d4,0,2);
          local_11d0 = ftell(local_11d4);
          fseek(local_11d4,0,0);
          local_11cc = (char *)calloc(local_11d0,1);
          if (local_11cc == (char *)0x0) {
            perror("Failed to read file.");
            close(local_11d8);
            goto LAB_00010cf4;
          }
          fread(local_11cc,1,local_11d0,local_11d4);
          fclose(local_11d4);
          inputlength = strlen(local_11cc);
          send(local_11d8,local_11cc,inputlength,0);
          free(local_11cc);
          memcpy(acStack4212,
                 "This is a IoT device made by ctf4b networks. Password authentication is required to operate.\n"
                 ,0x5e);
          inputlength = strlen(acStack4212);
          send(local_11d8,acStack4212,inputlength,0);
          local_109c = 0x75706e49;
          uStack4248 = 0x61702074;
          uStack4244 = 0x6f777373;
          uStack4240 = 0x28206472;
          local_108c = 0x73736170;
          uStack4232 = 0x64726f77;
          uStack4228 = 0x20736920;
          uStack4224 = 0x47414c46;
          local_107c = 0x203e2029;
          local_1078 = 0;
          inputlength = strlen((char *)&local_109c);
          send(local_11d8,&local_109c,inputlength,0);
          memset(input,0,0x1000);
          recv(local_11d8,input,0x1000,0);
          printf("%s",input);
          memcpy(enc_flag,&DAT_00010ea4,0xf4);
          inputlength = strlen((char *)input);
          if (inputlength != 0x3d) {
            local_10b4 = 0x6f636e49;
            uStack4272 = 0x63657272;
            uStack4268 = 0x61702074;
            uStack4264 = 0x6f777373;
            local_10a4 = 0xa2e6472;
            local_10a0 = 0;
            inputlength = strlen((char *)&local_10b4);
            send(local_11d8,&local_10b4,inputlength,0);
            close(local_11d8);
          }
          i = 0;
          while (i < 0x3d) {
            if ((uint)(input[i] ^ 0x53) != enc_flag[i]) {
              local_10b4 = 0x6f636e49;
              uStack4272 = 0x63657272;
              uStack4268 = 0x61702074;
              uStack4264 = 0x6f777373;
              local_10a4 = 0xa2e6472;
              local_10a0 = 0;
              inputlength = strlen((char *)&local_10b4);
              send(local_11d8,&local_10b4,inputlength,0);
              close(local_11d8);
            }
            i = i + 1;
          }
          local_10b4 = 0x72726f43;
          uStack4272 = 0x20746365;
          uStack4268 = 0x73736170;
          uStack4264 = 0x64726f77;
          local_10a4 = 0xa212121;
          local_10a0 = 0;
          inputlength = strlen((char *)&local_10b4);
          send(local_11d8,&local_10b4,inputlength,0);
          close(local_11d8);
        }
        perror("Failed to read file.");
        close(local_11d8);
      }
      else {
        perror("Failed to listen.");
      }
    }
    else {
      perror("Failed to bind.");
    }
  }
LAB_00010cf4:
  if (__stack_chk_guard != local_14) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 1;
}
```

solver ( Ghidra Script ) 

```python:test_firmware_ctf4b2021.py
#
# solver for SECCON Beginners CTF 2021 firmware
#

enc=getBytes(toAddr(0x10ea4),0x3d*4)
print(enc)

flag=[]

i = 0
while i < 0x3d:
    flag.append(enc[i*4] ^ 0x53)
    i = i + 1

print(''.join(map(chr,flag)))

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/c66c568f-5c9f-9451-db27-d4ff1e27ffc5.png)

# binwalk で解析

比較対象の`青い空を見上げればいつもそこに白い猫`のシグネチャ解析
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/30e92c65-4974-73c8-d09e-74b3d859adcc.png)

シグネチャ解析

```
# binwalk --signature ./firmware.bin 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
127           0x7F            Base64 standard index table
2343          0x927           Copyright string: "Copyright 2011-2021 The Bootstrap Authors"
2388          0x954           Copyright string: "Copyright 2011-2021 Twitter, Inc."
83503         0x1462F         PNG image, 594 x 100, 8-bit grayscale, non-interlaced
83544         0x14658         Zlib compressed data, best compression
90593         0x161E1         ELF, 32-bit LSB shared object, ARM, version 1 (SYSV)
100906        0x18A2A         Unix path: /usr/lib/gcc/arm-linux-gnueabihf/9/../../../arm-linux-gnueabihf/Scrt1.o
103485        0x1943D         JPEG image data, JFIF standard 1.01
117167        0x1C9AF         PEM certificate
117786        0x1CC1A         HTML document header
118641        0x1CF71         HTML document footer
```

自動抽出（ elf を抜くように extract.conf を編集済み）

```
# binwalk -e firmware.bin

/_firmware.bin.extracted# ls -al
total 132
drwxrwx--- 1 root vboxsf     0 May 27 15:28 .
drwxrwx--- 1 root vboxsf  4096 May 27 15:28 ..
-rwxrwx--- 1 root vboxsf 59500 May 27 15:28 14658
-rwxrwx--- 1 root vboxsf 36397 May 27 15:28 14658.zlib
-rwxrwx--- 1 root vboxsf 29348 May 27 15:28 161E1.elf
```

全部抜けない

個別抽出

```
# binwalk -D 'zip archive:zip:unzip %e' -D 'png image:png' firmware.bin

/_firmware.bin.extracted# ls -al
total 136
drwxrwx--- 1 root vboxsf     0 May 27 15:31 .
drwxrwx--- 1 root vboxsf  4096 May 27 15:31 ..
-rwxrwx--- 1 root vboxsf 36438 May 27 15:31 1462F.png
-rwxrwx--- 1 root vboxsf 59500 May 27 15:31 14658
-rwxrwx--- 1 root vboxsf 36397 May 27 15:31 14658.zlib
```

ELFの抜き方がわからんし，全部抜けん。

結論
自動抽出や個別抽出は抽出結果に拡張子がついて見やすいけど，全部抽出できない

本当に全部抜くコマンド

```
# binwalk -D=".*" firmware.bin

/_firmware.bin.extracted# ls -al
total 576
drwxrwx--- 1 root vboxsf   4096 May 27 15:34 .
drwxrwx--- 1 root vboxsf   4096 May 27 15:34 ..
-rwxrwx--- 1 root vboxsf  36438 May 27 15:34 1462F
-rwxrwx--- 1 root vboxsf  59500 May 27 15:34 14658
-rwxrwx--- 1 root vboxsf  36397 May 27 15:34 14658.zlib
-rwxrwx--- 1 root vboxsf  29348 May 27 15:34 161E1
-rwxrwx--- 1 root vboxsf  19035 May 27 15:34 18A2A
-rwxrwx--- 1 root vboxsf  16456 May 27 15:34 1943D
-rwxrwx--- 1 root vboxsf   2774 May 27 15:34 1C9AF
-rwxrwx--- 1 root vboxsf   2155 May 27 15:34 1CC1A
-rwxrwx--- 1 root vboxsf   1300 May 27 15:34 1CF71
-rwxrwx--- 1 root vboxsf 119814 May 27 15:34 7F
-rwxrwx--- 1 root vboxsf 117598 May 27 15:34 927
-rwxrwx--- 1 root vboxsf 117553 May 27 15:34 954


/_firmware.bin.extracted# file 161E1 
161E1: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=d4fde2a811fccb987ffb2e075b170db18f797b8a, for GNU/Linux 3.2.0, not stripped
```

ちゃんと抜けてます。
なんで，公式サイトに `binwalk -D=".*" firmware.bin`を書いてないんだろ？


↓↓↓本当に全部抜くコマンドが記載されていたサイト

https://satoooon1024.hatenablog.com/#firmware-59-solved

おまけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1163572/f322c2df-1027-ed10-d5fa-07178226ba70.png)