本文为人工撰写,仅使用生成式AI校对。

题目链接

依旧是IDA。

int __fastcall main(int argc, const char **argv, const char **envp)
{
  int v4; // [rsp+Ch] [rbp-14h] BYREF
  unsigned int i; // [rsp+10h] [rbp-10h]
  int v6; // [rsp+14h] [rbp-Ch]
  unsigned __int64 v7; // [rsp+18h] [rbp-8h]

  v7 = __readfsqword(0x28u);
  init(argc, argv, envp);
  initseed();
  srand(seed);
  puts("My lock looks strange鈥攃an you help me?");
  for ( i = 1; (int)i <= 10; ++i )
  {
    printf("password %d\n>", i);
    v6 = rand() % 10000;
    __isoc99_scanf("%d", &v4);
    if ( v6 != v4 )
      lose();
  }
  win();
  return 0;
}

查看initseed()

__int64 initseed()
{
  __int64 result; // rax
  int i; // [rsp+8h] [rbp-8h]
  int fd; // [rsp+Ch] [rbp-4h]

  fd = open("/dev/urandom", 0, 0LL);
  if ( fd < 0 )
  {
    puts("urandom");
    exit(1);
  }
  read(fd, &seed, 3uLL);
  close(fd);
  seed = seed % 0x64 + 1;
  for ( i = 1; i <= 120; ++i )
    change();
  while ( 1 )
  {
    result = seed & 1;
    if ( (seed & 1) != 0 )
      break;
    change();
  }
  return result;
}

注意到seed = seed % 0x64 + 1

并且:

__int64 change()
{
  __int64 result; // rax

  if ( (seed & 1) != 0 )
  {
    result = 3 * seed + 1;
    seed = 3 * seed + 1;
  }
  else
  {
    result = seed >> 1;
    seed >>= 1;
  }
  return result;
}

这里seed只有0x64种可能,并且后续的change()也是固定算法,我们可以爆破种子。

然后使用ctypes库来生成随机数。

爆破写到一半注意到:

  while ( 1 )
  {
    result = seed & 1;
    if ( (seed & 1) != 0 )
      break;
    change();
  }
	return result;

这里只能返回1。“老大我们被耍了!”。

那就直接用1为种子来算即可。

pwntools脚本:

from pwn import *
import ctypes
context(arch='amd64', os='linux', log_level='error')

io = connect("127.0.0.1", 38141)


libc = ctypes.CDLL("libc.so.6")

libc.srand(1)

for i in range(10):
    rand = libc.rand() % 10000;
    print(rand)
    io.sendline(str(rand).encode())



io.interactive()

输出:

9383
886
2777
6915
7793
8335
5386
492
6649
1421
My lock looks strange—can you help me?
password 1
>password 2
>password 3
>password 4
>password 5
>password 6
>password 7
>password 8
>password 9
>password 10
>It opened—how did you do that?
moectf{THIS_IS_FLAG}