mirror of
https://github.com/monoxgas/sRDI
synced 2026-06-06 16:14:36 +00:00
Add support for passing the shellcode base address to the module export
Some cleanup and additional notes to the README
This commit is contained in:
+28
-20
File diff suppressed because one or more lines are too long
+30
-19
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -10,10 +10,11 @@ def main():
|
||||
parser.add_argument('-f', '--function-name', dest='function_name', help='The function to call after DllMain', default='SayHello')
|
||||
parser.add_argument('-u', '--user-data', dest='user_data', help='Data to pass to the target function', default='dave')
|
||||
parser.add_argument('-c', '--clear-header', dest='clear_header', action='store_true', help='Clear the PE header on load')
|
||||
parser.add_argument('-b', '--pass-shellcode-base', dest='pass_shellcode_base', action='store_true', help='Pass shellcode base address to exported function')
|
||||
parser.add_argument('-i', '--obfuscate-imports', dest='obfuscate_imports', action='store_true', help='Randomize import dependency load order', default=False)
|
||||
parser.add_argument('-d', '--import-delay', dest='import_delay', help='Number of seconds to pause between loading imports', type=int, default=0)
|
||||
parser.add_argument('-of', '--output-format', dest='output_format', help='Output format of the shellcode (e.g. raw,string)', type=str, default="raw")
|
||||
|
||||
|
||||
arguments = parser.parse_args()
|
||||
|
||||
input_dll = arguments.input_dll
|
||||
@@ -29,13 +30,16 @@ def main():
|
||||
if arguments.obfuscate_imports:
|
||||
flags = flags | 0x4 | arguments.import_delay << 16
|
||||
|
||||
if arguments.pass_shellcode_base:
|
||||
flags |= 0x8
|
||||
|
||||
converted_dll = ConvertToShellcode(dll, HashFunctionName(arguments.function_name), arguments.user_data.encode(), flags)
|
||||
|
||||
|
||||
if arguments.output_format=="raw":
|
||||
print('Creating Shellcode: {}'.format(output_bin))
|
||||
with open(output_bin, 'wb') as f:
|
||||
f.write(converted_dll)
|
||||
|
||||
|
||||
elif arguments.output_format=="string":
|
||||
output_bin = input_dll.replace('.dll', '.txt')
|
||||
converted_dll_text ="".join([r"\x{}".format(str(format(c,'02x'))) for c in converted_dll])
|
||||
|
||||
@@ -28,11 +28,6 @@
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ConvertToShellcode.py" />
|
||||
<Compile Include="EncodeBlobs.py">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="pefile.py" />
|
||||
<Compile Include="peutils.py" />
|
||||
<Compile Include="ShellcodeRDI.py" />
|
||||
</ItemGroup>
|
||||
<!-- Uncomment the CoreCompile target to enable the Build command in
|
||||
|
||||
+25
-18
File diff suppressed because one or more lines are too long
@@ -52,7 +52,7 @@ The PE loader code uses `flags` argument to control the various options of loadi
|
||||
- `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.
|
||||
@@ -67,6 +67,27 @@ After building the project, the other binaries will be located at:
|
||||
- `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:
|
||||
|
||||
+9
-2
@@ -1,7 +1,7 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26430.16
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.31410.357
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestDLL", "TestDLL\TestDLL.vcxproj", "{558D08E4-48B4-4E5F-94E5-5783CF0557C4}"
|
||||
EndProject
|
||||
@@ -10,6 +10,10 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShellcodeRDI", "ShellcodeRDI\ShellcodeRDI.vcxproj", "{6FC09BDB-365F-4691-BBD9-CB7F69C9527A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Native", "Native\Native.vcxproj", "{68293519-3053-4AB6-921F-9690E2E1487F}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{6FC09BDB-365F-4691-BBD9-CB7F69C9527A} = {6FC09BDB-365F-4691-BBD9-CB7F69C9527A}
|
||||
{558D08E4-48B4-4E5F-94E5-5783CF0557C4} = {558D08E4-48B4-4E5F-94E5-5783CF0557C4}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{888888A0-9F3D-457C-B088-3A5042F75D52}") = "Python", "Python\Python.pyproj", "{BE642266-F34D-43C3-B6E4-EEBF8E489519}"
|
||||
EndProject
|
||||
@@ -78,4 +82,7 @@ Global
|
||||
{68293519-3053-4AB6-921F-9690E2E1487F} = {F602BD8E-D2C2-4B04-85C6-292388CF1D83}
|
||||
{BE642266-F34D-43C3-B6E4-EEBF8E489519} = {F602BD8E-D2C2-4B04-85C6-292388CF1D83}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {3C9908F0-8E60-451C-B039-CE1FD3FFB06A}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
+25
-16
@@ -11,6 +11,7 @@
|
||||
#define SRDI_CLEARHEADER 0x1
|
||||
#define SRDI_CLEARMEMORY 0x2
|
||||
#define SRDI_OBFUSCATEIMPORTS 0x4
|
||||
#define SRDI_PASS_SHELLCODE_BASE 0x8
|
||||
|
||||
#define DEREF( name )*(UINT_PTR *)(name)
|
||||
#define DEREF_64( name )*(DWORD64 *)(name)
|
||||
@@ -114,7 +115,7 @@ _wcslen(wchar_t* s) {
|
||||
string.MaximumLength = string.Length; \
|
||||
string.Buffer = (PCHAR)buffer
|
||||
|
||||
ULONG_PTR LoadDLL(PBYTE dllData, DWORD dwFunctionHash, LPVOID lpUserData, DWORD nUserdataLen, DWORD flags)
|
||||
ULONG_PTR LoadDLL(PBYTE pbModule, DWORD dwFunctionHash, LPVOID lpUserData, DWORD dwUserdataLen, PVOID pvShellcodeBase, DWORD dwFlags)
|
||||
{
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable : 4055 ) // Ignore cast warnings
|
||||
@@ -150,7 +151,9 @@ ULONG_PTR LoadDLL(PBYTE dllData, DWORD dwFunctionHash, LPVOID lpUserData, DWORD
|
||||
PIMAGE_BASE_RELOCATION relocation;
|
||||
PIMAGE_RELOC relocList;
|
||||
PIMAGE_EXPORT_DIRECTORY exportDir;
|
||||
#ifdef _WIN64
|
||||
PIMAGE_RUNTIME_FUNCTION_ENTRY rfEntry;
|
||||
#endif
|
||||
PDWORD expName;
|
||||
PWORD expOrdinal;
|
||||
LPCSTR expNameStr;
|
||||
@@ -255,7 +258,7 @@ ULONG_PTR LoadDLL(PBYTE dllData, DWORD dwFunctionHash, LPVOID lpUserData, DWORD
|
||||
// STEP 2: load our image into a new permanent location in memory
|
||||
///
|
||||
|
||||
ntHeaders = RVA(PIMAGE_NT_HEADERS, dllData, ((PIMAGE_DOS_HEADER)dllData)->e_lfanew);
|
||||
ntHeaders = RVA(PIMAGE_NT_HEADERS, pbModule, ((PIMAGE_DOS_HEADER)pbModule)->e_lfanew);
|
||||
|
||||
// Perform sanity checks on the image (Stolen from https://github.com/fancycode/MemoryModule/blob/master/MemoryModule.c)
|
||||
|
||||
@@ -310,16 +313,16 @@ ULONG_PTR LoadDLL(PBYTE dllData, DWORD dwFunctionHash, LPVOID lpUserData, DWORD
|
||||
|
||||
// Copy over the headers
|
||||
|
||||
if (flags & SRDI_CLEARHEADER) {
|
||||
((PIMAGE_DOS_HEADER)baseAddress)->e_lfanew = ((PIMAGE_DOS_HEADER)dllData)->e_lfanew;
|
||||
if (dwFlags & SRDI_CLEARHEADER) {
|
||||
((PIMAGE_DOS_HEADER)baseAddress)->e_lfanew = ((PIMAGE_DOS_HEADER)pbModule)->e_lfanew;
|
||||
|
||||
for (i = ((PIMAGE_DOS_HEADER)dllData)->e_lfanew; i < ntHeaders->OptionalHeader.SizeOfHeaders; i++) {
|
||||
((PBYTE)baseAddress)[i] = ((PBYTE)dllData)[i];
|
||||
for (i = ((PIMAGE_DOS_HEADER)pbModule)->e_lfanew; i < ntHeaders->OptionalHeader.SizeOfHeaders; i++) {
|
||||
((PBYTE)baseAddress)[i] = ((PBYTE)pbModule)[i];
|
||||
}
|
||||
|
||||
}else{
|
||||
for (i = 0; i < ntHeaders->OptionalHeader.SizeOfHeaders; i++) {
|
||||
((PBYTE)baseAddress)[i] = ((PBYTE)dllData)[i];
|
||||
((PBYTE)baseAddress)[i] = ((PBYTE)pbModule)[i];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -333,7 +336,7 @@ ULONG_PTR LoadDLL(PBYTE dllData, DWORD dwFunctionHash, LPVOID lpUserData, DWORD
|
||||
|
||||
for (i = 0; i < ntHeaders->FileHeader.NumberOfSections; i++, sectionHeader++) {
|
||||
for (c = 0; c < sectionHeader->SizeOfRawData; c++) {
|
||||
((PBYTE)(baseAddress + sectionHeader->VirtualAddress))[c] = ((PBYTE)(dllData + sectionHeader->PointerToRawData))[c];
|
||||
((PBYTE)(baseAddress + sectionHeader->VirtualAddress))[c] = ((PBYTE)(pbModule + sectionHeader->PointerToRawData))[c];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,7 +376,7 @@ ULONG_PTR LoadDLL(PBYTE dllData, DWORD dwFunctionHash, LPVOID lpUserData, DWORD
|
||||
///
|
||||
|
||||
dataDir = &ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
|
||||
randSeed = (DWORD)((ULONGLONG)dllData);
|
||||
randSeed = (DWORD)((ULONGLONG)pbModule);
|
||||
|
||||
if (dataDir->Size) {
|
||||
|
||||
@@ -384,8 +387,8 @@ ULONG_PTR LoadDLL(PBYTE dllData, DWORD dwFunctionHash, LPVOID lpUserData, DWORD
|
||||
}
|
||||
|
||||
importDesc = RVA(PIMAGE_IMPORT_DESCRIPTOR, baseAddress, dataDir->VirtualAddress);
|
||||
if (flags & SRDI_OBFUSCATEIMPORTS && importCount > 1) {
|
||||
sleep = (flags & 0xFFFF0000);
|
||||
if (dwFlags & SRDI_OBFUSCATEIMPORTS && importCount > 1) {
|
||||
sleep = (dwFlags & 0xFFFF0000);
|
||||
sleep = sleep >> 16;
|
||||
|
||||
for (i = 0; i < importCount - 1; i++) {
|
||||
@@ -419,7 +422,7 @@ ULONG_PTR LoadDLL(PBYTE dllData, DWORD dwFunctionHash, LPVOID lpUserData, DWORD
|
||||
}
|
||||
}
|
||||
|
||||
if (flags & SRDI_OBFUSCATEIMPORTS && importCount > 1) {
|
||||
if (sleep & dwFlags & SRDI_OBFUSCATEIMPORTS && importCount > 1) {
|
||||
pSleep(sleep * 1000);
|
||||
}
|
||||
}
|
||||
@@ -577,16 +580,22 @@ ULONG_PTR LoadDLL(PBYTE dllData, DWORD dwFunctionHash, LPVOID lpUserData, DWORD
|
||||
if (dwFunctionHash == funcHash && expOrdinal)
|
||||
{
|
||||
exportFunc = RVA(EXPORTFUNC, baseAddress, *(PDWORD)(baseAddress + exportDir->AddressOfFunctions + (*expOrdinal * 4)));
|
||||
exportFunc(lpUserData, nUserdataLen);
|
||||
|
||||
if (dwFlags & SRDI_PASS_SHELLCODE_BASE) {
|
||||
exportFunc(pvShellcodeBase, sizeof(PVOID));
|
||||
} else {
|
||||
exportFunc(lpUserData, dwUserdataLen);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (0);
|
||||
}
|
||||
|
||||
if (flags & SRDI_CLEARMEMORY && pVirtualFree && pLocalFree) {
|
||||
if (!pVirtualFree((LPVOID)dllData, 0, 0x8000))
|
||||
pLocalFree((LPVOID)dllData);
|
||||
if (dwFlags & SRDI_CLEARMEMORY && pVirtualFree && pLocalFree) {
|
||||
if (!pVirtualFree((LPVOID)pbModule, 0, 0x8000))
|
||||
pLocalFree((LPVOID)pbModule);
|
||||
}
|
||||
|
||||
// Atempt to return a handle to the module
|
||||
|
||||
Reference in New Issue
Block a user