fork download
  1. #include <iostream>
  2. #include <cstdint>
  3. #include <cstring>
  4. #include <stdexcept>
  5. #include <memory>
  6. using namespace std;
  7.  
  8. using DWORD = uint32_t;
  9. using DWORD_PTR = uintptr_t;
  10. using BOOL = int;
  11. using HANDLE = void*;
  12. using LPCVOID = const void*;
  13. using LPVOID = void*;
  14. using SIZE_T = size_t;
  15.  
  16. BOOL ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead)
  17. {
  18. memcpy(lpBuffer, lpBaseAddress, nSize);
  19. if (lpNumberOfBytesRead) *lpNumberOfBytesRead = nSize;
  20. return 1;
  21. }
  22.  
  23. HANDLE targetProcess = nullptr;
  24.  
  25. template<typename T>
  26. T read(DWORD_PTR addy)
  27. {
  28. T buffer;
  29. if (!ReadProcessMemory(targetProcess, (LPVOID)addy, &buffer, sizeof(T), NULL))
  30. throw std::runtime_error("ReadProcessMemory failed");
  31. return buffer;
  32. }
  33.  
  34. template<typename T, typename... OffsetTypes>
  35. T read(DWORD_PTR addy, DWORD offset, OffsetTypes... offsets)
  36. {
  37. DWORD_PTR ptr = read<DWORD_PTR>(addy);
  38. return read<T>(ptr + offset, offsets...);
  39. }
  40.  
  41. // I couldn't get alignas(1) to work correctly in this compiler,
  42. // so using some hacks to force it to work...
  43.  
  44. struct Struct1
  45. {
  46. /*
  47. char padding[0x50];
  48. LPVOID ptr;
  49. */
  50. char padding_and_ptr[0x50 + sizeof(LPVOID)];
  51. } s1;
  52.  
  53. struct Struct2
  54. {
  55. /*
  56. char padding[0x70];
  57. float value;
  58. */
  59. char padding_and_value[0x70 + sizeof(float)];
  60. } s2;
  61.  
  62. struct FakeProcessInfo
  63. {
  64. /*
  65. char padding[0x12345];
  66. LPVOID ptr;
  67. */
  68. char padding_and_ptr[0x12345 + sizeof(LPVOID)];
  69. };
  70.  
  71. int main()
  72. {
  73. auto FakeProcess = std::make_unique<FakeProcessInfo>();
  74.  
  75. // hacks
  76. LPVOID &fp_ptr = reinterpret_cast<LPVOID&>(FakeProcess->padding_and_ptr[0x12345]);
  77. LPVOID &s1_ptr = reinterpret_cast<LPVOID&>(s1.padding_and_ptr[0x50]);
  78. float &value = reinterpret_cast<float&>(s2.padding_and_value[0x70]);
  79. //
  80.  
  81. fp_ptr = std::addressof(s1);
  82. s1_ptr = std::addressof(s2);
  83. value = 12345.0f;
  84.  
  85. DWORD_PTR baseAddr = reinterpret_cast<DWORD_PTR>(FakeProcess.get());
  86. float data = read<float>(baseAddr+0x12345, 0x50, 0x70);
  87. cout << "data: " << data << endl;
  88. return 0;
  89. }
Success #stdin #stdout 0s 4384KB
stdin
Standard input is empty
stdout
data: 12345