Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error when injecting into CREATE_SUSPENDED process #13

Open
TinkerWorX opened this issue Sep 10, 2022 · 7 comments
Open

Error when injecting into CREATE_SUSPENDED process #13

TinkerWorX opened this issue Sep 10, 2022 · 7 comments

Comments

@TinkerWorX
Copy link

I get the following exception when I create an Injector for a suspended process:

System.ComponentModel.Win32Exception: 'Only part of a ReadProcessMemory or WriteProcessMemory request was completed'

This is the code I use to create the process and inject.

if (CreateProcess(location, new StringBuilder($@"""{location}"" {arguments}"), null, null, false, CREATE_PROCESS.CREATE_SUSPENDED, null, null, new STARTUPINFO(), out var processInformation))
{
    var process = Process.GetProcessById((int)processInformation.dwProcessId);
    var injector = new Injector(process);
}

If I create the process without the CREATE_SUSPENDED flag, it launches without any errors.

For context, I'm coming from EasyHook and was looking for a more updated alternative and found Reloaded.Injector/Reloaded.Hooks.
In EasyHook, injecting into a suspended thread works as expected, where I then resume the thread from inside when I'm ready.

@Sewer56
Copy link
Member

Sewer56 commented Sep 10, 2022

Hi,

This is unfortunately a limitation of the design of this library; it can't be used on a process that has started suspended. It is also the reason why I haven't really been updating this library ever since I released it; as I myself don't actively use it.

I originally wrote this library for use with Reloaded-II around 3 years ago but had to go back to the drawing board because I unfortunately ran across this exact same issue.

The exact specific reason comes down to EnumProcessModulesEx (and its friends). On Windows, you can't enumerate the modules of a process that was started suspended because they haven't been loaded in yet. This in turn means you can't get the address of kernel32.dll in an x86 process from a x64 process; and kernel32 is necessary for LoadLibraryW to in turn inject your DLLs.

What I wound up doing is creating a much, much more basic DLL Injector that spawns an x86 process to pass its address of Kernel32 to the main code using a memory mapped file process, injector, and reuse that in the DLL injection operation. Technically speaking, I could have done the same with this library; albeit the idea of using shellcode and PE parsing used here was pretty cool; and novel; so I kept it around. Unpacking and running a binary would also raise a lot of red flags from AV software.

@TinkerWorX
Copy link
Author

I appreciate the detailed description. I'll take a look at your other solution. I assume I can still use Reloaded.Hooks once injected?

@Sewer56
Copy link
Member

Sewer56 commented Sep 10, 2022

Yeah that'll work perfectly fine.

@Sewer56
Copy link
Member

Sewer56 commented Apr 17, 2023

I was thinking about this a bit when writing the spec for Reloaded3.
I actually found a workaround for this; so I'll probably release version 2.X.X sometime in the future and use it in Reloaded-II, thus resurrecting this library from limbo.

I just gotta get rid of some bloat (namely remove the need for PeNet, and parse the PE header in memory of target process directly. Most of the code for that already exists actually; I just need to move it out to a separate NuGet package.

@TinkerWorX
Copy link
Author

Let me know when you do, then I can try and test it with my project.

@Albeoris
Copy link

Albeoris commented Jun 7, 2024

@Sewer56, hello, how are you? :) Do you have the time and motivation to finish this task?

@Sewer56
Copy link
Member

Sewer56 commented Jun 7, 2024

I started working on 2.X, but decided to abandon it mid way through.
Instead I forked OpenByteDev/dll-syringe (Rust), which is available here.
My fork: Sewer56/dll-syringe.

On the add-c-exports branch (note: Ignore legacy readme), you can build the Rust library with C# bindings.
Those bindings aren't finalized, but they do work, and I made them work with suspended processes.

Reloaded-II had to switch over to using this fork/branch due to Defender suddenly disliking the old DLL Injection code, and me receiving around 200 user reports in the span of 2 days.

That API is here and a prebuilt package is here. But do note, they were made over a weekend in an emergency and are not final.

Main thing that's left to do with that code is some cleanup. I've been stripping dependencies etc. to decrease the DLL size, hope to get to around 1/5th of what the original Rust library was.

I wouldn't get to work on this for some months though. I need to finish the Reloaded3 spec first, and then Reloaded.Hooks-rs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants