Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // one should note this method builds x86 code which is not executable in a 64-bit application
- public int Call(IntPtr thisPointer, params object[] args)
- {
- // information that needs to be pushed to the stack
- // in a linear order
- // this co-responds directly to the op-code: PUSH value
- List<int> arguments = new List<int>();
- // a list of allocated resources that were marshalled for this call
- // for instance, strings must be marshaled over to the remote process
- // therefore, we must free the remotely marshaled string so we don't leave a memory leak
- List<ShellResource> freeResources = new List<ShellResource>();
- foreach (object obj in args)
- {
- if (obj is string)
- {
- string strObj = obj as string;
- byte[] bytes = Encoding.Default.GetBytes(strObj);
- ShellResource res = this.Environment.CreateResource(bytes.Length + 2);
- res.Write(bytes);
- res.Write(bytes.Length, new byte[2], 0, 2); // null terminator
- freeResources.Add(res);
- arguments.Add(res.RemoteAddress.ToInt32());
- }
- else if (obj is ulong || obj is long)
- {
- // if an argument is a long, it's actually pushed as 32-bit integers
- // the low 32-bit integer is pushed first, and then the high 32-bit integer is pushed next
- ulong i64Obj = Convert.ToUInt64(obj);
- arguments.Add((int)(i64Obj & 0xFFFFFFFF));
- arguments.Add((int)(i64Obj >> 32));
- }
- else if (obj is IntPtr)
- {
- arguments.Add(((IntPtr)obj).ToInt32());
- }
- else
- {
- arguments.Add(Convert.ToInt32(obj));
- }
- }
- // this is due to the fact that arguments are popped off the stack in reverse
- // therefore while 'args' is in the correct order, we must now reverse the order
- // added to arguments so that we can push them in the correct order
- arguments.Reverse();
- // initialize a new instance of a remote-method builder
- MethodBuilder builder = new MethodBuilder();
- // creates the method header, with an optional parameter (default: false) for a break point (int3)
- // the method header consists of all that good stuff, you know
- // push ebp
- // mov ebp, esp
- builder.MethodHeader();
- // push the arguments onto the stack
- foreach (int pushObj in arguments)
- builder.Push(pushObj);
- // if there was a this pointer, it's moved to ecx as ecx is set to the 'this' pointer before a __thiscall is invoked
- builder.MoveEcx(thisPointer);
- // this method basically moves to eax the remote value and then calls eax,
- // in pseudo code:
- // mov eax, this.RemoteAddress
- // call eax
- builder.CallEax(this.RemoteAddress);
- // if the method we just called is has the __cdecl calling convention we must align the stack
- // as in a __cdecl call, it is the callers job to align esp to the number of bytes pushed onto the stack
- // for the given call
- if (Convention == CallingConvention.Cdecl)
- builder.AlignStackPointer(arguments.Count * 4);
- // once again, like at the start, append the method footer, you know all that good stuff.
- builder.MethodFooter();
- int result;
- // so finally we translate from our builder to the byte[]
- byte[] methodBytes = builder.GetBytes();
- // we obtain a resource that represents our remote function
- ShellResource func = this.Environment.CreateResource(builder.CurrentSize);
- // we copy to the resource our remote function
- func.Write(builder.GetBytes());
- // invoke our remote function
- IntPtr exec = CreateRemoteThread(this.Environment.Handle, null, 0, func.RemoteAddress, null, 0, null);
- if (exec == IntPtr.Zero)
- throw new ShellException(this.Environment, "Failed to create remote function.");
- else
- {
- // if the thread has been successfully created, we block this call until that thread executes
- // this allows for linear execution
- WaitForSingleObject(exec, int.MaxValue);
- // this gets the return value of the function we just invoked.
- // the only problem that could occur here is if the return value is something greater than 32-bits
- GetExitCodeThread(exec, &result);
- CloseHandle(exec);
- }
- // free the remote resource containing our remote function
- func.Destroy();
- // clean up (free) all marshaled strings, objects, etc.
- foreach (ShellResource res in freeResources)
- res.Destroy();
- // return the result of whatever the remote function we just invoked. Boo ya'
- return result;
- }
Add Comment
Please, Sign In to add comment