Summary
A packed/obfuscated 32-bit DLL never finishes DllMain(PROCESS_ATTACH) when running under
Hangover's box64 WoW64 backend (wowbox64.dll, box64cpu.dll in older Hangover). The thread
enters DllMain and never returns: ~100% CPU indefinitely, no further progress, no window.
It is not specific to Hangover: the same DLL also fails to initialize when box64 emulates a
complete x86_64 Wine (standalone box64 + Wine 11.0 with new-WoW64), which is a completely
different architecture. It reproduces across three box64 generations and also with the
interpreter (BOX64_DYNAREC=0), so I don't think it's codegen-only.
Environment
|
|
| Device |
MANGMI Air X handheld — Qualcomm SM6115 (Snapdragon 662: 4x Cortex-A73 + 4x A53) |
| GPU |
Adreno 610, mesa 26.1.6 freedreno, GL 4.6 (device Vulkan is only 1.0) |
| OS |
ROCKNIX 20260820 (LibreELEC-derived), kernel 7.1.2 aarch64, glibc 2.41 |
| Page size |
4096 |
| Display |
sway + Xwayland, Wine X11 driver |
box64 versions tried, all via Hangover's prebuilt debian12_bookworm_arm64 tarballs:
| Hangover |
box64 |
backend DLL name |
Result |
| 9.22 (Nov 2024) |
version not printed by that build |
box64cpu.dll |
hang, c000001d ILLEGAL_INSTRUCTION |
| 11.9 (upstream, May 2026) |
v0.4.2 |
wowbox64.dll |
hang, c0000094 INT_DIVIDE_BY_ZERO, flags=1 |
| 11.16 (mikugirls fork, Aug 2026) |
v0.4.5 |
wowbox64.dll |
hang, c000001d ILLEGAL_INSTRUCTION at pc=0x100fe9d9c |
Also fails with standalone box64 emulating a full x86_64 Wine
To rule out Hangover's WoW64 shim, I ran the same game on a completely different stack:
ROCKNIX's own x86_64 Wine 11.0 executed entirely under box64 0.4.4 (new-WoW64 handling the
32-bit game). 32-bit cmd.exe works fine through it, so the stack is sound.
relocating ephinea.dll dynamic base 10000000 -> 76dd0000
process_attach (L"ephinea.dll",00000000) - START
MODULE_InitDLL (76DD0000 L"ephinea.dll",PROCESS_ATTACH,00000000) - CALL
MODULE_InitDLL (76DD0000 L"ephinea.dll",PROCESS_DETACH,00000000) - CALL
warn:module:process_attach Initialization of L"ephinea.dll" failed
Exceptions in that run: c000001d ILLEGAL_INSTRUCTION, 80000004 EXCEPTION_SINGLE_STEP,
c0000005 ACCESS_VIOLATION.
Timing detail that may be diagnostic: DllMain spins at ~100% CPU for 1-2 minutes before
failing (at t+1m the DLL is still mapped, no failure logged, CPU 101%; by t+2m the process has
exited). That is the same box64 0.4.4 which, used as Hangover's WoW64 backend, hangs in
DllMain indefinitely (verified over 10 minutes). Same engine and same DLL, but a different
integration produces a different endgame — which to me suggests exception delivery and
continuation semantics rather than instruction translation, though I may be wrong.
The single-step exception is probably the most useful clue in this report. A single-step
means the trap flag was set (or INT 1 executed). Combined with the deliberate divide-by-zero
and the illegal instruction seen in other runs, this looks like exception/trap-flag based
obfuscation: the packer raises faults on purpose and resumes from its own SEH handlers. If
box64's TF emulation or exception-continuation semantics differ from hardware, that would
explain both the hang (handler never resumes) and the crashes (resumed with wrong state).
The DLL
ephinea.dll from the Ephinea PSOBB client (free download, see repro below). 12.6 MB, clearly
packed:
- a section named
.banana (3.8 MB) plus several unnamed RWX sections
- prefers base
0x10000000, has DYNAMIC_BASE so Wine relocates it (0x73300000 /
0x74820000 / 0x73270000 in different runs)
- Wine logs
warn:module:alloc_module disabling no-exec because of L"ephinea.dll"
The host process is PsoBB.exe, a 32-bit PE which imports it.
What the failure looks like
trace:module:map_image_into_view relocating L"...\ephinea.dll" dynamic base 10000000 -> 73300000
warn:module:alloc_module disabling no-exec because of L"ephinea.dll"
trace:module:process_attach (L"ephinea.dll",00000000) - START
trace:module:MODULE_InitDLL (73300000 L"ephinea.dll",PROCESS_ATTACH,00000000) - CALL
trace:seh:dispatch_exception code=c0000094 (EXCEPTION_INT_DIVIDE_BY_ZERO) flags=1 addr=000000007A8CF894
<no matching RETURN — ~100% CPU indefinitely>
The DLL is mapped (grep -c ephinea /proc/<pid>/maps = 1) but DllMain never completes.
Over a 10-minute run: 100% CPU on one thread, read_bytes advanced only ~11 KB, no window.
On box64 0.4.5 the exception becomes c000001d EXCEPTION_ILLEGAL_INSTRUCTION at
pc=0x100fe9d9c — above the 4 GB boundary, so not inside the DLL (mapped at 0x73270000).
If I'm reading that right it's in box64's own JIT region, but I may be misreading it.
Steps to reproduce
The client is a free download and the installer does not need to be run:
curl -O https://files.pioneer2.net/Ephinea_PSOBB_Installer.exe # NSIS, ~855 MB
7z x Ephinea_PSOBB_Installer.exe -o/path/to/psobb
cd /path/to/psobb
export WINEPREFIX=~/.psobb-prefix
export WINEDLLOVERRIDES="mscoree=d;mshtml=d"
wine wineboot -u
# PSOBB only accepts 16-bit display modes; without this it exits before loading the DLL:
wine reg add 'HKCU\Software\Wine\X11 Driver' /v ScreenDepth /t REG_SZ /d 16 /f
HODLL=wowbox64.dll WINEDEBUG=+loaddll,+module,+seh \
wine explorer /desktop=pso,1280x720 PsoBB.exe
Then watch for MODULE_InitDLL ... ephinea.dll ... PROCESS_ATTACH - CALL with no matching
return, and a process pinned at 100% CPU.
What I've ruled out
- Not codegen alone:
BOX64_DYNAREC=0 (interpreter) hangs identically.
- Not dynarec tuning:
BOX64_DYNAREC_SAFEFLAGS=2 BIGBLOCK=0 CALLRET=0 STRONGMEM=3 — still
hangs. [BOX64] BOX64ENV: Variables overridden: confirms the variables were applied.
- No missing opcodes reported:
BOX64_DYNAREC_MISSING=1 printed none.
- Not general 32-bit breakage:
wine C:\windows\syswow64\cmd.exe /c echo hi works on all
three versions, and the rest of this 32-bit game runs fine — it renders D3D8 through
wined3d/GL, reaches its network login screen, and accepts input.
- Not the Windows version:
winecfg /v win7 and /v winxp behave identically.
- Not fixed by newer box64: 0.4.2 -> 0.4.5 changes only the exception type.
Possibly relevant (second-hand)
The PSOBB community reports that standalone box64 0.2.6–0.2.9 boots this game under
Winlator (box64 + a full x86 Wine + box86), while newer versions do not:
https://www.pioneer2.net/community/threads/ephinea-pso-bb-natively-on-android-via-winlator.28655/
I have not verified that myself, and it's a different architecture from Hangover's WoW64 use of
box64, so it may be unrelated — but if it is the same underlying bug, that range might make it
bisectable.
Speculation, flagged as such
box64 0.4.2 reports the divide-by-zero with flags=1 (EXCEPTION_NONCONTINUABLE). Packers
commonly use exception-based control flow — raise a deliberate fault, catch it in SEH, resume —
so I wondered whether a continuable guest exception is reaching the handler as non-continuable,
which would explain a hang. I have not verified this, and 0.4.5's illegal-instruction symptom
doesn't fit it neatly.
FEX (Hangover's other backend) fails differently on the same DLL: EXCEPTION_ACCESS_VIOLATION
inside the DLL's own range, at a nearly identical address on two versions (0x779CD33C and
0x7790D33C), after which Wine logs Initialization of ephinea.dll failed and the app
continues without the DLL.
Happy to help
The device has SSH access and I can run any env vars, log levels, or patched builds and report
back. If there's a preferred way to capture a useful trace of the hang (BOX64_LOG=2, dynarec
dumps, etc.), tell me what would help most and I'll produce it. I can also try building a
minimal 32-bit PE that raises a continuable divide-by-zero, catches it in __try/__except and
resumes, if a small repro would be more useful than an 855 MB game.
Summary
A packed/obfuscated 32-bit DLL never finishes
DllMain(PROCESS_ATTACH)when running underHangover's box64 WoW64 backend (
wowbox64.dll,box64cpu.dllin older Hangover). The threadenters
DllMainand never returns: ~100% CPU indefinitely, no further progress, no window.It is not specific to Hangover: the same DLL also fails to initialize when box64 emulates a
complete x86_64 Wine (standalone box64 + Wine 11.0 with new-WoW64), which is a completely
different architecture. It reproduces across three box64 generations and also with the
interpreter (
BOX64_DYNAREC=0), so I don't think it's codegen-only.Environment
box64 versions tried, all via Hangover's prebuilt
debian12_bookworm_arm64tarballs:box64cpu.dllc000001dILLEGAL_INSTRUCTIONwowbox64.dllc0000094INT_DIVIDE_BY_ZERO,flags=1wowbox64.dllc000001dILLEGAL_INSTRUCTION atpc=0x100fe9d9cAlso fails with standalone box64 emulating a full x86_64 Wine
To rule out Hangover's WoW64 shim, I ran the same game on a completely different stack:
ROCKNIX's own x86_64 Wine 11.0 executed entirely under box64 0.4.4 (new-WoW64 handling the
32-bit game). 32-bit
cmd.exeworks fine through it, so the stack is sound.Exceptions in that run:
c000001dILLEGAL_INSTRUCTION,80000004EXCEPTION_SINGLE_STEP,c0000005ACCESS_VIOLATION.Timing detail that may be diagnostic: DllMain spins at ~100% CPU for 1-2 minutes before
failing (at t+1m the DLL is still mapped, no failure logged, CPU 101%; by t+2m the process has
exited). That is the same box64 0.4.4 which, used as Hangover's WoW64 backend, hangs in
DllMain indefinitely (verified over 10 minutes). Same engine and same DLL, but a different
integration produces a different endgame — which to me suggests exception delivery and
continuation semantics rather than instruction translation, though I may be wrong.
The single-step exception is probably the most useful clue in this report. A single-step
means the trap flag was set (or
INT 1executed). Combined with the deliberate divide-by-zeroand the illegal instruction seen in other runs, this looks like exception/trap-flag based
obfuscation: the packer raises faults on purpose and resumes from its own SEH handlers. If
box64's TF emulation or exception-continuation semantics differ from hardware, that would
explain both the hang (handler never resumes) and the crashes (resumed with wrong state).
The DLL
ephinea.dllfrom the Ephinea PSOBB client (free download, see repro below). 12.6 MB, clearlypacked:
.banana(3.8 MB) plus several unnamed RWX sections0x10000000, has DYNAMIC_BASE so Wine relocates it (0x73300000/0x74820000/0x73270000in different runs)warn:module:alloc_module disabling no-exec because of L"ephinea.dll"The host process is
PsoBB.exe, a 32-bit PE which imports it.What the failure looks like
The DLL is mapped (
grep -c ephinea /proc/<pid>/maps= 1) butDllMainnever completes.Over a 10-minute run: 100% CPU on one thread,
read_bytesadvanced only ~11 KB, no window.On box64 0.4.5 the exception becomes
c000001d EXCEPTION_ILLEGAL_INSTRUCTIONatpc=0x100fe9d9c— above the 4 GB boundary, so not inside the DLL (mapped at0x73270000).If I'm reading that right it's in box64's own JIT region, but I may be misreading it.
Steps to reproduce
The client is a free download and the installer does not need to be run:
Then watch for
MODULE_InitDLL ... ephinea.dll ... PROCESS_ATTACH - CALLwith no matchingreturn, and a process pinned at 100% CPU.
What I've ruled out
BOX64_DYNAREC=0(interpreter) hangs identically.BOX64_DYNAREC_SAFEFLAGS=2 BIGBLOCK=0 CALLRET=0 STRONGMEM=3— stillhangs.
[BOX64] BOX64ENV: Variables overridden:confirms the variables were applied.BOX64_DYNAREC_MISSING=1printed none.wine C:\windows\syswow64\cmd.exe /c echo hiworks on allthree versions, and the rest of this 32-bit game runs fine — it renders D3D8 through
wined3d/GL, reaches its network login screen, and accepts input.
winecfg /v win7and/v winxpbehave identically.Possibly relevant (second-hand)
The PSOBB community reports that standalone box64 0.2.6–0.2.9 boots this game under
Winlator (box64 + a full x86 Wine + box86), while newer versions do not:
https://www.pioneer2.net/community/threads/ephinea-pso-bb-natively-on-android-via-winlator.28655/
I have not verified that myself, and it's a different architecture from Hangover's WoW64 use of
box64, so it may be unrelated — but if it is the same underlying bug, that range might make it
bisectable.
Speculation, flagged as such
box64 0.4.2 reports the divide-by-zero with
flags=1(EXCEPTION_NONCONTINUABLE). Packerscommonly use exception-based control flow — raise a deliberate fault, catch it in SEH, resume —
so I wondered whether a continuable guest exception is reaching the handler as non-continuable,
which would explain a hang. I have not verified this, and 0.4.5's illegal-instruction symptom
doesn't fit it neatly.
FEX (Hangover's other backend) fails differently on the same DLL:
EXCEPTION_ACCESS_VIOLATIONinside the DLL's own range, at a nearly identical address on two versions (
0x779CD33Cand0x7790D33C), after which Wine logsInitialization of ephinea.dll failedand the appcontinues without the DLL.
Happy to help
The device has SSH access and I can run any env vars, log levels, or patched builds and report
back. If there's a preferred way to capture a useful trace of the hang (
BOX64_LOG=2, dynarecdumps, etc.), tell me what would help most and I'll produce it. I can also try building a
minimal 32-bit PE that raises a continuable divide-by-zero, catches it in
__try/__exceptandresumes, if a small repro would be more useful than an 855 MB game.