Skip to content

Instantly share code, notes, and snippets.

@Novakov
Last active March 14, 2016 21:22
[Blog] Wstrzykiwanie biblioteki DLL do procesu
[<DllImport("kernel32.dll", SetLastError = true)>]
extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int nSize, int * lpNumberOfBytesWritten);
[<DllImport("kernel32.dll", SetLastError = true)>]
extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, IntPtr dwSize, AllocationType flAllocationType, MemoryProtection flProtect);
[<DllImport("kernel32.dll")>]
extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, UInt32 dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, UInt32 dwCreationFlags, IntPtr * lpThreadId);
[<DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)>]
extern bool IsWow64Process(IntPtr hProcess, bool * wow64Process);
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
injection();
return FALSE;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return FALSE;
}
int readStringLength(HANDLE pipe)
{
int count = 0;
int shift = 0;
uint8_t b;
do
{
ReadFile(pipe, &b, 1, NULL, NULL);
count |= (b & 0x7F) << shift;
shift += 7;
} while ((b & 0x80) != 0);
return count;
}
void writeStringLength(HANDLE pipe, int length)
{
auto v = (uint32_t)length;
uint8_t b;
while (v >= 0x80) {
b = (uint8_t)(v | 0x80);
WriteFile(pipe, &b, 1, NULL, NULL);
v >>= 7;
}
b = (uint8_t)v;
WriteFile(pipe, &b, 1, NULL, NULL);
}
wchar_t * readString(HANDLE pipe)
{
int length = readStringLength(pipe);
auto value = new wchar_t[length / 2 + 1]();
int offset = 0;
while (offset < length)
{
DWORD readBytes;
auto r = ReadFile(pipe, value + offset / 2, length - offset, &readBytes, NULL);
offset += readBytes;
}
return value;
}
void writeString(HANDLE pipe, wchar_t * str)
{
auto length = wcslen(str);
writeStringLength(pipe, length * sizeof(wchar_t));
WriteFile(pipe, str, length * sizeof(wchar_t), NULL, NULL);
}
void setEnv(HANDLE pipe)
{
auto variable = readString(pipe);
auto value = readString(pipe);
SetEnvironmentVariable(variable, value);
delete variable;
delete value;
}
void readEnv(HANDLE pipe)
{
auto variable = readString(pipe);
auto valueLength = GetEnvironmentVariable(variable, NULL, 0);
wchar_t * value;
if (valueLength == 0)
{
value = L"";
}
else
{
value = new wchar_t[valueLength]();
GetEnvironmentVariable(variable, value, valueLength);
}
writeString(pipe, value);
delete variable;
}
void pingPong(HANDLE pipe)
{
uint8_t response = 54;
WriteFile(pipe, &response, 1, NULL, NULL);
}
let echo (channel: NamedPipeServerStream) =
channel.WriteByte(45uy)
channel.ReadByte() = 54
let setEnvVar (channel: NamedPipeServerStream) (variable: string) (value: string) =
use writer = new BinaryWriter(channel, Encoding.Unicode)
writer.Write(01uy)
writer.Write(variable)
writer.Write(value)
channel
let readEnvVar (channel: NamedPipeServerStream) (variable: string) =
use writer = new BinaryWriter(channel, Encoding.Unicode)
writer.Write(02uy)
writer.Write(variable)
use reader = new BinaryReader(channel, Encoding.Unicode)
reader.ReadString()
let readPath (processId : int) =
use channel = openChannel processId
readEnvVar channel "PATH"
let setPath (processId : int) (path : string) =
use channel = openChannel processId
setEnvVar channel "PATH" path |> ignore
let loadLibrary = findFunction processHandle "kernel32.dll" "LoadLibraryA"
let mutable isWow = false
IsWow64Process(processHandle, &&isWow) |> ignore
let libraryPath = if isWow then library.Path86 else library.Path64
let arg = VirtualAllocEx(processHandle, IntPtr.Zero, nativeint (libraryPath.Length + 1), AllocationType.Commit ||| AllocationType.Reserve, MemoryProtection.ReadWrite)
let argPtr = Marshal.StringToHGlobalAnsi(libraryPath)
let mutable written = 0
WriteProcessMemory(processHandle, arg, argPtr, libraryPath.Length + 1, &&written) |> ignore
let mutable threadId = IntPtr.Zero
CreateRemoteThread(processHandle, IntPtr.Zero, 0u, loadLibrary, arg, 0u, &&threadId) |> ignore
void injection()
{
int i = 0;
wchar_t pipeName[1024];
wsprintf(pipeName, L"\\\\.\\pipe\\pather\\%d", GetCurrentProcessId());
HANDLE pipe = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
DWORD mode = PIPE_READMODE_MESSAGE | PIPE_WAIT;
SetNamedPipeHandleState(pipe, &mode, NULL, NULL);
while (true)
{
uint8_t commandCode;
if (!ReadFile(pipe, &commandCode, 1, NULL, NULL))
{
if (GetLastError() == ERROR_BROKEN_PIPE)
{
break;
}
}
switch (commandCode)
{
case 45:
pingPong(pipe);
break;
case 01:
setEnv(pipe);
break;
case 02:
readEnv(pipe);
break;
}
}
CloseHandle(pipe);
}
let private injectionPath =
let basePath = System.AppDomain.CurrentDomain.BaseDirectory
{
Native.LibraryPath.Path86 = Path.Combine(basePath, "Injections", "Injection.x86.dll")
Native.LibraryPath.Path64 = Path.Combine(basePath, "Injections", "Injection.x64.dll")
}
let openChannel (processId: int) =
let proc = Process.GetProcessById(processId)
let pipeName = sprintf "pather\%d" processId
let pipe = new NamedPipeServerStream(pipeName, PipeDirection.InOut, 1, PipeTransmissionMode.Message)
Native.injectLibrary proc.Handle injectionPath
pipe.WaitForConnection()
pipe
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment