美文网首页Ethical Hackers网络安全实验室
【Writeup】Pwnable.kr 0x05 passcod

【Writeup】Pwnable.kr 0x05 passcod

作者: Pino_HD | 来源:发表于2017-07-30 13:02 被阅读71次

    0x05 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 passcode@pwnable.kr -p2222 (pw:guest)
    

    解题思路:

    ssh登录上去后得到代码

    #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代码共有三个函数,分别是login、welcome、main,其中welcome函数提供了一个输入name然后打印出来的功能,login是输入两个passcode,如果与条件相等,那么就输出flag,但是我们可以看到login函数中的scanf方法没有加&取地址符号,在运行的过程中就会发生段错误,导致不能进行if的判断,那么这道题一定是通过某种方法绕过scanf,直接让程序输出flag。
    查阅资料发现了一个GOT覆写技术,这里不得不介绍一下GOT覆写技术了

    GOT表:

    概念:每一个外部定义的符号在全局偏移表(Global offset Table)中有相应的条目,GOT位于ELF的数据段中,叫做GOT段。

    作用:把位置无关的地址计算重定位到一个绝对地址。程序首次调用某个库函数时,运行时连接编辑器(rtld)找到相应的符号,并将它重定位到GOT之后每次调用这个函数都会将控制权直接转向那个位置,而不再调用rtld。

    PLT表:

    过程连接表(Procedure Linkage Table),一个PLT条目对应一个GOT条目

    当main()函数开始,会请求plt中这个函数的对应GOT地址,如果第一次调用那么GOT会重定位到plt,并向栈中压入一个偏移,程序的执行回到_init()函数,rtld得以调用就可以定位printf的符号地址,第二次运行程序再次调用这个函数时程序跳入plt,对应的GOT入口点就是真实的函数入口地址。

    动态连接器并不会把动态库函数在编译的时候就包含到ELF文件中,仅仅是在这个ELF被加载的时候,才会把那些动态函库数代码加载进来,之前系统只会在ELF文件中的GOT中保留一个调用地址.

    GOT覆写技术:

    原理:由于GOT表是可写的,把其中的函数地址覆盖为我们shellcode地址,在程序进行调用这个函数时就会执行shellcode。

    以上资料来源: http://jing0107.lofter.com/post/1cbc869f_8b3d8a5

    回到本题,有一个trick必须要知道,那就是scanf如果没有加&符号,程序会默认从栈中取4个字节当作scanf的地址,那么我们就可以把某个函数的地址放到栈中,然后覆写这个函数在GOT表中的内容为读取flag的函数,接着scanf运行后从栈中读取这个地址,那么就可以得到flag了。至于选择哪个函数都可以,这里我选择fflush函数。

    首先readelf -r passcode查看GOT信息


    得到fflush()的地址fflush_got=0x0804a004
    然后我们还要确定一下最终要执行的system("/bin/cat flag")这行代码的地址
    使用objdump -d passcode

    这里重点看一下高亮部分,其中movl $0x80487af,(%esp)这句汇编代码是将参数入栈,然后下一句call 8048460 system@plt是调用system函数,那么我们就将入栈的那句地址当作最终要执行代码的地址system_addr=0x080485e3

    接下来的工作是确定覆盖的无用参数的个数。
    首先,本程序在welcome函数中有一个输入name的过程,那么我们可以利用这里的scanf输入我们的代码。
    name的地址在welcome函数中



    得到name_addr=ebp-0x70
    passcode1的地址在login函数中



    得到passcode1_addr=ebp-0x10
    name和passcode1的地址相差96

    所以构造payload为



    得到flag
    需要注意的是,这里system_addr要改成10进制的写法,因为scanf是%d

    相关文章

      网友评论

        本文标题:【Writeup】Pwnable.kr 0x05 passcod

        本文链接:https://www.haomeiwen.com/subject/lpihlxtx.html