https://buuoj.cn/challenges#[%E7%BD%91%E9%BC%8E%E6%9D%AF%202020%20%E9%9D%92%E9%BE%99%E7%BB%84]jocker

32exe

https://blog.csdn.net/qq_32072825/article/details/121657090

ret 的使用

两处 sp 分析错误,改回来在函数最后按一下 c 就可以正常反编译了

发现一个奇怪的函数,搜一下:

https://www.cnblogs.com/CCb0nd/p/17857745.html

对内存权限进行了修改 SMC

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char input[50]; // [esp+12h] [ebp-96h] BYREF
  char Destination[80]; // [esp+44h] [ebp-64h] BYREF
  DWORD flOldProtect; // [esp+94h] [ebp-14h] BYREF
  size_t v7; // [esp+98h] [ebp-10h]
  int i; // [esp+9Ch] [ebp-Ch]
 
  __main();
  puts("please input you flag:");
  if ( !VirtualProtect(encrypt, 0xC8u, 4u, &flOldProtect) )
    exit(1);
  scanf("%40s", input);
  v7 = strlen(input);
  if ( v7 != 24 )
  {
    puts("Wrong!");
    exit(0);
  }
  strcpy(Destination, input);
  wrong(input);
  omg(input);
  for ( i = 0; i <= 186; ++i )
    *((_BYTE *)encrypt + i) ^= 0x41u;
  if ( encrypt(Destination) )
    finally(Destination);
  return 0;
}

复制出来输入,分成两个部分:

一个用 wrongomg 检验 input,另一个用加密的函数 encrypt 对副本检验并处理

先看前面:

char *__cdecl wrong(char *a1)
{
  char *result; // eax
  int i; // [esp+Ch] [ebp-4h]
 
  for ( i = 0; i <= 23; ++i )
  {
    result = &a1[i];
    if ( (i & 1) != 0 )
      a1[i] -= i;
    else
      a1[i] ^= i;
  }
  return result;
}
 
int __cdecl omg(char *a1)
{
  int v2[24]; // [esp+18h] [ebp-80h] BYREF
  int i; // [esp+78h] [ebp-20h]
  int v4; // [esp+7Ch] [ebp-1Ch]
 
  v4 = 1;
  qmemcpy(v2, &unk_4030C0, sizeof(v2));
  for ( i = 0; i <= 23; ++i )
  {
    if ( a1[i] != v2[i] )
      v4 = 0;
  }
  if ( v4 == 1 )
    return puts("hahahaha_do_you_find_me?");
  else
    return puts("wrong ~~ But seems a little program");
}
 
unsigned char ida_chars[] =
 
{
 
102, 0, 0, 0, 107, 0, 0, 0, 99, 0,
 
0, 0, 100, 0, 0, 0, 127, 0, 0, 0,
 
97, 0, 0, 0, 103, 0, 0, 0, 100, 0,
 
0, 0, 59, 0, 0, 0, 86, 0, 0, 0,
 
107, 0, 0, 0, 97, 0, 0, 0, 123, 0,
 
0, 0, 38, 0, 0, 0, 59, 0, 0, 0,
 
80, 0, 0, 0, 99, 0, 0, 0, 95, 0,
 
0, 0, 77, 0, 0, 0, 90, 0, 0, 0,
 
113, 0, 0, 0, 12, 0, 0, 0, 55, 0,
 
0, 0, 102, 0
 
};

解密脚本:

key = 0x66, 0x6B, 0x63, 0x64, 0x7F, 0x61, 0x67, 0x64, 0x3B, 0x56, 0x6B, 0x61, 0x7B, 0x26, 0x3B, 0x50, 0x63, 0x5F, 0x4D, 0x5A, 0x71, 0x0C, 0x37, 0x66
fake_flag = ''
 
 
for i in range(24):
    if i % 2 == 1:
        fake_flag += chr(key[i] + i)
    else:
        fake_flag += chr(key[i] ^ i)
 
 
print(fake_flag)
 
flag{fak3_alw35_sp_me!!}

果然不对,看下面加密函数

采用 dbg dump 的方法,输入 111111111111111111111111

运行到解密部分,进去函数

dump 出来重新用 IDA 打开,发现 start 点已经到 encrypt 函数里了(不过没有符号了)

int __cdecl start(int a1)
{
  int v2[19]; // [esp+1Ch] [ebp-6Ch] BYREF
  int v3; // [esp+68h] [ebp-20h]
  int i; // [esp+6Ch] [ebp-1Ch]
 
  v3 = 1;
  qmemcpy(v2, &unk_403040, sizeof(v2));
  for ( i = 0; i <= 18; ++i )
  {
    if ( (char)(*(_BYTE *)(i + a1) ^ aHahahahaDoYouF[i]) != v2[i] )
    {
      puts("wrong ~");
      v3 = 0;
      exit(0);
    }
  }
  puts("come here");
  return v3;
}

就是对输入进行一个异或后的比较

st = "hahahaha_do_you_find_me?"  
v2 = [0x0E, 0x0D, 0x09, 0x06, 0x13, 0x05, 0x58, 0x56, 0x3E, 0x06, 0x0C, 0x3C, 0x1F, 0x57, 0x14, 0x6B, 0x57, 0x59, 0x0D]  
  
flag = [ chr(v2[i] ^ ord(st[i])) for i in range(len(v2)) ]  
  
print("".join(flag))
flag{d07abccf8a410c

最后一个函数

int __cdecl sub_40159A(int a1)
{
  unsigned int v1; // eax
  char v3[9]; // [esp+13h] [ebp-15h] BYREF
  int v4; // [esp+1Ch] [ebp-Ch]
 
  strcpy(v3, "%tp&:");
  v1 = time(0);
  srand(v1);
  v4 = rand() % 100;
  v3[6] = 0;
  *(_WORD *)&v3[7] = 0;
  if ( (v3[(unsigned __int8)v3[5]] != *(_BYTE *)((unsigned __int8)v3[5] + a1)) == v4 )
    return puts("Really??? Did you find it?OMG!!!");
  else
    return puts("I hide the last part, you will not succeed!!!");
}

有随机数了,看着好像是那种大概率是不可能事件的类型,这样我们需要根据上下文来猜测补全程序想要做的事情

由于前面采用的是对字符串进行异或解密,这里也根据最后一位是 } 来异或回去,解密的对象是 "%tp&:"

st = "hahahaha_do_you_find_me?"  
v2 = [0x0E, 0x0D, 0x09, 0x06, 0x13, 0x05, 0x58, 0x56, 0x3E, 0x06, 0x0C, 0x3C, 0x1F, 0x57, 0x14, 0x6B, 0x57, 0x59, 0x0D]  
  
flag = [chr(v2[i] ^ ord(st[i])) for i in range(len(v2))]  
  
flag = "".join(flag)  
  
v3 = "%tp&:"  
v4 = ord(':') ^ ord('}')  
  
v5 = [ord(v3[i]) ^ v4 for i in range(len(v3))]  
flag += "".join([chr(i) for i in v5])  
  
print(flag)
flag{d07abccf8a410cb37a}