Guest User

Untitled

a guest
Oct 23rd, 2017
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 4.92 KB | None | 0 0
  1. // one should note this method builds x86 code which is not executable in a 64-bit application
  2.         public int Call(IntPtr thisPointer, params object[] args)
  3.         {
  4.  
  5. // information that needs to be pushed to the stack
  6. // in a linear order
  7. // this co-responds directly to the op-code:    PUSH value
  8.  
  9.             List<int> arguments = new List<int>();
  10.  
  11. // a list of allocated resources that were marshalled for this call
  12. // for instance, strings must be marshaled over to the remote process
  13. // therefore, we must free the remotely marshaled string so we don't leave a memory leak
  14.             List<ShellResource> freeResources = new List<ShellResource>();
  15.             foreach (object obj in args)
  16.             {
  17.                 if (obj is string)
  18.                 {
  19.                     string strObj = obj as string;
  20.                     byte[] bytes = Encoding.Default.GetBytes(strObj);
  21.                     ShellResource res = this.Environment.CreateResource(bytes.Length + 2);
  22.                     res.Write(bytes);
  23.                     res.Write(bytes.Length, new byte[2], 0, 2); // null terminator
  24.  
  25.                     freeResources.Add(res);
  26.                     arguments.Add(res.RemoteAddress.ToInt32());
  27.                 }
  28.                 else if (obj is ulong || obj is long)
  29.                 {
  30.  
  31. // if an argument is a long, it's actually pushed as 32-bit integers
  32. // the low 32-bit integer is pushed first, and then the high 32-bit integer is pushed next
  33.  
  34.                     ulong i64Obj = Convert.ToUInt64(obj);
  35.                     arguments.Add((int)(i64Obj & 0xFFFFFFFF));
  36.                     arguments.Add((int)(i64Obj >> 32));
  37.                 }
  38.                 else if (obj is IntPtr)
  39.                 {
  40.                     arguments.Add(((IntPtr)obj).ToInt32());
  41.                 }
  42.                 else
  43.                 {
  44.                     arguments.Add(Convert.ToInt32(obj));
  45.                 }
  46.             }
  47.  
  48. // this is due to the fact that arguments are popped off the stack in reverse
  49. // therefore while 'args' is in the correct order, we must now reverse the order
  50. // added to arguments so that we can push them in the correct order
  51.  
  52.             arguments.Reverse();
  53.  
  54. // initialize a new instance of a remote-method builder
  55.             MethodBuilder builder = new MethodBuilder();
  56. // creates the method header, with an optional parameter (default: false) for a break point (int3)
  57. // the method header consists of all that good stuff, you know
  58. // push ebp
  59. // mov ebp, esp
  60.             builder.MethodHeader();
  61. // push the arguments onto the stack
  62.             foreach (int pushObj in arguments)
  63.                 builder.Push(pushObj);
  64. // if there was a this pointer, it's moved to ecx as ecx is set to the 'this' pointer before a __thiscall is invoked
  65.             builder.MoveEcx(thisPointer);
  66. // this method basically moves to eax the remote value and then calls eax,
  67. // in pseudo code:
  68. // mov eax, this.RemoteAddress
  69. // call eax
  70.             builder.CallEax(this.RemoteAddress);
  71. // if the method we just called is has the __cdecl calling convention we must align the stack
  72. // as in a __cdecl call, it is the callers job to align esp to the number of bytes pushed onto the stack
  73. // for the given call
  74.             if (Convention == CallingConvention.Cdecl)
  75.                 builder.AlignStackPointer(arguments.Count * 4);
  76. // once again, like at the start, append the method footer, you know all that good stuff.
  77.             builder.MethodFooter();
  78.  
  79.             int result;
  80. // so finally we translate from our builder to the byte[]
  81.             byte[] methodBytes = builder.GetBytes();
  82. // we obtain a resource that represents our remote function
  83.             ShellResource func = this.Environment.CreateResource(builder.CurrentSize);
  84. // we copy to the resource our remote function
  85.             func.Write(builder.GetBytes());
  86. // invoke our remote function
  87.             IntPtr exec = CreateRemoteThread(this.Environment.Handle, null, 0, func.RemoteAddress, null, 0, null);
  88.             if (exec == IntPtr.Zero)
  89.                 throw new ShellException(this.Environment, "Failed to create remote function.");
  90.             else
  91.             {
  92. // if the thread has been successfully created, we block this call until that thread executes
  93. // this allows for linear execution
  94.                 WaitForSingleObject(exec, int.MaxValue);
  95. // this gets the return value of the function we just invoked.
  96. // the only problem that could occur here is if the return value is something greater than 32-bits
  97.                 GetExitCodeThread(exec, &result);
  98.                 CloseHandle(exec);
  99.             }
  100.  
  101. // free the remote resource containing our remote function
  102.             func.Destroy();
  103.  
  104. // clean up (free) all marshaled strings, objects, etc.
  105.             foreach (ShellResource res in freeResources)
  106.                 res.Destroy();
  107.  
  108. // return the result of whatever the remote function we just invoked. Boo ya'
  109.             return result;
  110.         }
Add Comment
Please, Sign In to add comment