9

I am trying to get the base address of ntdll.dll over the PEB. So, what I did was to dump the PEB (d fs:[30]). Then, I tried to get to PEB_LDR_DATA over the offset 0xC. Over the offset 0x1C of PEB_LDR_DATA I found the the pointer of InInitializationOrderModuleList and I was told that I can find the ntdll.dll address there. And that I should first find the address of kernel32.dll (which is always the second entry). So, I was able to find the address of kernel32.dll but it seems like I can't find the address of ntdll.dll.

00251ED8  .ܛὈ%Ậ%ὐ%Ẵ%.....@ᐴ@怀.TVٜڔ倀...뉨粘뉨粘趨即....ꮫꮫꮫꮫ......ܨ‐%Ỡ%‘%Ứ%
00251F58  †%Ẽ%.粑Ⱘ粒怀:Ȉ퀨粘⅘粓䀄耈..니粘니粘뾿䠂....ꮫꮫꮫꮫ......ܵC:\WINDOWS\system32\
00251FD8  kernel32.dll.ꮫꮫꮫꮫﻮﻮﻮ......߁⅐%Ὀ%⅘%ὐ%Ⅰ%὘%.粀똾粀耀@Bᾰ%Ῐ%䀄耈..늰粘늰粘뿀䠂
00252058  ....ꮫꮫꮫꮫ.....ߎC:\WINDOWS\WinSxS\x86_Microsoft.VC90.CRT_1fc8b3b
002520D8  9a1e18e3b_9.0.21022.8_x-ww_d08d0375\MSVCR90.dll.ꮫꮫꮫꮫ.....ߩẬ%‐%
00252158  Ẵ%‘%Ẽ%†%.硒ⵀ硔 .¾À⁸%℠%䀆逈..닀粘닀粘㷎䜱....ꮫꮫꮫꮫ....ߊ.ᓮîŸ%Ÿ%ﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮﻮ

This is the part where I have found the kernel32.dll. But in the fact of that this a linked list. Shouldn't I be able to find ntdll.dll too?

When, I open up the window of "Executable Modules" I can see the ntdll.dll but it seem I am not able to find the base address inside of the Struct.

Please tell me if you need clarification or if I am grievously mistaken.

2 Answers 2

12

The code below will set EAX to the image base address of ntdll.dll:

MOV EAX, DWORD PTR FS:[30]     ; EAX = PEB
MOV EAX, DWORD PTR DS:[EAX+0C] ; EAX = PEB->Ldr
MOV EAX, DWORD PTR DS:[EAX+1C] ; EAX = PEB->Ldr.InInitializationOrderModuleList.Flink
MOV EAX, DWORD PTR DS:[EAX+8]  ; EAX = image base of ntdll (LDR_MODULE's BaseAddress)

Based on your question above, it seems like you understand everything through the MOV EAX, DWORD PTR DS:[EAX+1C] instruction. Since ntdll.dll is the first module loaded, it's the first LDR_MODULE entry in InInitializationOrderModuleList. So with EAX pointing to PEB->Ldr.InInitializationOrderModuleList.Flink, [EAX+0] points to the list entry's Flink, [EAX+4] points to the list entry's Blink, and [EAX+8] is the BaseAddress value of the first LDR_MODULE entry (ntdll.dll's LDR_MODULE).

This image from http://blog.csdn.net/programmingring/article/details/11357393 may help:diagram

When EAX is set to PEB->Ldr.InInitializationOrderModuleList.Flink, it's pointing to the orange Flink in the first LDR_MODULE above. It's followed by the Blink at [EAX+4], and the "DllBase" (BaseAddress) at [EAX+8].

0
4

Assuming you want to see it in Windbg.

You can follow this walk through for each pointer points to successive LDR_DATA_TABLE_ENTRY the output is from calc.exe.

0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(@$peb+c)+c)
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\calc.exe"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(@$peb+c)+c))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\ntdll.dll"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(@$peb+c)+c)))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\kernel32.dll"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(poi(@$peb+c)+c))))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\SHELL32.dll"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(poi(poi(@$peb+c)+c)))))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\ADVAPI32.dll"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(poi(poi(poi(@$peb+c)+c))))))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\RPCRT4.dll"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(poi(poi(poi(poi(@$peb+c)+c)))))))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\Secur32.dll"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(poi(poi(poi(poi(poi(@$peb+c)+c))))))))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\GDI32.dll"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(@$peb+c)+c)))))))))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\USER32.dll"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(@$peb+c)+c))))))))))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\msvcrt.dll"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(@$peb+c)+c)))))))))))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\SHLWAPI.dll"
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(@$peb+c)+c))))))))))))
   +0x024 FullDllName : _UNICODE_STRING ""
0:000> dt ntdll!_LDR_DATA_TABLE_ENTRY -y Full poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(poi(@$peb+c)+c)))))))))))))
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\calc.exe"

an alternate representation of the above method

lkd> dt nt!_ldr_data_table_entry -y Full @@c++(@$peb->Ldr->InLoadOrderModuleList.Flink)
   +0x024 FullDllName : _UNICODE_STRING "C:\Program Files\Windows Kits\8.0\Debuggers\x86\windbg.exe"
lkd> dt nt!_ldr_data_table_entry -y Full @@c++(@$peb->Ldr->InLoadOrderModuleList.Flink->Flink)
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\ntdll.dll"
lkd> dt nt!_ldr_data_table_entry -y Full @@c++(@$peb->Ldr->InLoadOrderModuleList.Flink->Flink->Flink)
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\kernel32.dll"
lkd> dt nt!_ldr_data_table_entry -y Full @@c++(@$peb->Ldr->InLoadOrderModuleList.Flink->Flink->Flink->Flink)
   +0x024 FullDllName : _UNICODE_STRING "C:\WINDOWS\system32\ADVAPI32.dll"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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