[攻防世界]Reverse: xxxorrr


IDA64打开,函数乱七八糟的一堆。

main函数是这样,看到输入,但没看到输出。

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  int i; // [rsp+Ch] [rbp-34h]
  char s[40]; // [rsp+10h] [rbp-30h] BYREF
  unsigned __int64 v6; // [rsp+38h] [rbp-8h]

  v6 = __readfsqword(0x28u);
  sub_A90(sub_916, a2, a3);
  fgets(s, 35, stdin);
  for ( i = 0; i <= 33; ++i )
    s1[i] ^= s[i];
  return 0LL;
}

看strings发现Congratulations和Wrong,反查,发现输出结果的函数在sub_916。

unsigned __int64 sub_916()
{
  unsigned __int64 v1; // [rsp+8h] [rbp-8h]

  v1 = __readfsqword(0x28u);
  if ( !strcmp(s1, s2) )
    puts("Congratulations!");
  else
    puts("Wrong!");
  return __readfsqword(0x28u) ^ v1;
}

main里面也出现了sub_916,是不是一个事件注册或者回调之类的,没有能力深究。但总之sub_916里,会比较s1和s2。双击发现s1和s2都有初值。

按main里写的,flag应该就是s1和s2逐项异或的结果,但结果是“’/$ 2(}!d””:/m-TA*$INçÞ”,不是答案。

然后逐个翻了翻函数,发现一个sub_84A也对s1做了操作。

unsigned __int64 sub_84A()
{
  int i; // [rsp+Ch] [rbp-14h]
  unsigned __int64 v2; // [rsp+18h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  for ( i = 0; i <= 33; ++i )
    s1[i] ^= 2 * i + 65;
  return __readfsqword(0x28u) ^ v2;
}

于是把这个异或也加上,就算出了flag。

s1 = 'qasxcytgsasxcvrefghnrfghnjedfgbhn' + chr(0x20)
s2 = '564E5758515109461746545A59591F48325B6B7C756E7E6E2F774F7A71432B2689FE'
flag = ''
for i in range(34):
    flag += chr(ord(s1[i]) ^ (2*i+65) ^ int(s2[2*i:2*i+2],16))
print(flag)

# ┌──(.venv)─(kali㉿kali)-[~/ctf]
# └─$ /home/kali/ctf/.venv/bin/python /home/kali/ctf/xor.py
# flag{c0n5truct0r5_functi0n_in_41f]

但是为什么会有这么一个sub_84A呢?找找原因。

首先在函数名字上右键,找引用,发现init函数里面有一个func_A59变量的值等于sub_840。也就是for循环里调用了sub_84A,但还是没明白机制。

void __fastcall init(unsigned int a1, __int64 a2, __int64 a3)
{
  signed __int64 v4; // rbp
  __int64 i; // rbx

  v4 = &off_200D98 - &funcs_A59;
  init_proc();
  if ( v4 )
  {
    for ( i = 0LL; i != v4; ++i )
      ((void (__fastcall *)(_QWORD, __int64, __int64))*(&funcs_A59 + i))(a1, a2, a3);
  }
}

不过至少知道了main并不一定是第一个执行的函数,应该看一下main被哪个函数引用,然后看看这个函数里有没有在main前面执行什么。

,

发表回复

您的电子邮箱地址不会被公开。