682150de48
Loader no longer touches disk: drop the LoadLibraryW path that
extracted OpenZen.dll to %TEMP%\OpenZenLoader and replace it with
an in-process PE loader that maps the embedded DLL straight into
the target Java process.
native/loader (new manual_map.cpp/.h):
- VirtualAllocEx in the remote process for SizeOfImage,
locally apply relocations + IAT patching (kernel32 etc. are
KnownDLLs so local GetProcAddress addresses are valid in the
remote), WriteProcessMemory the finished image once,
VirtualProtectEx to match section characteristics, then run a
minimal x64 trampoline shellcode that calls DllMain with
DLL_PROCESS_ATTACH using the proper ABI (shadow space,
16-byte stack alignment).
- embedded_dll.cpp now hands back a pointer into the .rsrc
section instead of writing the DLL out. injector.cpp shrinks
to a 14-line shim around inject_in_memory.
native (top-level CMakeLists.txt):
- Force /MT (CMAKE_MSVC_RUNTIME_LIBRARY = MultiThreaded) for
both the DLL and the loader EXE. Without this the manual
mapper's local-address import resolution trips over
vcruntime140 / ucrtbase, which are not KnownDLLs and may have
different bases in the target process - leading to NULL
derefs inside msvcp140 after injection. With /MT the only
import surface left is KERNEL32.
native/dll (jar_extract.cpp):
- Replace FindResource/LoadResource/SizeofResource with a
hand-rolled PE resource directory walker. FindResource paths
through LdrFindResource_U, which depends on the PEB.Ldr table
that manual-mapped modules are not part of, so the standard
API returns NULL for the embedded zen.jar after injection.
native/loader UI:
- Drop the now-pointless DLL Path edit + Browse button.
- Add per-process "Window Class" column harvested via
GetClassNameW alongside the existing window title.
- Add a Minecraft Only checkbox (default on): show only rows
whose window title startsWith "Minecraft" and does not
contain "Launcher", filtering HMCL / MultiMC / generic Java
apps out of the picker.
build.gradle:
- Add cleanNative (Delete) hooked into clean so wiping the
project also removes native/build/ and the staged
native/zen.jar (CMake would otherwise hold onto the previous
configure).
gradle.properties:
- Fill in the real mod metadata (id=hey, name=OpenZen,
authors=Shirona1337, group=io.github.openzen, description).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
45 lines
1.4 KiB
CMake
45 lines
1.4 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
|
# CMP0091 NEW lets us drive the MSVC runtime via MSVC_RUNTIME_LIBRARY
|
|
# instead of patching CMAKE_CXX_FLAGS_*. CMake 3.15+ default, set
|
|
# explicitly so the build stays predictable across CMake versions.
|
|
cmake_policy(SET CMP0091 NEW)
|
|
project(OpenZenNative LANGUAGES CXX)
|
|
|
|
set(CMAKE_CXX_STANDARD 17)
|
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
|
|
# Statically link the MSVC C/C++ runtime into both the loader EXE and the
|
|
# injected DLL. This matters most for the DLL: our manual mapper resolves
|
|
# import addresses locally and assumes the imported DLL has the same base
|
|
# in both processes - true for kernel32/user32/ntdll (KnownDLLs) but NOT
|
|
# for vcruntime140/ucrtbase, so the mapped DLL would otherwise call CRT
|
|
# functions through wild pointers and crash the target Java process. /MT
|
|
# eliminates those imports entirely.
|
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
|
|
|
if(NOT DEFINED ENV{JAVA_HOME})
|
|
message(FATAL_ERROR "JAVA_HOME must be set so we can locate jni.h / jvmti.h")
|
|
endif()
|
|
|
|
set(JDK_INCLUDE "$ENV{JAVA_HOME}/include")
|
|
include_directories(${JDK_INCLUDE} ${JDK_INCLUDE}/win32)
|
|
|
|
if(NOT WIN32)
|
|
message(FATAL_ERROR "OpenZen native build only supports Windows")
|
|
endif()
|
|
|
|
add_compile_definitions(
|
|
UNICODE
|
|
_UNICODE
|
|
WIN32_LEAN_AND_MEAN
|
|
NOMINMAX
|
|
)
|
|
|
|
if(MSVC)
|
|
add_compile_options(/W3 /permissive- /utf-8 /EHsc)
|
|
endif()
|
|
|
|
add_subdirectory(dll)
|
|
add_subdirectory(loader)
|