diff --git a/README.md b/README.md index 8e2e218..f43758c 100644 --- a/README.md +++ b/README.md @@ -529,6 +529,12 @@ last_visit_time : 22/09/2020 12:04:07 [...Snipped...] ``` +### Reprobate + +Reprobate consists of two `cs` files which contain all of the [DynamicInvoke](https://thewover.github.io/Dynamic-Invoke/) functionality and are meant to be plug-and-play for your C# projects. This can be preferable to using a nuget package or whole-sale including [SharpSploit](https://github.com/cobbr/SharpSploit). Eventually I will integrate bubble-sort Syscall ID identification as well to avoid manual ntdll mapping/enumeration. + +For further details check out => [BlueHatIL 2020: Staying # and Bringing Covert Injection Tradecraft to .NET](https://github.com/FuzzySecurity/BlueHatIL-2020) + ## Windows API ### GetAPISetMapping diff --git a/Reprobate/h_reprobate.cs b/Reprobate/h_reprobate.cs new file mode 100644 index 0000000..37e9a20 --- /dev/null +++ b/Reprobate/h_reprobate.cs @@ -0,0 +1,2726 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace YourProjectHere +{ + class h_reprobate + { + [StructLayout(LayoutKind.Sequential)] + public struct UNICODE_STRING + { + public UInt16 Length; + public UInt16 MaximumLength; + public IntPtr Buffer; + } + + [StructLayout(LayoutKind.Sequential)] + public struct ANSI_STRING + { + public UInt16 Length; + public UInt16 MaximumLength; + public IntPtr Buffer; + } + + public struct PROCESS_BASIC_INFORMATION + { + public IntPtr ExitStatus; + public IntPtr PebBaseAddress; + public IntPtr AffinityMask; + public IntPtr BasePriority; + public UIntPtr UniqueProcessId; + public int InheritedFromUniqueProcessId; + + public int Size + { + get { return (int)Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)); } + } + } + + [StructLayout(LayoutKind.Sequential, Pack = 0)] + public struct OBJECT_ATTRIBUTES + { + public Int32 Length; + public IntPtr RootDirectory; + public IntPtr ObjectName; // -> UNICODE_STRING + public uint Attributes; + public IntPtr SecurityDescriptor; + public IntPtr SecurityQualityOfService; + } + + [StructLayout(LayoutKind.Sequential)] + public struct IO_STATUS_BLOCK + { + public IntPtr Status; + public IntPtr Information; + } + + [StructLayout(LayoutKind.Sequential)] + public struct CLIENT_ID + { + public IntPtr UniqueProcess; + public IntPtr UniqueThread; + } + + [StructLayout(LayoutKind.Sequential)] + public struct OSVERSIONINFOEX + { + public uint OSVersionInfoSize; + public uint MajorVersion; + public uint MinorVersion; + public uint BuildNumber; + public uint PlatformId; + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string CSDVersion; + public ushort ServicePackMajor; + public ushort ServicePackMinor; + public ushort SuiteMask; + public byte ProductType; + public byte Reserved; + } + + [StructLayout(LayoutKind.Sequential)] + public struct LIST_ENTRY + { + public IntPtr Flink; + public IntPtr Blink; + } + + public enum MEMORYINFOCLASS : int + { + MemoryBasicInformation = 0, + MemoryWorkingSetList, + MemorySectionName, + MemoryBasicVlmInformation + } + + public enum PROCESSINFOCLASS : int + { + ProcessBasicInformation = 0, // 0, q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION + ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX + ProcessIoCounters, // q: IO_COUNTERS + ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX + ProcessTimes, // q: KERNEL_USER_TIMES + ProcessBasePriority, // s: KPRIORITY + ProcessRaisePriority, // s: ULONG + ProcessDebugPort, // q: HANDLE + ProcessExceptionPort, // s: HANDLE + ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN + ProcessLdtInformation, // 10 + ProcessLdtSize, + ProcessDefaultHardErrorMode, // qs: ULONG + ProcessIoPortHandlers, // (kernel-mode only) + ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS + ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void + ProcessUserModeIOPL, + ProcessEnableAlignmentFaultFixup, // s: BOOLEAN + ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS + ProcessWx86Information, + ProcessHandleCount, // 20, q: ULONG, PROCESS_HANDLE_INFORMATION + ProcessAffinityMask, // s: KAFFINITY + ProcessPriorityBoost, // qs: ULONG + ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX + ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION + ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND + ProcessWow64Information, // q: ULONG_PTR + ProcessImageFileName, // q: UNICODE_STRING + ProcessLUIDDeviceMapsEnabled, // q: ULONG + ProcessBreakOnTermination, // qs: ULONG + ProcessDebugObjectHandle, // 30, q: HANDLE + ProcessDebugFlags, // qs: ULONG + ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables + ProcessIoPriority, // qs: ULONG + ProcessExecuteFlags, // qs: ULONG + ProcessResourceManagement, + ProcessCookie, // q: ULONG + ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION + ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION + ProcessPagePriority, // q: ULONG + ProcessInstrumentationCallback, // 40 + ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX + ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[] + ProcessImageFileNameWin32, // q: UNICODE_STRING + ProcessImageFileMapping, // q: HANDLE (input) + ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE + ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE + ProcessGroupInformation, // q: USHORT[] + ProcessTokenVirtualizationEnabled, // s: ULONG + ProcessConsoleHostProcess, // q: ULONG_PTR + ProcessWindowInformation, // 50, q: PROCESS_WINDOW_INFORMATION + ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 + ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION + ProcessDynamicFunctionTableInformation, + ProcessHandleCheckingMode, + ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION + ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION + MaxProcessInfoClass + }; + + /// + /// NT_CREATION_FLAGS is an undocumented enum. https://processhacker.sourceforge.io/doc/ntpsapi_8h_source.html + /// + public enum NT_CREATION_FLAGS : ulong + { + CREATE_SUSPENDED = 0x00000001, + SKIP_THREAD_ATTACH = 0x00000002, + HIDE_FROM_DEBUGGER = 0x00000004, + HAS_SECURITY_DESCRIPTOR = 0x00000010, + ACCESS_CHECK_IN_TARGET = 0x00000020, + INITIAL_THREAD = 0x00000080 + } + + /// + /// NTSTATUS is an undocument enum. https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55 + /// https://www.pinvoke.net/default.aspx/Enums/NtStatus.html + /// + public enum NTSTATUS : uint + { + // Success + Success = 0x00000000, + Wait0 = 0x00000000, + Wait1 = 0x00000001, + Wait2 = 0x00000002, + Wait3 = 0x00000003, + Wait63 = 0x0000003f, + Abandoned = 0x00000080, + AbandonedWait0 = 0x00000080, + AbandonedWait1 = 0x00000081, + AbandonedWait2 = 0x00000082, + AbandonedWait3 = 0x00000083, + AbandonedWait63 = 0x000000bf, + UserApc = 0x000000c0, + KernelApc = 0x00000100, + Alerted = 0x00000101, + Timeout = 0x00000102, + Pending = 0x00000103, + Reparse = 0x00000104, + MoreEntries = 0x00000105, + NotAllAssigned = 0x00000106, + SomeNotMapped = 0x00000107, + OpLockBreakInProgress = 0x00000108, + VolumeMounted = 0x00000109, + RxActCommitted = 0x0000010a, + NotifyCleanup = 0x0000010b, + NotifyEnumDir = 0x0000010c, + NoQuotasForAccount = 0x0000010d, + PrimaryTransportConnectFailed = 0x0000010e, + PageFaultTransition = 0x00000110, + PageFaultDemandZero = 0x00000111, + PageFaultCopyOnWrite = 0x00000112, + PageFaultGuardPage = 0x00000113, + PageFaultPagingFile = 0x00000114, + CrashDump = 0x00000116, + ReparseObject = 0x00000118, + NothingToTerminate = 0x00000122, + ProcessNotInJob = 0x00000123, + ProcessInJob = 0x00000124, + ProcessCloned = 0x00000129, + FileLockedWithOnlyReaders = 0x0000012a, + FileLockedWithWriters = 0x0000012b, + + // Informational + Informational = 0x40000000, + ObjectNameExists = 0x40000000, + ThreadWasSuspended = 0x40000001, + WorkingSetLimitRange = 0x40000002, + ImageNotAtBase = 0x40000003, + RegistryRecovered = 0x40000009, + + // Warning + Warning = 0x80000000, + GuardPageViolation = 0x80000001, + DatatypeMisalignment = 0x80000002, + Breakpoint = 0x80000003, + SingleStep = 0x80000004, + BufferOverflow = 0x80000005, + NoMoreFiles = 0x80000006, + HandlesClosed = 0x8000000a, + PartialCopy = 0x8000000d, + DeviceBusy = 0x80000011, + InvalidEaName = 0x80000013, + EaListInconsistent = 0x80000014, + NoMoreEntries = 0x8000001a, + LongJump = 0x80000026, + DllMightBeInsecure = 0x8000002b, + + // Error + Error = 0xc0000000, + Unsuccessful = 0xc0000001, + NotImplemented = 0xc0000002, + InvalidInfoClass = 0xc0000003, + InfoLengthMismatch = 0xc0000004, + AccessViolation = 0xc0000005, + InPageError = 0xc0000006, + PagefileQuota = 0xc0000007, + InvalidHandle = 0xc0000008, + BadInitialStack = 0xc0000009, + BadInitialPc = 0xc000000a, + InvalidCid = 0xc000000b, + TimerNotCanceled = 0xc000000c, + InvalidParameter = 0xc000000d, + NoSuchDevice = 0xc000000e, + NoSuchFile = 0xc000000f, + InvalidDeviceRequest = 0xc0000010, + EndOfFile = 0xc0000011, + WrongVolume = 0xc0000012, + NoMediaInDevice = 0xc0000013, + NoMemory = 0xc0000017, + ConflictingAddresses = 0xc0000018, + NotMappedView = 0xc0000019, + UnableToFreeVm = 0xc000001a, + UnableToDeleteSection = 0xc000001b, + IllegalInstruction = 0xc000001d, + AlreadyCommitted = 0xc0000021, + AccessDenied = 0xc0000022, + BufferTooSmall = 0xc0000023, + ObjectTypeMismatch = 0xc0000024, + NonContinuableException = 0xc0000025, + BadStack = 0xc0000028, + NotLocked = 0xc000002a, + NotCommitted = 0xc000002d, + InvalidParameterMix = 0xc0000030, + ObjectNameInvalid = 0xc0000033, + ObjectNameNotFound = 0xc0000034, + ObjectNameCollision = 0xc0000035, + ObjectPathInvalid = 0xc0000039, + ObjectPathNotFound = 0xc000003a, + ObjectPathSyntaxBad = 0xc000003b, + DataOverrun = 0xc000003c, + DataLate = 0xc000003d, + DataError = 0xc000003e, + CrcError = 0xc000003f, + SectionTooBig = 0xc0000040, + PortConnectionRefused = 0xc0000041, + InvalidPortHandle = 0xc0000042, + SharingViolation = 0xc0000043, + QuotaExceeded = 0xc0000044, + InvalidPageProtection = 0xc0000045, + MutantNotOwned = 0xc0000046, + SemaphoreLimitExceeded = 0xc0000047, + PortAlreadySet = 0xc0000048, + SectionNotImage = 0xc0000049, + SuspendCountExceeded = 0xc000004a, + ThreadIsTerminating = 0xc000004b, + BadWorkingSetLimit = 0xc000004c, + IncompatibleFileMap = 0xc000004d, + SectionProtection = 0xc000004e, + EasNotSupported = 0xc000004f, + EaTooLarge = 0xc0000050, + NonExistentEaEntry = 0xc0000051, + NoEasOnFile = 0xc0000052, + EaCorruptError = 0xc0000053, + FileLockConflict = 0xc0000054, + LockNotGranted = 0xc0000055, + DeletePending = 0xc0000056, + CtlFileNotSupported = 0xc0000057, + UnknownRevision = 0xc0000058, + RevisionMismatch = 0xc0000059, + InvalidOwner = 0xc000005a, + InvalidPrimaryGroup = 0xc000005b, + NoImpersonationToken = 0xc000005c, + CantDisableMandatory = 0xc000005d, + NoLogonServers = 0xc000005e, + NoSuchLogonSession = 0xc000005f, + NoSuchPrivilege = 0xc0000060, + PrivilegeNotHeld = 0xc0000061, + InvalidAccountName = 0xc0000062, + UserExists = 0xc0000063, + NoSuchUser = 0xc0000064, + GroupExists = 0xc0000065, + NoSuchGroup = 0xc0000066, + MemberInGroup = 0xc0000067, + MemberNotInGroup = 0xc0000068, + LastAdmin = 0xc0000069, + WrongPassword = 0xc000006a, + IllFormedPassword = 0xc000006b, + PasswordRestriction = 0xc000006c, + LogonFailure = 0xc000006d, + AccountRestriction = 0xc000006e, + InvalidLogonHours = 0xc000006f, + InvalidWorkstation = 0xc0000070, + PasswordExpired = 0xc0000071, + AccountDisabled = 0xc0000072, + NoneMapped = 0xc0000073, + TooManyLuidsRequested = 0xc0000074, + LuidsExhausted = 0xc0000075, + InvalidSubAuthority = 0xc0000076, + InvalidAcl = 0xc0000077, + InvalidSid = 0xc0000078, + InvalidSecurityDescr = 0xc0000079, + ProcedureNotFound = 0xc000007a, + InvalidImageFormat = 0xc000007b, + NoToken = 0xc000007c, + BadInheritanceAcl = 0xc000007d, + RangeNotLocked = 0xc000007e, + DiskFull = 0xc000007f, + ServerDisabled = 0xc0000080, + ServerNotDisabled = 0xc0000081, + TooManyGuidsRequested = 0xc0000082, + GuidsExhausted = 0xc0000083, + InvalidIdAuthority = 0xc0000084, + AgentsExhausted = 0xc0000085, + InvalidVolumeLabel = 0xc0000086, + SectionNotExtended = 0xc0000087, + NotMappedData = 0xc0000088, + ResourceDataNotFound = 0xc0000089, + ResourceTypeNotFound = 0xc000008a, + ResourceNameNotFound = 0xc000008b, + ArrayBoundsExceeded = 0xc000008c, + FloatDenormalOperand = 0xc000008d, + FloatDivideByZero = 0xc000008e, + FloatInexactResult = 0xc000008f, + FloatInvalidOperation = 0xc0000090, + FloatOverflow = 0xc0000091, + FloatStackCheck = 0xc0000092, + FloatUnderflow = 0xc0000093, + IntegerDivideByZero = 0xc0000094, + IntegerOverflow = 0xc0000095, + PrivilegedInstruction = 0xc0000096, + TooManyPagingFiles = 0xc0000097, + FileInvalid = 0xc0000098, + InsufficientResources = 0xc000009a, + InstanceNotAvailable = 0xc00000ab, + PipeNotAvailable = 0xc00000ac, + InvalidPipeState = 0xc00000ad, + PipeBusy = 0xc00000ae, + IllegalFunction = 0xc00000af, + PipeDisconnected = 0xc00000b0, + PipeClosing = 0xc00000b1, + PipeConnected = 0xc00000b2, + PipeListening = 0xc00000b3, + InvalidReadMode = 0xc00000b4, + IoTimeout = 0xc00000b5, + FileForcedClosed = 0xc00000b6, + ProfilingNotStarted = 0xc00000b7, + ProfilingNotStopped = 0xc00000b8, + NotSameDevice = 0xc00000d4, + FileRenamed = 0xc00000d5, + CantWait = 0xc00000d8, + PipeEmpty = 0xc00000d9, + CantTerminateSelf = 0xc00000db, + InternalError = 0xc00000e5, + InvalidParameter1 = 0xc00000ef, + InvalidParameter2 = 0xc00000f0, + InvalidParameter3 = 0xc00000f1, + InvalidParameter4 = 0xc00000f2, + InvalidParameter5 = 0xc00000f3, + InvalidParameter6 = 0xc00000f4, + InvalidParameter7 = 0xc00000f5, + InvalidParameter8 = 0xc00000f6, + InvalidParameter9 = 0xc00000f7, + InvalidParameter10 = 0xc00000f8, + InvalidParameter11 = 0xc00000f9, + InvalidParameter12 = 0xc00000fa, + ProcessIsTerminating = 0xc000010a, + MappedFileSizeZero = 0xc000011e, + TooManyOpenedFiles = 0xc000011f, + Cancelled = 0xc0000120, + CannotDelete = 0xc0000121, + InvalidComputerName = 0xc0000122, + FileDeleted = 0xc0000123, + SpecialAccount = 0xc0000124, + SpecialGroup = 0xc0000125, + SpecialUser = 0xc0000126, + MembersPrimaryGroup = 0xc0000127, + FileClosed = 0xc0000128, + TooManyThreads = 0xc0000129, + ThreadNotInProcess = 0xc000012a, + TokenAlreadyInUse = 0xc000012b, + PagefileQuotaExceeded = 0xc000012c, + CommitmentLimit = 0xc000012d, + InvalidImageLeFormat = 0xc000012e, + InvalidImageNotMz = 0xc000012f, + InvalidImageProtect = 0xc0000130, + InvalidImageWin16 = 0xc0000131, + LogonServer = 0xc0000132, + DifferenceAtDc = 0xc0000133, + SynchronizationRequired = 0xc0000134, + DllNotFound = 0xc0000135, + IoPrivilegeFailed = 0xc0000137, + OrdinalNotFound = 0xc0000138, + EntryPointNotFound = 0xc0000139, + ControlCExit = 0xc000013a, + InvalidAddress = 0xc0000141, + PortNotSet = 0xc0000353, + DebuggerInactive = 0xc0000354, + CallbackBypass = 0xc0000503, + PortClosed = 0xc0000700, + MessageLost = 0xc0000701, + InvalidMessage = 0xc0000702, + RequestCanceled = 0xc0000703, + RecursiveDispatch = 0xc0000704, + LpcReceiveBufferExpected = 0xc0000705, + LpcInvalidConnectionUsage = 0xc0000706, + LpcRequestsNotAllowed = 0xc0000707, + ResourceInUse = 0xc0000708, + ProcessIsProtected = 0xc0000712, + VolumeDirty = 0xc0000806, + FileCheckedOut = 0xc0000901, + CheckOutRequired = 0xc0000902, + BadFileType = 0xc0000903, + FileTooLarge = 0xc0000904, + FormsAuthRequired = 0xc0000905, + VirusInfected = 0xc0000906, + VirusDeleted = 0xc0000907, + TransactionalConflict = 0xc0190001, + InvalidTransaction = 0xc0190002, + TransactionNotActive = 0xc0190003, + TmInitializationFailed = 0xc0190004, + RmNotActive = 0xc0190005, + RmMetadataCorrupt = 0xc0190006, + TransactionNotJoined = 0xc0190007, + DirectoryNotRm = 0xc0190008, + CouldNotResizeLog = 0xc0190009, + TransactionsUnsupportedRemote = 0xc019000a, + LogResizeInvalidSize = 0xc019000b, + RemoteFileVersionMismatch = 0xc019000c, + CrmProtocolAlreadyExists = 0xc019000f, + TransactionPropagationFailed = 0xc0190010, + CrmProtocolNotFound = 0xc0190011, + TransactionSuperiorExists = 0xc0190012, + TransactionRequestNotValid = 0xc0190013, + TransactionNotRequested = 0xc0190014, + TransactionAlreadyAborted = 0xc0190015, + TransactionAlreadyCommitted = 0xc0190016, + TransactionInvalidMarshallBuffer = 0xc0190017, + CurrentTransactionNotValid = 0xc0190018, + LogGrowthFailed = 0xc0190019, + ObjectNoLongerExists = 0xc0190021, + StreamMiniversionNotFound = 0xc0190022, + StreamMiniversionNotValid = 0xc0190023, + MiniversionInaccessibleFromSpecifiedTransaction = 0xc0190024, + CantOpenMiniversionWithModifyIntent = 0xc0190025, + CantCreateMoreStreamMiniversions = 0xc0190026, + HandleNoLongerValid = 0xc0190028, + NoTxfMetadata = 0xc0190029, + LogCorruptionDetected = 0xc0190030, + CantRecoverWithHandleOpen = 0xc0190031, + RmDisconnected = 0xc0190032, + EnlistmentNotSuperior = 0xc0190033, + RecoveryNotNeeded = 0xc0190034, + RmAlreadyStarted = 0xc0190035, + FileIdentityNotPersistent = 0xc0190036, + CantBreakTransactionalDependency = 0xc0190037, + CantCrossRmBoundary = 0xc0190038, + TxfDirNotEmpty = 0xc0190039, + IndoubtTransactionsExist = 0xc019003a, + TmVolatile = 0xc019003b, + RollbackTimerExpired = 0xc019003c, + TxfAttributeCorrupt = 0xc019003d, + EfsNotAllowedInTransaction = 0xc019003e, + TransactionalOpenNotAllowed = 0xc019003f, + TransactedMappingUnsupportedRemote = 0xc0190040, + TxfMetadataAlreadyPresent = 0xc0190041, + TransactionScopeCallbacksNotSet = 0xc0190042, + TransactionRequiredPromotion = 0xc0190043, + CannotExecuteFileInTransaction = 0xc0190044, + TransactionsNotFrozen = 0xc0190045, + + MaximumNtStatus = 0xffffffff + } + + /////////////////win32 + /// + public static class Win32 + { + public static class Kernel32 + { + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_BASE_RELOCATION + { + public uint VirtualAdress; + public uint SizeOfBlock; + } + + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_IMPORT_DESCRIPTOR + { + public uint OriginalFirstThunk; + public uint TimeDateStamp; + public uint ForwarderChain; + public uint Name; + public uint FirstThunk; + } + + public struct SYSTEM_INFO + { + public ushort wProcessorArchitecture; + public ushort wReserved; + public uint dwPageSize; + public IntPtr lpMinimumApplicationAddress; + public IntPtr lpMaximumApplicationAddress; + public UIntPtr dwActiveProcessorMask; + public uint dwNumberOfProcessors; + public uint dwProcessorType; + public uint dwAllocationGranularity; + public ushort wProcessorLevel; + public ushort wProcessorRevision; + }; + + public enum Platform + { + x86, + x64, + IA64, + Unknown + } + + [Flags] + public enum ProcessAccessFlags : UInt32 + { + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms684880%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 + PROCESS_ALL_ACCESS = 0x001F0FFF, + PROCESS_CREATE_PROCESS = 0x0080, + PROCESS_CREATE_THREAD = 0x0002, + PROCESS_DUP_HANDLE = 0x0040, + PROCESS_QUERY_INFORMATION = 0x0400, + PROCESS_QUERY_LIMITED_INFORMATION = 0x1000, + PROCESS_SET_INFORMATION = 0x0200, + PROCESS_SET_QUOTA = 0x0100, + PROCESS_SUSPEND_RESUME = 0x0800, + PROCESS_TERMINATE = 0x0001, + PROCESS_VM_OPERATION = 0x0008, + PROCESS_VM_READ = 0x0010, + PROCESS_VM_WRITE = 0x0020, + SYNCHRONIZE = 0x00100000 + } + + [Flags] + public enum FileAccessFlags : UInt32 + { + DELETE = 0x10000, + FILE_READ_DATA = 0x1, + FILE_READ_ATTRIBUTES = 0x80, + FILE_READ_EA = 0x8, + READ_CONTROL = 0x20000, + FILE_WRITE_DATA = 0x2, + FILE_WRITE_ATTRIBUTES = 0x100, + FILE_WRITE_EA = 0x10, + FILE_APPEND_DATA = 0x4, + WRITE_DAC = 0x40000, + WRITE_OWNER = 0x80000, + SYNCHRONIZE = 0x100000, + FILE_EXECUTE = 0x20 + } + + [Flags] + public enum FileShareFlags : UInt32 + { + FILE_SHARE_NONE = 0x0, + FILE_SHARE_READ = 0x1, + FILE_SHARE_WRITE = 0x2, + FILE_SHARE_DELETE = 0x4 + } + + [Flags] + public enum FileOpenFlags : UInt32 + { + FILE_DIRECTORY_FILE = 0x1, + FILE_WRITE_THROUGH = 0x2, + FILE_SEQUENTIAL_ONLY = 0x4, + FILE_NO_INTERMEDIATE_BUFFERING = 0x8, + FILE_SYNCHRONOUS_IO_ALERT = 0x10, + FILE_SYNCHRONOUS_IO_NONALERT = 0x20, + FILE_NON_DIRECTORY_FILE = 0x40, + FILE_CREATE_TREE_CONNECTION = 0x80, + FILE_COMPLETE_IF_OPLOCKED = 0x100, + FILE_NO_EA_KNOWLEDGE = 0x200, + FILE_OPEN_FOR_RECOVERY = 0x400, + FILE_RANDOM_ACCESS = 0x800, + FILE_DELETE_ON_CLOSE = 0x1000, + FILE_OPEN_BY_FILE_ID = 0x2000, + FILE_OPEN_FOR_BACKUP_INTENT = 0x4000, + FILE_NO_COMPRESSION = 0x8000 + } + + [Flags] + public enum StandardRights : uint + { + Delete = 0x00010000, + ReadControl = 0x00020000, + WriteDac = 0x00040000, + WriteOwner = 0x00080000, + Synchronize = 0x00100000, + Required = 0x000f0000, + Read = ReadControl, + Write = ReadControl, + Execute = ReadControl, + All = 0x001f0000, + + SpecificRightsAll = 0x0000ffff, + AccessSystemSecurity = 0x01000000, + MaximumAllowed = 0x02000000, + GenericRead = 0x80000000, + GenericWrite = 0x40000000, + GenericExecute = 0x20000000, + GenericAll = 0x10000000 + } + + [Flags] + public enum ThreadAccess : uint + { + Terminate = 0x0001, + SuspendResume = 0x0002, + Alert = 0x0004, + GetContext = 0x0008, + SetContext = 0x0010, + SetInformation = 0x0020, + QueryInformation = 0x0040, + SetThreadToken = 0x0080, + Impersonate = 0x0100, + DirectImpersonation = 0x0200, + SetLimitedInformation = 0x0400, + QueryLimitedInformation = 0x0800, + All = StandardRights.Required | StandardRights.Synchronize | 0x3ff + } + + [Flags] + public enum AllocationType : uint + { + Commit = 0x1000, + Reserve = 0x2000, + Decommit = 0x4000, + Release = 0x8000, + Reset = 0x80000, + Physical = 0x400000, + TopDown = 0x100000, + WriteWatch = 0x200000, + ResetUndo = 0x1000000, + LargePages = 0x20000000 + } + + [Flags] + public enum MemoryProtection : uint + { + Execute = 0x10, + ExecuteRead = 0x20, + ExecuteReadWrite = 0x40, + ExecuteWriteCopy = 0x80, + NoAccess = 0x01, + ReadOnly = 0x02, + ReadWrite = 0x04, + WriteCopy = 0x08, + GuardModifierflag = 0x100, + NoCacheModifierflag = 0x200, + WriteCombineModifierflag = 0x400 + } + + public enum PSS_CAPTURE_FLAGS : uint + { + PSS_CAPTURE_NONE = 0x00000000, + PSS_CAPTURE_VA_CLONE = 0x00000001, + PSS_CAPTURE_RESERVED_00000002 = 0x00000002, + PSS_CAPTURE_HANDLES = 0x00000004, + PSS_CAPTURE_HANDLE_NAME_INFORMATION = 0x00000008, + PSS_CAPTURE_HANDLE_BASIC_INFORMATION = 0x00000010, + PSS_CAPTURE_HANDLE_TYPE_SPECIFIC_INFORMATION = 0x00000020, + PSS_CAPTURE_HANDLE_TRACE = 0x00000040, + PSS_CAPTURE_THREADS = 0x00000080, + PSS_CAPTURE_THREAD_CONTEXT = 0x00000100, + PSS_CAPTURE_THREAD_CONTEXT_EXTENDED = 0x00000200, + PSS_CAPTURE_RESERVED_00000400 = 0x00000400, + PSS_CAPTURE_VA_SPACE = 0x00000800, + PSS_CAPTURE_VA_SPACE_SECTION_INFORMATION = 0x00001000, + PSS_CREATE_BREAKAWAY_OPTIONAL = 0x04000000, + PSS_CREATE_BREAKAWAY = 0x08000000, + PSS_CREATE_FORCE_BREAKAWAY = 0x10000000, + PSS_CREATE_USE_VM_ALLOCATIONS = 0x20000000, + PSS_CREATE_MEASURE_PERFORMANCE = 0x40000000, + PSS_CREATE_RELEASE_SECTION = 0x80000000 + } + + public enum PSS_QUERY_INFORMATION_CLASS + { + PSS_QUERY_PROCESS_INFORMATION = 0, + PSS_QUERY_VA_CLONE_INFORMATION = 1, + PSS_QUERY_AUXILIARY_PAGES_INFORMATION = 2, + PSS_QUERY_VA_SPACE_INFORMATION = 3, + PSS_QUERY_HANDLE_INFORMATION = 4, + PSS_QUERY_THREAD_INFORMATION = 5, + PSS_QUERY_HANDLE_TRACE_INFORMATION = 6, + PSS_QUERY_PERFORMANCE_COUNTERS = 7 + } + } + + public static class User32 + { + public static int WH_KEYBOARD_LL { get; } = 13; + public static int WM_KEYDOWN { get; } = 0x0100; + + public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam); + } + + public static class Netapi32 + { + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct LOCALGROUP_USERS_INFO_0 + { + [MarshalAs(UnmanagedType.LPWStr)] internal string name; + } + + [StructLayout(LayoutKind.Sequential)] + public struct LOCALGROUP_USERS_INFO_1 + { + [MarshalAs(UnmanagedType.LPWStr)] public string name; + [MarshalAs(UnmanagedType.LPWStr)] public string comment; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct LOCALGROUP_MEMBERS_INFO_2 + { + public IntPtr lgrmi2_sid; + public int lgrmi2_sidusage; + [MarshalAs(UnmanagedType.LPWStr)] public string lgrmi2_domainandname; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct WKSTA_USER_INFO_1 + { + public string wkui1_username; + public string wkui1_logon_domain; + public string wkui1_oth_domains; + public string wkui1_logon_server; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct SESSION_INFO_10 + { + public string sesi10_cname; + public string sesi10_username; + public int sesi10_time; + public int sesi10_idle_time; + } + + public enum SID_NAME_USE : UInt16 + { + SidTypeUser = 1, + SidTypeGroup = 2, + SidTypeDomain = 3, + SidTypeAlias = 4, + SidTypeWellKnownGroup = 5, + SidTypeDeletedAccount = 6, + SidTypeInvalid = 7, + SidTypeUnknown = 8, + SidTypeComputer = 9 + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct SHARE_INFO_1 + { + public string shi1_netname; + public uint shi1_type; + public string shi1_remark; + + public SHARE_INFO_1(string netname, uint type, string remark) + { + this.shi1_netname = netname; + this.shi1_type = type; + this.shi1_remark = remark; + } + } + } + + public static class Advapi32 + { + + // http://www.pinvoke.net/default.aspx/advapi32.openprocesstoken + public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000; + public const UInt32 STANDARD_RIGHTS_READ = 0x00020000; + public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001; + public const UInt32 TOKEN_DUPLICATE = 0x0002; + public const UInt32 TOKEN_IMPERSONATE = 0x0004; + public const UInt32 TOKEN_QUERY = 0x0008; + public const UInt32 TOKEN_QUERY_SOURCE = 0x0010; + public const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020; + public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040; + public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080; + public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100; + public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY); + public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY | + TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE | + TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT | + TOKEN_ADJUST_SESSIONID); + public const UInt32 TOKEN_ALT = (TOKEN_ASSIGN_PRIMARY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY); + + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682434(v=vs.85).aspx + [Flags] + public enum CREATION_FLAGS : uint + { + NONE = 0x00000000, + DEBUG_PROCESS = 0x00000001, + DEBUG_ONLY_THIS_PROCESS = 0x00000002, + CREATE_SUSPENDED = 0x00000004, + DETACHED_PROCESS = 0x00000008, + CREATE_NEW_CONSOLE = 0x00000010, + NORMAL_PRIORITY_CLASS = 0x00000020, + IDLE_PRIORITY_CLASS = 0x00000040, + HIGH_PRIORITY_CLASS = 0x00000080, + REALTIME_PRIORITY_CLASS = 0x00000100, + CREATE_NEW_PROCESS_GROUP = 0x00000200, + CREATE_UNICODE_ENVIRONMENT = 0x00000400, + CREATE_SEPARATE_WOW_VDM = 0x00000800, + CREATE_SHARED_WOW_VDM = 0x00001000, + CREATE_FORCEDOS = 0x00002000, + BELOW_NORMAL_PRIORITY_CLASS = 0x00004000, + ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000, + INHERIT_PARENT_AFFINITY = 0x00010000, + INHERIT_CALLER_PRIORITY = 0x00020000, + CREATE_PROTECTED_PROCESS = 0x00040000, + EXTENDED_STARTUPINFO_PRESENT = 0x00080000, + PROCESS_MODE_BACKGROUND_BEGIN = 0x00100000, + PROCESS_MODE_BACKGROUND_END = 0x00200000, + CREATE_BREAKAWAY_FROM_JOB = 0x01000000, + CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000, + CREATE_DEFAULT_ERROR_MODE = 0x04000000, + CREATE_NO_WINDOW = 0x08000000, + PROFILE_USER = 0x10000000, + PROFILE_KERNEL = 0x20000000, + PROFILE_SERVER = 0x40000000, + CREATE_IGNORE_SYSTEM_DEFAULT = 0x80000000 + } + + [Flags] + public enum LOGON_FLAGS + { + NONE = 0x00000000, + LOGON_WITH_PROFILE = 0x00000001, + LOGON_NETCREDENTIALS_ONLY = 0x00000002 + } + + public enum LOGON_TYPE + { + LOGON32_LOGON_INTERACTIVE = 2, + LOGON32_LOGON_NETWORK, + LOGON32_LOGON_BATCH, + LOGON32_LOGON_SERVICE, + LOGON32_LOGON_UNLOCK = 7, + LOGON32_LOGON_NETWORK_CLEARTEXT, + LOGON32_LOGON_NEW_CREDENTIALS + } + + public enum LOGON_PROVIDER + { + LOGON32_PROVIDER_DEFAULT, + LOGON32_PROVIDER_WINNT35, + LOGON32_PROVIDER_WINNT40, + LOGON32_PROVIDER_WINNT50 + } + + [Flags] + public enum SCM_ACCESS : uint + { + SC_MANAGER_CONNECT = 0x00001, + SC_MANAGER_CREATE_SERVICE = 0x00002, + SC_MANAGER_ENUMERATE_SERVICE = 0x00004, + SC_MANAGER_LOCK = 0x00008, + SC_MANAGER_QUERY_LOCK_STATUS = 0x00010, + SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00020, + + SC_MANAGER_ALL_ACCESS = ACCESS_MASK.STANDARD_RIGHTS_REQUIRED | + SC_MANAGER_CONNECT | + SC_MANAGER_CREATE_SERVICE | + SC_MANAGER_ENUMERATE_SERVICE | + SC_MANAGER_LOCK | + SC_MANAGER_QUERY_LOCK_STATUS | + SC_MANAGER_MODIFY_BOOT_CONFIG, + + GENERIC_READ = ACCESS_MASK.STANDARD_RIGHTS_READ | + SC_MANAGER_ENUMERATE_SERVICE | + SC_MANAGER_QUERY_LOCK_STATUS, + + GENERIC_WRITE = ACCESS_MASK.STANDARD_RIGHTS_WRITE | + SC_MANAGER_CREATE_SERVICE | + SC_MANAGER_MODIFY_BOOT_CONFIG, + + GENERIC_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE | + SC_MANAGER_CONNECT | SC_MANAGER_LOCK, + + GENERIC_ALL = SC_MANAGER_ALL_ACCESS, + } + + [Flags] + public enum ACCESS_MASK : uint + { + DELETE = 0x00010000, + READ_CONTROL = 0x00020000, + WRITE_DAC = 0x00040000, + WRITE_OWNER = 0x00080000, + SYNCHRONIZE = 0x00100000, + STANDARD_RIGHTS_REQUIRED = 0x000F0000, + STANDARD_RIGHTS_READ = 0x00020000, + STANDARD_RIGHTS_WRITE = 0x00020000, + STANDARD_RIGHTS_EXECUTE = 0x00020000, + STANDARD_RIGHTS_ALL = 0x001F0000, + SPECIFIC_RIGHTS_ALL = 0x0000FFFF, + ACCESS_SYSTEM_SECURITY = 0x01000000, + MAXIMUM_ALLOWED = 0x02000000, + GENERIC_READ = 0x80000000, + GENERIC_WRITE = 0x40000000, + GENERIC_EXECUTE = 0x20000000, + GENERIC_ALL = 0x10000000, + DESKTOP_READOBJECTS = 0x00000001, + DESKTOP_CREATEWINDOW = 0x00000002, + DESKTOP_CREATEMENU = 0x00000004, + DESKTOP_HOOKCONTROL = 0x00000008, + DESKTOP_JOURNALRECORD = 0x00000010, + DESKTOP_JOURNALPLAYBACK = 0x00000020, + DESKTOP_ENUMERATE = 0x00000040, + DESKTOP_WRITEOBJECTS = 0x00000080, + DESKTOP_SWITCHDESKTOP = 0x00000100, + WINSTA_ENUMDESKTOPS = 0x00000001, + WINSTA_READATTRIBUTES = 0x00000002, + WINSTA_ACCESSCLIPBOARD = 0x00000004, + WINSTA_CREATEDESKTOP = 0x00000008, + WINSTA_WRITEATTRIBUTES = 0x00000010, + WINSTA_ACCESSGLOBALATOMS = 0x00000020, + WINSTA_EXITWINDOWS = 0x00000040, + WINSTA_ENUMERATE = 0x00000100, + WINSTA_READSCREEN = 0x00000200, + WINSTA_ALL_ACCESS = 0x0000037F + } + + [Flags] + public enum SERVICE_ACCESS : uint + { + SERVICE_QUERY_CONFIG = 0x00001, + SERVICE_CHANGE_CONFIG = 0x00002, + SERVICE_QUERY_STATUS = 0x00004, + SERVICE_ENUMERATE_DEPENDENTS = 0x00008, + SERVICE_START = 0x00010, + SERVICE_STOP = 0x00020, + SERVICE_PAUSE_CONTINUE = 0x00040, + SERVICE_INTERROGATE = 0x00080, + SERVICE_USER_DEFINED_CONTROL = 0x00100, + + SERVICE_ALL_ACCESS = (ACCESS_MASK.STANDARD_RIGHTS_REQUIRED | + SERVICE_QUERY_CONFIG | + SERVICE_CHANGE_CONFIG | + SERVICE_QUERY_STATUS | + SERVICE_ENUMERATE_DEPENDENTS | + SERVICE_START | + SERVICE_STOP | + SERVICE_PAUSE_CONTINUE | + SERVICE_INTERROGATE | + SERVICE_USER_DEFINED_CONTROL), + + GENERIC_READ = ACCESS_MASK.STANDARD_RIGHTS_READ | + SERVICE_QUERY_CONFIG | + SERVICE_QUERY_STATUS | + SERVICE_INTERROGATE | + SERVICE_ENUMERATE_DEPENDENTS, + + GENERIC_WRITE = ACCESS_MASK.STANDARD_RIGHTS_WRITE | + SERVICE_CHANGE_CONFIG, + + GENERIC_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE | + SERVICE_START | + SERVICE_STOP | + SERVICE_PAUSE_CONTINUE | + SERVICE_USER_DEFINED_CONTROL, + + ACCESS_SYSTEM_SECURITY = ACCESS_MASK.ACCESS_SYSTEM_SECURITY, + DELETE = ACCESS_MASK.DELETE, + READ_CONTROL = ACCESS_MASK.READ_CONTROL, + WRITE_DAC = ACCESS_MASK.WRITE_DAC, + WRITE_OWNER = ACCESS_MASK.WRITE_OWNER, + } + + [Flags] + public enum SERVICE_TYPE : uint + { + SERVICE_KERNEL_DRIVER = 0x00000001, + SERVICE_FILE_SYSTEM_DRIVER = 0x00000002, + SERVICE_WIN32_OWN_PROCESS = 0x00000010, + SERVICE_WIN32_SHARE_PROCESS = 0x00000020, + SERVICE_INTERACTIVE_PROCESS = 0x00000100, + } + + public enum SERVICE_START : uint + { + SERVICE_BOOT_START = 0x00000000, + SERVICE_SYSTEM_START = 0x00000001, + SERVICE_AUTO_START = 0x00000002, + SERVICE_DEMAND_START = 0x00000003, + SERVICE_DISABLED = 0x00000004, + } + + public enum SERVICE_ERROR + { + SERVICE_ERROR_IGNORE = 0x00000000, + SERVICE_ERROR_NORMAL = 0x00000001, + SERVICE_ERROR_SEVERE = 0x00000002, + SERVICE_ERROR_CRITICAL = 0x00000003, + } + } + + public static class Dbghelp + { + public enum MINIDUMP_TYPE + { + MiniDumpNormal = 0x00000000, + MiniDumpWithDataSegs = 0x00000001, + MiniDumpWithFullMemory = 0x00000002, + MiniDumpWithHandleData = 0x00000004, + MiniDumpFilterMemory = 0x00000008, + MiniDumpScanMemory = 0x00000010, + MiniDumpWithUnloadedModules = 0x00000020, + MiniDumpWithIndirectlyReferencedMemory = 0x00000040, + MiniDumpFilterModulePaths = 0x00000080, + MiniDumpWithProcessThreadData = 0x00000100, + MiniDumpWithPrivateReadWriteMemory = 0x00000200, + MiniDumpWithoutOptionalData = 0x00000400, + MiniDumpWithFullMemoryInfo = 0x00000800, + MiniDumpWithThreadInfo = 0x00001000, + MiniDumpWithCodeSegs = 0x00002000, + MiniDumpWithoutAuxiliaryState = 0x00004000, + MiniDumpWithFullAuxiliaryState = 0x00008000, + MiniDumpWithPrivateWriteCopyMemory = 0x00010000, + MiniDumpIgnoreInaccessibleMemory = 0x00020000, + MiniDumpWithTokenInformation = 0x00040000, + MiniDumpWithModuleHeaders = 0x00080000, + MiniDumpFilterTriage = 0x00100000, + MiniDumpValidTypeFlags = 0x001fffff + } + + public enum MINIDUMP_CALLBACK_TYPE : uint + { + ModuleCallback, + ThreadCallback, + ThreadExCallback, + IncludeThreadCallback, + IncludeModuleCallback, + MemoryCallback, + CancelCallback, + WriteKernelMinidumpCallback, + KernelMinidumpStatusCallback, + RemoveMemoryCallback, + IncludeVmRegionCallback, + IoStartCallback, + IoWriteAllCallback, + IoFinishCallback, + ReadMemoryFailureCallback, + SecondaryFlagsCallback, + IsProcessSnapshotCallback, + VmStartCallback, + VmQueryCallback, + VmPreReadCallback, + } + + public struct MINIDUMP_CALLBACK_INFORMATION + { + public MINIDUMP_CALLBACK_ROUTINE CallbackRoutine; + public IntPtr CallbackParam; + } + + [StructLayout(LayoutKind.Explicit, Pack = 4)] + public struct MINIDUMP_CALLBACK_OUTPUT + { + [FieldOffset(0)] + public int Status; + } + + [StructLayout(LayoutKind.Explicit)] + public struct MINIDUMP_CALLBACK_INPUT + { + [FieldOffset(0)] + public uint ProcessId; + [FieldOffset(4)] + public IntPtr ProcessHandle; + [FieldOffset(12)] + public MINIDUMP_CALLBACK_TYPE CallbackType; + [FieldOffset(16)] + public int Status; + } + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + [return: MarshalAs(UnmanagedType.Bool)] + public delegate bool MINIDUMP_CALLBACK_ROUTINE( + [In] IntPtr CallbackParam, + [In] ref MINIDUMP_CALLBACK_INPUT CallbackInput, + [In, Out] ref MINIDUMP_CALLBACK_OUTPUT CallbackOutput + ); + } + + public class WinBase + { + [StructLayout(LayoutKind.Sequential)] + public struct _SYSTEM_INFO + { + public UInt16 wProcessorArchitecture; + public UInt16 wReserved; + public UInt32 dwPageSize; + public IntPtr lpMinimumApplicationAddress; + public IntPtr lpMaximumApplicationAddress; + public IntPtr dwActiveProcessorMask; + public UInt32 dwNumberOfProcessors; + public UInt32 dwProcessorType; + public UInt32 dwAllocationGranularity; + public UInt16 wProcessorLevel; + public UInt16 wProcessorRevision; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _SECURITY_ATTRIBUTES + { + UInt32 nLength; + IntPtr lpSecurityDescriptor; + Boolean bInheritHandle; + }; + } + + public class WinNT + { + public const UInt32 PAGE_NOACCESS = 0x01; + public const UInt32 PAGE_READONLY = 0x02; + public const UInt32 PAGE_READWRITE = 0x04; + public const UInt32 PAGE_WRITECOPY = 0x08; + public const UInt32 PAGE_EXECUTE = 0x10; + public const UInt32 PAGE_EXECUTE_READ = 0x20; + public const UInt32 PAGE_EXECUTE_READWRITE = 0x40; + public const UInt32 PAGE_EXECUTE_WRITECOPY = 0x80; + public const UInt32 PAGE_GUARD = 0x100; + public const UInt32 PAGE_NOCACHE = 0x200; + public const UInt32 PAGE_WRITECOMBINE = 0x400; + public const UInt32 PAGE_TARGETS_INVALID = 0x40000000; + public const UInt32 PAGE_TARGETS_NO_UPDATE = 0x40000000; + + public const UInt32 SEC_COMMIT = 0x08000000; + public const UInt32 SEC_IMAGE = 0x1000000; + public const UInt32 SEC_IMAGE_NO_EXECUTE = 0x11000000; + public const UInt32 SEC_LARGE_PAGES = 0x80000000; + public const UInt32 SEC_NOCACHE = 0x10000000; + public const UInt32 SEC_RESERVE = 0x4000000; + public const UInt32 SEC_WRITECOMBINE = 0x40000000; + + public const UInt32 SE_PRIVILEGE_ENABLED = 0x2; + public const UInt32 SE_PRIVILEGE_ENABLED_BY_DEFAULT = 0x1; + public const UInt32 SE_PRIVILEGE_REMOVED = 0x4; + public const UInt32 SE_PRIVILEGE_USED_FOR_ACCESS = 0x3; + + public const UInt64 SE_GROUP_ENABLED = 0x00000004L; + public const UInt64 SE_GROUP_ENABLED_BY_DEFAULT = 0x00000002L; + public const UInt64 SE_GROUP_INTEGRITY = 0x00000020L; + public const UInt32 SE_GROUP_INTEGRITY_32 = 0x00000020; + public const UInt64 SE_GROUP_INTEGRITY_ENABLED = 0x00000040L; + public const UInt64 SE_GROUP_LOGON_ID = 0xC0000000L; + public const UInt64 SE_GROUP_MANDATORY = 0x00000001L; + public const UInt64 SE_GROUP_OWNER = 0x00000008L; + public const UInt64 SE_GROUP_RESOURCE = 0x20000000L; + public const UInt64 SE_GROUP_USE_FOR_DENY_ONLY = 0x00000010L; + + public enum _SECURITY_IMPERSONATION_LEVEL + { + SecurityAnonymous, + SecurityIdentification, + SecurityImpersonation, + SecurityDelegation + } + + public enum TOKEN_TYPE + { + TokenPrimary = 1, + TokenImpersonation + } + + public enum _TOKEN_ELEVATION_TYPE + { + TokenElevationTypeDefault = 1, + TokenElevationTypeFull, + TokenElevationTypeLimited + } + + [StructLayout(LayoutKind.Sequential)] + public struct _MEMORY_BASIC_INFORMATION32 + { + public UInt32 BaseAddress; + public UInt32 AllocationBase; + public UInt32 AllocationProtect; + public UInt32 RegionSize; + public UInt32 State; + public UInt32 Protect; + public UInt32 Type; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _MEMORY_BASIC_INFORMATION64 + { + public UInt64 BaseAddress; + public UInt64 AllocationBase; + public UInt32 AllocationProtect; + public UInt32 __alignment1; + public UInt64 RegionSize; + public UInt32 State; + public UInt32 Protect; + public UInt32 Type; + public UInt32 __alignment2; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _LUID_AND_ATTRIBUTES + { + public _LUID Luid; + public UInt32 Attributes; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _LUID + { + public UInt32 LowPart; + public UInt32 HighPart; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _TOKEN_STATISTICS + { + public _LUID TokenId; + public _LUID AuthenticationId; + public UInt64 ExpirationTime; + public TOKEN_TYPE TokenType; + public _SECURITY_IMPERSONATION_LEVEL ImpersonationLevel; + public UInt32 DynamicCharged; + public UInt32 DynamicAvailable; + public UInt32 GroupCount; + public UInt32 PrivilegeCount; + public _LUID ModifiedId; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _TOKEN_PRIVILEGES + { + public UInt32 PrivilegeCount; + public _LUID_AND_ATTRIBUTES Privileges; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _TOKEN_MANDATORY_LABEL + { + public _SID_AND_ATTRIBUTES Label; + } + + public struct _SID + { + public byte Revision; + public byte SubAuthorityCount; + public WinNT._SID_IDENTIFIER_AUTHORITY IdentifierAuthority; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + public ulong[] SubAuthority; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _SID_IDENTIFIER_AUTHORITY + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6, ArraySubType = UnmanagedType.I1)] + public byte[] Value; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _SID_AND_ATTRIBUTES + { + public IntPtr Sid; + public UInt32 Attributes; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _PRIVILEGE_SET + { + public UInt32 PrivilegeCount; + public UInt32 Control; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] + public _LUID_AND_ATTRIBUTES[] Privilege; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _TOKEN_USER + { + public _SID_AND_ATTRIBUTES User; + } + + public enum _SID_NAME_USE + { + SidTypeUser = 1, + SidTypeGroup, + SidTypeDomain, + SidTypeAlias, + SidTypeWellKnownGroup, + SidTypeDeletedAccount, + SidTypeInvalid, + SidTypeUnknown, + SidTypeComputer, + SidTypeLabel + } + + public enum _TOKEN_INFORMATION_CLASS + { + TokenUser = 1, + TokenGroups, + TokenPrivileges, + TokenOwner, + TokenPrimaryGroup, + TokenDefaultDacl, + TokenSource, + TokenType, + TokenImpersonationLevel, + TokenStatistics, + TokenRestrictedSids, + TokenSessionId, + TokenGroupsAndPrivileges, + TokenSessionReference, + TokenSandBoxInert, + TokenAuditPolicy, + TokenOrigin, + TokenElevationType, + TokenLinkedToken, + TokenElevation, + TokenHasRestrictions, + TokenAccessInformation, + TokenVirtualizationAllowed, + TokenVirtualizationEnabled, + TokenIntegrityLevel, + TokenUIAccess, + TokenMandatoryPolicy, + TokenLogonSid, + TokenIsAppContainer, + TokenCapabilities, + TokenAppContainerSid, + TokenAppContainerNumber, + TokenUserClaimAttributes, + TokenDeviceClaimAttributes, + TokenRestrictedUserClaimAttributes, + TokenRestrictedDeviceClaimAttributes, + TokenDeviceGroups, + TokenRestrictedDeviceGroups, + TokenSecurityAttributes, + TokenIsRestricted, + MaxTokenInfoClass + } + + // http://www.pinvoke.net/default.aspx/Enums.ACCESS_MASK + [Flags] + public enum ACCESS_MASK : uint + { + DELETE = 0x00010000, + READ_CONTROL = 0x00020000, + WRITE_DAC = 0x00040000, + WRITE_OWNER = 0x00080000, + SYNCHRONIZE = 0x00100000, + STANDARD_RIGHTS_REQUIRED = 0x000F0000, + STANDARD_RIGHTS_READ = 0x00020000, + STANDARD_RIGHTS_WRITE = 0x00020000, + STANDARD_RIGHTS_EXECUTE = 0x00020000, + STANDARD_RIGHTS_ALL = 0x001F0000, + SPECIFIC_RIGHTS_ALL = 0x0000FFF, + ACCESS_SYSTEM_SECURITY = 0x01000000, + MAXIMUM_ALLOWED = 0x02000000, + GENERIC_READ = 0x80000000, + GENERIC_WRITE = 0x40000000, + GENERIC_EXECUTE = 0x20000000, + GENERIC_ALL = 0x10000000, + DESKTOP_READOBJECTS = 0x00000001, + DESKTOP_CREATEWINDOW = 0x00000002, + DESKTOP_CREATEMENU = 0x00000004, + DESKTOP_HOOKCONTROL = 0x00000008, + DESKTOP_JOURNALRECORD = 0x00000010, + DESKTOP_JOURNALPLAYBACK = 0x00000020, + DESKTOP_ENUMERATE = 0x00000040, + DESKTOP_WRITEOBJECTS = 0x00000080, + DESKTOP_SWITCHDESKTOP = 0x00000100, + WINSTA_ENUMDESKTOPS = 0x00000001, + WINSTA_READATTRIBUTES = 0x00000002, + WINSTA_ACCESSCLIPBOARD = 0x00000004, + WINSTA_CREATEDESKTOP = 0x00000008, + WINSTA_WRITEATTRIBUTES = 0x00000010, + WINSTA_ACCESSGLOBALATOMS = 0x00000020, + WINSTA_EXITWINDOWS = 0x00000040, + WINSTA_ENUMERATE = 0x00000100, + WINSTA_READSCREEN = 0x00000200, + WINSTA_ALL_ACCESS = 0x0000037F, + + SECTION_ALL_ACCESS = 0x10000000, + SECTION_QUERY = 0x0001, + SECTION_MAP_WRITE = 0x0002, + SECTION_MAP_READ = 0x0004, + SECTION_MAP_EXECUTE = 0x0008, + SECTION_EXTEND_SIZE = 0x0010 + }; + } + + public class ProcessThreadsAPI + { + [Flags] + internal enum STARTF : uint + { + STARTF_USESHOWWINDOW = 0x00000001, + STARTF_USESIZE = 0x00000002, + STARTF_USEPOSITION = 0x00000004, + STARTF_USECOUNTCHARS = 0x00000008, + STARTF_USEFILLATTRIBUTE = 0x00000010, + STARTF_RUNFULLSCREEN = 0x00000020, + STARTF_FORCEONFEEDBACK = 0x00000040, + STARTF_FORCEOFFFEEDBACK = 0x00000080, + STARTF_USESTDHANDLES = 0x00000100, + } + + // https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + public struct _STARTUPINFO + { + public UInt32 cb; + public String lpReserved; + public String lpDesktop; + public String lpTitle; + public UInt32 dwX; + public UInt32 dwY; + public UInt32 dwXSize; + public UInt32 dwYSize; + public UInt32 dwXCountChars; + public UInt32 dwYCountChars; + public UInt32 dwFillAttribute; + public UInt32 dwFlags; + public UInt16 wShowWindow; + public UInt16 cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + }; + + //https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + public struct _STARTUPINFOEX + { + _STARTUPINFO StartupInfo; + // PPROC_THREAD_ATTRIBUTE_LIST lpAttributeList; + }; + + //https://msdn.microsoft.com/en-us/library/windows/desktop/ms684873(v=vs.85).aspx + [StructLayout(LayoutKind.Sequential)] + public struct _PROCESS_INFORMATION + { + public IntPtr hProcess; + public IntPtr hThread; + public UInt32 dwProcessId; + public UInt32 dwThreadId; + }; + } + + public class WinCred + { +#pragma warning disable 0618 + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] + public struct _CREDENTIAL + { + public CRED_FLAGS Flags; + public UInt32 Type; + public IntPtr TargetName; + public IntPtr Comment; + public FILETIME LastWritten; + public UInt32 CredentialBlobSize; + public UInt32 Persist; + public UInt32 AttributeCount; + public IntPtr Attributes; + public IntPtr TargetAlias; + public IntPtr UserName; + } +#pragma warning restore 0618 + + public enum CRED_FLAGS : uint + { + NONE = 0x0, + PROMPT_NOW = 0x2, + USERNAME_TARGET = 0x4 + } + + public enum CRED_PERSIST : uint + { + Session = 1, + LocalMachine, + Enterprise + } + + public enum CRED_TYPE : uint + { + Generic = 1, + DomainPassword, + DomainCertificate, + DomainVisiblePassword, + GenericCertificate, + DomainExtended, + Maximum, + MaximumEx = Maximum + 1000, + } + } + + public class Secur32 + { + public struct _SECURITY_LOGON_SESSION_DATA + { + public UInt32 Size; + public WinNT._LUID LoginID; + public _LSA_UNICODE_STRING Username; + public _LSA_UNICODE_STRING LoginDomain; + public _LSA_UNICODE_STRING AuthenticationPackage; + public UInt32 LogonType; + public UInt32 Session; + public IntPtr pSid; + public UInt64 LoginTime; + public _LSA_UNICODE_STRING LogonServer; + public _LSA_UNICODE_STRING DnsDomainName; + public _LSA_UNICODE_STRING Upn; + } + + [StructLayout(LayoutKind.Sequential)] + public struct _LSA_UNICODE_STRING + { + public UInt16 Length; + public UInt16 MaximumLength; + public IntPtr Buffer; + } + } + } + + /////////////////PE + /// + public class PE + { + // DllMain constants + public const UInt32 DLL_PROCESS_DETACH = 0; + public const UInt32 DLL_PROCESS_ATTACH = 1; + public const UInt32 DLL_THREAD_ATTACH = 2; + public const UInt32 DLL_THREAD_DETACH = 3; + + // Primary class for loading PE + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate bool DllMain(IntPtr hinstDLL, uint fdwReason, IntPtr lpvReserved); + + [Flags] + public enum DataSectionFlags : uint + { + TYPE_NO_PAD = 0x00000008, + CNT_CODE = 0x00000020, + CNT_INITIALIZED_DATA = 0x00000040, + CNT_UNINITIALIZED_DATA = 0x00000080, + LNK_INFO = 0x00000200, + LNK_REMOVE = 0x00000800, + LNK_COMDAT = 0x00001000, + NO_DEFER_SPEC_EXC = 0x00004000, + GPREL = 0x00008000, + MEM_FARDATA = 0x00008000, + MEM_PURGEABLE = 0x00020000, + MEM_16BIT = 0x00020000, + MEM_LOCKED = 0x00040000, + MEM_PRELOAD = 0x00080000, + ALIGN_1BYTES = 0x00100000, + ALIGN_2BYTES = 0x00200000, + ALIGN_4BYTES = 0x00300000, + ALIGN_8BYTES = 0x00400000, + ALIGN_16BYTES = 0x00500000, + ALIGN_32BYTES = 0x00600000, + ALIGN_64BYTES = 0x00700000, + ALIGN_128BYTES = 0x00800000, + ALIGN_256BYTES = 0x00900000, + ALIGN_512BYTES = 0x00A00000, + ALIGN_1024BYTES = 0x00B00000, + ALIGN_2048BYTES = 0x00C00000, + ALIGN_4096BYTES = 0x00D00000, + ALIGN_8192BYTES = 0x00E00000, + ALIGN_MASK = 0x00F00000, + LNK_NRELOC_OVFL = 0x01000000, + MEM_DISCARDABLE = 0x02000000, + MEM_NOT_CACHED = 0x04000000, + MEM_NOT_PAGED = 0x08000000, + MEM_SHARED = 0x10000000, + MEM_EXECUTE = 0x20000000, + MEM_READ = 0x40000000, + MEM_WRITE = 0x80000000 + } + + public struct IMAGE_DOS_HEADER + { // DOS .EXE header + public UInt16 e_magic; // Magic number + public UInt16 e_cblp; // Bytes on last page of file + public UInt16 e_cp; // Pages in file + public UInt16 e_crlc; // Relocations + public UInt16 e_cparhdr; // Size of header in paragraphs + public UInt16 e_minalloc; // Minimum extra paragraphs needed + public UInt16 e_maxalloc; // Maximum extra paragraphs needed + public UInt16 e_ss; // Initial (relative) SS value + public UInt16 e_sp; // Initial SP value + public UInt16 e_csum; // Checksum + public UInt16 e_ip; // Initial IP value + public UInt16 e_cs; // Initial (relative) CS value + public UInt16 e_lfarlc; // File address of relocation table + public UInt16 e_ovno; // Overlay number + public UInt16 e_res_0; // Reserved words + public UInt16 e_res_1; // Reserved words + public UInt16 e_res_2; // Reserved words + public UInt16 e_res_3; // Reserved words + public UInt16 e_oemid; // OEM identifier (for e_oeminfo) + public UInt16 e_oeminfo; // OEM information; e_oemid specific + public UInt16 e_res2_0; // Reserved words + public UInt16 e_res2_1; // Reserved words + public UInt16 e_res2_2; // Reserved words + public UInt16 e_res2_3; // Reserved words + public UInt16 e_res2_4; // Reserved words + public UInt16 e_res2_5; // Reserved words + public UInt16 e_res2_6; // Reserved words + public UInt16 e_res2_7; // Reserved words + public UInt16 e_res2_8; // Reserved words + public UInt16 e_res2_9; // Reserved words + public UInt32 e_lfanew; // File address of new exe header + } + + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_DATA_DIRECTORY + { + public UInt32 VirtualAddress; + public UInt32 Size; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IMAGE_OPTIONAL_HEADER32 + { + public UInt16 Magic; + public Byte MajorLinkerVersion; + public Byte MinorLinkerVersion; + public UInt32 SizeOfCode; + public UInt32 SizeOfInitializedData; + public UInt32 SizeOfUninitializedData; + public UInt32 AddressOfEntryPoint; + public UInt32 BaseOfCode; + public UInt32 BaseOfData; + public UInt32 ImageBase; + public UInt32 SectionAlignment; + public UInt32 FileAlignment; + public UInt16 MajorOperatingSystemVersion; + public UInt16 MinorOperatingSystemVersion; + public UInt16 MajorImageVersion; + public UInt16 MinorImageVersion; + public UInt16 MajorSubsystemVersion; + public UInt16 MinorSubsystemVersion; + public UInt32 Win32VersionValue; + public UInt32 SizeOfImage; + public UInt32 SizeOfHeaders; + public UInt32 CheckSum; + public UInt16 Subsystem; + public UInt16 DllCharacteristics; + public UInt32 SizeOfStackReserve; + public UInt32 SizeOfStackCommit; + public UInt32 SizeOfHeapReserve; + public UInt32 SizeOfHeapCommit; + public UInt32 LoaderFlags; + public UInt32 NumberOfRvaAndSizes; + + public IMAGE_DATA_DIRECTORY ExportTable; + public IMAGE_DATA_DIRECTORY ImportTable; + public IMAGE_DATA_DIRECTORY ResourceTable; + public IMAGE_DATA_DIRECTORY ExceptionTable; + public IMAGE_DATA_DIRECTORY CertificateTable; + public IMAGE_DATA_DIRECTORY BaseRelocationTable; + public IMAGE_DATA_DIRECTORY Debug; + public IMAGE_DATA_DIRECTORY Architecture; + public IMAGE_DATA_DIRECTORY GlobalPtr; + public IMAGE_DATA_DIRECTORY TLSTable; + public IMAGE_DATA_DIRECTORY LoadConfigTable; + public IMAGE_DATA_DIRECTORY BoundImport; + public IMAGE_DATA_DIRECTORY IAT; + public IMAGE_DATA_DIRECTORY DelayImportDescriptor; + public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; + public IMAGE_DATA_DIRECTORY Reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IMAGE_OPTIONAL_HEADER64 + { + public UInt16 Magic; + public Byte MajorLinkerVersion; + public Byte MinorLinkerVersion; + public UInt32 SizeOfCode; + public UInt32 SizeOfInitializedData; + public UInt32 SizeOfUninitializedData; + public UInt32 AddressOfEntryPoint; + public UInt32 BaseOfCode; + public UInt64 ImageBase; + public UInt32 SectionAlignment; + public UInt32 FileAlignment; + public UInt16 MajorOperatingSystemVersion; + public UInt16 MinorOperatingSystemVersion; + public UInt16 MajorImageVersion; + public UInt16 MinorImageVersion; + public UInt16 MajorSubsystemVersion; + public UInt16 MinorSubsystemVersion; + public UInt32 Win32VersionValue; + public UInt32 SizeOfImage; + public UInt32 SizeOfHeaders; + public UInt32 CheckSum; + public UInt16 Subsystem; + public UInt16 DllCharacteristics; + public UInt64 SizeOfStackReserve; + public UInt64 SizeOfStackCommit; + public UInt64 SizeOfHeapReserve; + public UInt64 SizeOfHeapCommit; + public UInt32 LoaderFlags; + public UInt32 NumberOfRvaAndSizes; + + public IMAGE_DATA_DIRECTORY ExportTable; + public IMAGE_DATA_DIRECTORY ImportTable; + public IMAGE_DATA_DIRECTORY ResourceTable; + public IMAGE_DATA_DIRECTORY ExceptionTable; + public IMAGE_DATA_DIRECTORY CertificateTable; + public IMAGE_DATA_DIRECTORY BaseRelocationTable; + public IMAGE_DATA_DIRECTORY Debug; + public IMAGE_DATA_DIRECTORY Architecture; + public IMAGE_DATA_DIRECTORY GlobalPtr; + public IMAGE_DATA_DIRECTORY TLSTable; + public IMAGE_DATA_DIRECTORY LoadConfigTable; + public IMAGE_DATA_DIRECTORY BoundImport; + public IMAGE_DATA_DIRECTORY IAT; + public IMAGE_DATA_DIRECTORY DelayImportDescriptor; + public IMAGE_DATA_DIRECTORY CLRRuntimeHeader; + public IMAGE_DATA_DIRECTORY Reserved; + } + + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public struct IMAGE_FILE_HEADER + { + public UInt16 Machine; + public UInt16 NumberOfSections; + public UInt32 TimeDateStamp; + public UInt32 PointerToSymbolTable; + public UInt32 NumberOfSymbols; + public UInt16 SizeOfOptionalHeader; + public UInt16 Characteristics; + } + + [StructLayout(LayoutKind.Explicit)] + public struct IMAGE_SECTION_HEADER + { + [FieldOffset(0)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public char[] Name; + [FieldOffset(8)] + public UInt32 VirtualSize; + [FieldOffset(12)] + public UInt32 VirtualAddress; + [FieldOffset(16)] + public UInt32 SizeOfRawData; + [FieldOffset(20)] + public UInt32 PointerToRawData; + [FieldOffset(24)] + public UInt32 PointerToRelocations; + [FieldOffset(28)] + public UInt32 PointerToLinenumbers; + [FieldOffset(32)] + public UInt16 NumberOfRelocations; + [FieldOffset(34)] + public UInt16 NumberOfLinenumbers; + [FieldOffset(36)] + public DataSectionFlags Characteristics; + + public string Section + { + get { return new string(Name); } + } + } + + [StructLayout(LayoutKind.Explicit)] + public struct IMAGE_EXPORT_DIRECTORY + { + [FieldOffset(0)] + public UInt32 Characteristics; + [FieldOffset(4)] + public UInt32 TimeDateStamp; + [FieldOffset(8)] + public UInt16 MajorVersion; + [FieldOffset(10)] + public UInt16 MinorVersion; + [FieldOffset(12)] + public UInt32 Name; + [FieldOffset(16)] + public UInt32 Base; + [FieldOffset(20)] + public UInt32 NumberOfFunctions; + [FieldOffset(24)] + public UInt32 NumberOfNames; + [FieldOffset(28)] + public UInt32 AddressOfFunctions; + [FieldOffset(32)] + public UInt32 AddressOfNames; + [FieldOffset(36)] + public UInt32 AddressOfOrdinals; + } + + [StructLayout(LayoutKind.Sequential)] + public struct IMAGE_BASE_RELOCATION + { + public uint VirtualAdress; + public uint SizeOfBlock; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PE_META_DATA + { + public UInt32 Pe; + public Boolean Is32Bit; + public IMAGE_FILE_HEADER ImageFileHeader; + public IMAGE_OPTIONAL_HEADER32 OptHeader32; + public IMAGE_OPTIONAL_HEADER64 OptHeader64; + public IMAGE_SECTION_HEADER[] Sections; + } + + [StructLayout(LayoutKind.Sequential)] + public struct PE_MANUAL_MAP + { + public String DecoyModule; + public IntPtr ModuleBase; + public PE_META_DATA PEINFO; + } + + [StructLayout(LayoutKind.Explicit)] + public struct IMAGE_THUNK_DATA32 + { + [FieldOffset(0)] + public UInt32 ForwarderString; + [FieldOffset(0)] + public UInt32 Function; + [FieldOffset(0)] + public UInt32 Ordinal; + [FieldOffset(0)] + public UInt32 AddressOfData; + } + + [StructLayout(LayoutKind.Explicit)] + public struct IMAGE_THUNK_DATA64 + { + [FieldOffset(0)] + public UInt64 ForwarderString; + [FieldOffset(0)] + public UInt64 Function; + [FieldOffset(0)] + public UInt64 Ordinal; + [FieldOffset(0)] + public UInt64 AddressOfData; + } + + [StructLayout(LayoutKind.Explicit)] + public struct ApiSetNamespace + { + [FieldOffset(0x0C)] + public int Count; + + [FieldOffset(0x10)] + public int EntryOffset; + } + + [StructLayout(LayoutKind.Explicit, Size = 24)] + public struct ApiSetNamespaceEntry + { + [FieldOffset(0x04)] + public int NameOffset; + + [FieldOffset(0x08)] + public int NameLength; + + [FieldOffset(0x10)] + public int ValueOffset; + } + + [StructLayout(LayoutKind.Explicit)] + public struct ApiSetValueEntry + { + [FieldOffset(0x0C)] + public int ValueOffset; + + [FieldOffset(0x10)] + public int ValueCount; + } + + [StructLayout(LayoutKind.Sequential)] + public struct LDR_DATA_TABLE_ENTRY + { + public LIST_ENTRY InLoadOrderLinks; + public LIST_ENTRY InMemoryOrderLinks; + public LIST_ENTRY InInitializationOrderLinks; + public IntPtr DllBase; + public IntPtr EntryPoint; + public UInt32 SizeOfImage; + public UNICODE_STRING FullDllName; + public UNICODE_STRING BaseDllName; + } + } + + /////////////////Native + /// + + public static NTSTATUS NtCreateThreadEx( + ref IntPtr threadHandle, + h_reprobate.Win32.WinNT.ACCESS_MASK desiredAccess, + IntPtr objectAttributes, + IntPtr processHandle, + IntPtr startAddress, + IntPtr parameter, + bool createSuspended, + int stackZeroBits, + int sizeOfStack, + int maximumStackSize, + IntPtr attributeList) + { + // Craft an array for the arguments + object[] funcargs = + { + threadHandle, desiredAccess, objectAttributes, processHandle, startAddress, parameter, createSuspended, stackZeroBits, + sizeOfStack, maximumStackSize, attributeList + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtCreateThreadEx", + typeof(DELEGATES.NtCreateThreadEx), ref funcargs); + + // Update the modified variables + threadHandle = (IntPtr)funcargs[0]; + + return retValue; + } + + public static NTSTATUS RtlCreateUserThread( + IntPtr Process, + IntPtr ThreadSecurityDescriptor, + bool CreateSuspended, + IntPtr ZeroBits, + IntPtr MaximumStackSize, + IntPtr CommittedStackSize, + IntPtr StartAddress, + IntPtr Parameter, + ref IntPtr Thread, + IntPtr ClientId) + { + // Craft an array for the arguments + object[] funcargs = + { + Process, ThreadSecurityDescriptor, CreateSuspended, ZeroBits, + MaximumStackSize, CommittedStackSize, StartAddress, Parameter, + Thread, ClientId + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"RtlCreateUserThread", + typeof(DELEGATES.RtlCreateUserThread), ref funcargs); + + // Update the modified variables + Thread = (IntPtr)funcargs[8]; + + return retValue; + } + + public static NTSTATUS NtCreateSection( + ref IntPtr SectionHandle, + uint DesiredAccess, + IntPtr ObjectAttributes, + ref ulong MaximumSize, + uint SectionPageProtection, + uint AllocationAttributes, + IntPtr FileHandle) + { + + // Craft an array for the arguments + object[] funcargs = + { + SectionHandle, DesiredAccess, ObjectAttributes, MaximumSize, SectionPageProtection, AllocationAttributes, FileHandle + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtCreateSection", typeof(DELEGATES.NtCreateSection), ref funcargs); + if (retValue != NTSTATUS.Success) + { + throw new InvalidOperationException("Unable to create section, " + retValue); + } + + // Update the modified variables + SectionHandle = (IntPtr)funcargs[0]; + MaximumSize = (ulong)funcargs[3]; + + return retValue; + } + + public static NTSTATUS NtUnmapViewOfSection(IntPtr hProc, IntPtr baseAddr) + { + // Craft an array for the arguments + object[] funcargs = + { + hProc, baseAddr + }; + + NTSTATUS result = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtUnmapViewOfSection", + typeof(DELEGATES.NtUnmapViewOfSection), ref funcargs); + + return result; + } + + public static NTSTATUS NtMapViewOfSection( + IntPtr SectionHandle, + IntPtr ProcessHandle, + ref IntPtr BaseAddress, + IntPtr ZeroBits, + IntPtr CommitSize, + IntPtr SectionOffset, + ref ulong ViewSize, + uint InheritDisposition, + uint AllocationType, + uint Win32Protect) + { + + // Craft an array for the arguments + object[] funcargs = + { + SectionHandle, ProcessHandle, BaseAddress, ZeroBits, CommitSize, SectionOffset, ViewSize, InheritDisposition, AllocationType, + Win32Protect + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtMapViewOfSection", typeof(DELEGATES.NtMapViewOfSection), ref funcargs); + if (retValue != NTSTATUS.Success && retValue != NTSTATUS.ImageNotAtBase) + { + throw new InvalidOperationException("Unable to map view of section, " + retValue); + } + + // Update the modified variables. + BaseAddress = (IntPtr)funcargs[2]; + ViewSize = (ulong)funcargs[6]; + + return retValue; + } + + public static void RtlInitUnicodeString(ref UNICODE_STRING DestinationString, [MarshalAs(UnmanagedType.LPWStr)] string SourceString) + { + // Craft an array for the arguments + object[] funcargs = + { + DestinationString, SourceString + }; + + reprobate.DynamicAPIInvoke(@"ntdll.dll", @"RtlInitUnicodeString", typeof(DELEGATES.RtlInitUnicodeString), ref funcargs); + + // Update the modified variables + DestinationString = (UNICODE_STRING)funcargs[0]; + } + + public static NTSTATUS LdrLoadDll(IntPtr PathToFile, UInt32 dwFlags, ref UNICODE_STRING ModuleFileName, ref IntPtr ModuleHandle) + { + // Craft an array for the arguments + object[] funcargs = + { + PathToFile, dwFlags, ModuleFileName, ModuleHandle + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"LdrLoadDll", typeof(DELEGATES.LdrLoadDll), ref funcargs); + + // Update the modified variables + ModuleHandle = (IntPtr)funcargs[3]; + + return retValue; + } + + public static void RtlZeroMemory(IntPtr Destination, int Length) + { + // Craft an array for the arguments + object[] funcargs = + { + Destination, Length + }; + + reprobate.DynamicAPIInvoke(@"ntdll.dll", @"RtlZeroMemory", typeof(DELEGATES.RtlZeroMemory), ref funcargs); + } + + public static NTSTATUS NtQueryInformationProcess(IntPtr hProcess, PROCESSINFOCLASS processInfoClass, out IntPtr pProcInfo) + { + int processInformationLength; + UInt32 RetLen = 0; + + switch (processInfoClass) + { + case PROCESSINFOCLASS.ProcessWow64Information: + pProcInfo = Marshal.AllocHGlobal(IntPtr.Size); + RtlZeroMemory(pProcInfo, IntPtr.Size); + processInformationLength = IntPtr.Size; + break; + case PROCESSINFOCLASS.ProcessBasicInformation: + PROCESS_BASIC_INFORMATION PBI = new PROCESS_BASIC_INFORMATION(); + pProcInfo = Marshal.AllocHGlobal(Marshal.SizeOf(PBI)); + RtlZeroMemory(pProcInfo, Marshal.SizeOf(PBI)); + Marshal.StructureToPtr(PBI, pProcInfo, true); + processInformationLength = Marshal.SizeOf(PBI); + break; + default: + throw new InvalidOperationException($"Invalid ProcessInfoClass: {processInfoClass}"); + } + + object[] funcargs = + { + hProcess, processInfoClass, pProcInfo, processInformationLength, RetLen + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtQueryInformationProcess", typeof(DELEGATES.NtQueryInformationProcess), ref funcargs); + if (retValue != NTSTATUS.Success) + { + throw new UnauthorizedAccessException("Access is denied."); + } + + // Update the modified variables + pProcInfo = (IntPtr)funcargs[2]; + + return retValue; + } + + public static bool NtQueryInformationProcessWow64Information(IntPtr hProcess) + { + NTSTATUS retValue = NtQueryInformationProcess(hProcess, PROCESSINFOCLASS.ProcessWow64Information, out IntPtr pProcInfo); + if (retValue != NTSTATUS.Success) + { + throw new UnauthorizedAccessException("Access is denied."); + } + + if (Marshal.ReadIntPtr(pProcInfo) == IntPtr.Zero) + { + return false; + } + return true; + } + + public static PROCESS_BASIC_INFORMATION NtQueryInformationProcessBasicInformation(IntPtr hProcess) + { + NTSTATUS retValue = NtQueryInformationProcess(hProcess, PROCESSINFOCLASS.ProcessBasicInformation, out IntPtr pProcInfo); + if (retValue != NTSTATUS.Success) + { + throw new UnauthorizedAccessException("Access is denied."); + } + + return (PROCESS_BASIC_INFORMATION)Marshal.PtrToStructure(pProcInfo, typeof(PROCESS_BASIC_INFORMATION)); + } + + public static IntPtr NtOpenProcess(UInt32 ProcessId, h_reprobate.Win32.Kernel32.ProcessAccessFlags DesiredAccess) + { + // Create OBJECT_ATTRIBUTES & CLIENT_ID ref's + IntPtr ProcessHandle = IntPtr.Zero; + OBJECT_ATTRIBUTES oa = new OBJECT_ATTRIBUTES(); + CLIENT_ID ci = new CLIENT_ID(); + ci.UniqueProcess = (IntPtr)ProcessId; + + // Craft an array for the arguments + object[] funcargs = + { + ProcessHandle, DesiredAccess, oa, ci + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtOpenProcess", typeof(DELEGATES.NtOpenProcess), ref funcargs); + if (retValue != NTSTATUS.Success && retValue == NTSTATUS.InvalidCid) + { + throw new InvalidOperationException("An invalid client ID was specified."); + } + if (retValue != NTSTATUS.Success) + { + throw new UnauthorizedAccessException("Access is denied."); + } + + // Update the modified variables + ProcessHandle = (IntPtr)funcargs[0]; + + return ProcessHandle; + } + + public static void NtQueueApcThread(IntPtr ThreadHandle, IntPtr ApcRoutine, IntPtr ApcArgument1, IntPtr ApcArgument2, IntPtr ApcArgument3) + { + // Craft an array for the arguments + object[] funcargs = + { + ThreadHandle, ApcRoutine, ApcArgument1, ApcArgument2, ApcArgument3 + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtQueueApcThread", typeof(DELEGATES.NtQueueApcThread), ref funcargs); + if (retValue != NTSTATUS.Success) + { + throw new InvalidOperationException("Unable to queue APC, " + retValue); + } + } + + public static IntPtr NtOpenThread(int TID, h_reprobate.Win32.Kernel32.ThreadAccess DesiredAccess) + { + // Create OBJECT_ATTRIBUTES & CLIENT_ID ref's + IntPtr ThreadHandle = IntPtr.Zero; + OBJECT_ATTRIBUTES oa = new OBJECT_ATTRIBUTES(); + CLIENT_ID ci = new CLIENT_ID(); + ci.UniqueThread = (IntPtr)TID; + + // Craft an array for the arguments + object[] funcargs = + { + ThreadHandle, DesiredAccess, oa, ci + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtOpenThread", typeof(DELEGATES.NtOpenProcess), ref funcargs); + if (retValue != NTSTATUS.Success && retValue == NTSTATUS.InvalidCid) + { + throw new InvalidOperationException("An invalid client ID was specified."); + } + if (retValue != NTSTATUS.Success) + { + throw new UnauthorizedAccessException("Access is denied."); + } + + // Update the modified variables + ThreadHandle = (IntPtr)funcargs[0]; + + return ThreadHandle; + } + + public static IntPtr NtAllocateVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref IntPtr RegionSize, h_reprobate.Win32.Kernel32.AllocationType AllocationType, UInt32 Protect) + { + // Craft an array for the arguments + object[] funcargs = + { + ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtAllocateVirtualMemory", typeof(DELEGATES.NtAllocateVirtualMemory), ref funcargs); + if (retValue == NTSTATUS.AccessDenied) + { + // STATUS_ACCESS_DENIED + throw new UnauthorizedAccessException("Access is denied."); + } + if (retValue == NTSTATUS.AlreadyCommitted) + { + // STATUS_ALREADY_COMMITTED + throw new InvalidOperationException("The specified address range is already committed."); + } + if (retValue == NTSTATUS.CommitmentLimit) + { + // STATUS_COMMITMENT_LIMIT + throw new InvalidOperationException("Your system is low on virtual memory."); + } + if (retValue == NTSTATUS.ConflictingAddresses) + { + // STATUS_CONFLICTING_ADDRESSES + throw new InvalidOperationException("The specified address range conflicts with the address space."); + } + if (retValue == NTSTATUS.InsufficientResources) + { + // STATUS_INSUFFICIENT_RESOURCES + throw new InvalidOperationException("Insufficient system resources exist to complete the API call."); + } + if (retValue == NTSTATUS.InvalidHandle) + { + // STATUS_INVALID_HANDLE + throw new InvalidOperationException("An invalid HANDLE was specified."); + } + if (retValue == NTSTATUS.InvalidPageProtection) + { + // STATUS_INVALID_PAGE_PROTECTION + throw new InvalidOperationException("The specified page protection was not valid."); + } + if (retValue == NTSTATUS.NoMemory) + { + // STATUS_NO_MEMORY + throw new InvalidOperationException("Not enough virtual memory or paging file quota is available to complete the specified operation."); + } + if (retValue == NTSTATUS.ObjectTypeMismatch) + { + // STATUS_OBJECT_TYPE_MISMATCH + throw new InvalidOperationException("There is a mismatch between the type of object that is required by the requested operation and the type of object that is specified in the request."); + } + if (retValue != NTSTATUS.Success) + { + // STATUS_PROCESS_IS_TERMINATING == 0xC000010A + throw new InvalidOperationException("An attempt was made to duplicate an object handle into or out of an exiting process."); + } + + BaseAddress = (IntPtr)funcargs[1]; + return BaseAddress; + } + + public static void NtFreeVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, ref IntPtr RegionSize, h_reprobate.Win32.Kernel32.AllocationType FreeType) + { + // Craft an array for the arguments + object[] funcargs = + { + ProcessHandle, BaseAddress, RegionSize, FreeType + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtFreeVirtualMemory", typeof(DELEGATES.NtFreeVirtualMemory), ref funcargs); + if (retValue == NTSTATUS.AccessDenied) + { + // STATUS_ACCESS_DENIED + throw new UnauthorizedAccessException("Access is denied."); + } + if (retValue == NTSTATUS.InvalidHandle) + { + // STATUS_INVALID_HANDLE + throw new InvalidOperationException("An invalid HANDLE was specified."); + } + if (retValue != NTSTATUS.Success) + { + // STATUS_OBJECT_TYPE_MISMATCH == 0xC0000024 + throw new InvalidOperationException("There is a mismatch between the type of object that is required by the requested operation and the type of object that is specified in the request."); + } + } + + public static string GetFilenameFromMemoryPointer(IntPtr hProc, IntPtr pMem) + { + // Alloc buffer for result struct + IntPtr pBase = IntPtr.Zero; + IntPtr RegionSize = (IntPtr)0x500; + IntPtr pAlloc = NtAllocateVirtualMemory(hProc, ref pBase, IntPtr.Zero, ref RegionSize, h_reprobate.Win32.Kernel32.AllocationType.Commit | h_reprobate.Win32.Kernel32.AllocationType.Reserve, h_reprobate.Win32.WinNT.PAGE_READWRITE); + + // Prepare NtQueryVirtualMemory parameters + MEMORYINFOCLASS memoryInfoClass = MEMORYINFOCLASS.MemorySectionName; + UInt32 MemoryInformationLength = 0x500; + UInt32 Retlen = 0; + + // Craft an array for the arguments + object[] funcargs = + { + hProc, pMem, memoryInfoClass, pAlloc, MemoryInformationLength, Retlen + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtQueryVirtualMemory", typeof(DELEGATES.NtQueryVirtualMemory), ref funcargs); + + string FilePath = string.Empty; + if (retValue == NTSTATUS.Success) + { + UNICODE_STRING sn = (UNICODE_STRING)Marshal.PtrToStructure(pAlloc, typeof(UNICODE_STRING)); + FilePath = Marshal.PtrToStringUni(sn.Buffer); + } + + // Free allocation + NtFreeVirtualMemory(hProc, ref pAlloc, ref RegionSize, h_reprobate.Win32.Kernel32.AllocationType.Reserve); + if (retValue == NTSTATUS.AccessDenied) + { + // STATUS_ACCESS_DENIED + throw new UnauthorizedAccessException("Access is denied."); + } + if (retValue == NTSTATUS.AccessViolation) + { + // STATUS_ACCESS_VIOLATION + throw new InvalidOperationException("The specified base address is an invalid virtual address."); + } + if (retValue == NTSTATUS.InfoLengthMismatch) + { + // STATUS_INFO_LENGTH_MISMATCH + throw new InvalidOperationException("The MemoryInformation buffer is larger than MemoryInformationLength."); + } + if (retValue == NTSTATUS.InvalidParameter) + { + // STATUS_INVALID_PARAMETER + throw new InvalidOperationException("The specified base address is outside the range of accessible addresses."); + } + return FilePath; + } + + public static UInt32 NtProtectVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, ref IntPtr RegionSize, UInt32 NewProtect) + { + // Craft an array for the arguments + UInt32 OldProtect = 0; + object[] funcargs = + { + ProcessHandle, BaseAddress, RegionSize, NewProtect, OldProtect + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtProtectVirtualMemory", typeof(DELEGATES.NtProtectVirtualMemory), ref funcargs); + if (retValue != NTSTATUS.Success) + { + throw new InvalidOperationException("Failed to change memory protection, " + retValue); + } + + OldProtect = (UInt32)funcargs[4]; + return OldProtect; + } + + public static UInt32 NtWriteVirtualMemory(IntPtr ProcessHandle, IntPtr BaseAddress, IntPtr Buffer, UInt32 BufferLength) + { + // Craft an array for the arguments + UInt32 BytesWritten = 0; + object[] funcargs = + { + ProcessHandle, BaseAddress, Buffer, BufferLength, BytesWritten + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtWriteVirtualMemory", typeof(DELEGATES.NtWriteVirtualMemory), ref funcargs); + if (retValue != NTSTATUS.Success) + { + throw new InvalidOperationException("Failed to write memory, " + retValue); + } + + BytesWritten = (UInt32)funcargs[4]; + return BytesWritten; + } + + public static IntPtr LdrGetProcedureAddress(IntPtr hModule, IntPtr FunctionName, IntPtr Ordinal, ref IntPtr FunctionAddress) + { + // Craft an array for the arguments + object[] funcargs = + { + hModule, FunctionName, Ordinal, FunctionAddress + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"LdrGetProcedureAddress", typeof(DELEGATES.LdrGetProcedureAddress), ref funcargs); + if (retValue != NTSTATUS.Success) + { + throw new InvalidOperationException("Failed get procedure address, " + retValue); + } + + FunctionAddress = (IntPtr)funcargs[3]; + return FunctionAddress; + } + + public static void RtlGetVersion(ref OSVERSIONINFOEX VersionInformation) + { + // Craft an array for the arguments + object[] funcargs = + { + VersionInformation + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"RtlGetVersion", typeof(DELEGATES.RtlGetVersion), ref funcargs); + if (retValue != NTSTATUS.Success) + { + throw new InvalidOperationException("Failed get procedure address, " + retValue); + } + + VersionInformation = (OSVERSIONINFOEX)funcargs[0]; + } + + public static UInt32 NtReadVirtualMemory(IntPtr ProcessHandle, IntPtr BaseAddress, IntPtr Buffer, ref UInt32 NumberOfBytesToRead) + { + // Craft an array for the arguments + UInt32 NumberOfBytesRead = 0; + object[] funcargs = + { + ProcessHandle, BaseAddress, Buffer, NumberOfBytesToRead, NumberOfBytesRead + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtReadVirtualMemory", typeof(DELEGATES.NtReadVirtualMemory), ref funcargs); + if (retValue != NTSTATUS.Success) + { + throw new InvalidOperationException("Failed to read memory, " + retValue); + } + + NumberOfBytesRead = (UInt32)funcargs[4]; + return NumberOfBytesRead; + } + + public static IntPtr NtOpenFile(ref IntPtr FileHandle, h_reprobate.Win32.Kernel32.FileAccessFlags DesiredAccess, ref OBJECT_ATTRIBUTES ObjAttr, ref IO_STATUS_BLOCK IoStatusBlock, h_reprobate.Win32.Kernel32.FileShareFlags ShareAccess, h_reprobate.Win32.Kernel32.FileOpenFlags OpenOptions) + { + // Craft an array for the arguments + object[] funcargs = + { + FileHandle, DesiredAccess, ObjAttr, IoStatusBlock, ShareAccess, OpenOptions + }; + + NTSTATUS retValue = (NTSTATUS)reprobate.DynamicAPIInvoke(@"ntdll.dll", @"NtOpenFile", typeof(DELEGATES.NtOpenFile), ref funcargs); + if (retValue != NTSTATUS.Success) + { + throw new InvalidOperationException("Failed to open file, " + retValue); + } + + + FileHandle = (IntPtr)funcargs[0]; + return FileHandle; + } + + /// + /// Holds delegates for API calls in the NT Layer. + /// Must be public so that they may be used with SharpSploit.Execution.DynamicInvoke.Generic.DynamicFunctionInvoke + /// + /// + /// + /// // These delegates may also be used directly. + /// + /// // Get a pointer to the NtCreateThreadEx function. + /// IntPtr pFunction = Execution.DynamicInvoke.Generic.GetLibraryAddress(@"ntdll.dll", "NtCreateThreadEx"); + /// + /// // Create an instance of a NtCreateThreadEx delegate from our function pointer. + /// DELEGATES.NtCreateThreadEx createThread = (NATIVE_DELEGATES.NtCreateThreadEx)Marshal.GetDelegateForFunctionPointer( + /// pFunction, typeof(NATIVE_DELEGATES.NtCreateThreadEx)); + /// + /// // Invoke NtCreateThreadEx using the delegate + /// createThread(ref threadHandle, h_reprobate.Win32.WinNT.ACCESS_MASK.SPECIFIC_RIGHTS_ALL | h_reprobate.Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, IntPtr.Zero, + /// procHandle, startAddress, IntPtr.Zero, NT_CREATION_FLAGS.HIDE_FROM_DEBUGGER, 0, 0, 0, IntPtr.Zero); + /// + /// + public struct DELEGATES + { + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate NTSTATUS NtCreateThreadEx( + out IntPtr threadHandle, + h_reprobate.Win32.WinNT.ACCESS_MASK desiredAccess, + IntPtr objectAttributes, + IntPtr processHandle, + IntPtr startAddress, + IntPtr parameter, + bool createSuspended, + int stackZeroBits, + int sizeOfStack, + int maximumStackSize, + IntPtr attributeList); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate NTSTATUS RtlCreateUserThread( + IntPtr Process, + IntPtr ThreadSecurityDescriptor, + bool CreateSuspended, + IntPtr ZeroBits, + IntPtr MaximumStackSize, + IntPtr CommittedStackSize, + IntPtr StartAddress, + IntPtr Parameter, + ref IntPtr Thread, + IntPtr ClientId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate NTSTATUS NtCreateSection( + ref IntPtr SectionHandle, + uint DesiredAccess, + IntPtr ObjectAttributes, + ref ulong MaximumSize, + uint SectionPageProtection, + uint AllocationAttributes, + IntPtr FileHandle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate NTSTATUS NtUnmapViewOfSection( + IntPtr hProc, + IntPtr baseAddr); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate NTSTATUS NtMapViewOfSection( + IntPtr SectionHandle, + IntPtr ProcessHandle, + out IntPtr BaseAddress, + IntPtr ZeroBits, + IntPtr CommitSize, + IntPtr SectionOffset, + out ulong ViewSize, + uint InheritDisposition, + uint AllocationType, + uint Win32Protect); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 LdrLoadDll( + IntPtr PathToFile, + UInt32 dwFlags, + ref UNICODE_STRING ModuleFileName, + ref IntPtr ModuleHandle); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void RtlInitUnicodeString( + ref UNICODE_STRING DestinationString, + [MarshalAs(UnmanagedType.LPWStr)] + string SourceString); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate void RtlZeroMemory( + IntPtr Destination, + int length); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtQueryInformationProcess( + IntPtr processHandle, + PROCESSINFOCLASS processInformationClass, + IntPtr processInformation, + int processInformationLength, + ref UInt32 returnLength); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtOpenProcess( + ref IntPtr ProcessHandle, + h_reprobate.Win32.Kernel32.ProcessAccessFlags DesiredAccess, + ref OBJECT_ATTRIBUTES ObjectAttributes, + ref CLIENT_ID ClientId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtQueueApcThread( + IntPtr ThreadHandle, + IntPtr ApcRoutine, + IntPtr ApcArgument1, + IntPtr ApcArgument2, + IntPtr ApcArgument3); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtOpenThread( + ref IntPtr ThreadHandle, + h_reprobate.Win32.Kernel32.ThreadAccess DesiredAccess, + ref OBJECT_ATTRIBUTES ObjectAttributes, + ref CLIENT_ID ClientId); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtAllocateVirtualMemory( + IntPtr ProcessHandle, + ref IntPtr BaseAddress, + IntPtr ZeroBits, + ref IntPtr RegionSize, + h_reprobate.Win32.Kernel32.AllocationType AllocationType, + UInt32 Protect); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtFreeVirtualMemory( + IntPtr ProcessHandle, + ref IntPtr BaseAddress, + ref IntPtr RegionSize, + h_reprobate.Win32.Kernel32.AllocationType FreeType); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtQueryVirtualMemory( + IntPtr ProcessHandle, + IntPtr BaseAddress, + MEMORYINFOCLASS MemoryInformationClass, + IntPtr MemoryInformation, + UInt32 MemoryInformationLength, + ref UInt32 ReturnLength); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtProtectVirtualMemory( + IntPtr ProcessHandle, + ref IntPtr BaseAddress, + ref IntPtr RegionSize, + UInt32 NewProtect, + ref UInt32 OldProtect); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtWriteVirtualMemory( + IntPtr ProcessHandle, + IntPtr BaseAddress, + IntPtr Buffer, + UInt32 BufferLength, + ref UInt32 BytesWritten); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 RtlUnicodeStringToAnsiString( + ref ANSI_STRING DestinationString, + ref UNICODE_STRING SourceString, + bool AllocateDestinationString); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 LdrGetProcedureAddress( + IntPtr hModule, + IntPtr FunctionName, + IntPtr Ordinal, + ref IntPtr FunctionAddress); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 RtlGetVersion( + ref OSVERSIONINFOEX VersionInformation); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtReadVirtualMemory( + IntPtr ProcessHandle, + IntPtr BaseAddress, + IntPtr Buffer, + UInt32 NumberOfBytesToRead, + ref UInt32 NumberOfBytesRead); + + [UnmanagedFunctionPointer(CallingConvention.StdCall)] + public delegate UInt32 NtOpenFile( + ref IntPtr FileHandle, + h_reprobate.Win32.Kernel32.FileAccessFlags DesiredAccess, + ref OBJECT_ATTRIBUTES ObjAttr, + ref IO_STATUS_BLOCK IoStatusBlock, + h_reprobate.Win32.Kernel32.FileShareFlags ShareAccess, + h_reprobate.Win32.Kernel32.FileOpenFlags OpenOptions); + } + } +} diff --git a/Reprobate/reprobate.cs b/Reprobate/reprobate.cs new file mode 100644 index 0000000..de15dda --- /dev/null +++ b/Reprobate/reprobate.cs @@ -0,0 +1,1445 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Text; + +namespace YourProjectHere +{ + class reprobate + { + /// + /// Dynamically invoke an arbitrary function from a DLL, providing its name, function prototype, and arguments. + /// + /// The Wover (@TheRealWover) + /// Name of the DLL. + /// Name of the function. + /// Prototype for the function, represented as a Delegate object. + /// Parameters to pass to the function. Can be modified if function uses call by reference. + /// Object returned by the function. Must be unmarshalled by the caller. + public static object DynamicAPIInvoke(string DLLName, string FunctionName, Type FunctionDelegateType, ref object[] Parameters) + { + IntPtr pFunction = GetLibraryAddress(DLLName, FunctionName); + return DynamicFunctionInvoke(pFunction, FunctionDelegateType, ref Parameters); + } + + /// + /// Dynamically invokes an arbitrary function from a pointer. Useful for manually mapped modules or loading/invoking unmanaged code from memory. + /// + /// The Wover (@TheRealWover) + /// A pointer to the unmanaged function. + /// Prototype for the function, represented as a Delegate object. + /// Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference. + /// Object returned by the function. Must be unmarshalled by the caller. + public static object DynamicFunctionInvoke(IntPtr FunctionPointer, Type FunctionDelegateType, ref object[] Parameters) + { + Delegate funcDelegate = Marshal.GetDelegateForFunctionPointer(FunctionPointer, FunctionDelegateType); + return funcDelegate.DynamicInvoke(Parameters); + } + + /// + /// Resolves LdrLoadDll and uses that function to load a DLL from disk. + /// + /// Ruben Boonen (@FuzzySec) + /// The path to the DLL on disk. Uses the LoadLibrary convention. + /// IntPtr base address of the loaded module or IntPtr.Zero if the module was not loaded successfully. + public static IntPtr LoadModuleFromDisk(string DLLPath) + { + h_reprobate.UNICODE_STRING uModuleName = new h_reprobate.UNICODE_STRING(); + h_reprobate.RtlInitUnicodeString(ref uModuleName, DLLPath); + + IntPtr hModule = IntPtr.Zero; + h_reprobate.NTSTATUS CallResult = h_reprobate.LdrLoadDll(IntPtr.Zero, 0, ref uModuleName, ref hModule); + if (CallResult != h_reprobate.NTSTATUS.Success || hModule == IntPtr.Zero) + { + return IntPtr.Zero; + } + + return hModule; + } + + /// + /// Helper for getting the pointer to a function from a DLL loaded by the process. + /// + /// Ruben Boonen (@FuzzySec) + /// The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll"). + /// Name of the exported procedure. + /// Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + /// IntPtr for the desired function. + 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); + } + + /// + /// Helper for getting the pointer to a function from a DLL loaded by the process. + /// + /// Ruben Boonen (@FuzzySec) + /// The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll"). + /// Ordinal of the exported procedure. + /// Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + /// IntPtr for the desired function. + public static IntPtr GetLibraryAddress(string DLLName, short Ordinal, 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, Ordinal); + } + + /// + /// Helper for getting the pointer to a function from a DLL loaded by the process. + /// + /// Ruben Boonen (@FuzzySec) + /// The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll"). + /// Hash of the exported procedure. + /// 64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788). + /// Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list. + /// IntPtr for the desired function. + public static IntPtr GetLibraryAddress(string DLLName, string FunctionHash, long Key, 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, FunctionHash, Key); + } + + /// + /// 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. This function uses the .NET System.Diagnostics.Process class. + /// + /// Ruben Boonen (@FuzzySec) + /// The name of the DLL (e.g. "ntdll.dll"). + /// IntPtr base address of the loaded module or IntPtr.Zero if the module is not found. + public static IntPtr GetLoadedModuleAddress(string DLLName) + { + ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules; + foreach (ProcessModule Mod in ProcModules) + { + if (Mod.FileName.ToLower().EndsWith(DLLName.ToLower())) + { + return Mod.BaseAddress; + } + } + return IntPtr.Zero; + } + + /// + /// 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. This function parses the _PEB_LDR_DATA structure. + /// + /// Ruben Boonen (@FuzzySec) + /// The name of the DLL (e.g. "ntdll.dll"). + /// IntPtr base address of the loaded module or IntPtr.Zero if the module is not found. + public static IntPtr GetPebLdrModuleEntry(string DLLName) + { + // Get _PEB pointer + h_reprobate.PROCESS_BASIC_INFORMATION pbi = h_reprobate.NtQueryInformationProcessBasicInformation((IntPtr)(-1)); + + // Set function variables + bool Is32Bit = false; + UInt32 LdrDataOffset = 0; + UInt32 InLoadOrderModuleListOffset = 0; + if (IntPtr.Size == 4) + { + Is32Bit = true; + LdrDataOffset = 0xc; + InLoadOrderModuleListOffset = 0xC; + } + else + { + LdrDataOffset = 0x18; + InLoadOrderModuleListOffset = 0x10; + } + + // Get module InLoadOrderModuleList -> _LIST_ENTRY + IntPtr PEB_LDR_DATA = Marshal.ReadIntPtr((IntPtr)((UInt64)pbi.PebBaseAddress + LdrDataOffset)); + IntPtr pInLoadOrderModuleList = (IntPtr)((UInt64)PEB_LDR_DATA + InLoadOrderModuleListOffset); + h_reprobate.LIST_ENTRY le = (h_reprobate.LIST_ENTRY)Marshal.PtrToStructure(pInLoadOrderModuleList, typeof(h_reprobate.LIST_ENTRY)); + + // Loop entries + IntPtr flink = le.Flink; + IntPtr hModule = IntPtr.Zero; + h_reprobate.PE.LDR_DATA_TABLE_ENTRY dte = (h_reprobate.PE.LDR_DATA_TABLE_ENTRY)Marshal.PtrToStructure(flink, typeof(h_reprobate.PE.LDR_DATA_TABLE_ENTRY)); + while (dte.InLoadOrderLinks.Flink != le.Blink) + { + // Match module name + if (Marshal.PtrToStringUni(dte.FullDllName.Buffer).EndsWith(DLLName, StringComparison.OrdinalIgnoreCase)) + { + hModule = dte.DllBase; + } + + // Move Ptr + flink = dte.InLoadOrderLinks.Flink; + dte = (h_reprobate.PE.LDR_DATA_TABLE_ENTRY)Marshal.PtrToStructure(flink, typeof(h_reprobate.PE.LDR_DATA_TABLE_ENTRY)); + } + + return hModule; + } + + /// + /// Generate an HMAC-MD5 hash of the supplied string using an Int64 as the key. This is useful for unique hash based API lookups. + /// + /// Ruben Boonen (@FuzzySec) + /// API name to hash. + /// 64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788). + /// string, the computed MD5 hash value. + public static string GetAPIHash(string APIName, long Key) + { + byte[] data = Encoding.UTF8.GetBytes(APIName.ToLower()); + byte[] kbytes = BitConverter.GetBytes(Key); + + using (HMACMD5 hmac = new HMACMD5(kbytes)) + { + byte[] bHash = hmac.ComputeHash(data); + return BitConverter.ToString(bHash).Replace("-", ""); + } + } + + /// + /// Given a module base address, resolve the address of a function by manually walking the module export table. + /// + /// Ruben Boonen (@FuzzySec) + /// A pointer to the base address where the module is loaded in the current process. + /// The name of the export to search for (e.g. "NtAlertResumeThread"). + /// IntPtr for the desired function. + public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName) + { + IntPtr FunctionPtr = IntPtr.Zero; + try + { + // Traverse the PE header in memory + Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C)); + Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14)); + Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18; + Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader); + Int64 pExport = 0; + if (Magic == 0x010b) + { + pExport = OptHeader + 0x60; + } + else + { + pExport = OptHeader + 0x70; + } + + // Read -> IMAGE_EXPORT_DIRECTORY + Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport); + Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10)); + Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14)); + Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18)); + Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C)); + Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20)); + Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24)); + + // Loop the array of export name RVA's + for (int i = 0; i < NumberOfNames; i++) + { + string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4)))); + if (FunctionName.Equals(ExportName, StringComparison.OrdinalIgnoreCase)) + { + Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase; + Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase)))); + FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA); + break; + } + } + } + catch + { + // Catch parser failure + throw new InvalidOperationException("Failed to parse module exports."); + } + + if (FunctionPtr == IntPtr.Zero) + { + // Export not found + throw new MissingMethodException(ExportName + ", export not found."); + } + return FunctionPtr; + } + + /// + /// Given a module base address, resolve the address of a function by manually walking the module export table. + /// + /// Ruben Boonen (@FuzzySec) + /// A pointer to the base address where the module is loaded in the current process. + /// The ordinal number to search for (e.g. 0x136 -> ntdll!NtCreateThreadEx). + /// IntPtr for the desired function. + public static IntPtr GetExportAddress(IntPtr ModuleBase, short Ordinal) + { + IntPtr FunctionPtr = IntPtr.Zero; + try + { + // Traverse the PE header in memory + Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C)); + Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14)); + Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18; + Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader); + Int64 pExport = 0; + if (Magic == 0x010b) + { + pExport = OptHeader + 0x60; + } + else + { + pExport = OptHeader + 0x70; + } + + // Read -> IMAGE_EXPORT_DIRECTORY + Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport); + Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10)); + Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14)); + Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18)); + Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C)); + Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20)); + Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24)); + + // Loop the array of export name RVA's + for (int i = 0; i < NumberOfNames; i++) + { + Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase; + if (FunctionOrdinal == Ordinal) + { + Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase)))); + FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA); + break; + } + } + } + catch + { + // Catch parser failure + throw new InvalidOperationException("Failed to parse module exports."); + } + + if (FunctionPtr == IntPtr.Zero) + { + // Export not found + throw new MissingMethodException(Ordinal + ", ordinal not found."); + } + return FunctionPtr; + } + + /// + /// Given a module base address, resolve the address of a function by manually walking the module export table. + /// + /// Ruben Boonen (@FuzzySec) + /// A pointer to the base address where the module is loaded in the current process. + /// Hash of the exported procedure. + /// 64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788). + /// IntPtr for the desired function. + public static IntPtr GetExportAddress(IntPtr ModuleBase, string FunctionHash, long Key) + { + IntPtr FunctionPtr = IntPtr.Zero; + try + { + // Traverse the PE header in memory + Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C)); + Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14)); + Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18; + Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader); + Int64 pExport = 0; + if (Magic == 0x010b) + { + pExport = OptHeader + 0x60; + } + else + { + pExport = OptHeader + 0x70; + } + + // Read -> IMAGE_EXPORT_DIRECTORY + Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport); + Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10)); + Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14)); + Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18)); + Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C)); + Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20)); + Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24)); + + // Loop the array of export name RVA's + for (int i = 0; i < NumberOfNames; i++) + { + string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4)))); + if (GetAPIHash(FunctionName, Key).Equals(FunctionHash, StringComparison.OrdinalIgnoreCase)) + { + Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase; + Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase)))); + FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA); + break; + } + } + } + catch + { + // Catch parser failure + throw new InvalidOperationException("Failed to parse module exports."); + } + + if (FunctionPtr == IntPtr.Zero) + { + // Export not found + throw new MissingMethodException(FunctionHash + ", export hash not found."); + } + return FunctionPtr; + } + + /// + /// Given a module base address, resolve the address of a function by calling LdrGetProcedureAddress. + /// + /// Ruben Boonen (@FuzzySec) + /// A pointer to the base address where the module is loaded in the current process. + /// The name of the export to search for (e.g. "NtAlertResumeThread"). + /// IntPtr for the desired function. + public static IntPtr GetNativeExportAddress(IntPtr ModuleBase, string ExportName) + { + h_reprobate.ANSI_STRING aFunc = new h_reprobate.ANSI_STRING + { + Length = (ushort)ExportName.Length, + MaximumLength = (ushort)(ExportName.Length + 2), + Buffer = Marshal.StringToCoTaskMemAnsi(ExportName) + }; + + IntPtr pAFunc = Marshal.AllocHGlobal(Marshal.SizeOf(aFunc)); + Marshal.StructureToPtr(aFunc, pAFunc, true); + + IntPtr pFuncAddr = IntPtr.Zero; + h_reprobate.LdrGetProcedureAddress(ModuleBase, pAFunc, IntPtr.Zero, ref pFuncAddr); + + Marshal.FreeHGlobal(pAFunc); + + return pFuncAddr; + } + + /// + /// Given a module base address, resolve the address of a function by calling LdrGetProcedureAddress. + /// + /// Ruben Boonen (@FuzzySec) + /// A pointer to the base address where the module is loaded in the current process. + /// The ordinal number to search for (e.g. 0x136 -> ntdll!NtCreateThreadEx). + /// IntPtr for the desired function. + public static IntPtr GetNativeExportAddress(IntPtr ModuleBase, short Ordinal) + { + IntPtr pFuncAddr = IntPtr.Zero; + IntPtr pOrd = (IntPtr)Ordinal; + + h_reprobate.LdrGetProcedureAddress(ModuleBase, IntPtr.Zero, pOrd, ref pFuncAddr); + + return pFuncAddr; + } + + /// + /// Retrieve PE header information from the module base pointer. + /// + /// Ruben Boonen (@FuzzySec) + /// Pointer to the module base. + /// h_reprobate.PE.PE_META_DATA + public static h_reprobate.PE.PE_META_DATA GetPeMetaData(IntPtr pModule) + { + h_reprobate.PE.PE_META_DATA PeMetaData = new h_reprobate.PE.PE_META_DATA(); + try + { + UInt32 e_lfanew = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + 0x3c)); + PeMetaData.Pe = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + e_lfanew)); + // Validate PE signature + if (PeMetaData.Pe != 0x4550) + { + throw new InvalidOperationException("Invalid PE signature."); + } + PeMetaData.ImageFileHeader = (h_reprobate.PE.IMAGE_FILE_HEADER)Marshal.PtrToStructure((IntPtr)((UInt64)pModule + e_lfanew + 0x4), typeof(h_reprobate.PE.IMAGE_FILE_HEADER)); + IntPtr OptHeader = (IntPtr)((UInt64)pModule + e_lfanew + 0x18); + UInt16 PEArch = (UInt16)Marshal.ReadInt16(OptHeader); + // Validate PE arch + if (PEArch == 0x010b) // Image is x32 + { + PeMetaData.Is32Bit = true; + PeMetaData.OptHeader32 = (h_reprobate.PE.IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure(OptHeader, typeof(h_reprobate.PE.IMAGE_OPTIONAL_HEADER32)); + } + else if (PEArch == 0x020b) // Image is x64 + { + PeMetaData.Is32Bit = false; + PeMetaData.OptHeader64 = (h_reprobate.PE.IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure(OptHeader, typeof(h_reprobate.PE.IMAGE_OPTIONAL_HEADER64)); + } + else + { + throw new InvalidOperationException("Invalid magic value (PE32/PE32+)."); + } + // Read sections + h_reprobate.PE.IMAGE_SECTION_HEADER[] SectionArray = new h_reprobate.PE.IMAGE_SECTION_HEADER[PeMetaData.ImageFileHeader.NumberOfSections]; + for (int i = 0; i < PeMetaData.ImageFileHeader.NumberOfSections; i++) + { + IntPtr SectionPtr = (IntPtr)((UInt64)OptHeader + PeMetaData.ImageFileHeader.SizeOfOptionalHeader + (UInt32)(i * 0x28)); + SectionArray[i] = (h_reprobate.PE.IMAGE_SECTION_HEADER)Marshal.PtrToStructure(SectionPtr, typeof(h_reprobate.PE.IMAGE_SECTION_HEADER)); + } + PeMetaData.Sections = SectionArray; + } + catch + { + throw new InvalidOperationException("Invalid module base specified."); + } + return PeMetaData; + } + + /// + /// Resolve host DLL for API Set DLL. + /// + /// Ruben Boonen (@FuzzySec) + /// Dictionary, a combination of Key:APISetDLL and Val:HostDLL. + public static Dictionary GetApiSetMapping() + { + h_reprobate.PROCESS_BASIC_INFORMATION pbi = h_reprobate.NtQueryInformationProcessBasicInformation((IntPtr)(-1)); + UInt32 ApiSetMapOffset = IntPtr.Size == 4 ? (UInt32)0x38 : 0x68; + + // Create mapping dictionary + Dictionary ApiSetDict = new Dictionary(); + + IntPtr pApiSetNamespace = Marshal.ReadIntPtr((IntPtr)((UInt64)pbi.PebBaseAddress + ApiSetMapOffset)); + h_reprobate.PE.ApiSetNamespace Namespace = (h_reprobate.PE.ApiSetNamespace)Marshal.PtrToStructure(pApiSetNamespace, typeof(h_reprobate.PE.ApiSetNamespace)); + for (var i = 0; i < Namespace.Count; i++) + { + h_reprobate.PE.ApiSetNamespaceEntry SetEntry = new h_reprobate.PE.ApiSetNamespaceEntry(); + SetEntry = (h_reprobate.PE.ApiSetNamespaceEntry)Marshal.PtrToStructure((IntPtr)((UInt64)pApiSetNamespace + (UInt64)Namespace.EntryOffset + (UInt64)(i * Marshal.SizeOf(SetEntry))), typeof(h_reprobate.PE.ApiSetNamespaceEntry)); + string ApiSetEntryName = Marshal.PtrToStringUni((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.NameOffset), SetEntry.NameLength / 2) + ".dll"; + + h_reprobate.PE.ApiSetValueEntry SetValue = new h_reprobate.PE.ApiSetValueEntry(); + SetValue = (h_reprobate.PE.ApiSetValueEntry)Marshal.PtrToStructure((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.ValueOffset), typeof(h_reprobate.PE.ApiSetValueEntry)); + string ApiSetValue = string.Empty; + if (SetValue.ValueCount != 0) + { + ApiSetValue = Marshal.PtrToStringUni((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetValue.ValueOffset), SetValue.ValueCount / 2); + } + + // Add pair to dict + ApiSetDict.Add(ApiSetEntryName, ApiSetValue); + } + + // Return dict + return ApiSetDict; + } + + /// + /// Call a manually mapped PE by its EntryPoint. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (h_reprobate.PE.PE_META_DATA). + /// Base address of the module in memory. + /// void + public static void CallMappedPEModule(h_reprobate.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase) + { + // Call module by EntryPoint (eg Mimikatz.exe) + IntPtr hRemoteThread = IntPtr.Zero; + IntPtr lpStartAddress = PEINFO.Is32Bit ? (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader32.AddressOfEntryPoint) : + (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader64.AddressOfEntryPoint); + + h_reprobate.NtCreateThreadEx( + ref hRemoteThread, + h_reprobate.Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, + IntPtr.Zero, (IntPtr)(-1), + lpStartAddress, IntPtr.Zero, + false, 0, 0, 0, IntPtr.Zero + ); + } + + /// + /// Call a manually mapped DLL by DllMain -> DLL_PROCESS_ATTACH. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (h_reprobate.PE.PE_META_DATA). + /// Base address of the module in memory. + /// void + public static void CallMappedDLLModule(h_reprobate.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase) + { + IntPtr lpEntryPoint = PEINFO.Is32Bit ? (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader32.AddressOfEntryPoint) : + (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader64.AddressOfEntryPoint); + + h_reprobate.PE.DllMain fDllMain = (h_reprobate.PE.DllMain)Marshal.GetDelegateForFunctionPointer(lpEntryPoint, typeof(h_reprobate.PE.DllMain)); + bool CallRes = fDllMain(ModuleMemoryBase, h_reprobate.PE.DLL_PROCESS_ATTACH, IntPtr.Zero); + if (!CallRes) + { + throw new InvalidOperationException("Failed to call DllMain -> DLL_PROCESS_ATTACH"); + } + } + + /// + /// Call a manually mapped DLL by Export. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (h_reprobate.PE.PE_META_DATA). + /// Base address of the module in memory. + /// The name of the export to search for (e.g. "NtAlertResumeThread"). + /// Prototype for the function, represented as a Delegate object. + /// Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference. + /// Specify whether to invoke the module's entry point. + /// void + public static object CallMappedDLLModuleExport(h_reprobate.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, string ExportName, Type FunctionDelegateType, object[] Parameters, bool CallEntry = true) + { + // Call entry point if user has specified + if (CallEntry) + { + CallMappedDLLModule(PEINFO, ModuleMemoryBase); + } + + // Get export pointer + IntPtr pFunc = GetExportAddress(ModuleMemoryBase, ExportName); + + // Call export + return DynamicFunctionInvoke(pFunc, FunctionDelegateType, ref Parameters); + } + + /// + /// Read ntdll from disk, find/copy the appropriate syscall stub and free ntdll. + /// + /// Ruben Boonen (@FuzzySec) + /// The name of the function to search for (e.g. "NtAlertResumeThread"). + /// IntPtr, Syscall stub + public static IntPtr GetSyscallStub(string FunctionName) + { + // Verify process & architecture + bool isWOW64 = h_reprobate.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Generating Syscall stubs is not supported for WOW64."); + } + + // Find the path for ntdll by looking at the currently loaded module + string NtdllPath = string.Empty; + ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules; + foreach (ProcessModule Mod in ProcModules) + { + if (Mod.FileName.EndsWith("ntdll.dll", StringComparison.OrdinalIgnoreCase)) + { + NtdllPath = Mod.FileName; + } + } + + // Alloc module into memory for parsing + IntPtr pModule = AllocateFileToMemory(NtdllPath); + + // Fetch PE meta data + h_reprobate.PE.PE_META_DATA PEINFO = GetPeMetaData(pModule); + + // Alloc PE image memory -> RW + IntPtr BaseAddress = IntPtr.Zero; + IntPtr RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage; + UInt32 SizeOfHeaders = PEINFO.Is32Bit ? PEINFO.OptHeader32.SizeOfHeaders : PEINFO.OptHeader64.SizeOfHeaders; + + IntPtr pImage = h_reprobate.NtAllocateVirtualMemory( + (IntPtr)(-1), ref BaseAddress, IntPtr.Zero, ref RegionSize, + h_reprobate.Win32.Kernel32.AllocationType.Commit | h_reprobate.Win32.Kernel32.AllocationType.Reserve, + h_reprobate.Win32.WinNT.PAGE_READWRITE + ); + + // Write PE header to memory + UInt32 BytesWritten = h_reprobate.NtWriteVirtualMemory((IntPtr)(-1), pImage, pModule, SizeOfHeaders); + + // Write sections to memory + foreach (h_reprobate.PE.IMAGE_SECTION_HEADER ish in PEINFO.Sections) + { + // Calculate offsets + IntPtr pVirtualSectionBase = (IntPtr)((UInt64)pImage + ish.VirtualAddress); + IntPtr pRawSectionBase = (IntPtr)((UInt64)pModule + ish.PointerToRawData); + + // Write data + BytesWritten = h_reprobate.NtWriteVirtualMemory((IntPtr)(-1), pVirtualSectionBase, pRawSectionBase, ish.SizeOfRawData); + if (BytesWritten != ish.SizeOfRawData) + { + throw new InvalidOperationException("Failed to write to memory."); + } + } + + // Get Ptr to function + IntPtr pFunc = GetExportAddress(pImage, FunctionName); + if (pFunc == IntPtr.Zero) + { + throw new InvalidOperationException("Failed to resolve ntdll export."); + } + + // Alloc memory for call stub + BaseAddress = IntPtr.Zero; + RegionSize = (IntPtr)0x50; + IntPtr pCallStub = h_reprobate.NtAllocateVirtualMemory( + (IntPtr)(-1), ref BaseAddress, IntPtr.Zero, ref RegionSize, + h_reprobate.Win32.Kernel32.AllocationType.Commit | h_reprobate.Win32.Kernel32.AllocationType.Reserve, + h_reprobate.Win32.WinNT.PAGE_READWRITE + ); + + // Write call stub + BytesWritten = h_reprobate.NtWriteVirtualMemory((IntPtr)(-1), pCallStub, pFunc, 0x50); + if (BytesWritten != 0x50) + { + throw new InvalidOperationException("Failed to write to memory."); + } + + // Change call stub permissions + h_reprobate.NtProtectVirtualMemory((IntPtr)(-1), ref pCallStub, ref RegionSize, h_reprobate.Win32.WinNT.PAGE_EXECUTE_READ); + + // Free temporary allocations + Marshal.FreeHGlobal(pModule); + RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage; + + h_reprobate.NtFreeVirtualMemory((IntPtr)(-1), ref pImage, ref RegionSize, h_reprobate.Win32.Kernel32.AllocationType.Reserve); + + return pCallStub; + } + + /// + /// Maps a DLL from disk into a Section using NtCreateSection. + /// + /// The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + /// Full path fo the DLL on disk. + /// h_reprobate.PE.PE_MANUAL_MAP + public static h_reprobate.PE.PE_MANUAL_MAP MapModuleFromDisk(string DLLPath) + { + // Check file exists + if (!File.Exists(DLLPath)) + { + throw new InvalidOperationException("Filepath not found."); + } + + // Open file handle + h_reprobate.UNICODE_STRING ObjectName = new h_reprobate.UNICODE_STRING(); + h_reprobate.RtlInitUnicodeString(ref ObjectName, (@"\??\" + DLLPath)); + IntPtr pObjectName = Marshal.AllocHGlobal(Marshal.SizeOf(ObjectName)); + Marshal.StructureToPtr(ObjectName, pObjectName, true); + + h_reprobate.OBJECT_ATTRIBUTES objectAttributes = new h_reprobate.OBJECT_ATTRIBUTES(); + objectAttributes.Length = Marshal.SizeOf(objectAttributes); + objectAttributes.ObjectName = pObjectName; + objectAttributes.Attributes = 0x40; // OBJ_CASE_INSENSITIVE + + h_reprobate.IO_STATUS_BLOCK ioStatusBlock = new h_reprobate.IO_STATUS_BLOCK(); + + IntPtr hFile = IntPtr.Zero; + h_reprobate.NtOpenFile( + ref hFile, + h_reprobate.Win32.Kernel32.FileAccessFlags.FILE_READ_DATA | + h_reprobate.Win32.Kernel32.FileAccessFlags.FILE_EXECUTE | + h_reprobate.Win32.Kernel32.FileAccessFlags.FILE_READ_ATTRIBUTES | + h_reprobate.Win32.Kernel32.FileAccessFlags.SYNCHRONIZE, + ref objectAttributes, ref ioStatusBlock, + h_reprobate.Win32.Kernel32.FileShareFlags.FILE_SHARE_READ | + h_reprobate.Win32.Kernel32.FileShareFlags.FILE_SHARE_DELETE, + h_reprobate.Win32.Kernel32.FileOpenFlags.FILE_SYNCHRONOUS_IO_NONALERT | + h_reprobate.Win32.Kernel32.FileOpenFlags.FILE_NON_DIRECTORY_FILE + ); + + // Create section from hFile + IntPtr hSection = IntPtr.Zero; + ulong MaxSize = 0; + h_reprobate.NTSTATUS ret = h_reprobate.NtCreateSection( + ref hSection, + (UInt32)h_reprobate.Win32.WinNT.ACCESS_MASK.SECTION_ALL_ACCESS, + IntPtr.Zero, + ref MaxSize, + h_reprobate.Win32.WinNT.PAGE_READONLY, + h_reprobate.Win32.WinNT.SEC_IMAGE, + hFile + ); + + // Map view of file + IntPtr pBaseAddress = IntPtr.Zero; + h_reprobate.NtMapViewOfSection( + hSection, (IntPtr)(-1), ref pBaseAddress, + IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, + ref MaxSize, 0x2, 0x0, + h_reprobate.Win32.WinNT.PAGE_READWRITE + ); + + // Prepare return object + h_reprobate.PE.PE_MANUAL_MAP SecMapObject = new h_reprobate.PE.PE_MANUAL_MAP + { + PEINFO = GetPeMetaData(pBaseAddress), + ModuleBase = pBaseAddress + }; + + return SecMapObject; + } + + /// + /// Allocate file to memory from disk + /// + /// Ruben Boonen (@FuzzySec) + /// Full path to the file to be alloacted. + /// IntPtr base address of the allocated file. + public static IntPtr AllocateFileToMemory(string FilePath) + { + if (!File.Exists(FilePath)) + { + throw new InvalidOperationException("Filepath not found."); + } + + byte[] bFile = File.ReadAllBytes(FilePath); + return AllocateBytesToMemory(bFile); + } + + /// + /// Allocate a byte array to memory + /// + /// Ruben Boonen (@FuzzySec) + /// Byte array to be allocated. + /// IntPtr base address of the allocated file. + public static IntPtr AllocateBytesToMemory(byte[] FileByteArray) + { + IntPtr pFile = Marshal.AllocHGlobal(FileByteArray.Length); + Marshal.Copy(FileByteArray, 0, pFile, FileByteArray.Length); + return pFile; + } + + /// + /// Relocates a module in memory. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (h_reprobate.PE.PE_META_DATA). + /// Base address of the module in memory. + /// void + public static void RelocateModule(h_reprobate.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase) + { + h_reprobate.PE.IMAGE_DATA_DIRECTORY idd = PEINFO.Is32Bit ? PEINFO.OptHeader32.BaseRelocationTable : PEINFO.OptHeader64.BaseRelocationTable; + Int64 ImageDelta = PEINFO.Is32Bit ? (Int64)((UInt64)ModuleMemoryBase - PEINFO.OptHeader32.ImageBase) : + (Int64)((UInt64)ModuleMemoryBase - PEINFO.OptHeader64.ImageBase); + + // Ptr for the base reloc table + IntPtr pRelocTable = (IntPtr)((UInt64)ModuleMemoryBase + idd.VirtualAddress); + Int32 nextRelocTableBlock = -1; + // Loop reloc blocks + while (nextRelocTableBlock != 0) + { + h_reprobate.PE.IMAGE_BASE_RELOCATION ibr = new h_reprobate.PE.IMAGE_BASE_RELOCATION(); + ibr = (h_reprobate.PE.IMAGE_BASE_RELOCATION)Marshal.PtrToStructure(pRelocTable, typeof(h_reprobate.PE.IMAGE_BASE_RELOCATION)); + + Int64 RelocCount = ((ibr.SizeOfBlock - Marshal.SizeOf(ibr)) / 2); + for (int i = 0; i < RelocCount; i++) + { + // Calculate reloc entry ptr + IntPtr pRelocEntry = (IntPtr)((UInt64)pRelocTable + (UInt64)Marshal.SizeOf(ibr) + (UInt64)(i * 2)); + UInt16 RelocValue = (UInt16)Marshal.ReadInt16(pRelocEntry); + + // Parse reloc value + // The type should only ever be 0x0, 0x3, 0xA + // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#base-relocation-types + UInt16 RelocType = (UInt16)(RelocValue >> 12); + UInt16 RelocPatch = (UInt16)(RelocValue & 0xfff); + + // Perform relocation + if (RelocType != 0) // IMAGE_REL_BASED_ABSOLUTE (0 -> skip reloc) + { + try + { + IntPtr pPatch = (IntPtr)((UInt64)ModuleMemoryBase + ibr.VirtualAdress + RelocPatch); + if (RelocType == 0x3) // IMAGE_REL_BASED_HIGHLOW (x86) + { + Int32 OriginalPtr = Marshal.ReadInt32(pPatch); + Marshal.WriteInt32(pPatch, (OriginalPtr + (Int32)ImageDelta)); + } + else // IMAGE_REL_BASED_DIR64 (x64) + { + Int64 OriginalPtr = Marshal.ReadInt64(pPatch); + Marshal.WriteInt64(pPatch, (OriginalPtr + ImageDelta)); + } + } + catch + { + throw new InvalidOperationException("Memory access violation."); + } + } + } + + // Check for next block + pRelocTable = (IntPtr)((UInt64)pRelocTable + ibr.SizeOfBlock); + nextRelocTableBlock = Marshal.ReadInt32(pRelocTable); + } + } + + /// + /// Rewrite IAT for manually mapped module. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (h_reprobate.PE.PE_META_DATA). + /// Base address of the module in memory. + /// void + public static void RewriteModuleIAT(h_reprobate.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase) + { + h_reprobate.PE.IMAGE_DATA_DIRECTORY idd = PEINFO.Is32Bit ? PEINFO.OptHeader32.ImportTable : PEINFO.OptHeader64.ImportTable; + + // Check if there is no import table + if (idd.VirtualAddress == 0) + { + // Return so that the rest of the module mapping process may continue. + return; + } + + // Ptr for the base import directory + IntPtr pImportTable = (IntPtr)((UInt64)ModuleMemoryBase + idd.VirtualAddress); + + // Get API Set mapping dictionary if on Win10+ + h_reprobate.OSVERSIONINFOEX OSVersion = new h_reprobate.OSVERSIONINFOEX(); + h_reprobate.RtlGetVersion(ref OSVersion); + Dictionary ApiSetDict = new Dictionary(); + if (OSVersion.MajorVersion >= 10) + { + ApiSetDict = GetApiSetMapping(); + } + + // Loop IID's + int counter = 0; + h_reprobate.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR iid = new h_reprobate.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR(); + iid = (h_reprobate.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR)Marshal.PtrToStructure( + (IntPtr)((UInt64)pImportTable + (uint)(Marshal.SizeOf(iid) * counter)), + typeof(h_reprobate.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR) + ); + while (iid.Name != 0) + { + // Get DLL + string DllName = string.Empty; + try + { + DllName = Marshal.PtrToStringAnsi((IntPtr)((UInt64)ModuleMemoryBase + iid.Name)); + } + catch { } + + // Loop imports + if (DllName == string.Empty) + { + throw new InvalidOperationException("Failed to read DLL name."); + } + else + { + // API Set DLL? + if (OSVersion.MajorVersion >= 10 && (DllName.StartsWith("api-") || DllName.StartsWith("ext-")) && + ApiSetDict.ContainsKey(DllName) && ApiSetDict[DllName].Length > 0) + { + // Not all API set DLL's have a registered host mapping + DllName = ApiSetDict[DllName]; + } + + // Check and / or load DLL + IntPtr hModule = GetLoadedModuleAddress(DllName); + if (hModule == IntPtr.Zero) + { + hModule = LoadModuleFromDisk(DllName); + if (hModule == IntPtr.Zero) + { + throw new FileNotFoundException(DllName + ", unable to find the specified file."); + } + } + + // Loop thunks + if (PEINFO.Is32Bit) + { + h_reprobate.PE.IMAGE_THUNK_DATA32 oft_itd = new h_reprobate.PE.IMAGE_THUNK_DATA32(); + for (int i = 0; true; i++) + { + oft_itd = (h_reprobate.PE.IMAGE_THUNK_DATA32)Marshal.PtrToStructure((IntPtr)((UInt64)ModuleMemoryBase + iid.OriginalFirstThunk + (UInt32)(i * (sizeof(UInt32)))), typeof(h_reprobate.PE.IMAGE_THUNK_DATA32)); + IntPtr ft_itd = (IntPtr)((UInt64)ModuleMemoryBase + iid.FirstThunk + (UInt64)(i * (sizeof(UInt32)))); + if (oft_itd.AddressOfData == 0) + { + break; + } + + if (oft_itd.AddressOfData < 0x80000000) // !IMAGE_ORDINAL_FLAG32 + { + IntPtr pImpByName = (IntPtr)((UInt64)ModuleMemoryBase + oft_itd.AddressOfData + sizeof(UInt16)); + IntPtr pFunc = IntPtr.Zero; + pFunc = GetNativeExportAddress(hModule, Marshal.PtrToStringAnsi(pImpByName)); + + // Write ProcAddress + Marshal.WriteInt32(ft_itd, pFunc.ToInt32()); + } + else + { + ulong fOrdinal = oft_itd.AddressOfData & 0xFFFF; + IntPtr pFunc = IntPtr.Zero; + pFunc = GetNativeExportAddress(hModule, (short)fOrdinal); + + // Write ProcAddress + Marshal.WriteInt32(ft_itd, pFunc.ToInt32()); + } + } + } + else + { + h_reprobate.PE.IMAGE_THUNK_DATA64 oft_itd = new h_reprobate.PE.IMAGE_THUNK_DATA64(); + for (int i = 0; true; i++) + { + oft_itd = (h_reprobate.PE.IMAGE_THUNK_DATA64)Marshal.PtrToStructure((IntPtr)((UInt64)ModuleMemoryBase + iid.OriginalFirstThunk + (UInt64)(i * (sizeof(UInt64)))), typeof(h_reprobate.PE.IMAGE_THUNK_DATA64)); + IntPtr ft_itd = (IntPtr)((UInt64)ModuleMemoryBase + iid.FirstThunk + (UInt64)(i * (sizeof(UInt64)))); + if (oft_itd.AddressOfData == 0) + { + break; + } + + if (oft_itd.AddressOfData < 0x8000000000000000) // !IMAGE_ORDINAL_FLAG64 + { + IntPtr pImpByName = (IntPtr)((UInt64)ModuleMemoryBase + oft_itd.AddressOfData + sizeof(UInt16)); + IntPtr pFunc = IntPtr.Zero; + pFunc = GetNativeExportAddress(hModule, Marshal.PtrToStringAnsi(pImpByName)); + + // Write pointer + Marshal.WriteInt64(ft_itd, pFunc.ToInt64()); + } + else + { + ulong fOrdinal = oft_itd.AddressOfData & 0xFFFF; + IntPtr pFunc = IntPtr.Zero; + pFunc = GetNativeExportAddress(hModule, (short)fOrdinal); + + // Write pointer + Marshal.WriteInt64(ft_itd, pFunc.ToInt64()); + } + } + } + counter++; + iid = (h_reprobate.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR)Marshal.PtrToStructure( + (IntPtr)((UInt64)pImportTable + (uint)(Marshal.SizeOf(iid) * counter)), + typeof(h_reprobate.Win32.Kernel32.IMAGE_IMPORT_DESCRIPTOR) + ); + } + } + } + + /// + /// Set correct module section permissions. + /// + /// Ruben Boonen (@FuzzySec) + /// Module meta data struct (h_reprobate.PE.PE_META_DATA). + /// Base address of the module in memory. + /// void + public static void SetModuleSectionPermissions(h_reprobate.PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase) + { + // Apply RO to the module header + IntPtr BaseOfCode = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.BaseOfCode : (IntPtr)PEINFO.OptHeader64.BaseOfCode; + h_reprobate.NtProtectVirtualMemory((IntPtr)(-1), ref ModuleMemoryBase, ref BaseOfCode, h_reprobate.Win32.WinNT.PAGE_READONLY); + + // Apply section permissions + foreach (h_reprobate.PE.IMAGE_SECTION_HEADER ish in PEINFO.Sections) + { + bool isRead = (ish.Characteristics & h_reprobate.PE.DataSectionFlags.MEM_READ) != 0; + bool isWrite = (ish.Characteristics & h_reprobate.PE.DataSectionFlags.MEM_WRITE) != 0; + bool isExecute = (ish.Characteristics & h_reprobate.PE.DataSectionFlags.MEM_EXECUTE) != 0; + uint flNewProtect = 0; + if (isRead & !isWrite & !isExecute) + { + flNewProtect = h_reprobate.Win32.WinNT.PAGE_READONLY; + } + else if (isRead & isWrite & !isExecute) + { + flNewProtect = h_reprobate.Win32.WinNT.PAGE_READWRITE; + } + else if (isRead & isWrite & isExecute) + { + flNewProtect = h_reprobate.Win32.WinNT.PAGE_EXECUTE_READWRITE; + } + else if (isRead & !isWrite & isExecute) + { + flNewProtect = h_reprobate.Win32.WinNT.PAGE_EXECUTE_READ; + } + else if (!isRead & !isWrite & isExecute) + { + flNewProtect = h_reprobate.Win32.WinNT.PAGE_EXECUTE; + } + else + { + throw new InvalidOperationException("Unknown section flag, " + ish.Characteristics); + } + + // Calculate base + IntPtr pVirtualSectionBase = (IntPtr)((UInt64)ModuleMemoryBase + ish.VirtualAddress); + IntPtr ProtectSize = (IntPtr)ish.VirtualSize; + + // Set protection + h_reprobate.NtProtectVirtualMemory((IntPtr)(-1), ref pVirtualSectionBase, ref ProtectSize, flNewProtect); + } + } + + /// + /// Manually map module into current process. + /// + /// Ruben Boonen (@FuzzySec) + /// Full path to the module on disk. + /// PE_MANUAL_MAP object + public static h_reprobate.PE.PE_MANUAL_MAP MapModuleToMemory(string ModulePath) + { + // Verify process & architecture + bool isWOW64 = h_reprobate.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Manual mapping in WOW64 is not supported."); + } + + // Alloc module into memory for parsing + IntPtr pModule = AllocateFileToMemory(ModulePath); + return MapModuleToMemory(pModule); + } + + /// + /// Manually map module into current process. + /// + /// Ruben Boonen (@FuzzySec) + /// Full byte array of the module. + /// PE_MANUAL_MAP object + public static h_reprobate.PE.PE_MANUAL_MAP MapModuleToMemory(byte[] Module) + { + // Verify process & architecture + bool isWOW64 = h_reprobate.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Manual mapping in WOW64 is not supported."); + } + + // Alloc module into memory for parsing + IntPtr pModule = AllocateBytesToMemory(Module); + return MapModuleToMemory(pModule); + } + + /// + /// Manually map module into current process starting at the specified base address. + /// + /// The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + /// Full byte array of the module. + /// Address in memory to map module to. + /// PE_MANUAL_MAP object + public static h_reprobate.PE.PE_MANUAL_MAP MapModuleToMemory(byte[] Module, IntPtr pImage) + { + // Verify process & architecture + Boolean isWOW64 = h_reprobate.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Manual mapping in WOW64 is not supported."); + } + + // Alloc module into memory for parsing + IntPtr pModule = AllocateBytesToMemory(Module); + + return MapModuleToMemory(pModule, pImage); + } + + /// + /// Manually map module into current process. + /// + /// Ruben Boonen (@FuzzySec) + /// Pointer to the module base. + /// PE_MANUAL_MAP object + public static h_reprobate.PE.PE_MANUAL_MAP MapModuleToMemory(IntPtr pModule) + { + // Fetch PE meta data + h_reprobate.PE.PE_META_DATA PEINFO = GetPeMetaData(pModule); + + // Check module matches the process architecture + if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4)) + { + Marshal.FreeHGlobal(pModule); + throw new InvalidOperationException("The module architecture does not match the process architecture."); + } + + // Alloc PE image memory -> RW + IntPtr BaseAddress = IntPtr.Zero; + IntPtr RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage; + IntPtr pImage = h_reprobate.NtAllocateVirtualMemory( + (IntPtr)(-1), ref BaseAddress, IntPtr.Zero, ref RegionSize, + h_reprobate.Win32.Kernel32.AllocationType.Commit | h_reprobate.Win32.Kernel32.AllocationType.Reserve, + h_reprobate.Win32.WinNT.PAGE_READWRITE + ); + return MapModuleToMemory(pModule, pImage, PEINFO); + } + + /// + /// Manually map module into current process. + /// + /// Ruben Boonen (@FuzzySec) + /// Pointer to the module base. + /// Pointer to the PEINFO image. + /// PE_MANUAL_MAP object + public static h_reprobate.PE.PE_MANUAL_MAP MapModuleToMemory(IntPtr pModule, IntPtr pImage) + { + h_reprobate.PE.PE_META_DATA PEINFO = GetPeMetaData(pModule); + return MapModuleToMemory(pModule, pImage, PEINFO); + } + + /// + /// Manually map module into current process. + /// + /// Ruben Boonen (@FuzzySec) + /// Pointer to the module base. + /// Pointer to the PEINFO image. + /// PE_META_DATA of the module being mapped. + /// PE_MANUAL_MAP object + public static h_reprobate.PE.PE_MANUAL_MAP MapModuleToMemory(IntPtr pModule, IntPtr pImage, h_reprobate.PE.PE_META_DATA PEINFO) + { + // Check module matches the process architecture + if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4)) + { + Marshal.FreeHGlobal(pModule); + throw new InvalidOperationException("The module architecture does not match the process architecture."); + } + + // Write PE header to memory + UInt32 SizeOfHeaders = PEINFO.Is32Bit ? PEINFO.OptHeader32.SizeOfHeaders : PEINFO.OptHeader64.SizeOfHeaders; + UInt32 BytesWritten = h_reprobate.NtWriteVirtualMemory((IntPtr)(-1), pImage, pModule, SizeOfHeaders); + + // Write sections to memory + foreach (h_reprobate.PE.IMAGE_SECTION_HEADER ish in PEINFO.Sections) + { + // Calculate offsets + IntPtr pVirtualSectionBase = (IntPtr)((UInt64)pImage + ish.VirtualAddress); + IntPtr pRawSectionBase = (IntPtr)((UInt64)pModule + ish.PointerToRawData); + + // Write data + BytesWritten = h_reprobate.NtWriteVirtualMemory((IntPtr)(-1), pVirtualSectionBase, pRawSectionBase, ish.SizeOfRawData); + if (BytesWritten != ish.SizeOfRawData) + { + throw new InvalidOperationException("Failed to write to memory."); + } + } + + // Perform relocations + RelocateModule(PEINFO, pImage); + + // Rewrite IAT + RewriteModuleIAT(PEINFO, pImage); + + // Set memory protections + SetModuleSectionPermissions(PEINFO, pImage); + + // Free temp HGlobal + Marshal.FreeHGlobal(pModule); + + // Prepare return object + h_reprobate.PE.PE_MANUAL_MAP ManMapObject = new h_reprobate.PE.PE_MANUAL_MAP + { + ModuleBase = pImage, + PEINFO = PEINFO + }; + + return ManMapObject; + } + + /// + /// Free a module that was mapped into the current process. + /// + /// The Wover (@TheRealWover) + /// The metadata of the manually mapped module. + public static void FreeModule(h_reprobate.PE.PE_MANUAL_MAP PEMapped) + { + // Check if PE was mapped via module overloading + if (!string.IsNullOrEmpty(PEMapped.DecoyModule)) + { + h_reprobate.NtUnmapViewOfSection((IntPtr)(-1), PEMapped.ModuleBase); + } + // If PE not mapped via module overloading, free the memory. + else + { + h_reprobate.PE.PE_META_DATA PEINFO = PEMapped.PEINFO; + + // Get the size of the module in memory + IntPtr size = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage; + IntPtr pModule = PEMapped.ModuleBase; + + h_reprobate.NtFreeVirtualMemory((IntPtr)(-1), ref pModule, ref size, h_reprobate.Win32.Kernel32.AllocationType.Release); + } + } + + /// + /// Locate a signed module with a minimum size which can be used for overloading. + /// + /// The Wover (@TheRealWover) + /// Minimum module byte size. + /// Whether to require that the module be legitimately signed. + /// + /// String, the full path for the candidate module if one is found, or an empty string if one is not found. + /// + public static string FindDecoyModule(long MinSize, bool LegitSigned = true) + { + string SystemDirectoryPath = Environment.GetEnvironmentVariable("WINDIR") + Path.DirectorySeparatorChar + "System32"; + List files = new List(Directory.GetFiles(SystemDirectoryPath, "*.dll")); + foreach (ProcessModule Module in Process.GetCurrentProcess().Modules) + { + if (files.Any(s => s.Equals(Module.FileName, StringComparison.OrdinalIgnoreCase))) + { + files.RemoveAt(files.FindIndex(x => x.Equals(Module.FileName, StringComparison.OrdinalIgnoreCase))); + } + } + + // Pick a random candidate that meets the requirements + Random r = new Random(); + // List of candidates that have been considered and rejected + List candidates = new List(); + while (candidates.Count != files.Count) + { + // Iterate through the list of files randomly + int rInt = r.Next(0, files.Count); + string currentCandidate = files[rInt]; + + // Check that the size of the module meets requirements + if (candidates.Contains(rInt) == false && + new FileInfo(currentCandidate).Length >= MinSize) + { + // Check that the module meets signing requirements + if (LegitSigned == true) + { + if (FileHasValidSignature(currentCandidate) == true) + { + return currentCandidate; + } + else + { + candidates.Add(rInt); + } + } + else + { + return currentCandidate; + } + } + candidates.Add(rInt); + } + return string.Empty; + } + + /// + /// Load a signed decoy module into memory, creating legitimate file-backed memory sections within the process. Afterwards overload that + /// module by manually mapping a payload in it's place causing the payload to execute from what appears to be file-backed memory. + /// + /// The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + /// Full path to the payload module on disk. + /// Optional, full path the decoy module to overload in memory. + /// PE.PE_MANUAL_MAP + public static h_reprobate.PE.PE_MANUAL_MAP OverloadModule(string PayloadPath, string DecoyModulePath = null) + { + // Verify process & architecture + bool isWOW64 = h_reprobate.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Module overloading in WOW64 is not supported."); + } + + // Get approximate size of Payload + if (!File.Exists(PayloadPath)) + { + throw new InvalidOperationException("Payload filepath not found."); + } + byte[] Payload = File.ReadAllBytes(PayloadPath); + + return OverloadModule(Payload, DecoyModulePath); + } + + /// + /// Load a signed decoy module into memory creating legitimate file-backed memory sections within the process. Afterwards overload that + /// module by manually mapping a payload in it's place causing the payload to execute from what appears to be file-backed memory. + /// + /// The Wover (@TheRealWover), Ruben Boonen (@FuzzySec) + /// Full byte array for the payload module. + /// Optional, full path the decoy module to overload in memory. + /// PE.PE_MANUAL_MAP + public static h_reprobate.PE.PE_MANUAL_MAP OverloadModule(byte[] Payload, string DecoyModulePath = null) + { + // Verify process & architecture + bool isWOW64 = h_reprobate.NtQueryInformationProcessWow64Information((IntPtr)(-1)); + if (IntPtr.Size == 4 && isWOW64) + { + throw new InvalidOperationException("Module overloading in WOW64 is not supported."); + } + + // Did we get a DecoyModule? + if (!string.IsNullOrEmpty(DecoyModulePath)) + { + if (!File.Exists(DecoyModulePath)) + { + throw new InvalidOperationException("Decoy filepath not found."); + } + byte[] DecoyFileBytes = File.ReadAllBytes(DecoyModulePath); + if (DecoyFileBytes.Length < Payload.Length) + { + throw new InvalidOperationException("Decoy module is too small to host the payload."); + } + } + else + { + DecoyModulePath = FindDecoyModule(Payload.Length); + if (string.IsNullOrEmpty(DecoyModulePath)) + { + throw new InvalidOperationException("Failed to find suitable decoy module."); + } + } + + // Map decoy from disk + h_reprobate.PE.PE_MANUAL_MAP DecoyMetaData = MapModuleFromDisk(DecoyModulePath); + IntPtr RegionSize = DecoyMetaData.PEINFO.Is32Bit ? (IntPtr)DecoyMetaData.PEINFO.OptHeader32.SizeOfImage : (IntPtr)DecoyMetaData.PEINFO.OptHeader64.SizeOfImage; + + // Change permissions to RW + h_reprobate.NtProtectVirtualMemory((IntPtr)(-1), ref DecoyMetaData.ModuleBase, ref RegionSize, h_reprobate.Win32.WinNT.PAGE_READWRITE); + + // Zero out memory + h_reprobate.RtlZeroMemory(DecoyMetaData.ModuleBase, (int)RegionSize); + + // Overload module in memory + h_reprobate.PE.PE_MANUAL_MAP OverloadedModuleMetaData = MapModuleToMemory(Payload, DecoyMetaData.ModuleBase); + OverloadedModuleMetaData.DecoyModule = DecoyModulePath; + + return OverloadedModuleMetaData; + } + + public static bool FileHasValidSignature(string FilePath) + { + X509Certificate2 FileCertificate; + try + { + X509Certificate signer = X509Certificate.CreateFromSignedFile(FilePath); + FileCertificate = new X509Certificate2(signer); + } + catch + { + return false; + } + + X509Chain CertificateChain = new X509Chain(); + CertificateChain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain; + CertificateChain.ChainPolicy.RevocationMode = X509RevocationMode.Offline; + CertificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag; + + return CertificateChain.Build(FileCertificate); + } + } +}