Created
July 5, 2014 09:56
-
-
Save LRNAB/1275ba38d3ef0a66cf09 to your computer and use it in GitHub Desktop.
Edit Image Path, Dll Path and Directory of a Process
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
unsafe class PEBEditor | |
{ | |
[DllImport("ntdll.dll")] | |
static extern UInt32 NtQueryInformationProcess(IntPtr ProcessHandle, Int32 ProcessInformationClass, out Process_Basic_Information ProcessInformation, UInt32 ProcessInformationLength, out UInt32 ReturnLength); | |
[DllImport("kernel32.dll")] | |
static extern Boolean VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, UInt32 dwSize, UInt32 flNewProtect, out UInt32 lpflOldProtect); | |
[DllImport("kernel32.dll")] | |
static extern Boolean WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, UInt32 nSize, out UInt32 lpNumberOfBytesWritten); | |
[DllImport("kernel32.dll")] | |
static extern Boolean ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, UInt32 nSize, out UInt32 lpNumberOfBytesRead); | |
[StructLayout(LayoutKind.Sequential)] | |
struct Process_Basic_Information | |
{ | |
public IntPtr Reserved1; | |
public IntPtr PebBaseAddress; | |
public IntPtr Reserved2a; | |
public IntPtr Reserved2b; | |
public UInt32 UniqueProcessId; | |
public IntPtr Reserved3; | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
struct Process_Environment_Block | |
{ | |
public fixed Byte Reserved1[2]; | |
public Byte BeingDebugged; | |
public fixed Byte Reserved2[1]; | |
public IntPtr Mutant; | |
public IntPtr ImageBaseAddress; | |
public IntPtr LoaderData; | |
public IntPtr ProcessParameters; | |
public fixed Byte Reserved4[104]; | |
public fixed UInt32 Reserved5[52]; | |
public IntPtr PostProcessInitRoutine; | |
public fixed Byte Reserved6[128]; | |
public fixed UInt32 Reserved7[1]; | |
public UInt32 SessionId; | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
struct Rtl_User_Process_Parameters | |
{ | |
public UInt32 MaximumLength; | |
public UInt32 Length; | |
public UInt32 Flags; | |
public UInt32 DebugFlags; | |
public IntPtr ConsoleHandle; | |
public UInt32 ConsoleFlags; | |
public IntPtr StdInputHandle; | |
public IntPtr StdOutputHandle; | |
public IntPtr StdErrorHandle; | |
public UNICODE_STRING CurrentDirectoryPath; | |
public IntPtr CurrentDirectoryHandle; | |
public UNICODE_STRING DllPath; | |
public UNICODE_STRING ImagePathName; | |
public UNICODE_STRING CommandLine; | |
public IntPtr Environment; | |
public UInt32 StartingPositionLeft; | |
public UInt32 StartingPositionTop; | |
public UInt32 Width; | |
public UInt32 Height; | |
public UInt32 CharWidth; | |
public UInt32 CharHeight; | |
public UInt32 ConsoleTextAttributes; | |
public UInt32 WindowFlags; | |
public UInt32 ShowWindowFlags; | |
public UNICODE_STRING WindowTitle; | |
public UNICODE_STRING DesktopName; | |
public UNICODE_STRING ShellInfo; | |
public UNICODE_STRING RuntimeData; | |
public fixed Byte DLCurrentDirectory[0x20 * 0xc]; | |
} | |
public struct UNICODE_STRING | |
{ | |
public UInt16 Length; | |
public UInt16 MaximumLength; | |
public IntPtr Buffer; | |
} | |
public static void EditPaths(IntPtr hProcess, String imagepathname, String dllpath, String currentdirectorypath) | |
{ | |
if (hProcess == IntPtr.Zero) | |
return; | |
var ProcessBasicInfo = new Process_Basic_Information(); | |
var PEB = new Process_Environment_Block(); | |
var UserProcessParam = new Rtl_User_Process_Parameters(); | |
var ProcessBasicInfoSize = (UInt32)Marshal.SizeOf(typeof(Process_Basic_Information)); | |
var PEBSize = (UInt32)Marshal.SizeOf(typeof(Process_Environment_Block)); | |
var UserProcessParamSize = (UInt32)Marshal.SizeOf(typeof(Rtl_User_Process_Parameters)); | |
UInt32 BytesRead = 0; | |
UInt32 BytesWritten = 0; | |
// Fill ProcessBasicInfo to get PEBBaseAddress. 0x00000000 is NtStatus.Success | |
if (NtQueryInformationProcess(hProcess, 0, out ProcessBasicInfo, ProcessBasicInfoSize, out BytesRead) != 0x00000000) | |
return; | |
// Output | |
Console.WriteLine(String.Concat("PEBBaseAddress: ", ProcessBasicInfo.PebBaseAddress)); | |
Console.WriteLine("Continue? y/n"); | |
if (Console.ReadKey(false).Key != ConsoleKey.Y) | |
return; | |
Console.WriteLine(" "); | |
// Read from the PEBBaseAddress to fill PEB and get ProcessParameters(Pointer to RTL_USER_PROCESS_PARAMETERS structure). | |
if (!Convert.ToBoolean(ReadProcessMemory(hProcess, ProcessBasicInfo.PebBaseAddress, (IntPtr)(&PEB), PEBSize, out BytesRead))) | |
return; | |
// Output | |
Console.WriteLine(String.Concat("ProcessParameters: ", PEB.ProcessParameters)); | |
Console.WriteLine(String.Concat("ImageBaseAddress: ", PEB.ImageBaseAddress)); | |
Console.WriteLine("Continue? y/n"); | |
if (Console.ReadKey(false).Key != ConsoleKey.Y) | |
return; | |
Console.WriteLine(" "); | |
// Get RTL_USER_PROCESS_PARAMETERS from ProcessParameters | |
if (!ReadProcessMemory(hProcess, PEB.ProcessParameters, (IntPtr)(&UserProcessParam), UserProcessParamSize, out BytesRead)) | |
return; | |
// Write new locations | |
WriteString(hProcess, ref UserProcessParam.ImagePathName, imagepathname); | |
WriteString(hProcess, ref UserProcessParam.CommandLine, dllpath); | |
WriteString(hProcess, ref UserProcessParam.CurrentDirectoryPath, currentdirectorypath); | |
// Update the memory to reflect the changes. | |
if (!WriteProcessMemory(hProcess, PEB.ProcessParameters, (IntPtr)(&UserProcessParam), UserProcessParamSize, out BytesWritten)) | |
return; | |
// Output | |
Console.WriteLine("Finished!"); | |
} | |
private static void WriteString(IntPtr hProcess, ref UNICODE_STRING unicode, String ascii) | |
{ | |
if (String.IsNullOrEmpty(ascii)) | |
return; | |
UInt32 oldaccess; | |
// Encode the String | |
Byte[] stringbuffer = Encoding.Unicode.GetBytes(ascii); | |
// Allocate unmanaged memory in this process | |
IntPtr ptr = Marshal.AllocHGlobal(stringbuffer.Length); | |
// Copy encoded string to the unmanaged memory allocated | |
Marshal.Copy(stringbuffer, 0, ptr, stringbuffer.Length); | |
// Grant me PAGE_EXECUTE_READWRITE access to memory of process | |
VirtualProtectEx(hProcess, unicode.Buffer, (UInt32)stringbuffer.Length, 0x40, out oldaccess); | |
// Decode Unicode String to ASCII | |
Console.WriteLine(String.Concat("Over-writing ", unicode.ToString(), " with ", ascii)); | |
Console.WriteLine("Continue? y/n"); | |
if (Console.ReadKey(false).Key != ConsoleKey.Y) | |
return; | |
Console.WriteLine(" "); | |
// Overwrite the memory | |
WriteProcessMemory(hProcess, unicode.Buffer, ptr, (UInt32)stringbuffer.Length, out oldaccess); | |
// Convert ASCII length to Unicode Length | |
unicode.Length = (UInt16)(ascii.Length * 2); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment