A tiny spice2x hook DLL that makes AVS's keepalive
"raw socket" check pass in environments where the process can't obtain
CAP_NET_RAW — unprivileged Wine/proot setups such as GameNative or Winlator on
Android. It lets AVS-based titles clear the network check without root and
without a chroot.
Games built on the AVS runtime create an ICMP keepalive socket during startup, roughly:
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);Raw sockets require the CAP_NET_RAW capability. On a normal desktop Wine
install this is usually available, but in unprivileged/sandboxed Linux
environments — Android emulation layers like GameNative or Winlator, or any
proot/no-root setup — the process can't get that capability, so the call fails
with EACCES. AVS reports "failed to create raw socket" and the game's
NETWORK CHECK never turns OK.
The conventional workaround on Android is to run the whole stack inside a
rooted chroot so raw sockets are permitted. sockhook removes that
requirement.
sockhook uses MinHook to inline-hook
the Winsock entry points in ws2_32.dll from inside the game process:
- Downgrade the socket. When AVS calls
socket()/WSASocketW()withSOCK_RAW, the hook rewrites the request toSOCK_DGRAMand creates a normal datagram socket instead. It records each handle it downgraded. - Satisfy the raw-only setup. AVS then performs raw-only configuration on
that handle —
setsockopt,bind,WSAIoctl,ioctlsocket— which a datagram socket rejects. For the tracked handles only, the hook lets the real call run and, if it fails, returns success anyway without forwarding the unsupported option to the kernel.
AVS sees every step succeed, treats its keepalive socket as correctly set up, and marks the network OK. Nothing else in the process is affected.
Every intercepted call is written to sockhook.log next to the DLL, so you can
see exactly what AVS attempted and where it would otherwise have tripped.
The raw ICMP socket exists only for a local liveness keepalive. In a
private-server or offline setup the real network liveness is handled by the
server's HTTP keepalive, so the local raw-socket path is functionally redundant —
there is nothing meaningful being kept alive over ICMP. sockhook only fakes the
calls a datagram socket can't accept; the underlying handle is a real ICMP
datagram socket, so with ping_group_range configured it can still send/receive
ICMP to localhost if anything ever needs it.
This is a compatibility shim, not a network exploit: it changes only the behavior of the game's own socket calls inside its own process.
- Tested:
popn28(dataM39-2025092400) under spice2x. - Expected but unconfirmed: other AVS-based titles loaded through spice2x that
fail the same raw-socket keepalive check. The hook is game-agnostic — it keys
off the
SOCK_RAWrequest, not any specific title — so it should apply broadly, but only pop'n has been verified. Reports welcome.
- Build:
mingw-w64(bothi686-andx86_64-targets). MinHook is bundled inthird_party/MinHook, so there's nothing else to fetch. - Runtime: links only against Wine builtins (
kernel32,msvcrt,ws2_32). No extra runtime dependencies. - A working spice2x setup for your title. This repository contains no game data — you supply your own.
Prebuilt DLLs are attached to every release — no build step required:
sockhook-x86.dll— for 32-bitspice.exesockhook-x64.dll— for 64-bitspice64.exe
Grab the one that matches your spice executable, drop it next to it, and jump to Usage. Prefer to build from source? See Build below.
MinHook is bundled in this repo, so a plain clone is all you need:
git clone <your-repo-url>
cd sockhook
./build.shOutput:
build/x86/sockhook.dll # for 32-bit spice.exe
build/x64/sockhook.dll # for 64-bit spice64.exe
If you'd rather not use the script:
# 32-bit
i686-w64-mingw32-gcc -O2 -Wall -D_WIN32_WINNT=0x0601 \
-Ithird_party/MinHook/include \
src/sockhook.c \
third_party/MinHook/src/*.c third_party/MinHook/src/hde/*.c \
-shared -static-libgcc -o sockhook.dll -lws2_32 -lkernel32
# 64-bit
x86_64-w64-mingw32-gcc -O2 -Wall -D_WIN32_WINNT=0x0601 \
-Ithird_party/MinHook/include \
src/sockhook.c \
third_party/MinHook/src/*.c third_party/MinHook/src/hde/*.c \
-shared -static-libgcc -o sockhook.dll -lws2_32 -lkernel32- Get the DLL of the correct bitness for your spice executable — download it from
Releases or build it
yourself. 32-bit for
spice.exe, 64-bit forspice64.exe. - Drop
sockhook.dllnext to that executable. - Add it to your launch arguments with spice2x's
-Khook flag, alongside any hooks you already load:
spice.exe -K sockhook.dll # add alongside any other -K hooks you already load
On the next launch the NETWORK CHECK should clear without a rooted chroot. If you
want to confirm the hooks fired, check sockhook.log next to the DLL.
- MinHook by Tsuda Kageyu — inline
hooking library (BSD-2-Clause), bundled in
third_party/MinHook. - spice2x — the loader whose
-Khook interface this plugs into.
The engineering, reverse-engineering, and design decisions behind this project are my own — but I'll freely admit it wouldn't have come together without Claude. It was a genuine collaborator for working through the Winsock hooking approach, making sense of AVS's socket behavior, and getting the build and packaging right.
MIT — see LICENSE. MinHook is a separate component distributed under its own BSD-2-Clause license.