I found an ancient (2011) unpacker I wrote for popcap games. It was decompiled with IDA, don't have the source code anymore.
CHAR *FindPopcapgame1Process()
{
HANDLE Toolhelp32Snapshot;
void *v1;
while ( 1 )
{
Toolhelp32Snapshot = CreateToolhelp32Snapshot(2u, 0);
v1 = Toolhelp32Snapshot;
if ( Toolhelp32Snapshot != (HANDLE)-1 )
{
pe.dwSize = 296;
if ( Process32First(Toolhelp32Snapshot, &pe) )
break;
}
LABEL_28:
Sleep(0x64u);
}
while ( stricmp(pe.szExeFile, "popcapgame1.exe") )
{
if ( (pe.szExeFile[0] == 'p' || pe.szExeFile[0] == 'P')
&& (pe.szExeFile[1] == 'o' || pe.szExeFile[1] == 'O')
&& (pe.szExeFile[2] == 'p' || pe.szExeFile[2] == 'P')
&& (pe.szExeFile[3] == 'c' || pe.szExeFile[3] == 'C')
&& (pe.szExeFile[4] == 'a' || pe.szExeFile[4] == 'A')
&& (pe.szExeFile[5] == 'p' || pe.szExeFile[5] == 'P')
&& (pe.szExeFile[6] == 'g' || pe.szExeFile[6] == 'G')
&& (pe.szExeFile[7] == 'a' || pe.szExeFile[7] == 'A')
&& (pe.szExeFile[8] == 'm' || pe.szExeFile[8] == 'M')
&& (pe.szExeFile[9] == 'e' || pe.szExeFile[9] == 'E') )
{
CloseHandle(v1);
break;
}
if ( !Process32Next(v1, &pe) )
goto LABEL_28;
}
dwProcessId = pe.th32ProcessID;
return pe.szExeFile;
}
int __cdecl Unpack(LPCSTR workingDirectory, LPCSTR applicationPath)
{
CHAR *popcapgame1_exe_path;
HANDLE v4;
char Destination[4];
CHAR v6[256];
CHAR NewFileName[4];
_BYTE v8[251];
struct _STARTUPINFOA StartupInfo;
struct _PROCESS_INFORMATION ProcessInformation;
*(_DWORD *)NewFileName = 0;
memset(v8, 0, sizeof(v8));
*(_DWORD *)Destination = 0;
memset(v6, 0, sizeof(v6));
SetCurrentDirectoryA(workingDirectory);
if ( !CreateProcessA(applicationPath, 0, 0, 0, 1, CREATE_DEFAULT_ERROR_MODE, 0, 0, &StartupInfo, &ProcessInformation) )
return 0;
popcapgame1_exe_path = FindPopcapgame1Process();
strcpy(::Destination, popcapgame1_exe_path);
wsprintfA(NewFileName, "%s.bak", applicationPath);
strcpy(Destination, applicationPath);
v4 = OpenProcess(1u, 0, dwProcessId);
if ( !TerminateProcess(v4, 0) )
return 0;
Sleep(0x64u);
if ( !TerminateProcess(ProcessInformation.hProcess, 0) )
return 0;
Sleep(0x64u);
if ( !SetFileAttributesA(::Destination, 0x80u) )
return 0;
Sleep(0x64u);
if ( !CopyFileA(applicationPath, NewFileName, 0) )
return 0;
Sleep(0x64u);
if ( !DeleteFileA(applicationPath) )
return 0;
Sleep(0x64u);
if ( !CopyFileA(::Destination, Destination, 0) )
return 0;
Sleep(0x64u);
if ( !DeleteFileA(::Destination) )
return 0;
CloseHandle(ProcessInformation.hProcess);
CloseHandle(ProcessInformation.hThread);
return 1;
}
It looks like a subprocess popcapgame1.exe is created when the game runs. The unpacker simply copies that executable to 'unpack' it.