Created
August 30, 2022 19:26
-
-
Save lab313ru/34c52f0e448da1f86f5becce31f1abfb to your computer and use it in GitHub Desktop.
TitanEngine unp64
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <stdio.h> | |
#include <psapi.h> | |
#include "inc\TitanEngine.h" | |
PROCESS_INFORMATION* fdProcessInfo; | |
LPVOID lpBaseOfImage; | |
char szDumpName[MAX_PATH] = ""; | |
static void log(const char* format, ...) | |
{ | |
va_list args; | |
va_start(args, format); | |
char msg[1024] = ""; | |
vsprintf(msg, format, args); | |
puts(msg); | |
} | |
static void cbOep() | |
{ | |
long long rip = GetContextData(UE_RIP); | |
log("> OEP 0x%llX reached!", rip); | |
log("> Dumping..."); | |
DeleteFileA(szDumpName); | |
// Dump the process (notice that szDumpName need to be a full path) | |
if (!DumpProcess(fdProcessInfo->hProcess, lpBaseOfImage, szDumpName, rip)) | |
{ | |
log("> DumpProcess failed..."); | |
StopDebug(); | |
return; | |
} | |
log("> Dumping done!"); | |
log("> Fixing imports..."); | |
ULONG_PTR iatStart = 0; | |
ULONG_PTR iatSize = 0; | |
// Search for IAT (Search start is 'OEP' in Scylla) | |
ImporterAutoSearchIAT(fdProcessInfo->dwProcessId, szDumpName, rip, &iatStart, &iatSize); | |
if (!iatStart || !iatSize) | |
{ | |
log("> IAT not found..."); | |
StopDebug(); | |
return; | |
} | |
log("> IAT Start: 0x%llX, IAT Size: 0x%llX", iatStart, iatSize); | |
char szSectionName[] = ".unp64"; | |
// Auto fix the file (append a section & fix IAT) | |
if (!ImporterExportIATEx(szDumpName, szDumpName, szSectionName)) | |
{ | |
log("> ImporterExportIATEx failed..."); | |
StopDebug(); | |
return; | |
} | |
log("> Imports fixed!"); | |
// Stop debugging | |
StopDebug(); | |
} | |
static void cbNearOep() | |
{ | |
log("> Near OEP!"); | |
// Step using the trap flag | |
StepInto((void*)cbOep); | |
} | |
static void cbPeSpin() | |
{ | |
// Set a hardware breakpoint at RSP with size 8 on read/write | |
SetHardwareBreakPoint(GetContextData(UE_RSP), UE_DR0, UE_HARDWARE_READWRITE, 8, (void*)cbNearOep); | |
} | |
static void cbEntry() | |
{ | |
// Get RIP register | |
long long rip = GetContextData(UE_RIP); | |
log("> Entry point 0x%llX reached!", rip); | |
// Search for MPRESS pattern | |
unsigned char pattern[4] = { 0x5D, 0x5B, 0xC3, 0xE9 }; | |
BYTE wildcard = 0; | |
long long found = Find((void*)rip, 0x1000, pattern, 4, &wildcard); | |
if (!found) | |
{ // Search for PESpin pattern | |
unsigned char pespin[4] = { 0xFF, 0x64, 0x24, 0xF8 }; | |
long long found = Find((void*)rip, 0x1000, pespin, 4, &wildcard); | |
if (!found) | |
{ | |
log("> MPRESS/PESpin pattern NOT found..."); | |
StopDebug(); | |
return; | |
} | |
log("> PESpin pattern found on 0x%llX!", found); | |
// Step over | |
StepOver((void*)cbPeSpin); | |
return; | |
} | |
// Set a simple INT3 breakpoint | |
SetBPX(found + 3, UE_BREAKPOINT, (void*)cbNearOep); | |
log("> MPRESS pattern found on 0x%llX!", found); | |
} | |
static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo) | |
{ | |
// Get the loaded base | |
lpBaseOfImage = CreateProcessInfo->lpBaseOfImage; | |
log("> Process created on 0x%llX!", lpBaseOfImage); | |
} | |
static bool DevicePathToPath(const char* devicepath, char* path, size_t path_size) | |
{ | |
if (!devicepath || !path) | |
return false; | |
char curDrive[3] = " :"; | |
char curDevice[MAX_PATH] = ""; | |
for (char drive = 'C'; drive <= 'Z'; drive++) | |
{ | |
*curDrive = drive; | |
if (!QueryDosDeviceA(curDrive, curDevice, MAX_PATH)) | |
continue; | |
size_t curDevice_len = strlen(curDevice); | |
if (!_strnicmp(devicepath, curDevice, curDevice_len)) | |
// we match the device | |
{ | |
if (strlen(devicepath) - curDevice_len >= path_size) | |
return false; | |
sprintf(path, "%s%s", curDrive, devicepath + curDevice_len); | |
return true; | |
} | |
} | |
return false; | |
} | |
static bool GetFileNameFromHandle(HANDLE hFile, char* szFileName) | |
{ | |
if (!GetFileSize(hFile, 0)) | |
return false; | |
HANDLE hFileMap = CreateFileMappingA(hFile, 0, PAGE_READONLY, 0, 1, 0); | |
if (!hFileMap) | |
return false; | |
void* pFileMap = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1); | |
if (!pFileMap) | |
{ | |
CloseHandle(hFileMap); | |
return false; | |
} | |
char szMappedName[MAX_PATH] = ""; | |
if (GetMappedFileNameA(GetCurrentProcess(), pFileMap, szMappedName, MAX_PATH)) | |
{ | |
DevicePathToPath(szMappedName, szFileName, MAX_PATH); | |
UnmapViewOfFile(pFileMap); | |
CloseHandle(hFileMap); | |
return true; | |
} | |
UnmapViewOfFile(pFileMap); | |
CloseHandle(hFileMap); | |
return false; | |
} | |
static void unpack(char* szFileName) | |
{ | |
// Set an engine variable (hide console window of created process) | |
SetEngineVariable(UE_ENGINE_NO_CONSOLE_WINDOW, true); | |
// Get full file path | |
HANDLE hFile = CreateFileA(szFileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); | |
if (hFile == INVALID_HANDLE_VALUE) | |
{ | |
log("> File \"%s\" doesn't exist...", szFileName); | |
return; | |
} | |
GetFileNameFromHandle(hFile, szDumpName); | |
CloseHandle(hFile); | |
log("> Unpack of file \"%s\" started...", szFileName); | |
FILE_STATUS_INFO inFileStatus = {}; | |
if (IsPE32FileValidEx(szFileName, UE_DEPTH_DEEP, &inFileStatus) && inFileStatus.FileIs64Bit && !inFileStatus.FileIsDLL) | |
{ | |
log("> 64-bit PE file detected!"); | |
// Make name of dumped file | |
int len = strlen(szDumpName); | |
while (szDumpName[len] != '.' && len) | |
len--; | |
if (!len) | |
len = strlen(szDumpName); | |
strcpy(szDumpName + len, "_unp64.exe"); | |
// Start the process | |
fdProcessInfo = (PROCESS_INFORMATION*)InitDebugEx(szFileName, 0, 0, (void*)cbEntry); | |
if (fdProcessInfo) | |
{ | |
log("> InitDebug OK!"); | |
// Set a custom handler | |
SetCustomHandler(UE_CH_CREATEPROCESS, (void*)cbCreateProcess); | |
// Start debug loop | |
DebugLoop(); | |
} | |
else | |
log("> InitDebug failed..."); | |
} | |
else | |
{ | |
log("> Invalid/x86/DLL file..."); | |
} | |
log("> Unpack ended"); | |
} | |
int main(int argc, char* argv[]) | |
{ | |
puts("unp64 v0.1\n\nSupported packers:\nMPRESS v2.19\nPESpin v1.22 (Packer only)\n"); | |
if (argc < 2) | |
puts("usage: unp64 [file.exe]"); | |
else | |
unpack(argv[1]); | |
Sleep(2500); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment