📚 OpenRCE is preserved as a read-only archive. Launched at RECon Montreal in 2005. Registration and posting are disabled.








Flag: Tornado! Hurricane!

 Forums >>  Debuggers  >>  reading procmem or kernmem with phys addresses

Topic created on: March 6, 2006 03:13 CST by maco .

as a proof of concept, here is a programmatic way to read the memory of another process or the kernel using physical memory. also features a cheezy way to page in the memory if it also paged out.

this is windows specific and would not be portable (it exploits the windows mmu behavior). one particularly cool thing about it is that it can handle prototype ptes (e.g., can find the physical page representing a shared virtual address). if you actually write to this page, you can instantly hook all processes using that page (very nice way to hook code in shared pages).

a sample is here:
http://www.cybertech.net/~sh0ksh0k/projects/DumpCPU

the main functionality is here:
http://www.cybertech.net/~sh0ksh0k/projects/win32toolkit/kernel.c

you can resolve any exported variable in an loaded kernel module by adding it to KernelModuleImports[] array in kernel.c:

KERNEL_EXPORT NtoskrnlExports[] =
{
// This doesn't work properly on WinXPSP2.. still need to find out why
// The virtual address is correct, but the physical page returned is wrong
//{ "PsInitialSystemProcess", FALSE, PAGE_SIZE, (BYTE **)&PsInitialSystemProcess, NULL },

{ "KeServiceDescriptorTable", TRUE, sizeof(KSERVICE_TABLE_DESCRIPTOR), (BYTE **)&KeServiceDescriptorTable, NULL },
{ NULL, FALSE, 0, NULL, NULL }
};

KERNEL_MODULE_IMPORT KernelModuleImports[] =
{
{ "NTOSKRNL.EXE", NULL, 0, 0, 0, (KERNEL_EXPORT *)NtoskrnlExports },
{ NULL, NULL, 0, 0, 0, NULL }
};

to read the memory of another process, you need to find it's page directory base, the steps are basically:
PageDirectoryBase = GetPageDirectoryBase(ProcessID);
PhysicalAddress = GetPhysicalAddress(BlahVirtualAddress, PageDirectoryBase);
ptr = MapPhysicalMemory(PhysicalAddress, sizeof(struct blah), &BaseAddress, PAGE_READWRITE);

now ptr points to the physical memory of 'blah' and you can write to it directly. when finished, call UnmapPhysicalMemory(BaseAddress)

if you need to use any offsets into an undocumented structure, use WinDbg "dt nt!_XXXX" for each OS you want to support, then add it to OSOffsets[]:

OS offsets you can get using WinDbg 'dt nt!_STRUCT_YOU_WANT' and then add it to OS_OFFSETS structure

then add an entry into OSOffsets like this:

{
5, 0, OSTYPE_WIN50, // Win2K
0x1FC, // EPROCESS.ImageFileName
0x9C,  // EPROCESS.UniqueProcessId
0xA0,  // EPROCESS.ActiveProcessLinks
0x18,  // EPROCESS.DirectoryTableBase
0x20,  // EPROCESS.LdtDescriptor
0x128, // EPROCESS.ObjectTable
0x12C, // EPROCESS.Token
0x50,  // EPROCESS.ThreadListHead
0x38,  // KPCR.IDT
0x3C,  // KPCR.GDT
0x40,  // KPCR.TSS
0x124, // KPCR.CurrentThread
0x12C, // KPCR.IdleThread
0x800  // KPCR.DpcListHead
},

to read the structure cross-platform, you can do this:

Offset = GetOSOffsets(NtMajorVersion, NtMinorVersion);

CR3 = READ_DWORD(PsInitialSystemProcess, Offset->DirectoryTableBase)

where READ_DWORD is like:
#define READ_DWORD(base, off) \
  *((DWORD *)((ULONG_PTR)(base) + (off))

if you see any strange behavior let me know what OS you use and how much RAM you hvae. in some cases the virtual address is resolving to a physical page, but the contents on the page don't match what you would see in softice. i don't have a lot of machines to test with, so i can't figure out if this is due to a MMU change between windows 2000 and windows xp sp2, or if it depends on how much memory (i see the weird behavior on a machine with 1GB ram). but at least on a machine with < 1GB RAM and running windows 2000, this seems to work peffectly. on xpsp2 with > 1GB RAM, i see this bug with certain addresses.

  bugcheck     March 21, 2006 00:01.40 CST
I hope you dont use softICE as your primary debugger! =) just kidding.  Just wanted to say really nice work. All of your code is structured nicely and is a pleasure to read.

  vmukhi     March 21, 2006 05:11.49 CST
I would like to write to a physical memory location. The following program dispalys 0xffffffff

#include <windows.h>
#include <stdio.h>
long base;int pid;
main(int argc, char **argv)
{
//KernelLoad();
pid = GetProcessID(argv[1],1);
printf("%d %x\n",pid,pid);
base = GetPageDirectoryBase(pid);
printf("base=%x\n",base);
}

I run the program as b calc.exe. This prints me the process id of calc.exe but the GetPageDirectoryBase method fails. I i supply a pid of 0 and uncoment the KernelLoad I get a value 39000. Can someone give me code that allows me to write to a physical address either in ring 0 or ring 3

Note: Registration is required to post to the forums.

There are 31,328 total registered users.


Recently Created Topics
[help] Unpacking VMP...
Mar/12
Reverse Engineering ...
Jul/06
let 'IDAPython' impo...
Sep/24
set 'IDAPython' as t...
Sep/24
GuessType return une...
Sep/20
About retrieving the...
Sep/07
How to find specific...
Aug/15
How to get data depe...
Jul/07
Identify RVA data in...
May/06
Question about memor...
Dec/12


Recent Forum Posts
Finding the procedur...
rolEYder
Question about debbu...
rolEYder
Identify RVA data in...
sohlow
let 'IDAPython' impo...
sohlow
How to find specific...
hackgreti
Problem with ollydbg
sh3dow
How can I write olly...
sh3dow
New LoadMAP plugin v...
mefisto...
Intel pin in loaded ...
djnemo
OOP_RE tool available?
Bl4ckm4n


Recent Blog Entries
halsten
Mar/14
Breaking IonCUBE VM

oleavr
Oct/24
Anatomy of a code tracer

hasherezade
Sep/24
IAT Patcher - new tool for ...

oleavr
Aug/27
CryptoShark: code tracer ba...

oleavr
Jun/25
Build a debugger in 5 minutes

More ...


Recent Blog Comments
nieo on:
Mar/22
IAT Patcher - new tool for ...

djnemo on:
Nov/17
Kernel debugger vs user mod...

acel on:
Nov/14
Kernel debugger vs user mod...

pedram on:
Dec/21
frida.github.io: scriptable...

capadleman on:
Jun/19
Using NtCreateThreadEx for ...

More ...


Imagery
SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit