Skip to content

Commit

Permalink
Click.
Browse files Browse the repository at this point in the history
  • Loading branch information
0vercl0k committed Jul 18, 2021
1 parent 6fb7be0 commit fbecc98
Show file tree
Hide file tree
Showing 7 changed files with 391 additions and 1 deletion.
45 changes: 45 additions & 0 deletions .github/workflows/inject.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Builds

on: [push, pull_request]

permissions:
actions: read
contents: read
security-events: write

jobs:
Windows:
name: Windows latest
runs-on: windows-latest
strategy:
fail-fast: false
matrix:
platform: ['x86', 'x64']
configuration: ['Debug', 'Release']
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive

- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: cpp

- name: Setup vs prompt
uses: ilammy/msvc-dev-cmd@v1

- name: Build
run: msbuild /p:Configuration=${{ matrix.configuration }} /p:Platform=${{ matrix.platform }} src\inject.sln

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

- name: Upload artifacts
uses: actions/upload-artifact@v2
with:
name: bin-${{ matrix.platform }}.${{matrix.configuration }}
path: |
src/**/${{ matrix.configuration }}/inject.exe
src/**/${{ matrix.configuration }}/inject.pdb
13 changes: 12 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,13 @@
# inject
Yet another Windows DLL injector
![Builds](https://github.com/0vercl0k/inject/workflows/Builds/badge.svg)

## Overview
Yet another Windows DLL injector I wrote to support some work I was doing with [wtf](https://github.com/0vercl0k/wtf).

<p align='center'>
<img src='pics/inject.gif'>
</p>

## Authors

* Axel '[0vercl0k](https://twitter.com/0vercl0k)' Souchet
Binary file added pics/inject.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/.clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BasedOnStyle: LLVM
147 changes: 147 additions & 0 deletions src/inject.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
// Axel '0vercl0k' Souchet - March 14 2020
#include <windows.h>

#include <cstdint>
#include <cstdio>
#include <filesystem>
#include <memory>
#include <tlhelp32.h>
#include <vector>

bool InjectDll(const uint32_t ProcessId, const std::filesystem::path &Path) {
const uint32_t ProcessRights =
PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION |
PROCESS_VM_WRITE | PROCESS_VM_READ;
const HANDLE Process = OpenProcess(ProcessRights, false, ProcessId);

if (Process == nullptr) {
return EXIT_FAILURE;
}

const PVOID RemoteDllPath = VirtualAllocEx(
Process, nullptr, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

if (RemoteDllPath == nullptr) {
printf("VirtualAllocEx failed.\n");
return EXIT_FAILURE;
}

const std::string DllPath = Path.string();
const size_t DllPathLen = DllPath.size() + 1;
SIZE_T BytesWritten;
if (!WriteProcessMemory(Process, RemoteDllPath, DllPath.c_str(), DllPathLen,
&BytesWritten)) {
printf("WriteProcessMemory failed.\n");
return EXIT_FAILURE;
}

const HMODULE Kernelbase = GetModuleHandleA("kernelbase");
if (Kernelbase == nullptr) {
printf("GetModuleHandleA failed.\n");
return EXIT_FAILURE;
}

const PVOID LoadLibraryA = PVOID(GetProcAddress(Kernelbase, "LoadLibraryA"));
if (LoadLibraryA == nullptr) {
printf("GetProcAddress failed.\n");
return EXIT_FAILURE;
}

DWORD Tid;
const HANDLE Thread = CreateRemoteThread(Process, nullptr, 0,
LPTHREAD_START_ROUTINE(LoadLibraryA),
RemoteDllPath, 0, &Tid);

if (Thread == NULL) {
printf("CreateRemoteThread failed.\n");
return EXIT_FAILURE;
}

WaitForSingleObject(Thread, INFINITE);

DWORD ExitCode = 0;
GetExitCodeThread(Thread, &ExitCode);

if (ExitCode == 0) {
printf("/!\\ The thread failed to load the dll.\n");
}

CloseHandle(Thread);
VirtualFreeEx(Process, RemoteDllPath, 0, MEM_RELEASE);
CloseHandle(Process);
return ExitCode != 0;
}

bool Pid2Name(const char *ProcessName, uint32_t &Pid) {
PROCESSENTRY32 Pe32;
HANDLE Snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (Snap == INVALID_HANDLE_VALUE) {
return false;
}

Pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(Snap, &Pe32)) {
CloseHandle(Snap);
return false;
}

bool FoundPid = false;
do {
const bool Match = _stricmp(Pe32.szExeFile, ProcessName) == 0;
if (Match) {
if (FoundPid) {
printf("There are several instances of %s, pid %d will be used.\n",
Pe32.szExeFile, Pid);
} else {
FoundPid = true;
Pid = Pe32.th32ProcessID;
}
}
} while (Process32Next(Snap, &Pe32));

CloseHandle(Snap);
return FoundPid;
}

int main(int Argc, const char *Argv[]) {
if (Argc != 3) {
printf("./injectdll <pid | process name> <dll path | dll dir path>\n");
return EXIT_FAILURE;
}

uint32_t ProcessId = strtol(Argv[1], nullptr, 0);
if (ProcessId == 0) {
const bool Success = Pid2Name(Argv[1], ProcessId);
if (!Success) {
printf("Pid2Name failed, exiting.\n");
return EXIT_FAILURE;
}
}

std::vector<std::filesystem::path> Dlls;
if (std::filesystem::is_directory(Argv[2])) {
const std::filesystem::directory_iterator DirIt(Argv[2]);
for (const auto &DirEntry : DirIt) {
if (DirEntry.path().extension().string() == ".dll") {
Dlls.emplace_back(DirEntry);
}
}
} else {
Dlls.emplace_back(Argv[2]);
}

for (const std::filesystem::path &Dll : Dlls) {
const std::filesystem::path DllAbsolute = std::filesystem::absolute(Dll);
const bool Succeed = InjectDll(ProcessId, DllAbsolute);
if (!Succeed) {
printf("Error while injecting %ls in %d\n", DllAbsolute.c_str(),
ProcessId);
return EXIT_FAILURE;
}

printf("Successfully injected %ls in %d\n", DllAbsolute.c_str(), ProcessId);
}

printf("Done!\n");
return EXIT_SUCCESS;
}
31 changes: 31 additions & 0 deletions src/inject.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.31424.327
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "inject", "inject.vcxproj", "{CFF27EB6-C404-4E7E-9EE7-72FEDE08E737}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{CFF27EB6-C404-4E7E-9EE7-72FEDE08E737}.Debug|x64.ActiveCfg = Debug|x64
{CFF27EB6-C404-4E7E-9EE7-72FEDE08E737}.Debug|x64.Build.0 = Debug|x64
{CFF27EB6-C404-4E7E-9EE7-72FEDE08E737}.Debug|x86.ActiveCfg = Debug|Win32
{CFF27EB6-C404-4E7E-9EE7-72FEDE08E737}.Debug|x86.Build.0 = Debug|Win32
{CFF27EB6-C404-4E7E-9EE7-72FEDE08E737}.Release|x64.ActiveCfg = Release|x64
{CFF27EB6-C404-4E7E-9EE7-72FEDE08E737}.Release|x64.Build.0 = Release|x64
{CFF27EB6-C404-4E7E-9EE7-72FEDE08E737}.Release|x86.ActiveCfg = Release|Win32
{CFF27EB6-C404-4E7E-9EE7-72FEDE08E737}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8B53551B-C77B-4FDD-8910-6FA2351A8EEE}
EndGlobalSection
EndGlobal
Loading

0 comments on commit fbecc98

Please sign in to comment.