digitalmars.D.learn - ReadProcessMemory + address from ollydbg
- bauss (22/22) Jun 30 2017 I'm currently getting garbage data when using ReadProcessMemory
- ag0aep6g (6/20) Jun 30 2017 I guess the first cast is necessary when `address` isn't typed as
- bauss (23/44) Jun 30 2017 It's the same.
- bauss (6/40) Jun 30 2017 I mean I get data, it's not like the call fails or gives an
- Stefan Koch (2/6) Jun 30 2017 You are aware that processes life in different memory spaces ?
- bauss (4/11) Jun 30 2017 Well it's a static address I'm trying to read from, so it
- ag0aep6g (9/28) Jun 30 2017 The second cast still looks suspicious. PVOID is void*, right? Then any
- bauss (7/36) Jun 30 2017 Using ".idup" makes no difference in the result. I was under the
- ag0aep6g (6/16) Jun 30 2017 [...]
- H. S. Teoh via Digitalmars-d-learn (11/26) Jun 30 2017 [...]
I'm currently getting garbage data when using ReadProcessMemory to read from another process. This is my definition: BOOL ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead); And I'm reading it like this: if (!ReadProcessMemory(process, cast(PCVOID)address, cast(PVOID)&data, cast(DWORD)stringSize, cast(PDWORD)&bytesRead)) { return defaultValue; } process is a HANDLE that I got from OpenProcess() address is a DWORD data is char[1024] stringSize is size_t bytesRead is PDWORD The address I obtained was from Ollydbg and it's a static address. I'm not sure if I however need some kind of offset etc. I tried to search and found you might have to use GetModuleHandleA() but I tried that and I still get garbage data with the offset from that. What am I doing wrong?
Jun 30 2017
On Friday, 30 June 2017 at 20:14:15 UTC, bauss wrote:This is my definition: BOOL ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead); And I'm reading it like this: if (!ReadProcessMemory(process, cast(PCVOID)address, cast(PVOID)&data, cast(DWORD)stringSize, cast(PDWORD)&bytesRead)) { return defaultValue; }I guess the first cast is necessary when `address` isn't typed as a pointer yet. But the other casts shouldn't be needed. If you get errors without them, those errors might give a hint on what's wrong.process is a HANDLE that I got from OpenProcess() address is a DWORD data is char[1024] stringSize is size_t bytesRead is PDWORDbytesRead is a SIZE_T, no? Or maybe a DWORD.
Jun 30 2017
On Friday, 30 June 2017 at 21:36:25 UTC, ag0aep6g wrote:On Friday, 30 June 2017 at 20:14:15 UTC, bauss wrote:It's the same. This is my read function: string ReadWinString(HANDLE process, DWORD address, size_t stringSize, string defaultValue = "") { if (!process || !address) { return defaultValue; } SIZE_T bytesRead; char[1024] data; if (!ReadProcessMemory(process, cast(PCVOID)address, cast(PVOID)&data, stringSize, &bytesRead)) { return defaultValue; } auto s = cast(string)data[0 .. stringSize]; return s ? s : defaultValue; } And this is how I call it: auto text = ReadWinString(handleFromOpenProcess, 0x0000000, 16, "defaultString..."); where 0x0000000 is the address obviously. If you can spot what I'm doing wrong it would be appreciated.This is my definition: BOOL ReadProcessMemory(HANDLE hProcess, LPCVOID lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead); And I'm reading it like this: if (!ReadProcessMemory(process, cast(PCVOID)address, cast(PVOID)&data, cast(DWORD)stringSize, cast(PDWORD)&bytesRead)) { return defaultValue; }I guess the first cast is necessary when `address` isn't typed as a pointer yet. But the other casts shouldn't be needed. If you get errors without them, those errors might give a hint on what's wrong.process is a HANDLE that I got from OpenProcess() address is a DWORD data is char[1024] stringSize is size_t bytesRead is PDWORDbytesRead is a SIZE_T, no? Or maybe a DWORD.
Jun 30 2017
On Friday, 30 June 2017 at 23:41:19 UTC, bauss wrote:On Friday, 30 June 2017 at 21:36:25 UTC, ag0aep6g wrote:I mean I get data, it's not like the call fails or gives an error. It's just not the data I'm expecting. I suspect the address is wrong, but it's the static address I picked up from ollydbg, so I'm kinda lost as for how ollydbg can get the correct string and I get the wrong one using same address.On Friday, 30 June 2017 at 20:14:15 UTC, bauss wrote:It's the same. This is my read function: string ReadWinString(HANDLE process, DWORD address, size_t stringSize, string defaultValue = "") { if (!process || !address) { return defaultValue; } SIZE_T bytesRead; char[1024] data; if (!ReadProcessMemory(process, cast(PCVOID)address, cast(PVOID)&data, stringSize, &bytesRead)) { return defaultValue; } auto s = cast(string)data[0 .. stringSize]; return s ? s : defaultValue; } And this is how I call it: auto text = ReadWinString(handleFromOpenProcess, 0x0000000, 16, "defaultString..."); where 0x0000000 is the address obviously. If you can spot what I'm doing wrong it would be appreciated.[...]I guess the first cast is necessary when `address` isn't typed as a pointer yet. But the other casts shouldn't be needed. If you get errors without them, those errors might give a hint on what's wrong.[...]bytesRead is a SIZE_T, no? Or maybe a DWORD.
Jun 30 2017
On Friday, 30 June 2017 at 23:53:19 UTC, bauss wrote:I suspect the address is wrong, but it's the static address I picked up from ollydbg, so I'm kinda lost as for how ollydbg can get the correct string and I get the wrong one using same address.You are aware that processes life in different memory spaces ?
Jun 30 2017
On Friday, 30 June 2017 at 23:56:10 UTC, Stefan Koch wrote:On Friday, 30 June 2017 at 23:53:19 UTC, bauss wrote:Well it's a static address I'm trying to read from, so it shouldn't matter if I have the write handle to the process and the static address, should it?I suspect the address is wrong, but it's the static address I picked up from ollydbg, so I'm kinda lost as for how ollydbg can get the correct string and I get the wrong one using same address.You are aware that processes life in different memory spaces ?
Jun 30 2017
On 07/01/2017 01:41 AM, bauss wrote:string ReadWinString(HANDLE process, DWORD address, size_t stringSize, string defaultValue = "") { if (!process || !address) { return defaultValue; } SIZE_T bytesRead; char[1024] data; if (!ReadProcessMemory(process, cast(PCVOID)address, cast(PVOID)&data,The second cast still looks suspicious. PVOID is void*, right? Then any mutable pointer type should implicitly convert to PVOID and you shouldn't need the cast.stringSize, &bytesRead)) { return defaultValue; } auto s = cast(string)data[0 .. stringSize]; return s ? s : defaultValue;Here's an error that produces garbage. `data` is a fixed-sized array, so the values are on the stack. That means `s` points to the stack. You can't return a pointer to the stack. It becomes invalid when the function returns. You can put it on the heap instead: `auto s = data[0 .. stringSize].idup;`.}
Jun 30 2017
On Saturday, 1 July 2017 at 00:23:36 UTC, ag0aep6g wrote:On 07/01/2017 01:41 AM, bauss wrote:Using ".idup" makes no difference in the result. I was under the impression the cast would already do that though, guess not. However the result is the same. I also tried to check "data" directly and it's already garbage there. Well the address is not a pointer. It's DWORD which is uint, so the cast is necessary since it stores the address.string ReadWinString(HANDLE process, DWORD address, size_t stringSize, string defaultValue = "") { if (!process || !address) { return defaultValue; } SIZE_T bytesRead; char[1024] data; if (!ReadProcessMemory(process, cast(PCVOID)address, cast(PVOID)&data,The second cast still looks suspicious. PVOID is void*, right? Then any mutable pointer type should implicitly convert to PVOID and you shouldn't need the cast.stringSize, &bytesRead)) { return defaultValue; } auto s = cast(string)data[0 .. stringSize]; return s ? s : defaultValue;Here's an error that produces garbage. `data` is a fixed-sized array, so the values are on the stack. That means `s` points to the stack. You can't return a pointer to the stack. It becomes invalid when the function returns. You can put it on the heap instead: `auto s = data[0 .. stringSize].idup;`.}
Jun 30 2017
On 07/01/2017 02:30 AM, bauss wrote:On Saturday, 1 July 2017 at 00:23:36 UTC, ag0aep6g wrote:[...]On 07/01/2017 01:41 AM, bauss wrote:[...]if (!ReadProcessMemory(process, cast(PCVOID)address, cast(PVOID)&data,The second cast still looks suspicious. PVOID is void*, right? Then any mutable pointer type should implicitly convert to PVOID and you shouldn't need the cast.Well the address is not a pointer. It's DWORD which is uint, so the cast is necessary since it stores the address.Not that one. The other one. This one: `cast(PVOID)&data`. I don't expect it to be related to your problem, but it shouldn't be necessary as far as I see.
Jun 30 2017
On Saturday, 1 July 2017 at 00:40:11 UTC, ag0aep6g wrote:On 07/01/2017 02:30 AM, bauss wrote:Yeah, the cast was unnecessary. So this is my code after the changes: string ReadWinString(HANDLE process, DWORD address, size_t stringSize, string defaultValue = "") { if (!process || !address) { return defaultValue; } SIZE_T bytesRead; char[1024] data; if (!ReadProcessMemory(process, cast(LPCVOID)address, &data, stringSize, &bytesRead)) { return defaultValue; } auto s = cast(string)data[0 .. stringSize].idup; return s ? s : defaultValue; } Results are still garbage data, correct length in bytesRead however. I tried to pass the address with the main module's base address because I saw some posts online suggesting you might need to do that. If I do that however I just get error 299 (ERROR_PARTIAL_COPY), so I don't think I needed the base address, but still can't figure out what exactly is wrong with my code and why I can't read the string from the address I give it, when it's a static address. Every time I look with ollydbg the address is the same and ollydbg can find the string just fine.On Saturday, 1 July 2017 at 00:23:36 UTC, ag0aep6g wrote:[...]On 07/01/2017 01:41 AM, bauss wrote:[...]if (!ReadProcessMemory(process, cast(PCVOID)address, cast(PVOID)&data,The second cast still looks suspicious. PVOID is void*, right? Then any mutable pointer type should implicitly convert to PVOID and you shouldn't need the cast.Well the address is not a pointer. It's DWORD which is uint, so the cast is necessary since it stores the address.Not that one. The other one. This one: `cast(PVOID)&data`. I don't expect it to be related to your problem, but it shouldn't be necessary as far as I see.
Jun 30 2017
On Saturday, 1 July 2017 at 00:48:01 UTC, bauss wrote:On Saturday, 1 July 2017 at 00:40:11 UTC, ag0aep6g wrote:I have solved the problem. It was caused by an invalid address, so the code actually worked fine.[...]Yeah, the cast was unnecessary. So this is my code after the changes: string ReadWinString(HANDLE process, DWORD address, size_t stringSize, string defaultValue = "") { if (!process || !address) { return defaultValue; } [...]
Jul 01 2017
On Sat, Jul 01, 2017 at 02:23:36AM +0200, ag0aep6g via Digitalmars-d-learn wrote:On 07/01/2017 01:41 AM, bauss wrote:[...][...] The compiler is supposed to catch errors like these with -dip1000. Recently there was a DIP1000-related fix checked in that fixed some of the problems with -dip1000 (specifically, a linker error I was running into), so you may want to consider compiling with -dip1000 if you're running the latest compiler. T -- Klein bottle for rent ... inquire within. -- Stephen MulraneystringSize, &bytesRead)) { return defaultValue; } auto s = cast(string)data[0 .. stringSize]; return s ? s : defaultValue;Here's an error that produces garbage. `data` is a fixed-sized array, so the values are on the stack. That means `s` points to the stack. You can't return a pointer to the stack. It becomes invalid when the function returns. You can put it on the heap instead: `auto s = data[0 .. stringSize].idup;`.
Jun 30 2017