/src/SharpMonoInjector/Memory.cs

https://github.com/warbler/SharpMonoInjector · C# · 104 lines · 80 code · 24 blank · 0 comment · 7 complexity · 249ec36eb0805f0298c7f445ba6fa052 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. namespace SharpMonoInjector
  7. {
  8. public class Memory : IDisposable
  9. {
  10. private readonly IntPtr _handle;
  11. private readonly Dictionary<IntPtr, int> _allocations = new Dictionary<IntPtr, int>();
  12. public Memory(IntPtr processHandle)
  13. {
  14. _handle = processHandle;
  15. }
  16. public string ReadString(IntPtr address, int length, Encoding encoding)
  17. {
  18. List<byte> bytes = new List<byte>();
  19. for (int i = 0; i < length; i++) {
  20. byte read = ReadBytes(address + bytes.Count, 1)[0];
  21. if (read == 0x00)
  22. break;
  23. bytes.Add(read);
  24. }
  25. return encoding.GetString(bytes.ToArray());
  26. }
  27. public string ReadUnicodeString(IntPtr address, int length)
  28. {
  29. return Encoding.Unicode.GetString(ReadBytes(address, length));
  30. }
  31. public short ReadShort(IntPtr address)
  32. {
  33. return BitConverter.ToInt16(ReadBytes(address, 2), 0);
  34. }
  35. public int ReadInt(IntPtr address)
  36. {
  37. return BitConverter.ToInt32(ReadBytes(address, 4), 0);
  38. }
  39. public long ReadLong(IntPtr address)
  40. {
  41. return BitConverter.ToInt64(ReadBytes(address, 8), 0);
  42. }
  43. public byte[] ReadBytes(IntPtr address, int size)
  44. {
  45. byte[] bytes = new byte[size];
  46. if (!Native.ReadProcessMemory(_handle, address, bytes, size))
  47. throw new InjectorException("Failed to read process memory", new Win32Exception(Marshal.GetLastWin32Error()));
  48. return bytes;
  49. }
  50. public IntPtr AllocateAndWrite(byte[] data)
  51. {
  52. IntPtr addr = Allocate(data.Length);
  53. Write(addr, data);
  54. return addr;
  55. }
  56. public IntPtr AllocateAndWrite(string data) => AllocateAndWrite(Encoding.UTF8.GetBytes(data));
  57. public IntPtr AllocateAndWrite(int data) => AllocateAndWrite(BitConverter.GetBytes(data));
  58. public IntPtr AllocateAndWrite(long data) => AllocateAndWrite(BitConverter.GetBytes(data));
  59. public IntPtr Allocate(int size)
  60. {
  61. IntPtr addr =
  62. Native.VirtualAllocEx(_handle, IntPtr.Zero, size,
  63. AllocationType.MEM_COMMIT, MemoryProtection.PAGE_EXECUTE_READWRITE);
  64. if (addr == IntPtr.Zero)
  65. throw new InjectorException("Failed to allocate process memory", new Win32Exception(Marshal.GetLastWin32Error()));
  66. _allocations.Add(addr, size);
  67. return addr;
  68. }
  69. public void Write(IntPtr addr, byte[] data)
  70. {
  71. if (!Native.WriteProcessMemory(_handle, addr, data, data.Length))
  72. throw new InjectorException("Failed to write process memory", new Win32Exception(Marshal.GetLastWin32Error()));
  73. }
  74. public void Dispose()
  75. {
  76. foreach (var kvp in _allocations)
  77. Native.VirtualFreeEx(_handle, kvp.Key, kvp.Value, MemoryFreeType.MEM_DECOMMIT);
  78. }
  79. }
  80. }