Skip to content

Instantly share code, notes, and snippets.

@TetteDev
Created July 4, 2021 07:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save TetteDev/a53b283dee7a11457f8216412aa7a176 to your computer and use it in GitHub Desktop.
Save TetteDev/a53b283dee7a11457f8216412aa7a176 to your computer and use it in GitHub Desktop.
Unlinking Module from PEB with c# (64bit tested only)
public unsafe static bool UnlinkModuleFromPeb(IntPtr hModule)
{
if (hModule == IntPtr.Zero) return false;
PEB* peb = Get_PEB();
if (peb == null) return false;
LIST_ENTRY* CurrentEntry = peb->Ldr->InLoadOrderModuleList.Flink;
Debug.Assert(CurrentEntry != null);
LDR_DATA_TABLE_ENTRY* Current = null;
//var RtlRbRemoveNode = (delegate* unmanaged[Stdcall]<RTL_RB_TREE* , RTL_BALANCED_NODE*, uint /* NTSTATUS */>)GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlRbRemoveNode");
//Debug.Assert(RtlRbRemoveNode != null);
//RTL_RB_TREE* start = null;
while (CurrentEntry != &peb->Ldr->InLoadOrderModuleList && CurrentEntry != null)
{
Current = CONTAINING_RECORD<LDR_DATA_TABLE_ENTRY>(CurrentEntry, "InLoadOrderLinks");
Debug.Assert(Current != null);
//if (start == null) start = (RTL_RB_TREE*)&Current->BaseAddressIndexNode;
if (Current->DllBase == hModule.ToPointer())
{
if (!Current->InLoadOrderLinks.Equals(default(LIST_ENTRY)))
UNLINK(Current->InLoadOrderLinks);
if (!Current->InInitializationOrderLinks.Equals(default(LIST_ENTRY)))
UNLINK(Current->InInitializationOrderLinks);
if (!Current->InMemoryOrderLinks.Equals(default(LIST_ENTRY)))
UNLINK(Current->InMemoryOrderLinks);
if (!Current->HashLinks.Equals(default(LIST_ENTRY)))
UNLINK(Current->HashLinks);
// Fuck some red black trees up here
//var ntstatus = RtlRbRemoveNode(start, (RTL_BALANCED_NODE*)&Current->BaseAddressIndexNode);
return true;
}
CurrentEntry = CurrentEntry->Flink;
Debug.Assert(CurrentEntry != null);
}
return false;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe static void UNLINK(LIST_ENTRY x)
{
x.Flink->Blink = x.Blink;
x.Blink->Flink = x.Flink;
}
public unsafe static PEB* Get_PEB()
{
byte[] asm = Environment.Is64BitProcess ? new byte[]
{
0x65, 0x48, 0xA1, 0x60, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xC3,
} : new byte[]
{
0x64, 0xa1, 0x30, 0x00, 0x00, 0x00,
0xC3,
};
// yup, im going to hell
fixed (void* p = asm)
{
VirtualProtect((IntPtr)p, (UIntPtr)asm.Length, MemoryProtection.ExecuteReadWrite, out var old);
var ret = ((delegate* unmanaged[Stdcall]<PEB*>)p)();
VirtualProtect((IntPtr)p, (UIntPtr)asm.Length, old, out _);
return ret;
}
}
private unsafe static OUT_TYPE* CONTAINING_RECORD<OUT_TYPE>(void* address, string fieldName)
where OUT_TYPE : unmanaged
{
if (string.IsNullOrEmpty(fieldName)) return null;
return (OUT_TYPE*)IntPtr.Subtract((IntPtr)address, Marshal.OffsetOf<OUT_TYPE>(fieldName).ToInt32());
}
[StructLayout(LayoutKind.Explicit)]
public unsafe struct PEB
{
[FieldOffset(0x2)]
public byte BeingDebugged;
#if WIN64
[FieldOffset(0x18)]
public PEB_LDR_DATA* Ldr;
[FieldOffset(0xbc)]
public uint NtGlobalFlag;
[FieldOffset(0x7c4)]
public uint NtGlobalFlag2;
#else
[FieldOffset(0x0C)]
public PEB_LDR_DATA* Ldr;
#endif
}
public unsafe struct LIST_ENTRY
{
public LIST_ENTRY* Flink;
public LIST_ENTRY* Blink;
}
[StructLayout(LayoutKind.Explicit)]
public unsafe struct LDR_DATA_TABLE_ENTRY
{
#if WIN64
[FieldOffset(0x00)]
public LIST_ENTRY InLoadOrderLinks;
[FieldOffset(0x10)]
public LIST_ENTRY InMemoryOrderLinks;
[FieldOffset(0x20)]
public LIST_ENTRY InInitializationOrderLinks;
[FieldOffset(0x30)]
public void* DllBase;
[FieldOffset(0x70)]
public LIST_ENTRY HashLinks;
[FieldOffset(0x68)]
public RTL_BALANCED_NODE BaseAddressIndexNode;
#else
[FieldOffset(0x00)]
public LIST_ENTRY InLoadOrderLinks;
[FieldOffset(0x08)]
public LIST_ENTRY InMemoryOrderLinks;
[FieldOffset(0x10)]
public LIST_ENTRY InInitializationOrderLinks;
[FieldOffset(0x18)]
public void* DllBase;
[FieldOffset(0x3C)]
public LIST_ENTRY HashLinks;
[FieldOffset(0x68)]
public RTL_BALANCED_NODE BaseAddressIndexNode;
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment