pwnable.kr的passcode


前段時間找到一個練習pwn的網站,pwnable.kr

這里記錄其中的passcode的做題過程,給自己加深印象。

廢話不多說了,看一下題目,

看到題目,就ssh連接進去,就看到三個文件如下

看了一下我們的用戶名,並不能直接查看flag這個文件。查看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;    
}

可以看到整個程序的流程很簡單,就是要我們輸入兩個數,讓這兩個數等於特定的數,就輸出flag的內容,但是根據她的提示,程序有問題,可以直接使用gcc來嘗試編譯一下,就發現在登錄函數里,對於兩個passcode的值沒有加上取地址符號,這將會導致scanf把passcode1和passcode2中的值作為存儲輸入的地址,如果地址不可寫,就會造成一個內存錯誤。這樣我們直接輸入特定的值肯定不行了。。。。這里我們看一下這個程序的防護

程序有棧溢出保護和NX(數據執行保護)看了大牛的wp之后,知道關鍵點在welcome這里,因為welcome這里開了一個有點大的數組,有沒有可能改變login中passcode1或passcode2的值,因為welcome和login這兩個函數是連續調用的,導致他們擁有相同的棧底。我們看一下passcode的反匯編代碼。。objdump -d passcode

 

08048564 <login>:                     //這里是login函數
 8048564:    55                       push   %ebp
 8048565:    89 e5                    mov    %esp,%ebp
 8048567:    83 ec 28                 sub    $0x28,%esp        //分配棧空間
 804856a:    b8 70 87 04 08           mov    $0x8048770,%eax
 804856f:    89 04 24                 mov    %eax,(%esp)
 8048572:    e8 a9 fe ff ff           call   8048420 <printf@plt>
 8048577:    b8 83 87 04 08           mov    $0x8048783,%eax
 804857c:    8b 55 f0                 mov    -0x10(%ebp),%edx       //看到這里是passcode1的內容作為參數傳遞給scanf
 804857f:    89 54 24 04              mov    %edx,0x4(%esp)
 8048583:    89 04 24                 mov    %eax,(%esp)
 8048586:    e8 15 ff ff ff           call   80484a0 <__isoc99_scanf@plt>
 804858b:    a1 2c a0 04 08           mov    0x804a02c,%eax
 8048590:    89 04 24                 mov    %eax,(%esp)
 8048593:    e8 98 fe ff ff           call   8048430 <fflush@plt>
 8048598:    b8 86 87 04 08           mov    $0x8048786,%eax
 804859d:    89 04 24                 mov    %eax,(%esp)
 80485a0:    e8 7b fe ff ff           call   8048420 <printf@plt>
 80485a5:    b8 83 87 04 08           mov    $0x8048783,%eax
 80485aa:    8b 55 f4                 mov    -0xc(%ebp),%edx    //這里是passcode2的內容作為參數傳遞給scanf
 80485ad:    89 54 24 04              mov    %edx,0x4(%esp)
 80485b1:    89 04 24                 mov    %eax,(%esp)
 80485b4:    e8 e7 fe ff ff           call   80484a0 <__isoc99_scanf@plt>
 80485b9:    c7 04 24 99 87 04 08     movl   $0x8048799,(%esp)
 80485c0:    e8 8b fe ff ff           call   8048450 <puts@plt>
 80485c5:    81 7d f0 e6 28 05 00     cmpl   $0x528e6,-0x10(%ebp)    //第一個比較
 80485cc:    75 23                    jne    80485f1 <login+0x8d>
 80485ce:    81 7d f4 c9 07 cc 00     cmpl   $0xcc07c9,-0xc(%ebp)    //第二個比較
 80485d5:    75 1a                    jne    80485f1 <login+0x8d>
 80485d7:    c7 04 24 a5 87 04 08     movl   $0x80487a5,(%esp)
 80485de:    e8 6d fe ff ff           call   8048450 <puts@plt>
 80485e3:    c7 04 24 af 87 04 08     movl   $0x80487af,(%esp)
 80485ea:    e8 71 fe ff ff           call   8048460 <system@plt>    //執行系統命令,關鍵點
 80485ef:    c9                       leave  
 80485f0:    c3                       ret    
 80485f1:    c7 04 24 bd 87 04 08     movl   $0x80487bd,(%esp)
 80485f8:    e8 53 fe ff ff           call   8048450 <puts@plt>
 80485fd:    c7 04 24 00 00 00 00     movl   $0x0,(%esp)
 8048604:    e8 77 fe ff ff           call   8048480 <exit@plt>

08048609 <welcome>:
 8048609:    55                       push   %ebp
 804860a:    89 e5                    mov    %esp,%ebp
 804860c:    81 ec 88 00 00 00        sub    $0x88,%esp
 8048612:    65 a1 14 00 00 00        mov    %gs:0x14,%eax
 8048618:    89 45 f4                 mov    %eax,-0xc(%ebp)
 804861b:    31 c0                    xor    %eax,%eax
 804861d:    b8 cb 87 04 08           mov    $0x80487cb,%eax
 8048622:    89 04 24                 mov    %eax,(%esp)
 8048625:    e8 f6 fd ff ff           call   8048420 <printf@plt>
 804862a:    b8 dd 87 04 08           mov    $0x80487dd,%eax
 804862f:    8d 55 90                 lea    -0x70(%ebp),%edx       //name的地址 8048632:    89 54 24 04              mov    %edx,0x4(%esp)
 8048636:    89 04 24                 mov    %eax,(%esp)
 8048639:    e8 62 fe ff ff           call   80484a0 <__isoc99_scanf@plt>
 804863e:    b8 e3 87 04 08           mov    $0x80487e3,%eax
 8048643:    8d 55 90                 lea    -0x70(%ebp),%edx
 8048646:    89 54 24 04              mov    %edx,0x4(%esp)
 804864a:    89 04 24                 mov    %eax,(%esp)
 804864d:    e8 ce fd ff ff           call   8048420 <printf@plt>
 8048652:    8b 45 f4                 mov    -0xc(%ebp),%eax
 8048655:    65 33 05 14 00 00 00     xor    %gs:0x14,%eax
 804865c:    74 05                    je     8048663 <welcome+0x5a>
 804865e:    e8 dd fd ff ff           call   8048440 <__stack_chk_fail@plt>
 8048663:    c9                       leave  
 8048664:    c3                       ret    

08048665 <main>:
 8048665:    55                       push   %ebp
 8048666:    89 e5                    mov    %esp,%ebp
 8048668:    83 e4 f0                 and    $0xfffffff0,%esp
 804866b:    83 ec 10                 sub    $0x10,%esp
 804866e:    c7 04 24 f0 87 04 08     movl   $0x80487f0,(%esp)
 8048675:    e8 d6 fd ff ff           call   8048450 <puts@plt>
 804867a:    e8 8a ff ff ff           call   8048609 <welcome>
 804867f:    e8 e0 fe ff ff           call   8048564 <login>          //連續調用,導致棧底是相同的
 8048684:    c7 04 24 18 88 04 08     movl   $0x8048818,(%esp)
 804868b:    e8 c0 fd ff ff           call   8048450 <puts@plt>
 8048690:    b8 00 00 00 00           mov    $0x0,%eax
 8048695:    c9                       leave  
 8048696:    c3                       ret    
 8048697:    90                       nop
 8048698:    90                       nop
 8048699:    90                       nop
 804869a:    90                       nop
 804869b:    90                       nop
 804869c:    90                       nop
 804869d:    90                       nop
 804869e:    90                       nop
 804869f:    90                       nop

 

從上面我們看到,因為welcome和login的棧底相同,看到name的地址在ebp-0x70, 而passcode1的地址在ebp-0x10, 0x70 == 112, 0x10 == 16

所以0x70-0x10 == 0x60 == 96,所以我們可以看到name的最后四個字節就是passcode1的值,所以我們可以利用welcome來改變passcode1的值,

因為程序開啟了棧溢出保護,所以我們不能再繼續增加name的輸入來改變passcode2的值(如果能改,直接改為兩個特定數就可以了,但這里不行)。

從大牛的WP知道,這里我們要使用的是一種GOT表復寫的技術,GOT表就是一個函數指針數組(具體搜索),我們看到程序在我們輸入之后會調用pritnf函數,

所以我們可以將passcode1的值改為printf的地址,然后接下來會通過scanf將上面的關鍵系統命令的地址寫進去,改變整個程序的執行過程,當程序調用

printf函數的時候,由於它的地址已經被改變了,所以會跳到關鍵系統命令的地方去。

 

80485e3:    c7 04 24 af 87 04 08     movl   $0x80487af,(%esp)
80485ea:    e8 71 fe ff ff           call   8048460 <system@plt>

 

所以我們要知道printf的got地址,然后將它的地址改為 0x080485ea這個關鍵的地方。使用objdump -R passcode來看一下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          //printf的地址
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

我這里使用pwntools這個包來寫利用腳本。因為scanf是要求%d輸入,所以0x080485ea == 134514154

 

最后就看到flag了。。。。。。。。        

                                        --好好學習,天天向上

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM