# 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}`