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








Flag: Tornado! Hurricane!

 Forums >>  Brainstorms - General  >>  Translate Virtual Address To Physical Address

Topic created on: August 23, 2008 18:00 CDT by staticares .

Im working on translating a virtual address to a physical address.
I know that in Real mode its just
physical address = virtual address * 0x10 + OFFSET

But, as im running in Protected mode. It has to be done differently. I need to use the descriptor table and segment descriptor.
Here are the steps i was told to take:

1. Find the start of the descriptor table (GDTR register)
2. Find the SEGMENTth entry of the table, this is the segment descriptor corresponding to the segment SEGMENT.
3. Find the base physical address � of the segment
4. Compute � = � + OFFSET


My question is, can I receive some help on doing this starting with step 1?

Thanks,

Static Ares

  GynvaelColdwind     August 23, 2008 19:41.50 CDT
Are You using some OS+API ?

If it's Windows, for step 1 there is a function called "GetThreadSelectorEntry". Example of usage (gcc/g++):


/* ignore the 'control reaches end of non-void function' warnings */
*/
#include<windows.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>

/* push SEG; pop eax */
WORD GetCS(void) { __asm__(".ascii \"\\x0E\\x58\""); }
WORD GetDS(void) { __asm__(".ascii \"\\x1E\\x58\""); }
WORD GetES(void) { __asm__(".ascii \"\\x06\\x58\""); }
WORD GetFS(void) { __asm__(".ascii \"\\x0F\\xA0\\x58\""); }
WORD GetGS(void) { __asm__(".ascii \"\\x0F\\xA8\\x58\""); }
WORD GetSS(void) { __asm__(".ascii \"\\x16\\x58\""); }

int
main(void)
{
  LDT_ENTRY ldt;
  HANDLE thdl = GetCurrentThread();

#define PRINT_SEG(a) { GetThreadSelectorEntry(thdl, Get ## a (), &ldt);\
                       printf(#a ": %.8x (%.8x)%s\n",\
         ldt.BaseLow | (ldt.HighWord.Bytes.BaseMid << 16) | (ldt.HighWord.Bytes.BaseHi << 24),\
         (int)(short)ldt.LimitLow, ldt.LimitLow > 0 ? "" : " [unused]"); }
  
  PRINT_SEG(CS);
  PRINT_SEG(DS);
  PRINT_SEG(ES);
  PRINT_SEG(FS);
  PRINT_SEG(GS);
  PRINT_SEG(SS);

  return 0;
}




If You are not using Windows, for example You are in protected mode, then there is an instruction called SGDT (Store Global Descriptor Table Register).

  staticares     August 24, 2008 04:14.34 CDT
Thanks!, looks like a very clear awnser. Ill study the source above.

ps. Yes, im on windows (xp).

--
Update
--

I compiled the source. Running on windows xp like:
nameofexe.exe > temp.txt

The content in temp.txt after execution is:

CS: 00000000 (ffffffff)
DS: 00000000 (ffffffff)
ES: 00000000 (ffffffff)
FS: 7ffde000 (00000fff)
GS: 00000000 (00000000) [unused]
SS: 00000000 (ffffffff)

So that start of the Descriptor table for this application  is stored in FS and has the value(/address) 7ffde000?

--
Update
--
Here is a version that compiles under Visual Studio:

#include<windows.h>
#include<string.h>
#include<stdlib.h>
#include<stdio.h>

/* push SEG; pop eax */
WORD GetCS(){__asm{
PUSH CS
POP EAX}}

WORD GetDS(){__asm{
PUSH DS
POP EAX}}

WORD GetES(){__asm{
PUSH ES
POP EAX}}

WORD GetFS(){__asm{
PUSH FS
POP EAX}}

WORD GetGS(){__asm{
PUSH GS
POP EAX}}

WORD GetSS(){__asm{
PUSH SS
POP SS}}

int main(void)
{
  LDT_ENTRY ldt;
  HANDLE thdl = GetCurrentThread();

#define PRINT_SEG(a) { GetThreadSelectorEntry(thdl, Get ## a (), &ldt);\
                       printf(#a ": %.8x (%.8x)%s\n",\
         ldt.BaseLow | (ldt.HighWord.Bytes.BaseMid << 16) | (ldt.HighWord.Bytes.BaseHi << 24),\
         (int)(short)ldt.LimitLow, ldt.LimitLow > 0 ? "" : " [unused]"); }
  
  PRINT_SEG(CS);
  PRINT_SEG(DS);
  PRINT_SEG(ES);
  PRINT_SEG(FS);
  PRINT_SEG(GS);
  PRINT_SEG(SS);

  return 0;
}

  GynvaelColdwind     August 24, 2008 06:39.53 CDT
Oh, sorry, I didn't look through all the points. There is one more thing that I should have pointed out.
Mainly, your points are missing one step, and a little mistaking in another.
I'll try to explain:

When You have for example mov eax, [0x12345678], then 0x12345678 is in fact a Virtual Address in the segment DS (so it's DS:0x12345678).
First, You have to convert that DS:0x12345678 to a Linear Address, which is still kinda Virtual, but does not have the segment inside.
To do that, You have to use the above code. In case of DS, the segment starts at DS: 00000000 (as You have pasted). To calculate the Linear Address, You just add that 0x12345678 to the start of DS segment. You'll get 0x12345678 of course.
Please note that all the segments except of GS (which is unused) and FS (which has a special value) have the start at 0 in the linear address space.

OK, Now You have the Linear Address, and You have to convert it to a Physical Address.

The Linear Address has 3 parts (see this picture). The bottom 12 bits are an offset on a Page (the page normally has 4096 bytes (0x1000), but sometimes it's larger; however I'll focus on the 0x1000 type), the middle 10 bits is the Page Index in the Page Table, and the top 10 bits are the Page Table Index in the Page Directory.
So in the example case it's the following:
Offset    = 0x678
PageIndex = 0x345
PageTable = 0x48


  unsigned int addr = 0x12345678;
  printf("Offset   : %x\n", addr & 0xfff);
  printf("PageIndex: %x\n", (addr >> 12) & 0x3ff);
  printf("PageTable: %x\n", (addr >> 22) & 0x3ff);


Anyway, once You have this, You must have access to the Page Directory, Page Table etc. And as far as I know, You don't normally have access to it - You have to be in ring 0, or have the tables exported somehow into ring 3 (a driver could do it).

After reading where the page starts in the physical memory (using that PageDirectory[PageTable][PageIndex]), You add teh Page offset to it, and that finally is the physical address ;>

Btw, thanks for the code for CL ;>

  staticares     August 24, 2008 12:56.26 CDT
0.o Wow.

I think im going to read this a couple times before I react..

----
Update
----

I understand now. Thanks for all this information!

  injstar     August 26, 2008 13:54.28 CDT
Well you  can try the Virtual2Physical ollydbg plugin (Open Source)

  staticares     August 26, 2008 15:43.33 CDT
> injstar: Well you  can try the Virtual2Physical ollydbg plugin (Open Source)

Im going to look into that. Thanks for the tip.

------
Update
------

Olly keeps crashing, ill keep working on it, but any hint or tip is welcome.

  forgot   August 28, 2008 00:13.56 CDT
normally only FS segments has a non-zero base address,
CS/DS/SS should be 0..FFFFFFFF always, according to flat mode. you can use SGDT [somewhere] instruction to get base:limit for GDT. and if you have trouble with crashing, check some stuff about PAE.

  staticares     August 28, 2008 08:57.06 CDT
Thanks. I Will.

  RabidCicada     September 28, 2008 10:44.11 CDT
To be honest static...Your best bet is to read up in the intel docs on x86 assembly.  That'll show you how things work.

You'll want to go here:
http://developer.intel.com/products/processor/manuals/index.htm

Get the BAsic Architecture, instruction references, and programming guides.  They are long...But you can look at the bits you want.

Really becoming good at this stuff is about experimentation and actually reading up on your stuff.  Not dark magic(though some of us might like to think so:) )

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