-
Notifications
You must be signed in to change notification settings - Fork 44
Expand file tree
/
Copy pathNtUtils.NtUser.Oleacc.pas
More file actions
148 lines (114 loc) · 4.07 KB
/
NtUtils.NtUser.Oleacc.pas
File metadata and controls
148 lines (114 loc) · 4.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
unit NtUtils.NtUser.Oleacc;
{
This module provides support for OLE Accessibility Hooks.
}
interface
uses
Ntapi.WinUser, Ntapi.Versions, NtUtils;
// Open a process handle via an OLE accessibility hook
// See GetProcessHandleFromHwnd docs on MSDN
[MinOSVersion(OsWin10RS1)]
function OleacxOpenProcessByWindow(
out hxProcess: IHandle;
hwnd: THwnd;
TimeoutMs: Cardinal = 5000
): TNtxStatus;
implementation
uses
Ntapi.WinNt, Ntapi.ntseapi, Ntapi.ntmmapi, Ntapi.ntuser, Ntapi.ntpsapi,
Ntapi.ObjIdl, DelphiUtils.AutoObjects, NtUtils.Ldr, NtUtils.NtUser,
NtUtils.SysUtils, NtUtils.Tokens.Info, NtUtils.Security, NtUtils.Security.Acl,
NtUtils.Sections, NtUtils.Objects, NtUtils.Objects.Namespace;
{$BOOLEVAL OFF}
{$IFOPT R+}{$DEFINE R+}{$ENDIF}
{$IFOPT Q+}{$DEFINE Q+}{$ENDIF}
function RtlxMakeCurrentIntegritySecurityDescriptor(
out SD: ISecurityDescriptor
): TNtxStatus;
var
IntegritySid: ISid;
SdData: TSecurityDescriptorData;
begin
// Determine the current SID
Result := NtxQuerySidToken(NtxCurrentProcessToken, TokenIntegrityLevel,
IntegritySid);
if not Result.IsSuccess then
Exit;
SdData := Default(TSecurityDescriptorData);
SdData.Control := SE_SACL_PRESENT;
// Prepare a SACL with the corresponding no-write-up label
Result := RtlxBuildAcl(SdData.Sacl, [TAceData.New(
SYSTEM_MANDATORY_LABEL_ACE_TYPE, 0, SYSTEM_MANDATORY_LABEL_NO_WRITE_UP,
IntegritySid)]);
if not Result.IsSuccess then
Exit;
// Capture it in self-relative security descriptor
Result := RtlxAllocateSecurityDescriptor(SdData, SD);
end;
function OleacxOpenProcessByWindow;
var
BnoPath: String;
hxSection, hxHook: IHandle;
SD: ISecurityDescriptor;
Mapping: IMemory<POleaccRequestMessage>;
MessageId: Cardinal;
TargetThreadId: TThreadId;
hProcess: THandle;
begin
// The logic depends on the OLEACC hooking library being available
Result := LdrxCheckDelayedImport(delayed_OleAccHook_CallWndProc);
if not Result.IsSuccess then
Exit;
// Determine the window's owning thread
Result := NtxWindow.Query(hwnd, WindowThread, TargetThreadId);
if not Result.IsSuccess then
Exit;
Result := RtlxGetNamedObjectPath(BnoPath);
if not Result.IsSuccess then
Exit;
// Prepare a unique name for the shared section
BnoPath := RtlxCombinePaths(BnoPath, RtlxFormatString(
'OLEACC_HOOK_SHMEM_%d_%d', [NtCurrentProcessId, NtCurrentThreadId]));
// Prepare a security descriptor to protect it from anybody below our
// integrity (they will fail to send us the process handle anyway)
Result := RtlxMakeCurrentIntegritySecurityDescriptor(SD);
if not Result.IsSuccess then
Exit;
// Create a section for sharing data with the OLEACC hooks
Result := NtxCreateSection(hxSection, SizeOf(TOleaccRequestMessage),
PAGE_READWRITE, SEC_COMMIT, AttributeBuilder.UseName(BnoPath)
.UseSecurity(SD));
if not Result.IsSuccess then
Exit;
// Install the OLEACC hook in the target process
Result := NtxSetWindowsHookEx(
hxHook,
WH_CALLWNDPROC,
delayed_OleAccHook_CallWndProc.FunctionAddress,
RtlxGetNtSystemRoot + '\system32\' + oleacchooks,
delayed_OleAccHook_CallWndProc.Dll.DllAddress,
TargetThreadId
);
if not Result.IsSuccess then
Exit;
// Identify the message ID to use with the hook
Result := NtxRegisterWindowMessage('WM_OLEACC_HOOK', MessageId);
if not Result.IsSuccess then
Exit;
// Send a message to trigger the hook. The hook will duplicate the taget's
// process handle back to use and report its value via the shared section.
Result := NtxSendMessage(hwnd, MessageId, NtCurrentProcessId,
NativeInt(NtCurrentThreadId), SMTO_BLOCK or SMTO_ABORTIFHUNG or
SMTO_ERRORONEXIT, TimeoutMs);
if not Result.IsSuccess then
Exit;
// Prepare for using the section
Result := NtxMapViewOfSection(hxSection, NtxCurrentProcess, IMemory(Mapping),
MappingParameters.UseProtection(PAGE_READWRITE));
if not Result.IsSuccess then
Exit;
// Capture ownership of the sent handle
hProcess := AtomicExchange(Mapping.Data.ClientRelativeHandle, 0);
Result := NtxCaptureHandle(hxProcess, hProcess);
end;
end.