guess_num

64位程序查看源代码

__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-------------\\n", (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);
  return 0LL;
}

十次猜数字必须全对,才能拿到flag,否则gg

在输入名字的时候覆盖随机数种子的值。

exp

编写c程序:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    srand(0x61616161);
    for (int i = 0; i < 10; i++)
    {
        int b = rand() % 6 + 1;
        printf("%d\\n", b);
    }
    system("pause");
    return (0);
}

运行后的序列就是种子的前10位。

forgot

checksec检查是32版本

打开ida,查看main函数

int __cdecl main()
{
  size_t v0; // ebx
  char v2[32]; // [esp+10h] [ebp-74h]
  int (*v3)(); // [esp+30h] [ebp-54h]
  int (*v4)(); // [esp+34h] [ebp-50h]
  int (*v5)(); // [esp+38h] [ebp-4Ch]
  int (*v6)(); // [esp+3Ch] [ebp-48h]
  int (*v7)(); // [esp+40h] [ebp-44h]
  int (*v8)(); // [esp+44h] [ebp-40h]
  int (*v9)(); // [esp+48h] [ebp-3Ch]
  int (*v10)(); // [esp+4Ch] [ebp-38h]
  int (*v11)(); // [esp+50h] [ebp-34h]
  int (*v12)(); // [esp+54h] [ebp-30h]
  char s; // [esp+58h] [ebp-2Ch]
  int v14; // [esp+78h] [ebp-Ch]
  size_t i; // [esp+7Ch] [ebp-8h]

  v14 = 1;
  v3 = sub_8048604;
  v4 = sub_8048618;
  v5 = sub_804862C;
  v6 = sub_8048640;
  v7 = sub_8048654;
  v8 = sub_8048668;
  v9 = sub_804867C;
  v10 = sub_8048690;
  v11 = sub_80486A4;
  v12 = sub_80486B8;
  puts("What is your name?");
  printf("> ");
  fflush(stdout);
  fgets(&s, 32, stdin);
  sub_80485DD((int)&s);
  fflush(stdout);
  printf("I should give you a pointer perhaps. Here: %x\\n\\n", sub_8048654);
  fflush(stdout);
  puts("Enter the string to be validate");
  printf("> ");
  fflush(stdout);
  __isoc99_scanf("%s", v2);
  for ( i = 0; ; ++i )
  {
    v0 = i;
    if ( v0 >= strlen(v2) )
      break;
    switch ( v14 )
    {
      case 1:
        if ( sub_8048702(v2[i]) )
          v14 = 2;
        break;
      case 2:
        if ( v2[i] == 64 )
          v14 = 3;
        break;
      case 3:
        if ( sub_804874C(v2[i]) )
          v14 = 4;
        break;
      case 4:
        if ( v2[i] == 46 )
          v14 = 5;
        break;
      case 5:
        if ( sub_8048784(v2[i]) )
          v14 = 6;
        break;
      case 6:
        if ( sub_8048784(v2[i]) )
          v14 = 7;
        break;
      case 7:
        if ( sub_8048784(v2[i]) )
          v14 = 8;
        break;
      case 8:
        if ( sub_8048784(v2[i]) )
          v14 = 9;
        break;
      case 9:
        v14 = 10;
        break;
      default:
        continue;
    }
  }
  (*(&v3 + --v14))();
  return fflush(stdout);
}

发现__isoc99_scanf("%s", v2);存在溢出漏洞,查看栈

-00000074 var_74          db 32 dup(?)            ; v2
-00000054 anonymous_1     dd ?                    ; v3
-00000050 anonymous_2     dd ?
-0000004C anonymous_3     dd ?
-00000048 anonymous_4     dd ?
-00000044 anonymous_5     dd ?
-00000040 anonymous_6     dd ?
-0000003C anonymous_7     dd ?
-00000038 anonymous_8     dd ?
-00000034 anonymous_9     dd ?
-00000030 anonymous_10    dd ?                    ; v12
-0000002C s               db ?
-0000002B                 db ? ; undefined
-0000002A                 db ? ; undefined
-00000029                 db ? ; undefined
-00000028                 db ? ; undefined
-00000027                 db ? ; undefined
-00000026                 db ? ; undefined
-00000025                 db ? ; undefined
-00000024                 db ? ; undefined
-00000023                 db ? ; undefined
-00000022                 db ? ; undefined
-00000021                 db ? ; undefined
-00000020                 db ? ; undefined
-0000001F                 db ? ; undefined
-0000001E                 db ? ; undefined
-0000001D                 db ? ; undefined
-0000001C                 db ? ; undefined
-0000001B                 db ? ; undefined
-0000001A                 db ? ; undefined
-00000019                 db ? ; undefined
-00000018                 db ? ; undefined
-00000017                 db ? ; undefined
-00000016                 db ? ; undefined
-00000015                 db ? ; undefined
-00000014                 db ? ; undefined
-00000013                 db ? ; undefined
-00000012                 db ? ; undefined
-00000011                 db ? ; undefined
-00000010                 db ? ; undefined
-0000000F                 db ? ; undefined
-0000000E                 db ? ; undefined
-0000000D                 db ? ; undefined
-0000000C anonymous_0     dd ?                    ; v14
-00000008 anonymous_11    dd ?
-00000004 var_4           dd ?
+00000000  s              db 4 dup(?)
+00000004  r              db 4 dup(?)
+00000008
+00000008 ; end of stack variables

v14初始值是1,如果保持1,那么((&v3 + --v14))();就相当于(&v3)(),即执行v3的值所指向地址的函数。要让v14值不改变就是要让v14在switch里if不成立,结合sub_8048702()函数。

_BOOL4 __cdecl sub_8048702(char a1)
{
  return a1 > 96 && a1 <= 122 || a1 > 47 && a1 <= 57 || a1 == 95 || a1 == 45 || a1 == 43 || a1 == 46;
}

发现__isoc99_scanf("%s", v2);输入时不能是小写字母。ststem地址为0x080486CC

exp(python3版本的pwntool字符串前加b)