LoginSignup
0
0

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-05-27

問題

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

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

ファイル・データ抽出ボタン
image.png

算出サイズを無視してにチェック
検索除外対象のzlibのチェックを外す
検索実行ボタン
image.png

ELFを選択
算出サイズを下選択で修正 4MBを指定
リスト選択項目を保存ボタン
image.png

保存したELFをGhidraで開く
image.png
ARMだ

strings
image.png
Input password
Incorrect password
などの文字が見える

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

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
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 )

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

binwalk で解析

比較対象の青い空を見上げればいつもそこに白い猫のシグネチャ解析
image.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を書いてないんだろ?

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

おまけ
image.png

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0