Process Hacker
svcext.c
Go to the documentation of this file.
1 /*
2  * Process Hacker .NET Tools -
3  * phsvc extensions
4  *
5  * Copyright (C) 2015 wj32
6  *
7  * This file is part of Process Hacker.
8  *
9  * Process Hacker is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Process Hacker is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include "dn.h"
24 #include "svcext.h"
25 #include "clrsup.h"
26 
28  _In_ HANDLE ProcessId,
29  _In_ ULONG64 Address,
30  _Out_opt_ PULONG64 Displacement
31  )
32 {
33  NTSTATUS status;
37  ULONG bufferSize;
38  PVOID buffer;
39  PPH_STRING name = NULL;
40 
41  if (!PhPluginQueryPhSvc(&client))
42  return NULL;
43 
44  in.i.ProcessId = HandleToUlong(ProcessId);
45  in.i.Address = Address;
46 
47  bufferSize = 0x1000;
48 
49  if (!(buffer = client.CreateString(NULL, bufferSize, &in.i.Name)))
50  return NULL;
51 
52  status = PhPluginCallPhSvc(PluginInstance, DnGetRuntimeNameByAddressApiNumber, &in, sizeof(in), &out, sizeof(out));
53 
54  if (status == STATUS_BUFFER_OVERFLOW)
55  {
56  client.FreeHeap(buffer);
57  bufferSize = out.o.NameLength;
58 
59  if (!(buffer = client.CreateString(NULL, bufferSize, &in.i.Name)))
60  return NULL;
61 
62  status = PhPluginCallPhSvc(PluginInstance, DnGetRuntimeNameByAddressApiNumber, &in, sizeof(in), &out, sizeof(out));
63  }
64 
65  if (NT_SUCCESS(status))
66  {
67  name = PhCreateStringEx(buffer, out.o.NameLength);
68 
69  if (Displacement)
70  *Displacement = out.o.Displacement;
71  }
72 
73  client.FreeHeap(buffer);
74 
75  return name;
76 }
77 
79  _In_ PPH_PLUGIN_PHSVC_REQUEST Request,
82  )
83 {
84  NTSTATUS status = STATUS_SUCCESS;
85  PVOID nameBuffer;
86  PCLR_PROCESS_SUPPORT support;
87  PPH_STRING name;
88 
89  if (!NT_SUCCESS(status = Request->ProbeBuffer(&In->i.Name, sizeof(WCHAR), FALSE, &nameBuffer)))
90  return status;
91 
92  support = CreateClrProcessSupport(UlongToHandle(In->i.ProcessId));
93 
94  if (!support)
95  return STATUS_UNSUCCESSFUL;
96 
97  name = GetRuntimeNameByAddressClrProcess(support, In->i.Address, &Out->o.Displacement);
98 
99  if (!name)
100  {
101  status = STATUS_UNSUCCESSFUL;
102  goto CleanupExit;
103  }
104 
105  memcpy(nameBuffer, name->Buffer, min(name->Length, In->i.Name.Length));
106  Out->o.NameLength = (ULONG)name->Length;
107 
108  if (In->i.Name.Length < name->Length)
109  status = STATUS_BUFFER_OVERFLOW;
110 
111 CleanupExit:
112  FreeClrProcessSupport(support);
113 
114  return status;
115 }
116 
118  _In_ HANDLE ProcessId,
119  _In_ HANDLE ThreadId,
120  _In_ PVOID PcAddress,
121  _In_ PVOID FrameAddress,
122  _In_ PVOID StackAddress,
123  _Out_ PVOID *PredictedEip,
124  _Out_ PVOID *PredictedEbp,
125  _Out_ PVOID *PredictedEsp
126  )
127 {
128  PH_PLUGIN_PHSVC_CLIENT client;
131 
132  *PredictedEip = NULL;
133  *PredictedEbp = NULL;
134  *PredictedEsp = NULL;
135 
136  if (!PhPluginQueryPhSvc(&client))
137  return;
138 
139  in.i.ProcessId = HandleToUlong(ProcessId);
140  in.i.ThreadId = HandleToUlong(ThreadId);
141  in.i.PcAddress = PtrToUlong(PcAddress);
142  in.i.FrameAddress = PtrToUlong(FrameAddress);
143  in.i.StackAddress = PtrToUlong(StackAddress);
144 
145  if (NT_SUCCESS(PhPluginCallPhSvc(PluginInstance, DnPredictAddressesFromClrDataApiNumber, &in, sizeof(in), &out, sizeof(out))))
146  {
147  *PredictedEip = UlongToPtr(out.o.PredictedEip);
148  *PredictedEbp = UlongToPtr(out.o.PredictedEbp);
149  *PredictedEsp = UlongToPtr(out.o.PredictedEsp);
150  }
151 }
152 
154  _In_ PPH_PLUGIN_PHSVC_REQUEST Request,
157  )
158 {
159  PCLR_PROCESS_SUPPORT support;
160  PVOID predictedEip;
161  PVOID predictedEbp;
162  PVOID predictedEsp;
163 
164  support = CreateClrProcessSupport(UlongToHandle(In->i.ProcessId));
165 
166  if (!support)
167  return STATUS_UNSUCCESSFUL;
168 
170  support,
171  UlongToHandle(In->i.ThreadId),
172  UlongToPtr(In->i.PcAddress),
173  UlongToPtr(In->i.FrameAddress),
174  UlongToPtr(In->i.StackAddress),
175  &predictedEip,
176  &predictedEbp,
177  &predictedEsp
178  );
179  FreeClrProcessSupport(support);
180 
181  Out->o.PredictedEip = PtrToUlong(predictedEip);
182  Out->o.PredictedEbp = PtrToUlong(predictedEbp);
183  Out->o.PredictedEsp = PtrToUlong(predictedEsp);
184 
185  return STATUS_SUCCESS;
186 }
187 
189  _In_ PVOID Parameter
190  )
191 {
192  PPH_PLUGIN_PHSVC_REQUEST request = Parameter;
193  PVOID inBuffer;
194 
195  // InBuffer can alias OutBuffer, so make a copy of InBuffer.
196  inBuffer = PhAllocateCopy(request->InBuffer, request->InLength);
197 
198  switch (request->SubId)
199  {
201  request->ReturnStatus = DispatchGetRuntimeNameByAddress(request, inBuffer, request->OutBuffer);
202  break;
204  request->ReturnStatus = DispatchPredictAddressesFromClrData(request, inBuffer, request->OutBuffer);
205  break;
206  }
207 
208  PhFree(inBuffer);
209 }