Skip to content

Commit 452e508

Browse files
committed
Add GitHub Actions workflow for build and release process; update CMakeLists for Windows compatibility and improve main.c usage instructions
1 parent 51405d3 commit 452e508

7 files changed

Lines changed: 148 additions & 71 deletions

File tree

.github/workflows/build.yml

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
name: Build and Release GhostInjector
2+
3+
on:
4+
push:
5+
branches: [ main, master ]
6+
pull_request:
7+
branches: [ main, master ]
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: write
12+
13+
jobs:
14+
build-and-release:
15+
runs-on: ubuntu-latest
16+
17+
steps:
18+
- name: Checkout repository
19+
uses: actions/checkout@v4
20+
with:
21+
submodules: recursive
22+
23+
- name: Install dependencies
24+
run: |
25+
sudo apt-get update
26+
sudo apt-get install -y mingw-w64
27+
28+
- name: Configure CMake
29+
run: |
30+
cmake -B build -DCMAKE_TOOLCHAIN_FILE=toolchain-mingw.cmake -DCMAKE_BUILD_TYPE=Release
31+
- name: Build
32+
run: cmake --build build
33+
- name: Rename executable
34+
run: mv build/ghostinjector-*.exe build/ghostinjector.exe
35+
36+
- name: Create Release
37+
if: (github.ref == 'refs/heads/main' && github.event_name == 'push') || startsWith(github.ref, 'refs/tags/v')
38+
uses: softprops/action-gh-release@v2
39+
with:
40+
tag_name: ${{ (github.ref == 'refs/heads/main' && 'latest') || github.ref_name }}
41+
name: ${{ (github.ref == 'refs/heads/main' && 'Latest Build (Development)') || github.ref_name }}
42+
body: |
43+
## 🚀 Latest Development Build
44+
45+
**Commit:** ${{ github.sha }}
46+
47+
### 📥 Download
48+
- **Windows:** `ghostinjector.exe`
49+
files: build/ghostinjector.exe
50+
draft: false
51+
prerelease: ${{ github.ref == 'refs/heads/main' }}
52+
make_latest: ${{ github.ref == 'refs/heads/main' }}
53+
env:
54+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
55+

CMakeLists.txt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
cmake_minimum_required(VERSION 3.10)
22
project(GhostInjector VERSION 1.0.2 LANGUAGES C)
33

4+
if(MSVC)
5+
string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
6+
endif()
7+
8+
# Set C standard to C99 for the entire project
9+
set(CMAKE_C_STANDARD 99)
10+
set(CMAKE_C_STANDARD_REQUIRED ON)
11+
set(CMAKE_C_EXTENSIONS OFF)
12+
13+
if(WIN32)
14+
set(CMAKE_EXECUTABLE_SUFFIX ".exe")
15+
endif()
16+
417
add_subdirectory(Neptune)
518
add_subdirectory(NThread)
619
add_subdirectory(NThreadOSUtils)
@@ -21,10 +34,8 @@ target_link_libraries(${EXECUTABLE_NAME} PRIVATE NThreadOSUtils)
2134
target_compile_definitions(${EXECUTABLE_NAME} PRIVATE
2235
LOG_LEVEL_2
2336
NEPTUNE_MODULERULES_HEADER="ntosutils_rules.h"
24-
LOG_FORCE_COLOR
2537
NEPTUNE_ENABLE_MEMMEM
2638
VERSION=${PROJECT_VERSION}
2739
LOG_FILE_PATH=L"ghostinjector.log"
2840
LOG_ON_STDOUT=1
29-
)
30-
41+
)

src/main.c

Lines changed: 71 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* furnished to do so, subject to the following conditions:
1212
*
1313
* The above copyright notice and this permission notice shall be included in all
14-
* copies or substantial portions of the Software.
14+
* copies or substantial portions of the Software.
1515
*
1616
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1717
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@@ -22,44 +22,49 @@
2222
* SOFTWARE.
2323
*/
2424

25+
#include <stdio.h>
26+
#include <stdlib.h>
27+
#include <string.h>
28+
#include <windows.h>
29+
2530
#include "nerror.h"
2631
#include "ntosutils.h"
2732
#include "ntmem.h"
2833
#include "ntosutilswin.h"
2934

35+
void print_usage() {
36+
printf("GhostInjector - DLL Injection tool for Windows processes\n\n");
37+
printf("Examples:\n");
38+
printf(" ghostinjector.exe 1234 mydll.dll\n");
39+
printf(" ghostinjector.exe 5678 first.dll second.dll third.dll\n\n");
40+
printf("Usage:\n");
41+
printf(" ghostinjector.exe <process_id> <dll_path> [dll_path2 ...]\n");
42+
printf(" ghostinjector.exe -h | --help\n");
43+
}
44+
3045
int main(int argc, char *argv[])
3146
{
3247
if (HAS_ERR(neptune_init()))
3348
return EXIT_FAILURE;
3449

35-
if (argc < 3) {
36-
#ifdef LOG_LEVEL_1
37-
LOG_INFO(
38-
"Usage: %s <thread_id:DWORD or process_id:DWORD> <dll_path:string>",
39-
argv[0]);
40-
#endif /* ifdef LOG_LEVEL_1 */
41-
42-
return 0x10;
50+
if (argc < 3 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
51+
print_usage();
52+
neptune_destroy();
53+
return EXIT_SUCCESS;
4354
}
4455

45-
#ifdef LOG_LEVEL_1
46-
LOG_INFO("Neptune initilaized!");
47-
#endif /* ifdef LOG_LEVEL_1 */
48-
49-
const char *dll_path = argv[2];
50-
const char *id_str = argv[1];
56+
uint32_t id = atoi(argv[1]);
5157

5258
#ifdef LOG_LEVEL_1
53-
LOG_INFO("DLL Path(%s)", dll_path);
54-
#endif /* ifdef LOG_LEVEL_1 */
55-
56-
DWORD id = atoi(id_str);
59+
LOG_INFO("Neptune initialized!");
60+
LOG_INFO("ID: %u", id);
61+
LOG_INFO("Number of DLLs to inject: %d", argc - 2);
62+
#endif
5763

58-
if (id < 0) {
64+
if (id == 0) {
5965
#ifdef LOG_LEVEL_1
6066
LOG_ERROR("Invalid id: must be greater than 0");
61-
#endif /* ifdef LOG_LEVEL_1 */
62-
67+
#endif
6368
neptune_destroy();
6469
return 0x11;
6570
}
@@ -68,85 +73,86 @@ int main(int argc, char *argv[])
6873
if (kernel32 == NULL) {
6974
#ifdef LOG_LEVEL_1
7075
LOG_ERROR("GetModuleHandleA failed");
71-
#endif /* ifdef LOG_LEVEL_1 */
72-
76+
#endif
7377
neptune_destroy();
7478
return 0x20;
7579
}
7680

77-
void *load_library_func = GetProcAddress(kernel32, "LoadLibraryA");
81+
FARPROC load_library_func = GetProcAddress(kernel32, "LoadLibraryA");
7882
if (load_library_func == NULL) {
7983
#ifdef LOG_LEVEL_1
8084
LOG_ERROR("GetProcAddress failed");
81-
#endif /* ifdef LOG_LEVEL_1 */
82-
85+
#endif
86+
neptune_destroy();
8387
return 0x21;
8488
}
8589

8690
#ifdef LOG_LEVEL_1
87-
LOG_INFO("LoadLibraryA=%p", load_library_func);
88-
#endif /* ifdef LOG_LEVEL_1 */
91+
LOG_INFO("LoadLibraryA=%p", (void *)load_library_func);
92+
#endif
8993

90-
// Initialize the ntutils layer for working on the target thread.
9194
if (HAS_ERR(nosu_attach(id))) {
9295
#ifdef LOG_LEVEL_1
9396
LOG_WARN("nosu_attach failed");
94-
#endif /* ifdef LOG_LEVEL_1 */
97+
#endif
9598

9699
if (HAS_ERR(nosu_find_thread_and_upgrade(id))) {
97100
#ifdef LOG_LEVEL_1
98101
LOG_ERROR("nosu_find_thread_and_upgrade failed");
99-
#endif /* ifdef LOG_LEVEL_1 */
100-
102+
#endif
101103
neptune_destroy();
102104
return 0x06;
103105
}
104106
}
105107

106-
size_t dll_path_len = strlen(dll_path);
107-
size_t dll_path_size = dll_path_len + 1;
108+
for (int i = 2; i < argc; i++) {
109+
const char *dll_path = argv[i];
108110

109-
ntmem_t *ntmem = ntm_create_with_alloc_ex(dll_path_size + 1);
110-
if (ntmem == NULL) {
111111
#ifdef LOG_LEVEL_1
112-
LOG_ERROR("ntm_create failed");
113-
#endif /* ifdef LOG_LEVEL_1 */
112+
LOG_INFO("Injecting DLL [%d/%d]: %s", i - 1, argc - 2, dll_path);
113+
#endif
114114

115-
ntu_destroy();
116-
neptune_destroy();
117-
return 0x92;
118-
}
115+
size_t dll_path_len = strlen(dll_path);
116+
size_t dll_path_size = dll_path_len + 1;
119117

120-
// Copy the converted string into memory that will be pushed to the target.
121-
void *local = NTM_LOCAL(ntmem);
122-
memcpy(local, dll_path, dll_path_size);
123-
124-
// Push the DLL path into the remote memory.
125-
void *dll_path_addr = ntm_push(ntmem);
126-
if (dll_path_addr == NULL) {
118+
ntmem_t *ntmem = ntm_create_with_alloc_ex(dll_path_size + 1);
119+
if (ntmem == NULL) {
127120
#ifdef LOG_LEVEL_1
128-
LOG_ERROR("ntm_push failed");
129-
#endif /* ifdef LOG_LEVEL_1 */
121+
LOG_ERROR("ntm_create failed for %s", dll_path);
122+
#endif
123+
continue;
124+
}
130125

131-
ntu_destroy();
132-
neptune_destroy();
133-
return 0x93;
134-
}
126+
void *local = NTM_LOCAL(ntmem);
127+
memcpy(local, dll_path, dll_path_size);
135128

129+
void *dll_path_addr = ntm_push(ntmem);
130+
if (dll_path_addr == NULL) {
136131
#ifdef LOG_LEVEL_1
137-
LOG_INFO("DLL Path Address(%p)", dll_path_addr);
138-
#endif /* ifdef LOG_LEVEL_1 */
139-
140-
// Call LoadLibraryA inside the target thread context.
141-
void *load_library_ret = ntu_ucall(load_library_func, dll_path_addr);
132+
LOG_ERROR("ntm_push failed for %s", dll_path);
133+
#endif
134+
ntm_delete(ntmem);
135+
continue;
136+
}
142137

143138
#ifdef LOG_LEVEL_1
144-
LOG_INFO("Return Value(%p)", load_library_ret);
145-
#endif /* ifdef LOG_LEVEL_1 */
139+
LOG_INFO("DLL Path Address(%p)", dll_path_addr);
140+
#endif
141+
142+
void *load_library_ret = ntu_ucall((void *)load_library_func, dll_path_addr);
146143

147-
ntm_delete(ntmem);
144+
#ifdef LOG_LEVEL_1
145+
LOG_INFO("LoadLibrary returned: %p", load_library_ret);
146+
if (load_library_ret != NULL) {
147+
LOG_INFO("Successfully injected: %s", dll_path);
148+
} else {
149+
LOG_ERROR("Failed to inject: %s", dll_path);
150+
}
151+
#endif
148152

153+
ntm_delete(ntmem);
154+
}
149155
ntu_destroy();
150156
neptune_destroy();
151157
return EXIT_SUCCESS;
152-
}
158+
}

toolchain-mingw.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# toolchain-mingw.cmake
2+
set(CMAKE_SYSTEM_NAME Windows)
3+
set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc)
4+
set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
5+
set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)

0 commit comments

Comments
 (0)