ReadMemory in extension on Win7-64

I’m writing a debug extension to monitor some memory mapped IO. To do this, I’ve written a little bit of code that uses the ReadMemory routine and writes the result ot a file. But, it doesn’t seem to work. That is, it gets a ‘read 0 bytes’ result for certain addresses. Not sure what is going on, because when I plug the address into the memory display on the debugger, there are certainly values there.

For instance:
!printio label fffff6fc400173f0
Got label: label and address: fffff6fc400173f0
Read 0 bytes
MEMORY: label:00000000

But:
!printio label fffff8a0005fda54
Got label: label and address: fffff8a0005fda54
Read 4 bytes
MEMORY: label:00000000

(unfortunately, the memory here doesn’t actually contain all zero’s so this didn’t really work either).

#define KDEXT_64BIT
#include <wdbgexts.h>
#include <dbgeng.h>
<…>
DECLARE_API (printio)
{
UINT64 address;
ULONG StringAddress = 0;
ULONG Bytes = 0;
WCHAR MyString[51] = {0};
char label[255];

// parse the command line (expecting a string label and an address)
sscanf(args, “%s %llx”, label, &address);

dprintf(“Got label: %s and address: %llx\n”, label, address);

ReadMemory(address, &StringAddress, sizeof(StringAddress), &Bytes);
dprintf(“Read %d bytes\n”, Bytes);
dprintf(“MEMORY: %s:%08x\n”, label, StringAddress);

if(fp) {
fprintf(fp, “%s:%08x\n”, label, StringAddress);
}

}</dbgeng.h></wdbgexts.h>

when i started with extensions i was advised that it is better to move
to engexts based or dbgeng based extensions and it would be worth
taking some time to familiarize oneself with the IDebug Interfaces as
one may not be able to gather enough good advices for wdbgexts based
extensions

the code below is an aid to read memory it is not an for an extension
but for a standalone app

you can adapt the concept in extension and it is engext based

#include <stdio.h>
#include <engextcpp.hpp>
#define MAXERRSTRSIZE 0x350

int __cdecl ReadVirtualUncached(int Pid, unsigned long VaRead, char
ReturnedStr)
{
IDebugClient
g_Client = NULL;
IDebugControl* g_Control = NULL;
IDebugDataSpaces* g_DebugDataSpaces = NULL;
BYTE Buffer[0x85] = {0};
ULONG BytesRead = NULL;
HRESULT status = NULL;
if ((status = DebugCreate(__uuidof(IDebugClient), (void**)&g_Client
)) != S_OK )
{
sprintf_s(ReturnedStr, MAXERRSTRSIZE, “%s Failed”,“DebugCreate(
__uuidof(IDebugClient”);
goto cleanup;
}
if ((status = g_Client->QueryInterface(__uuidof(IDebugDataSpaces),
(void**)&g_DebugDataSpaces )) != S_OK )
{
sprintf_s( ReturnedStr, MAXERRSTRSIZE, “%s Failed”,“QueryInterface(
__uuidof(IDebugDataSpaces)”);
goto cleanup;
}
if ((status = g_Client->QueryInterface(__uuidof(IDebugControl),
(void**)&g_Control )) != S_OK )
{
sprintf_s( ReturnedStr, MAXERRSTRSIZE, “%s Failed”,“QueryInterface(
__uuidof(IDebugControl)”);
goto cleanup;
}
if ((status = g_Client->AttachKernel(DEBUG_ATTACH_LOCAL_KERNEL,NULL)) != S_OK )
{
sprintf_s( ReturnedStr, MAXERRSTRSIZE, “%s Failed”,“AttachKernel(”);
goto cleanup;
}
if ((status = g_Control->WaitForEvent( 0, INFINITE )) != S_OK )
{
sprintf_s( ReturnedStr, MAXERRSTRSIZE, “%s Failed”, “g_Control->WaitForEvent(”
);
goto cleanup;
}
sprintf_s(ReturnedStr,MAXERRSTRSIZE,
“.foreach /ps 100 /pS 12 (place { !process %x 0 } ) { r $t0 =
place; .process /p /r @$t0 }”,Pid);
if(( g_Control->Execute( DEBUG_OUTCTL_IGNORE, ReturnedStr,
DEBUG_EXECUTE_DEFAULT )) != S_OK)
{
sprintf_s( ReturnedStr, MAXERRSTRSIZE,“%s Failed”, “g_Control->Execute(” );
goto cleanup;
}
if ((status = g_DebugDataSpaces->ReadVirtualUncached(VaRead, Buffer,
sizeof(Buffer)-5,&BytesRead)) != S_OK )
{
sprintf_s( ReturnedStr, MAXERRSTRSIZE,“%s Failed”, “ReadVirtualUncached(” );
goto cleanup;
}
int l = 0;
printf(“DUMP*************\n”);
while( l < sizeof(Buffer)-5 )
{
for (int i = l+0; i < l+0x10 ;i++)
{
printf(“%02x “,Buffer[i]);
}
for (int i = l+0; i < l+0x10 ;i++)
{
printf(”%c”,Buffer[i]);
}
printf(“\n”);
l+= 0x10;
}
printf(“DUMP*************\n”);
return TRUE;
cleanup:
if(g_Client)
g_Client->Release();
if(g_Control)
g_Control->Release();
if(g_DebugDataSpaces)
g_DebugDataSpaces->Release();
return FALSE;
}
int__cdecl main( void )
{
char ReturnedStr[0x400];
int Pid;
unsigned long VaRead;
printf(“enter Pid as Decimal\n”);
scanf(“%d”,&Pid);
printf(“enter address to read from in target process\n”);
scanf(“%x”,&VaRead);
if((ReadVirtualUncached(Pid,VaRead,ReturnedStr)) == FALSE) {
printf(“some error go check %s\n”,ReturnedStr);
}
return 0;
}

result as follows

>ReadVirtualUncached.exe
enter Pid as Decimal
2392
enter address to read from in target process
403000
************************DUMP *************
49 63 7a 65 6c 69 6f 6e 27 73 20 74 75 74 6f 72 Iczelion’s tutor
69 61 6c 20 6e 6f 2e 32 00 57 69 6e 33 32 20 41 ial no.2 Win32 A
73 73 65 6d 62 6c 79 20 69 73 20 47 72 65 61 74 ssembly is Great
21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 !
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
DUMP *************

>ReadVirtualUncached.exe
enter Pid as Decimal
2392
enter address to read from in target process
804d7000 base of nt
DUMP *************
4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00 MZÉ :heart: :diamonds:
b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ╕ @
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 e0 00 00 00 α
0e 1f ba 0e 00 b4 09 cd 21 b8 01 4c cd 21 54 68 ♫▼║♫ ┤ ═!╕☺L═!Th
69 73 20 70 72 6f 67 72 61 6d 20 63 61 6e 6e 6f is program canno
74 20 62 65 20 72 75 6e 20 69 6e 20 44 4f 53 20 t be run in DOS
6d 6f 64 65 2e 0d 0d 0a 24 00 00 00 00 00 00 00 mode.
$
DUMP *************

>ReadVirtualUncached.exe
enter Pid as Decimal
2392
enter address to read from in target process
ffdff124 fs:124 aka nt!_KPCR PrcbData PrcbData.CurrentThread ffdff000
DUMP *************
20 d0 49 86 00 00 00 00 c0 27 55 80 00 00 02 00 ╨Iå └’UÇ :slight_smile:
01 00 00 00 06 01 01 16 00 00 00 00 00 00 00 00 :smiling_face: :spades::smiling_face::smiling_face:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
DUMP *************************************

F:\windbg\612windbg\sdk\samples\symstack\ui3here\opendump\ReadVirtualUncached\te
st>

On 10/15/12, xxxxx@jhuapl.edu wrote:
> I’m writing a debug extension to monitor some memory mapped IO. To do this,
> I’ve written a little bit of code that uses the ReadMemory routine and
> writes the result ot a file. But, it doesn’t seem to work. That is, it gets
> a ‘read 0 bytes’ result for certain addresses. Not sure what is going on,
> because when I plug the address into the memory display on the debugger,
> there are certainly values there.
>
> For instance:
> !printio label fffff6fc400173f0
> Got label: label and address: fffff6fc400173f0
> Read 0 bytes
> MEMORY: label:00000000
>
> But:
> !printio label fffff8a0005fda54
> Got label: label and address: fffff8a0005fda54
> Read 4 bytes
> MEMORY: label:00000000
>
> (unfortunately, the memory here doesn’t actually contain all zero’s so this
> didn’t really work either).
>
> #define KDEXT_64BIT
> #include <wdbgexts.h>
> #include <dbgeng.h>
> <…>
> DECLARE_API (printio)
> {
> UINT64 address;
> ULONG StringAddress = 0;
> ULONG Bytes = 0;
> WCHAR MyString[51] = {0};
> char label[255];
>
> // parse the command line (expecting a string label and an address)
> sscanf(args, “%s %llx”, label, &address);
>
> dprintf(“Got label: %s and address: %llx\n”, label, address);
>
> ReadMemory(address, &StringAddress, sizeof(StringAddress), &Bytes);
> dprintf(“Read %d bytes\n”, Bytes);
> dprintf(“MEMORY: %s:%08x\n”, label, StringAddress);
>
> if(fp) {
> fprintf(fp, “%s:%08x\n”, label, StringAddress);
> }
>
> }
>
> —
> WINDBG is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
></dbgeng.h></wdbgexts.h></engextcpp.hpp></stdio.h>