Skip to content

Commit 21594df

Browse files
add linux support (#2)
1 parent 2110152 commit 21594df

File tree

9 files changed

+133
-14
lines changed

9 files changed

+133
-14
lines changed

.github/workflows/ci.yml

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,32 @@
11
name: CI
22
on:
33
push:
4+
branches: [ master ]
45
pull_request:
6+
branches: [ master ]
57
workflow_dispatch:
68

79
jobs:
8-
build:
10+
linux-build:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: actions/setup-node@v4
17+
with:
18+
node-version: 20
19+
20+
- name: Build project
21+
run: ./_build.sh
22+
23+
- name: Run project without root
24+
run: ./_run.sh
25+
26+
- name: Run project with root
27+
run: ./_run.sh -a
28+
29+
windows-build:
930
runs-on: windows-latest
1031

1132
steps:

Bootstrapper/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
cmake_minimum_required(VERSION 3.20)
22
project(Bootstrapper)
33

4-
set(CMAKE_CXX_STANDARD 20)
4+
set(CMAKE_CXX_STANDARD 23)
55
set(CMAKE_CXX_STANDARD_REQUIRED ON)
66

77
add_library(${PROJECT_NAME} SHARED src/library.cpp)

Bootstrapper/build.sh

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/bin/env bash
2+
set -ex
3+
4+
mkdir -p build && cd build
5+
6+
cmake ..
7+
cmake --build . --config Release

Bootstrapper/src/library.cpp

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#else
55
#define EXPORT __attribute__((visibility("default")))
66
#include <dlfcn.h>
7-
#include <cstdio>
7+
#include <thread>
88
#endif
99

1010
/// This class helps to manage shared libraries
@@ -113,3 +113,32 @@ extern "C" EXPORT InitializeResult bootstrapper_load_assembly(
113113

114114
return InitializeResult::Success;
115115
}
116+
117+
#ifndef _WIN32
118+
std::string getEnvVar(const char *name) {
119+
auto val = std::getenv(name);
120+
return val == nullptr ? std::string() : std::string(val);
121+
}
122+
123+
__attribute__((constructor))
124+
void initialize_library() {
125+
auto runtime_config_path = getEnvVar("RUNTIME_CONFIG_PATH");
126+
auto assembly_path = getEnvVar("ASSEMBLY_PATH");
127+
auto type_name = getEnvVar("TYPE_NAME");
128+
auto method_name = getEnvVar("METHOD_NAME");
129+
130+
if (!runtime_config_path.empty() && !assembly_path.empty() && !type_name.empty() && !method_name.empty()) {
131+
std::thread thread([=] {
132+
sleep(1);
133+
auto ret = bootstrapper_load_assembly(
134+
runtime_config_path.c_str(),
135+
assembly_path.c_str(),
136+
type_name.c_str(),
137+
method_name.c_str()
138+
);
139+
printf("[+] api.inject() => %d\n", (uint32_t) ret);
140+
});
141+
thread.detach();
142+
}
143+
}
144+
#endif

DemoApplication/build.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env bash
2+
set -ex
3+
dotnet publish -c Release -r linux-x64 -p:PublishDir="$(pwd)/dist" --self-contained

README.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,32 +11,36 @@ CLI tool that can replace C# methods in .NET Core applications
1111

1212
### Requirements
1313

14-
- Visual Studio 2022 with installed C++ & C# build tools: https://visualstudio.microsoft.com/en/vs/
14+
- C++ & C#
15+
- Linux: g++, .NET 8: https://dotnet.microsoft.com/en-us/download/dotnet/8.0
16+
- Windows: Visual Studio 2022 with installed C++ & C# build tools: https://visualstudio.microsoft.com/en/vs/
1517
- Node.js: https://nodejs.org/en/download/
1618
- frida: https://frida.re
1719

18-
### Installation on Windows
20+
### Building
1921

2022
Open command line and run this script
2123

24+
- `_build.sh` on Linux
25+
- `_build.bat` on Windows
26+
2227
It will build
2328

2429
- Node.js package [net-core-injector](package.json) - DLL-injector written in TypeScript
2530
- [Bootstrapper](Bootstrapper) - helper native library written in C++ to interact with .NET Core runtime
2631
- [DemoApplication](DemoApplication) - test application to demonstrate how it works
2732
- [RuntimePatcher](RuntimePatcher) - code that attaches to [DemoApplication](DemoApplication)
2833

29-
```
30-
_build.bat
31-
```
32-
3334
### Running
3435

3536
This script should produce output like the GIF above
3637

37-
```
38-
_run.bat
39-
```
38+
- `_run.sh` on Linux
39+
40+
Note: If you want to attach to an existing process on Linux, this requires root privileges. In this case, use
41+
`_run.sh -a` (attach).
42+
43+
- `_run.bat` on Windows
4044

4145
### Internal documentation
4246

@@ -50,8 +54,8 @@ I did it in [`Bootstrapper/src/library.cpp`](Bootstrapper/src/library.cpp).
5054

5155
[`net-core-injector/src/main.ts`](src/main.ts) injects `Bootstrapper.dll` into C# process and loads custom assembly
5256

53-
5457
The following command runs `DemoApplication.exe` on another thread and injects code.
58+
5559
```
5660
start DemoApplication\dist\DemoApplication.exe
5761
@@ -64,6 +68,7 @@ RuntimePatcher\dist\RuntimePatcher.dll ^
6468
```
6569

6670
Then the execution happens in this order:
71+
6772
1. get into `DemoApplication.exe` process memory via DLL-injection of `Bootstrapper.dll`
6873
2. call native C++ code
6974
```cpp
@@ -86,4 +91,4 @@ You can use this to mod games written in C# or to patch any software
8691
8792
### TODO
8893
89-
- Linux support is incomplete due to some issues with the secondary host context in `hostfxr`
94+
- I don't have macOS device so it's supported for now. External contributors are welcome.

RuntimePatcher/build.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/usr/bin/env bash
2+
set -ex
3+
dotnet publish -c Release -p:PublishDir="$(pwd)/dist"

_build.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/usr/bin/env bash
2+
set -ex
3+
4+
npm install
5+
6+
cd Bootstrapper
7+
./build.sh
8+
cd ..
9+
10+
cd DemoApplication
11+
./build.sh
12+
cd ..
13+
14+
cd RuntimePatcher
15+
./build.sh
16+
cd ..

_run.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env bash
2+
set -e
3+
4+
while getopts "a" OPTION 2> /dev/null; do
5+
case ${OPTION} in
6+
a)
7+
DO_ATTACH="yes"
8+
;;
9+
\?)
10+
break
11+
;;
12+
esac
13+
done
14+
15+
if [ "$DO_ATTACH" == "yes" ]; then
16+
set -m
17+
sudo sysctl kernel.yama.ptrace_scope=0
18+
19+
./DemoApplication/dist/DemoApplication &
20+
npm start -- inject \
21+
DemoApplication \
22+
Bootstrapper/build/libBootstrapper.so \
23+
RuntimePatcher/dist/RuntimePatcher.runtimeconfig.json \
24+
RuntimePatcher/dist/RuntimePatcher.dll \
25+
"RuntimePatcher.Main, RuntimePatcher" \
26+
"InitializePatches"
27+
fg %1
28+
else
29+
LD_PRELOAD=./Bootstrapper/build/libBootstrapper.so \
30+
RUNTIME_CONFIG_PATH="$(pwd)/RuntimePatcher/dist/RuntimePatcher.runtimeconfig.json" \
31+
ASSEMBLY_PATH="$(pwd)/RuntimePatcher/dist/RuntimePatcher.dll" \
32+
TYPE_NAME="RuntimePatcher.Main, RuntimePatcher" \
33+
METHOD_NAME="InitializePatches" \
34+
./DemoApplication/dist/DemoApplication
35+
fi

0 commit comments

Comments
 (0)