GithubHelp home page GithubHelp logo

monoxgas / srdi Goto Github PK

View Code? Open in Web Editor NEW
2.0K 63.0 455.0 424 KB

Shellcode implementation of Reflective DLL Injection. Convert DLLs to position independent shellcode

License: Other

C# 21.91% C++ 13.40% C 8.36% Python 12.62% PowerShell 43.71%

srdi's Introduction

sRDI - Shellcode Reflective DLL Injection

sRDI allows for the conversion of DLL files to position independent shellcode. It attempts to be a fully functional PE loader supporting proper section permissions, TLS callbacks, and sanity checks. It can be thought of as a shellcode PE loader strapped to a packed DLL.

Functionality is accomplished via two components:

  • C project which compiles a PE loader implementation (RDI) to shellcode
  • Conversion code which attaches the DLL, RDI, and user data together with a bootstrap

This project is comprised of the following elements:

  • ShellcodeRDI: Compiles shellcode for the DLL loader
  • NativeLoader: Converts DLL to shellcode if neccesarry, then injects into memory
  • DotNetLoader: C# implementation of NativeLoader
  • Python\ConvertToShellcode.py: Convert DLL to shellcode in place
  • Python\EncodeBlobs.py: Encodes compiled sRDI blobs for static embedding
  • PowerShell\ConvertTo-Shellcode.ps1: Convert DLL to shellcode in place
  • FunctionTest: Imports sRDI C function for debug testing
  • TestDLL: Example DLL that includes two exported functions for call on Load and after

The DLL does not need to be compiled with RDI, however the technique is cross compatiable.

Use Cases / Examples

Before use, I recommend you become familiar with Reflective DLL Injection and it's purpose.

Convert DLL to shellcode using python

from ShellcodeRDI import *

dll = open("TestDLL_x86.dll", 'rb').read()
shellcode = ConvertToShellcode(dll)

Load DLL into memory using C# loader

DotNetLoader.exe TestDLL_x64.dll

Convert DLL with python script and load with Native EXE

python ConvertToShellcode.py TestDLL_x64.dll
NativeLoader.exe TestDLL_x64.bin

Convert DLL with powershell and load with Invoke-Shellcode

Import-Module .\Invoke-Shellcode.ps1
Import-Module .\ConvertTo-Shellcode.ps1
Invoke-Shellcode -Shellcode (ConvertTo-Shellcode -File TestDLL_x64.dll)

Flags

The PE loader code uses flags argument to control the various options of loading logic:

  • SRDI_CLEARHEADER [0x1]: The DOS Header and DOS Stub for the target DLL are completley wiped with null bytes on load (Except for e_lfanew). This might cause issues with stock windows APIs when supplying the base address as a psuedo HMODULE.
  • SRDI_CLEARMEMORY [0x2]: After calling functions in the loaded module (DllMain and any exports), the DLL data will be cleared from memory. This is dangerous if you expect to continue executing code out of the module (Threads / GetProcAddressR).
  • SRDI_OBFUSCATEIMPORTS [0x4]: The order of imports in the module will be randomized before starting IAT patching. Additionally, the high 16 bits of the flag can be used to store the number of seconds to pause before processing the next import. For example, flags | (3 << 16) will pause 3 seconds between every import.
  • SRDI_PASS_SHELLCODE_BASE [0x8]: As opposed to passing supplied user data to the exported function, sRDI will instead pass the base address of the currently executing shellcode block. This can be useful for self-cleanup inside more advanced modules.

Building

This project is built using Visual Studio 2019 (v142) and Windows SDK 10. The python script is written using Python 3.

The Python and Powershell scripts are located at:

  • Python\ConvertToShellcode.py
  • PowerShell\ConvertTo-Shellcode.ps1

After building the project, the other binaries will be located at:

  • bin\NativeLoader.exe
  • bin\DotNetLoader.exe
  • bin\TestDLL_<arch>.dll
  • bin\ShellcodeRDI_<arch>.bin

If you would like to update the static blobs inside any of the tools:

> python .\lib\Python\EncodeBlobs.py -h
usage: EncodeBlobs.py [-h] solution_dir

sRDI Blob Encoder

positional arguments:
  solution_dir  Solution Directory

optional arguments:
  -h, --help    show this help message and exit

> python lib\Python\EncodeBlobs.py C:\code\srdi

[+] Updated C:\code\srdi\Native/Loader.cpp
[+] Updated C:\code\srdi\DotNet/Program.cs
[+] Updated C:\code\srdi\Python/ShellcodeRDI.py
[+] Updated C:\code\srdi\PowerShell/ConvertTo-Shellcode.ps1

Alternatives

If you find my code disgusting, or just looking for an alternative memory-PE loader project, check out some of these:

Credits

The basis of this project is derived from "Improved Reflective DLL Injection" from Dan Staples which itself is derived from the original project by Stephen Fewer.

The project framework for compiling C code as shellcode is taken from Mathew Graeber's reasearch "PIC_BindShell"

srdi's People

Contributors

coldfusion39 avatar funoverip avatar hmnthabit avatar jnokin avatar monoxgas avatar zerosteiner avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

srdi's Issues

Crash when test on win8.1 x64 with x86 shellcode

there's some problem when using x86 shellcode on win8.1 X64,maybe is the problem in dealing with the fun "GetProcAddressWithHash" ,the shellcode move the param to ecx, not using "push" I guess.
test

Execute by ordinal?

Is it currently possible to execute by ordinal after load? This would be a pretty neat feature combined with Cobalt Strike/DanderSpiritz, etc.

[UPDATE]

Just hit me that both of those have export names, would still be a nice feature though.

NativeLoader uses hard coded DLL path instead of argv[1]

Hey, great project!

I just wanted to note that the native loader is set to use a hard coded dll path: "C:\Users\Nick\Documents\Projects\Throwback\Throwback2.5\bin\Persistence_InstallUtil_x64.dll"

Changing this string to argv[1] allows the NativeLoader to work as expected. This might have just been a commit mistake from testing. Just wanted to point it out. Thanks!

Source link:

if (!GetFileContents("C:\\Users\\Nick\\Documents\\Projects\\Throwback\\Throwback2.5\\bin\\Persistence_InstallUtil_x64.dll", &data, dataSize)) {

Function hashed name

Hi,

I want to use sRDI to convert a DLL that is managed code (.Net C#) with an exported function (using DllExport from RGiesecke.DllExport) to be used from unmanaged code. I need to call this specific exported function.

According to the Powershell ConvertTo-Shellcode script, I should be able to specify the function to call (and even pass it some arguments), however it is required to provide the hashed name of the function.

So I have 2 questions:

  1. Would this work even work knowing that the DLL I'll be using is a managed one with unmanaged exports ?
  2. How do I calculate the function hashed name ?

Thanks a lot for your help !

Exported function name hash calculation is not right

I pick out the hash calculation snippet from FunctionTest.cpp, and recreate a project with it, code as below:
#include "stdafx.h"
#include <Windows.h>

#define ROTR32(value, shift) (((DWORD) value >> (BYTE) shift) | ((DWORD) value << (32 - (BYTE) shift)))
DWORD HashFunctionName(LPSTR name) {
DWORD hash = 0;

do
{
	hash = ROTR32(hash, 13);
	hash += *name;
	name++;
} while (*(name - 1) != 0);

return hash;

}

int main(int argc, char **argv)
{
if (argc == 2) {
printf("0x%x\n", HashFunctionName(argv[1]));
}
return 0;
}

The output is clearly not right, what's wrong?

Reflective Dll injection asm source code

Hello, sRDI's Developers:
I am researching on Reflective DLL Injection, and use it for software protector.
However, I can't find Reflective DLL Injection asm source code, only shellcode over Google.
Hope you can give me it, help my study. Thank you.

PE loading improvements

On the short list of things the loading process still needs:

  • TLS callback initialization
  • Late imports (a fork of sRDI already has this, just needs merging)

Exception handling

Hey, I'm using your library to load a test compiled DLL as shellcode. To load I'm using the Native loader. everything was compiled using v141 toolset in VS2017.
The function does something simple and just echoes back a formatted string to OutputDebugString. Inside the function I've added a throw of std::exception and I'm not catching it in the respective catch clause or any other catch clause other than the ellipsis catch handler. The compiled code and shellcode are all x64 and it runs well aside from exception handling, which I saw the shellcode adds via a call to RtlAddFunctionTable.
Would love to hear what is done wrong in trying to catch the exception. Whether I need to add a hack to parse the exception structure or something the shellcode RDI needs to do to be able to handle specific exceptions.

.rsrc section does not behave as expected

DLLs cannot use FindResource when converted into shellcode. Same code works when not loaded using sRDI. Issue seems to be the same as TheWover/donut#70 where the PE stomping breaks the .rsrc section.
EDIT: Based on PE structure, not sure if there is a workaround other than disabling the SRDI_CLEARHEADER flag. Any ideas?
EDIT 2: Even with SRDI_CLEARHEADER it doesnt seem to work.

Python script crashes?

I've successfully compiled the TestDLL.dll, but the python script does not seem to work

%> python ConvertToShellcode.py ../Release/TestDLL.dll
Creating Shellcode: ../Release/TestDLL.bin
Traceback (most recent call last):
  File "ConvertToShellcode.py", line 24, in <module>
    main()
  File "ConvertToShellcode.py", line 19, in main
    converted_dll = ConvertToShellcode(dll, HashFunctionName(arguments.function_name))
  File "/tmp/sRDI-master/Python/ShellcodeRDI.py", line 43, in HashFunctionName
    functionHash += b
TypeError: unsupported operand type(s) for +=: 'int' and 'str'

convert user32.dll to shellcode and load it into memory failed

Environment: Win10 1709
DLL: C:\Windows\SysWOW64\user32.dll

  1. I firstly use command python Python\ConvertToShellcode.py user32.dll convert user32.dll to user32.bin.
  2. Then I change the code in Native\Loader.cpp to call API MessageBoxA after loading the user32.dll and compile the Native project using Visual Studio 2015 Debug x86.
	// Only set the first page to RWX
	// This is should sufficiently cover the sRDI shellcode up top
	if (VirtualProtect(finalShellcode, sysInfo.dwPageSize, PAGE_EXECUTE_READWRITE, &dwOldProtect1)) {
		RDI rdi = (RDI)(finalShellcode);

		printf("[+] Executing RDI\n");
 		UINT_PTR hLoadedDLL = rdi(); // Excute DLL

		free(finalShellcode); // Free the RDI blob. We no longer need it.

		/*Function exportedFunction = (Function)GetProcAddressR(hLoadedDLL, "SayGoodbye");
		if (exportedFunction) {
			printf("[+] Calling exported functon\n");
			exportedFunction();
		}*/
		MyMessageBoxA exportedFunction = (MyMessageBoxA)GetProcAddressR(hLoadedDLL, "MessageBoxA");
		if (exportedFunction) {
			printf("[+] Calling exported functon\n");
			exportedFunction(0, "Hello", "user32.dll message", 1);
		}
	}


----

typedef int (WINAPI *MyMessageBoxA)(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
  1. Then use command Native.exe user32.bin to load the shellcode.
    The exe crashed and report a error :

0x7774CCC5 (ntdll.dll) (located at Native.exe) Exception: 0xC0000005: Access violation reading location 0x00000008.

I ensure that the GetProcAddressR return the correct address of MessageBoxA.

I found that the 0x7774CCC5 belongs to ntdll.dll!RtlAllocateHeap function:
image

Do you have comments that which possible cause this problem? My conclusion is that reflective loading a DLL written by ourselves works fine but loading a system dll(ntdll, user32..) will not work. It seems that there is something the loader doesn't handle when load the system dll into memory.

Why is it very slow to load shellcode?

When my program runs to this line of code, it takes a long time to return:
HMODULE hLoadedDLL = (HMODULE)rdi();
It's been running here for too long, what is the reason for this?

Infinite loop when executing NativeLoader_x64.exe

Hello,

I'm having trouble converting sources to C or C++ with ConvertToShellcode.py

Indeed, when I try to convert some code into shellcode, I get an infinite loop when I test the shellcode on the generated .bin, even using the base dll of the TestDLL_x64.dll project:

python ConvertToShellcode.py TestDLL_x64.dll
Creating Shellcode: TestDLL_x64.bin

NativeLoader_x64.exe TestDLL_x64.bin
[+] Executing RDI
-> Infinite loop here

How can I solve this issue please?

static template class dll will crash

this is my code
dllmain.cpp

#include <windows.h>
#include "template.h"

void go();

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
		go();
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

void go()
{
	string sa = "sasas";

	static test<string>* t = new test<string>();
	printf("t ptr: 0x%x\n", t);
	t->add(&sa);
	printf("count: %d\n", t->count());
}

template.h

#pragma once
#include <stdio.h>
#include <map>
#include <string>
#include <windows.h>

using namespace std;

template <class T>
class test
{
public:
	test() = default;

	int add(T *ptr)
	{
		LPEXCEPTION_POINTERS info = NULL;
		DWORD code;
		__try
		{
			m_map[m_count] = ptr;
			return m_count++;
		}
		__except (code = GetExceptionCode(), info = GetExceptionInformation(), EXCEPTION_EXECUTE_HANDLER)
		{

			printf("Exception happene code: 0x%x, %d\n", code, info->ExceptionRecord->ExceptionInformation[1]);
			//info->ExceptionRecord->ExceptionInformation
			exit(0);
		}

	}

	int count()
	{
		return m_count;
	}

private:
	int m_count = 0;
	map<int, T*> m_map;
};


Natice Loader.cpp

...
	if (VirtualProtect(finalShellcode, sysInfo.dwPageSize, PAGE_EXECUTE_READWRITE, &dwOldProtect1)) {
		RDI rdi = (RDI)(finalShellcode);
		printf("[+] Executing RDI\n");
		HANDLE t = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)finalShellcode, NULL, 0, NULL);
		//WaitForSingleObject(t, INFINITE);
		getchar();
		free(finalShellcode); // Free the RDI blob. We no longer need it.
	}

when i remote inject via ProcessHacker work ok,but i use Native.exe load this dll is crash.
when i change static test<string>* t = new test<string>(); to test<string>* t = new test<string>(); in dllmain.cpp both work ok
the ptr always is NULL when i use static

this is result
ProcessHacker:

t ptr: 0xad7a0
count: 1

Native.exe Loader:

[+] File is a DLL, attempting to convert
[+] Successfully Converted
[+] Executing RDI
t ptr: 0x0
Exception happene code: 0xc0000005, 8

LoadDLL GetNativeSystemInfo fail

System environment: win7 x64

I use loaddll to convert wow64\user32 DLL loading will fail here. I don't know why,

if (alignedImageSize != AlignValueUp(lastSectionEnd, sysInfo.dwPageSize)) {
//It will return here, win10 is OK
return 0;
}

ConvertTo-Shellcode against a DLL produces shellcode that hangs execution

When running either ConvertTo-Shellcode in powershell or ConvertToShellcode(dll) in python the resulting shellcode causes the terminal to hang. This happens when executing the shellcode via Invoke-Shellcode or running the shellcode via Python's ctypes library. For reference, the dll I'm testing with is from https://github.com/CuckooEXE/PopCalc. Seems like a pretty simple dll which is written in C++. Still looking at the system calls currently, will update if I see something out of place.

'PE' does not exist in the current context error

Attempting to convert a simple DLL to shellcode, but receiving the following error. Am I doing something incorrect?

Note: DLL is 64bit

PS C:\Users\dev\Desktop\sRDI\PowerShell> Invoke-Shellcode -Shellcode (ConvertTo-Shellcode -File MessageBoxDLL.dll)
Add-Type : c:\Users\dev\AppData\Local\Temp\pn4hozhz\pn4hozhz.0.cs(65) : The name 'PE' does not exist in the current
context
c:\Users\dev\AppData\Local\Temp\pn4hozhz\pn4hozhz.0.cs(64) :
c:\Users\dev\AppData\Local\Temp\pn4hozhz\pn4hozhz.0.cs(65) : >>>         if (PE.Is64BitDLL(dllBytes))
c:\Users\dev\AppData\Local\Temp\pn4hozhz\pn4hozhz.0.cs(66) :         {
At C:\Users\dev\Desktop\sRDI\PowerShell\ConvertTo-Shellcode.ps1:353 char:5
+     Add-Type -TypeDefinition $Source -Language CSharp -CompilerParame ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (Microsoft.Power...peCompilerError:AddTypeCompilerError) [Add-Type], Except
   ion
    + FullyQualifiedErrorId : SOURCE_CODE_ERROR,Microsoft.PowerShell.Commands.AddTypeCommand

Two undefined names

Python 3 removed file().

flake8 testing of https://github.com/monoxgas/sRDI on Python 3.6.2

$ flake8 . --count --select=E901,E999,F821,F822,F823 --show-source --statistics

./Python/pefile.py:928:14: F821 undefined name 'exceptions'
						except exceptions.ValueError as e:
             ^
./Python/peutils.py:405:14: F821 undefined name 'file'
					sig_f = file( filename, 'rt' )
             ^

Minor issue with python

sRDI/Python$ cat bug.py
from ShellcodeRDI import *

dll = open("../testexploit.dll", 'rb').read()
shellcode = ConvertToShellcode(dll)

sRDI/Python$ python3 bug.py
Traceback (most recent call last):
  File "bug.py", line 4, in <module>
    shellcode = ConvertToShellcode(dll)
  File "sRDI/Python/ShellcodeRDI.py", line 212, in ConvertToShellcode
    return bootstrap + rdiShellcode + dllBytes + userData
TypeError: can't concat str to bytes

Fix is to change:
https://github.com/monoxgas/sRDI/blob/master/Python/ShellcodeRDI.py#L59

    rdiShellcode32 = b"\x83\xEC......

I suspect EncodeBlobs.py already does this so I didn't send a pull request.
Great project!

SRDI_CLEARMEMORY bug or missing feature?

I am trying to use the SRDI_CLEARMEMORY flag, but I am having a couple of issues. First, if I try running the shellcode generated using the PIC code of ShellcodeRDI.c I don't get any call to VirtualFree and it seems that there is no visible effect on the allocated memory.
After reading the ShellcodeRDI.c, the code responsible for the memory cleaning looks like is the following:

if (flags & SRDI_CLEARMEMORY && pVirtualFree && pLocalFree) {
		if (!pVirtualFree((LPVOID)dllData, 0, 0x00008000))
		{
			pLocalFree((LPVOID)dllData);
		}
		
	}

However, it looks to me that pVirtualFree and pLocalFree are initialised but no value is assigned to them?
I tried modifying the code myself and added the following at line ~ 260 of ShellcodeRDI.c:

BYTE sLocalFree[] = { 'L', 'o', 'c', 'a', 'l', 'F', 'r', 'e', 'e' };
BYTE sVirtualFree[] = { 'V', 'i', 'r', 't', 'u', 'a', 'l', 'F', 'r', 'e', 'e' };

FILL_STRING_WITH_BUF(aString, sLocalFree);
pLdrGetProcAddress(library, &aString, 0, (PVOID*)&pLocalFree);

FILL_STRING_WITH_BUF(aString, sVirtualFree);
pLdrGetProcAddress(library, &aString, 0, (PVOID*)&pVirtualFree);

Now, if I debug the program with something like x64dbg, I can see the invocation to VirtualFree but the following error is returned:

image

LocalFree fails as well with this:

image

The program I used to inject the sRDI shellcode is the DotNet loader in the main repository, where the ConvertToShellcode function is called with the 0x2 flag.

Am I doing something wrong here (except for spending my Sunday reading C code)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.