バイナリファイルを自作して objdump, GHex で簡単に解析してみる

概要

  • バイナリファイルを自作して解析する。
  • バイナリファイルに隠れている FLAG を手に入れる。

使用ツール

  • Visual Studio Code
  • objdump
  • GHex

手順

1.プログラムを書く

binary.c
#include <stdio.h>
#include <string.h>

int main() {
   char buf[32];
   char key[] = "password";

   puts("input the password:");
   fgets(buf, sizeof(buf), stdin);
   strtok(buf, "\n");

   if(!strcmp(buf, key)) {
      puts("FLAG{ctf_binary}");
   } else {
      puts("miss");
   }

   return 0;
}

2.コンパイルしてバイナリファイルを作成する

gcc binary.c -o binary

"binary" というバイナリファイルが生成される。試しに実行してみる。パスワードを聞かれるので、適当に "hogehoge" と入力する。そうすると、"miss" と表示される(間違っているよーと)。

binary

input the password:
hogehoge
miss

3.objdump でバイナリファイルを逆アセンブルする

objdump banary

とすると、

<省略>

00000000004006a6 <main>:
  4006a6:    55                       push   rbp
  4006a7:    48 89 e5                 mov    rbp,rsp
  4006aa:    48 83 ec 40              sub    rsp,0x40
  4006ae:    64 48 8b 04 25 28 00     mov    rax,QWORD PTR fs:0x28
  4006b5:    00 00
  4006b7:    48 89 45 f8              mov    QWORD PTR [rbp-0x8],rax
  4006bb:    31 c0                    xor    eax,eax
  4006bd:    48 b8 32 30 31 38 5f     movabs rax,0x5f34305f38313032
  4006c4:    30 34 5f
  4006c7:    48 89 45 c0              mov    QWORD PTR [rbp-0x40],rax
  4006cb:    66 c7 45 c8 32 35        mov    WORD PTR [rbp-0x38],0x3532
  4006d1:    c6 45 ca 00              mov    BYTE PTR [rbp-0x36],0x0
  4006d5:    bf d8 07 40 00           mov    edi,0x4007d8
  4006da:    e8 61 fe ff ff           call   400540 <puts@plt>
  4006df:    48 8b 15 7a 09 20 00     mov    rdx,QWORD PTR [rip+0x20097a]        # 601060 <stdin@@GLIBC_2.2.5>
  4006e6:    48 8d 45 d0              lea    rax,[rbp-0x30]
  4006ea:    be 20 00 00 00           mov    esi,0x20
  4006ef:    48 89 c7                 mov    rdi,rax
  4006f2:    e8 79 fe ff ff           call   400570 <fgets@plt>
  4006f7:    48 8d 45 d0              lea    rax,[rbp-0x30]
  4006fb:    be 00 08 40 00           mov    esi,0x400800
  400700:    48 89 c7                 mov    rdi,rax
  400703:    e8 88 fe ff ff           call   400590 <strtok@plt>
  400708:    48 8d 55 c0              lea    rdx,[rbp-0x40]
  40070c:    48 8d 45 d0              lea    rax,[rbp-0x30]
  400710:    48 89 d6                 mov    rsi,rdx
  400713:    48 89 c7                 mov    rdi,rax
  400716:    e8 65 fe ff ff           call   400580 <strcmp@plt>
  40071b:    85 c0                    test   eax,eax
  40071d:    75 0c                    jne    40072b <main+0x85>
  40071f:    bf 08 08 40 00           mov    edi,0x400808
  400724:    e8 17 fe ff ff           call   400540 <puts@plt>
  400729:    eb 0a                    jmp    400735 <main+0x8f>
  40072b:    bf 51 08 40 00           mov    edi,0x400851
  400730:    e8 0b fe ff ff           call   400540 <puts@plt>
  400735:    b8 00 00 00 00           mov    eax,0x0
  40073a:    48 8b 4d f8              mov    rcx,QWORD PTR [rbp-0x8]
  40073e:    64 48 33 0c 25 28 00     xor    rcx,QWORD PTR fs:0x28
  400745:    00 00
  400747:    74 05                    je     40074e <main+0xa8>
  400749:    e8 02 fe ff ff           call   400550 <__stack_chk_fail@plt>
  40074e:    c9                       leave 
  40074f:    c3                       ret

<省略>

と出力される。注目したいのは、400716 で strcmp が呼ばれていて、少しすると 40071d jne が呼ばれる。この jne 命令(分岐命令)を無効にすることで、パスワードが間違っていても FLAG が手に入るかも。jne を無効にするには、75 0c → 90 90 に書き換える。

4.GHex でバイナリファイルを書き換える
Screenshot from 2018-05-02 23-31-31.png
objdump で確認した jne 命令のアドレスは 40071d だから GHex も 700 行目あたりにあるのかな? あったので、75 0c → 90 90 に書き換えてみる。
Screenshot from 2018-05-02 23-31-53.png
書き換えたら、名前をつけて保存する。

5.書き換えたバイナリを実行する。

binary

input the password:
hogehoge
FLAG{ctf_binary}

パスワードを聞かれるので、適当に "hogehoge" って入力してみる。2.のときは "miss" と表示されていたが、今度はフラグを見つけることができた!

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.