First of all, we need to know the CR3, this register stores the bases address of page directory.
32 bits of linear address are divided into three fields:
directory: most significant 10 bits
table: intermediate 10 bits
offset: least significant 12 bits
there are 1024 (2^10 bytes / 4 bytes)entries in page directory table
there are 1024 (2^10 bytes / 4 bytes)entries in page table table
This link explain the structure of page directory entry and page table entry:
http://valhalla.bofh.pl/~l4mer/WDM/secureread/pde-pte.htm
I also wrote a program to find all kernel memory in a memory dump: the assumption is I need to know CR3 of kernel mode.
here is the program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NUMOFARG 3
#define SMALLBUFSIZE 20
#define NUMPDE 1024
#define NUMPTE 1024
#define COUNTER1 1024*1024*256
#define COUNTER2 1024*1024*4
#define COUNTER3 1024*4
int main(int argc, char **argv)
{
if(argc != NUMOFARG)
{
fprintf(stderr, "Usage: %s MemFile RegFile\n", argv[0]);
exit(1);
}
/* Generate new memory file with size of 256 MB
* which initial to 0 */
FILE *newMemFile = fopen("newMemDump", "w+");
if(newMemFile == NULL)
{
fprintf(stderr, "Cannot create new memory file\n");
exit(1);
}
int m;
for(m = 0; m < COUNTER1; m++)
fputc('\0', newMemFile);
/* Read the CR3 from register file */
FILE *regFile = fopen(argv[2], "r");
if(regFile == NULL)
{
fprintf(stderr, "Cannot open register file\n");
exit(1);
}
char regName[SMALLBUFSIZE];
char regEqual[SMALLBUFSIZE];
unsigned int regAddr;
int ret;
int numOf4K = 0;
int numOf4M = 0;
while(1)
{
ret = fscanf(regFile, "%s\t%s\t%x\n", regName, regEqual, ®Addr);
// printf("%s\t%s\t%x\n", regName,regEqual, regAddr);
if(strcmp(regName, "CR3") == 0)
break;
if(ret == 0 || ferror(regFile) || feof(regFile))
break;
}
fclose(regFile);
/* Read the memory file */
FILE *memFile = fopen(argv[1], "r");
if(memFile == NULL)
{
fprintf(stderr, "Cannot open memroy file\n");
exit(1);
}
/* Loop for Each Page Directory Entry
* There are 2^10 = 1024 entries in PDE
* We will check the present bit in each PDE
* */
int i, j;
unsigned int CR3 = regAddr;
// Store the content of Page Direcotry Entry
unsigned int PDEContent;
unsigned int PTEContent;
for(i = 0; i < NUMPDE; i++)
{
fseek(memFile, CR3+4*i, SEEK_SET);
if(fread(&PDEContent, 4, 1, memFile) != 1)
{
fprintf(stderr, "Read Page Direcotry Entry Error\n");
exit(1);
}
// if the last bit of the PDE entry is 0, this PDE entry is
// not present. we just jump to next loop
if(PDEContent%2 == 0)
continue;
// printf("%x\n", PDEContent);
// check if the 4M bit has been setted
if(PDEContent & 0x00000080 )
{
// This PDEContent has the 4M bit set
numOf4M++;
// copy the memory file to new memory file
// 1. seek the original file indicator
// 2. seek the new meory file indicator
// 3. copy the content to the new memory file
PDEContent &= 0xFFFFF000;
fseek(newMemFile, PDEContent, SEEK_SET);
fseek(memFile, PDEContent, SEEK_SET);
for(m = 0; m < COUNTER2; m++)
fputc(fgetc(memFile), newMemFile);
}
else
{
// This PDE has 4KB bit set, so we need to go though page
// table entry.
PDEContent &= 0xFFFFF000;
for(j = 0; j < NUMPTE; j++)
{
fseek(memFile, PDEContent+4*j, SEEK_SET);
if(fread(&PTEContent, 4, 1, memFile) != 1)
{
fprintf(stderr, "Read Page Table Entry Error\n");
exit(1);
}
// if the present bit is not set in the Page Table Entry
// we jump to next iteration
if(PTEContent%2 == 0)
continue;
numOf4K++;
PTEContent &= 0xFFFFF000;
fseek(newMemFile, PTEContent, SEEK_SET);
fseek(memFile, PTEContent, SEEK_SET);
for(m = 0; m < COUNTER3; m++)
fputc(fgetc(memFile), newMemFile);
}
}
}
fclose(newMemFile);
fclose(memFile);
printf("num of 4M is: %d\n", numOf4M);
printf("Num of 4K is: %d\n", numOf4K);
printf("Total kenerl memory size is: %d K\n", numOf4M*4096 + numOf4K);
return 1;
}
No comments:
Post a Comment