3

Here is a sample C code which prints Windows version directly from address of KUSER_SHARED_DATA. Tested in Windows 10 only. The raw memory address differ in Windows version but that's not the point.

#include <stdio.h>

int main(void)
{
    wprintf(
        L"Version: %lu.%lu.%lu\n",
        *(unsigned int *)(0x7FFE0000 + 0x026C),
        *(unsigned int *)(0x7FFE0000 + 0x0270),
        *(unsigned int *)(0x7FFE0000 + 0x0260)
    );
}

Here are the decompiled code:

In GHIDRA:

int main(int _Argc,char **_Argv,char **_Env)

{
    wprintf(L"Version: %lu.%lu.%lu\n",
        (ulonglong)_DAT_7ffe026c,
        (ulonglong)_DAT_7ffe0270,
        (ulonglong)_DAT_7ffe0260);
  return 0;
}

In IDA Pro + Hex-Rays:

int __fastcall main()
{
    wprintf(L"Version: %lu.%lu.%lu\n",
        MEMORY[0x7FFE026C],
        MEMORY[0x7FFE0270],
        MEMORY[0x7FFE0260]);
  return 0;
}

My question: In decompiled code, is it possible to show the memory address as the member of KUSER_SHARED_DATA? For example, I want to show MEMORY[0x7FFE0260] as SharedData.NtBuildNumber or something similar to it.

3

For IDA/Hex-Rays:

  1. In the Loaded Type Libraries window (View->Open subviews->Type libraries), load ntddk_win10 (or whatever Windows version you want, back to Windows XP and Windows Server 2003).

Available Type Libraries

  1. In the Structures window (View->Open subviews->Structures), import KUSER_SHARED_DATA. You can simply write the name of the type in the dialog box and press OK, as in the following image:

Create structure/union

  1. Under Edit->Segments->Create segment, create a new segment with that memory range, as in the following image.

Create a new segment

  1. At the beginning of the new segment, use Edit->Struct var, and select KUSER_SHARED_DATA.

Choose a structure type

That's it. Now the disassembly listing looks like this:

Disassembly

And the decompilation looks like this:

Decompilation

3
  • Is it possible to do this automatically or with one command or script? – Biswapriyo Oct 23 '20 at 6:51
  • 1
    You could write a script to do all of that automatically if you wanted to. Is it really worth the effort, however? It took less than two minutes to do it. Unless you're doing it very frequently for some reason, I personally don't see the point in investing the effort into writing a script. As for whether there's one command to do all of that, why on earth would there be? What would you propose for the name of that command? – Rolf Rolles Oct 23 '20 at 7:44
  • ^ Just curious. Thank you for helping :) – Biswapriyo Oct 23 '20 at 8:34
2

ghidra

addr = toAddr(0x7ffe0000)
currentProgram.memory.createUninitializedBlock("KUSER_SHARED_PAGE",addr,0x1000,0)
createData(addr,getDataTypes("KUSER_SHARED_DATA")[0])

result

undefined8 main(void)

{
  wprintf((__crt_locale_pointers *)L"Version: %lu.%lu.%lu\n",
          (ulonglong)KUSER_SHARED_DATA_7ffe0000.NtMajorVersion,
          (ulonglong)KUSER_SHARED_DATA_7ffe0000.NtMinorVersion,
          (ulonglong)KUSER_SHARED_DATA_7ffe0000.NtBuildNumber);
  return 0;
}

Method 1)

Use VirtualQuery to get the size
shown below is a python poc compare the result to (MEMORY_BASIC_INFO *)foo.RegionSize

:\>cat vq.py
from ctypes import *
meminfo =(c_ulong * 0x8)()
windll.kernel32.VirtualQuery(0x7ffe0000,byref(meminfo),sizeof(meminfo))
for i in meminfo:
    print (hex(i))


:\>python vq.py
0x7ffe0000
0x7ffe0000
0x2
0x1000
0x1000
0x2
0x20000
0x0

Method 2)

use windbg !vprot to get the same

:\>cdb -c "!vprot 7ffe0000;q" cdb | awk "/Reading/,/quit/"
0:000> cdb: Reading initial command '!vprot 7ffe0000;q'
BaseAddress:       7ffe0000
AllocationBase:    7ffe0000
AllocationProtect: 00000002  PAGE_READONLY
RegionSize:        00001000
State:             00001000  MEM_COMMIT
Protect:           00000002  PAGE_READONLY
Type:              00020000  MEM_PRIVATE
quit:

Method 3)

use windbg !address to Get a more Verbose Details of the same Address Space

:\>cdb -c "!address 7ffe0000;q" cdb | awk "/Usage:/,/quit/"
Usage:                  Other
Base Address:           7ffe0000
End Address:            7ffe1000
Region Size:            00001000 (   4.000 kB)
State:                  00001000          MEM_COMMIT
Protect:                00000002          PAGE_READONLY
Type:                   00020000          MEM_PRIVATE
Allocation Base:        7ffe0000
Allocation Protect:     00000002          PAGE_READONLY
Additional info:        User Shared Data


Content source: 1 (target), length: 1000
quit:
2
  • O, yeah! BTW, how do you know it's 0x1000 bytes? Is it just to make enough space? ntddk.h shows 0x720 bytes. – Biswapriyo Oct 24 '20 at 3:03
  • 1
    edited the answer – blabb Oct 24 '20 at 6:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.