---
# System prepended metadata

title: Simple Reverse - 0x19(2023 Lab - WinMalware - Extract Next Stage Payload)
tags: [Reverse, eductf, CTF]

---

# Simple Reverse - 0x19(2023 Lab - WinMalware - Extract Next Stage Payload)
## Description
> 取出 eductf-lab.exe 中的 next stage payload (embedded PE file)，並計算其 MD5 hash。
> Flag format: FLAG{462fe0000...} (hex character must be lowercase)
## Background
* DOS Header
    ![](https://hackmd.io/_uploads/HJ9P9gpfp.png)
* NT Headers - Optional Header
    ![](https://hackmd.io/_uploads/SkjNqeazT.png)

## Source code
* sub_140001870
    :::spoiler IDA Source Code解析前
    ```cpp
    __int64 __fastcall sub_140001870(char **pe_file, _QWORD *pe_file_size)
    {
      *pe_file = byte_140005040;
      *pe_file_size = 72770i64;                     // 這是個是怎麼判斷成PE size我也不知道
      if ( **pe_file == 'ZM' )
      {
        if ( *(sub_1400013D0(*pe_file) + 0x18) == 0x20B )
        {
          return 1i64;
        }
        else
        {
          sub_140001260("remote dll optional header magic check failed\n");
          return 0i64;
        }
      }
      else
      {
        sub_140001260("remote dll magic check failed\n");
        return 0i64;
      }
    }
    ```
    :::
## Recon
1. 進到`sub_140001BF0`之後可以先觀察`sub_140001870`，前面有source code可以看到他正在比對`byte_140005040`的前面兩個字元是不是等於`MZ`，也就是一支PE file的magic header，並且又比對了後面0x18的位置是不是等於0x20B，也就是另外一個magic header(用來判斷該程式是否可於64-bits運行)，由以上操作幾乎可以確定駭客把真正的程式(可能是惡意的)塞在正常的PE file中
    :::info
    如果只是要解題的話，到這邊就可以了，只要利用前一題學到的把`byte_140005040`改變他的type，變成`char[72770]`，再用Shift+E，把raw data export出來，丟到[online md5 checksum](https://emn178.github.io/online-tools/md5_checksum.html)，就可以得到這支檔案的hash(`462fe0007f86957f59824e113f78947c`)
    ![](https://hackmd.io/_uploads/SJoeiepGT.png)
    ![](https://hackmd.io/_uploads/rk7SigpGp.png)
    :::
2. `sub_1400013D0`仔細看他的操作，其實就是把`byte_140005040`的地址，加上`0x3C`，再取值，就是`e_lfanew`，也就是NT Headers的file offset，這個offset加上原本的原本的`140005040`就是NT header，所以可以把`sub_1400013D0` rename成`getNtHdr`
    ```cpp
    __int64 __fastcall getNtHdr(__int64 a1)
    {
      return *(a1 + 0x3C) + a1;
    }
    ```
3. 接下來可以改變這個function的type，按Y，`改IMAGE_NT_HEADERS *__fastcall getNtHdr(_QWORD)`，就變得非常簡潔好看，另外，要把`pe_file`的type從`_int64`改成`_QWORD`的原因是`pe_file`存的是`byte_140005040`的地址，不是數字，雖然代表的byte數一樣，但意義不相同，所以IDA可能會解析不出來
    ![](https://hackmd.io/_uploads/ryHl0gaG6.png)
    ![](https://hackmd.io/_uploads/rJniAlaM6.png)
4. 最後就把目前的這個sub function rename成`getEmbeddedPE_File`就可以了

:::info
![](https://hackmd.io/_uploads/HJaNxWpzp.png)
:::
:::spoiler 解析後
```cpp
__int64 returnTargetPid()
{
  DWORD LastError; // eax
  DWORD v2; // eax
  WCHAR *szExeFile; // rax
  signed __int64 v4; // rcx
  WCHAR v5; // dx
  int v6; // eax
  DWORD th32ProcessID; // [rsp+20h] [rbp-288h]
  HANDLE hSnapshot; // [rsp+28h] [rbp-280h]
  HANDLE hObject; // [rsp+30h] [rbp-278h]
  HANDLE CurrentProcess; // [rsp+38h] [rbp-270h]
  PSID pSid1; // [rsp+40h] [rbp-268h] BYREF
  PSID pSid2; // [rsp+48h] [rbp-260h] BYREF
  PROCESSENTRY32W pe; // [rsp+50h] [rbp-258h] BYREF

  hSnapshot = CreateToolhelp32Snapshot(2u, 0);
  if ( hSnapshot == (HANDLE)-1i64 )
  {
    LastError = GetLastError();
    sub_140001260("CreateToolhelp32Snapshot failed with error %lu\n", LastError);
    return 0i64;
  }
  else
  {
    pe.dwSize = 568;
    if ( Process32FirstW(hSnapshot, &pe) )
    {
      pSid2 = malloc(0x44ui64);
      CurrentProcess = GetCurrentProcess();
      sub_140001500(CurrentProcess, &pSid2);
      th32ProcessID = 0;
      do
      {
        pSid1 = malloc(0x44ui64);
        hObject = OpenProcess(0x400u, 0, pe.th32ProcessID);
        if ( hObject )
        {
          if ( (unsigned int)sub_140001500(hObject, &pSid1) )
          {
            if ( EqualSid(pSid1, pSid2) )
            {
              szExeFile = pe.szExeFile;
              v4 = (char *)L"msedge.exe" - (char *)pe.szExeFile;
              while ( 1 )
              {
                v5 = *szExeFile;
                if ( *szExeFile != *(WCHAR *)((char *)szExeFile + v4) )
                  break;
                ++szExeFile;
                if ( !v5 )
                {
                  v6 = 0;
                  goto LABEL_14;
                }
              }
              v6 = v5 < *(WCHAR *)((char *)szExeFile + v4) ? -1 : 1;
LABEL_14:
              if ( !v6 )
                th32ProcessID = pe.th32ProcessID;
            }
            free(pSid1);
          }
          CloseHandle(hObject);
        }
      }
      while ( !th32ProcessID && Process32NextW(hSnapshot, &pe) );
      free(pSid2);
      CloseHandle(hSnapshot);
      return th32ProcessID;
    }
    else
    {
      v2 = GetLastError();
      sub_140001260("Process32First failed with error %lu\n", v2);
      CloseHandle(hSnapshot);
      return 0i64;
    }
  }
}
```
:::
Flag: `FLAG{462fe0007f86957f59824e113f78947c}`