Created
July 4, 2021 07:31
-
-
Save TetteDev/a53b283dee7a11457f8216412aa7a176 to your computer and use it in GitHub Desktop.
Unlinking Module from PEB with c# (64bit tested only)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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