VEH 异常回调

简单看一下main函数 运行一下 考点是第二段密码 所以我们去找相对应的解密函数

image

int __cdecl main(int argc, const char **argv, const char **envp)
{
  const CHAR *v3; // ebx
  HMODULE ModuleHandleA; // eax
  void (__stdcall *ProcAddress)(HMODULE, LPCSTR); // eax
  char Str1[20]; // [esp+1h] [ebp-157h] BYREF
  char Str2[11]; // [esp+15h] [ebp-143h] BYREF
  int v9; // [esp+20h] [ebp-138h] BYREF
  _DWORD v10[6]; // [esp+26h] [ebp-132h] BYREF
  __int16 v11; // [esp+3Eh] [ebp-11Ah]
  _DWORD v12[7]; // [esp+40h] [ebp-118h] BYREF
  _DWORD v13[4]; // [esp+5Ch] [ebp-FCh] BYREF
  _DWORD v14[2]; // [esp+6Ch] [ebp-ECh] BYREF
  char v15; // [esp+74h] [ebp-E4h]
  _DWORD v16[8]; // [esp+75h] [ebp-E3h] BYREF
  __int16 v17; // [esp+95h] [ebp-C3h]
  _DWORD v18[8]; // [esp+97h] [ebp-C1h] BYREF
  char v19; // [esp+B7h] [ebp-A1h]
  int v20; // [esp+B8h] [ebp-A0h] BYREF
  _DWORD v21[8]; // [esp+BEh] [ebp-9Ah] BYREF
  char v22; // [esp+DEh] [ebp-7Ah]
  _DWORD v23[8]; // [esp+DFh] [ebp-79h] BYREF
  __int16 v24; // [esp+FFh] [ebp-59h]
  int v25; // [esp+101h] [ebp-57h]
  int v26; // [esp+105h] [ebp-53h]
  char v27; // [esp+109h] [ebp-4Fh]
  _DWORD v28[4]; // [esp+10Ah] [ebp-4Eh] BYREF
  _DWORD v29[7]; // [esp+11Ah] [ebp-3Eh] BYREF
  _DWORD v30[6]; // [esp+136h] [ebp-22h] BYREF
  __int16 v31; // [esp+14Eh] [ebp-Ah]
  int *p_argc; // [esp+150h] [ebp-8h]

  p_argc = &argc;
  sub_402940();
  puts(
    "            .     \n"
    "           _|_    ROBOTIC AUTHENTICATION SYSTEM\n"
    "    /\\/\\  (. .)  /\n"
    "    `||'   |#|  \n"
    "     ||__.-\"-\"-.___   \n"
    "     `---| . . |--.\\  \n"
    "         | : : |  ,||,\n"
    "         `..-..'  \\/\\/\n"
    "          || ||   \n"
    "          || ||    \n"
    "         |__|__|  \n");
  v20 = 1337;
  qmemcpy(v21, "Qmd`rd!douds!uid!ghsru!Q`rrvnse;", sizeof(v21));
  v22 = 1;
  qmemcpy(v18, "Qmd`rd!douds!uid!ghsru!Q`rrvnse;", sizeof(v18));
  v19 = 1;
  qmemcpy(v23, "Qmd`rd!douds!uid!rdbnoe!Q`rrvnse", sizeof(v23));
  v24 = 315;
  qmemcpy(v16, "Qmd`rd!douds!uid!rdbnoe!Q`rrvnse", sizeof(v16));
  v17 = 315;
  v25 = 1869557876;
  v26 = 1718432615;
  v27 = 3;
  v14[0] = 1869557876;
  v14[1] = 1718432615;
  v15 = 3;
  qmemcpy(v28, "jdsodm23/emm", 12);
  v28[3] = 20906241;
  qmemcpy(v13, "jdsodm23/emm", 12);
  v13[3] = 20906241;
  qmemcpy(v29, "@eeWdbunsdeDybdquhnoI`oe", 24);
  v29[6] = 24339565;
  qmemcpy(v12, "@eeWdbunsdeDybdquhnoI`oe", 24);
  v12[6] = 24339565;
  qmemcpy(v30, "Xnt!vho/!Bnofs`utm`uhnor", sizeof(v30));
  v31 = 288;
  qmemcpy(v10, "Xnt!vho/!Bnofs`utm`uhnor", sizeof(v10));
  v11 = 288;
  v9 = 1337;
  strcpy(Str2, "r0b0RUlez!");
  dword_40AD94 = (int)&v9;
  dword_40ADA0 = (int)&v20;
  dword_40AD8C = (char *)v18;
  dword_40AD90 = (char *)v16;
  dword_40AD98 = (int)v14;
  lpProcName = (LPCSTR)v12;
  lpModuleName = (LPCSTR)v13;
  Buffer = (char *)v10;
  sub_401500(0);
  v3 = lpProcName;
  ModuleHandleA = GetModuleHandleA(lpModuleName);
  ProcAddress = (void (__stdcall *)(HMODULE, LPCSTR))GetProcAddress(ModuleHandleA, v3);
  ProcAddress((HMODULE)1, (LPCSTR)sub_40157F);
  puts(dword_40AD8C);
  scanf("%20s", Str1);
  if ( !strcmp(Str1, Str2) )
  {
    puts("You passed level1!");
    sub_4015EA(0);
  }
  return 0;
}

sub_20157F 能看到这里出现了第二个scanf

void __cdecl __noreturn sub_40157F(int a1)
{
  _BYTE v1[20]; // [esp+18h] [ebp-20h] BYREF
  int v2; // [esp+2Ch] [ebp-Ch]

  v2 = *(_DWORD *)(*(_DWORD *)(a1 + 4) + 184);
  if ( v2 == dword_40ADA8 + 6 )
  {
    scanf("%20s", v1);
    if ( !sub_401547(v1, (_BYTE *)dword_40AD98) )
      puts(Buffer);
  }
  ExitProcess(0);
}

sub_401547 这里是一个简单的^2 所以我们要去找这个dword_40AD98的值是多少 接着往下看 能看到这个

int __cdecl sub_401547(_BYTE *a1, _BYTE *a2)
{
  while ( *a2 != 2 )
  {
    if ( *a1 != (*a2 ^ 2) )
      return 1;
    ++a1;
    ++a2;
  }
  return 0;
}

sub_4015EA 能看到这里有一个__debugbreak() 也就是触发异常函数

int __cdecl sub_4015EA(int a1)
{
  if ( a1 <= 9 )
    return sub_4015EA(a1 + 1);
  puts(dword_40AD90);
  dword_40ADA8 = 4199961;
  __debugbreak();
  return 0;
}

总体流程是main 里注册了一个 VEH 异常处理函数:

ProcAddress = GetProcAddress(GetModuleHandleA(lpModuleName), lpProcName);
ProcAddress((HMODULE)1, (LPCSTR)sub_40157F);

这里 lpModuleNamelpProcName 经过 sub_401500(0) 解密后分别是

kernel32.dll
AddVectoredExceptionHandler

所以实际上是

AddVectoredExceptionHandler(1, sub_40157F);

第一段密码很明显

strcpy(Str2, "r0b0RUlez!");

所以第一段输入

r0b0RUlez!

输入正确后进入

sub_4015EA(0);

递归到 a1 &gt; 9 后执行

puts(dword_40AD90);
dword_40ADA8 = 4199961;
__debugbreak();

__debugbreak() 会触发异常,从而进入 VEH 回调函数 sub_40157F

所以我们就知道 来动调一下看看吧 到这里就能看到他的值是多少了

image

image

u1nnf2lg

异或2可得

w3lld0ne

image
flag

flag{r0b0RUlez!_w3lld0ne}