From bed58f50cee5480678151bb2611907c0e7bf7552 Mon Sep 17 00:00:00 2001 From: jonnysoe <84360198+jonnysoe@users.noreply.github.com> Date: Wed, 3 Jan 2024 23:20:38 +0800 Subject: [PATCH] Add CMake support - This also adds vscode support --- .gitignore | 3 + .vscode/extensions.json | 5 + .vscode/launch.json | 27 ++++++ .vscode/settings.json | 15 +++ 1.NtCreateUserProcess/CMakeLists.txt | 1 + 1.NtCreateUserProcess/main.c | 10 ++ 2.RtlCloneUserProcess/CMakeLists.txt | 1 + 2.RtlCloneUserProcess/main.c | 10 ++ 3.CloneAndMinidump/CMakeLists.txt | 6 ++ 4.InspectClonedMemory/CMakeLists.txt | 2 + 5.Library/CMakeLists.txt | 9 ++ 5.Library/Library/CMakeLists.txt | 2 + CMakeLists.txt | 140 +++++++++++++++++++++++++++ 13 files changed, 231 insertions(+) create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 1.NtCreateUserProcess/CMakeLists.txt create mode 100644 2.RtlCloneUserProcess/CMakeLists.txt create mode 100644 3.CloneAndMinidump/CMakeLists.txt create mode 100644 4.InspectClonedMemory/CMakeLists.txt create mode 100644 5.Library/CMakeLists.txt create mode 100644 5.Library/Library/CMakeLists.txt create mode 100644 CMakeLists.txt diff --git a/.gitignore b/.gitignore index 34c8dee..9d99613 100644 --- a/.gitignore +++ b/.gitignore @@ -386,3 +386,6 @@ FodyWeavers.xsd # JetBrains Rider .idea/ *.sln.iml + +# CMake +build/ diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..ec8b2e0 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": ["ms-vscode.cmake-tools"] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..70e9045 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,27 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(cppvsdbg) Launch", + "type": "cppvsdbg", + "request": "launch", + "program": "${command:cmake.launchTargetPath}", + "args": [], + "stopAtEntry": false, + "cwd": "${workspaceFolder}", + "environment": [ + { + // Bug in Windows Debugger ${env:PATH} + // add the directory where our target was built to the PATHs + // it gets resolved by CMake Tools: + "name": "PATH", + "value": "%PATH%;${command:cmake.launchTargetDirectory};${workspaceFolder}" + } + ], + "console": "integratedTerminal", + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..f8d9243 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "editor.detectIndentation": false, + "editor.tabSize": 4, + "editor.insertSpaces": true, + "files.trimTrailingWhitespace": true, + "C_Cpp.autoAddFileAssociations": false, + "C_Cpp.default.includePath": [ + "${default}", + "${workspaceFolder}/**", + ], + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "cmake.preferredGenerators": ["Ninja"], + "cmake.options.statusBarVisibility": "compact", + "cmake.setBuildTypeOnMultiConfig": true, +} \ No newline at end of file diff --git a/1.NtCreateUserProcess/CMakeLists.txt b/1.NtCreateUserProcess/CMakeLists.txt new file mode 100644 index 0000000..b16d755 --- /dev/null +++ b/1.NtCreateUserProcess/CMakeLists.txt @@ -0,0 +1 @@ +add_executable(NtCreateUserProcess main.c) \ No newline at end of file diff --git a/1.NtCreateUserProcess/main.c b/1.NtCreateUserProcess/main.c index 9e49ddd..53d8b12 100644 --- a/1.NtCreateUserProcess/main.c +++ b/1.NtCreateUserProcess/main.c @@ -69,6 +69,10 @@ int wmain(int argc, wchar_t* argv[]) status = NtWaitForSingleObject(hProcess, FALSE, NULL); + // Save exit code before closing the process handle + DWORD exitCode; + GetExitCodeProcess(hProcess, &exitCode); + NtClose(hProcess); NtClose(hThread); @@ -78,6 +82,12 @@ int wmain(int argc, wchar_t* argv[]) return status; } + if (!NT_SUCCESS(exitCode)) + { + wprintf_s(L"Clone exit with error: 0x%x\r\n", exitCode); + return exitCode; + } + wprintf_s(L"The clone exited.\r\n"); } diff --git a/2.RtlCloneUserProcess/CMakeLists.txt b/2.RtlCloneUserProcess/CMakeLists.txt new file mode 100644 index 0000000..cc38096 --- /dev/null +++ b/2.RtlCloneUserProcess/CMakeLists.txt @@ -0,0 +1 @@ +add_executable(RtlCloneUserProcess main.c) \ No newline at end of file diff --git a/2.RtlCloneUserProcess/main.c b/2.RtlCloneUserProcess/main.c index 84cbdd3..f9543fe 100644 --- a/2.RtlCloneUserProcess/main.c +++ b/2.RtlCloneUserProcess/main.c @@ -59,6 +59,10 @@ int wmain(int argc, wchar_t* argv[]) status = NtWaitForSingleObject(processInfo.ProcessHandle, FALSE, NULL); + // Save exit code before closing the process handle + DWORD exitCode; + GetExitCodeProcess(processInfo.ProcessHandle, &exitCode); + NtClose(processInfo.ProcessHandle); NtClose(processInfo.ThreadHandle); @@ -68,6 +72,12 @@ int wmain(int argc, wchar_t* argv[]) return status; } + if (!NT_SUCCESS(exitCode)) + { + wprintf_s(L"Clone exit with error: 0x%x\r\n", exitCode); + return exitCode; + } + wprintf_s(L"The clone exited.\r\n"); } diff --git a/3.CloneAndMinidump/CMakeLists.txt b/3.CloneAndMinidump/CMakeLists.txt new file mode 100644 index 0000000..1f0e24f --- /dev/null +++ b/3.CloneAndMinidump/CMakeLists.txt @@ -0,0 +1,6 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/) + +# Cannot use find_library as well +link_libraries(Dbghelp) + +add_executable(CloneAndMinidump main.c CloneAndMinidump.rc) \ No newline at end of file diff --git a/4.InspectClonedMemory/CMakeLists.txt b/4.InspectClonedMemory/CMakeLists.txt new file mode 100644 index 0000000..5d96b8b --- /dev/null +++ b/4.InspectClonedMemory/CMakeLists.txt @@ -0,0 +1,2 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/) +add_executable(InspectClonedMemory main.c InspectClonedMemory.rc) \ No newline at end of file diff --git a/5.Library/CMakeLists.txt b/5.Library/CMakeLists.txt new file mode 100644 index 0000000..d041e5a --- /dev/null +++ b/5.Library/CMakeLists.txt @@ -0,0 +1,9 @@ +add_subdirectory(Library) + +add_executable(example example.c) +target_link_libraries(example PUBLIC cloning) + +# Hack: Possible bug, target_link_libraries didn't inherit include_directories +# Haven't figure out what went wrong, cmake is already at latest 3.28.1... +get_target_property(INCLUDE_DIRECTORIES cloning INCLUDE_DIRECTORIES) +target_include_directories(example PUBLIC ${INCLUDE_DIRECTORIES}) \ No newline at end of file diff --git a/5.Library/Library/CMakeLists.txt b/5.Library/Library/CMakeLists.txt new file mode 100644 index 0000000..cfe612d --- /dev/null +++ b/5.Library/Library/CMakeLists.txt @@ -0,0 +1,2 @@ +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/) +add_library(cloning STATIC cloning.c) \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..9765ecf --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,140 @@ +cmake_minimum_required(VERSION 3.15.0) +get_filename_component(ProjectId ${CMAKE_CURRENT_SOURCE_DIR} NAME) +string(REPLACE " " "_" ProjectId ${ProjectId}) + +message(STATUS "CMAKE_GENERATOR: ${CMAKE_GENERATOR}") + +# Treat string as is, do not treat as variables to be expanded +cmake_policy(SET CMP0054 NEW) +cmake_policy(SET CMP0079 NEW) # target not created in current directory hack. + +project(${ProjectId} VERSION 0.1.0) + +# Enable CCache +# https://stackoverflow.com/a/64600661/19336104 +find_program(CCACHE_PROGRAM ccache) +if(CCACHE_PROGRAM) + message(STATUS "Using ccache: ${CCACHE_PROGRAM}") + set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM}) + set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM}) +endif() + +#Set the default build type if not specified +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING + "Choose the type of build: None, Debug, Release, RelWithDebInfo, MinSizeRel" + FORCE) +else() + # Case-insensitive correction hack + string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_LOWER) + if(CMAKE_BUILD_TYPE_LOWER STREQUAL "release") + set(CMAKE_BUILD_TYPE "Release") + elseif(CMAKE_BUILD_TYPE_LOWER STREQUAL "debug") + set(CMAKE_BUILD_TYPE "Debug") + elseif(CMAKE_BUILD_TYPE_LOWER STREQUAL "relwithdebinfo") + set(CMAKE_BUILD_TYPE "RelWithDebInfo") + elseif(CMAKE_BUILD_TYPE_LOWER STREQUAL "minsizerel") + set(CMAKE_BUILD_TYPE "MinSizeRel") + endif() +endif() + +if(WIN32) + add_compile_definitions(_WIN32) +endif() + +if(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") + add_compile_options( + -Werror=return-type # Clang by default does not file error when return type does not match function return + -Wno-int-conversion + -Wno-visibility + -Wno-pragma-pack + -Wno-microsoft-enum-forward-reference + -Wno-sizeof-pointer-memaccess + ) + + # Windows LLVM/Clang does not use libstdc++ like the Clang/GCC counterpart, + # Linux Clang counterpart does not require GCC as base + if("${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC") + # Need to use quotes around CMAKE_CXX_SIMULATE_ID as not every configuration have this definition + # https://blog.conan.io/2022/10/13/Different-flavors-Clang-compiler-Windows.html + message(STATUS "LLVM/Clang outputs natvis debug information by default.") + elseif(${CMAKE_BUILD_TYPE} MATCHES "Debug") + # Clang workaround to emit string to libstdc++ + # https://stackoverflow.com/a/44727479/19336104 + message(STATUS "Clang does not output to libstdc++, enabling 'no-limit-debug-info'") + add_compile_options(-fno-limit-debug-info) + endif() +endif() + +if(${CMAKE_BUILD_TYPE} MATCHES "Debug") + # Debug mode have weird behaviors relocating symbols in static library if linked by shared library + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + + if(NOT MSVC) + # This is for compatibility with MSVC + # CMake Tools uses "--config Debug" which doesn't have _DEBUG definition + # this is added instead of explicitly adding -D_DEBUG when calling cmake + # https://learn.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library?view=msvc-170 + add_compile_definitions(_DEBUG) + endif() +elseif(${CMAKE_BUILD_TYPE} MATCHES "Release") + if(NOT MSVC) + # This is for compatibility with MSVC + # CMake Tools uses "--config Debug" which doesn't have _DEBUG definition + # this is added instead of explicitly adding -D_DEBUG when calling cmake + # https://learn.microsoft.com/en-us/cpp/build/reference/md-mt-ld-use-run-time-library?view=msvc-170 + add_compile_definitions(NDEBUG) + endif() +endif() + +if(MSVC) + # add_compile_definitions(_CRT_SECURE_NO_WARNINGS) + + # Remove default /W3 and /W4 by CMake MSVC + # https://stackoverflow.com/a/58711983/19336104 + string(REGEX REPLACE "/W[3|4]" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REGEX REPLACE " " " " CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + string(REGEX REPLACE "/W[3|4]" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + string(REGEX REPLACE " " " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") +endif() + +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) # .exe for executable +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) # .lib for linker +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) # .dll for runtime load library + +# Use C++17 +set(CMAKE_CXX_STANDARD 17) + +# Add phnt headers +file(GLOB DIR_LIST ${CMAKE_CURRENT_SOURCE_DIR}/Dependencies/phnt/*) +list(LENGTH DIR_LIST DIR_LEN) +if(DIR_LEN EQUAL 0) + # phnt directory is empty + message(STATUS "Initializing phnt submodule") + find_package(Git QUIET) + if(GIT_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} submodule update --init Dependencies/phnt + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE GIT_RETURN + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET) + endif() + + if(NOT GIT_FOUND OR NOT ${GIT_RETURN} EQUAL 0) + message(FATAL_ERROR "Failed to initialize phnt submodule!") + endif() +endif() +include_directories(Dependencies/phnt) + +# Link to Nt libraries +# Cannot use find_library +# Windows SDK will not be added to PATH if LLVM/Clang was set as compiler without calling vcvarsall.bat +link_libraries(ntdll) + +# Executable +add_subdirectory(1.NtCreateUserProcess) +add_subdirectory(2.RtlCloneUserProcess) +add_subdirectory(3.CloneAndMinidump) +add_subdirectory(4.InspectClonedMemory) +add_subdirectory(5.Library) \ No newline at end of file