The DLL is partly missed in remote kernel debugging - windows

I'm doing some remote kernel debugging with IDA + WinDBG plugin and I want to set a breakpoint in some function inside the DLL, which I found while disassembling it in IDA. I switched to the process, which loads the target DLL, but unfortunately I found out that the DLL in memory is partly missed including my function.
Examples for proof are below. Here IDA recognized the function sub_180001FC8, but in WinDBG this disassembly breaks off on address 0x7fff3d131fff.
Screenshot 1 - DLL loaded into memory in live kernel debugging
Screenshot 2 - same DLL opened in IDA "statically"
What's wrong and how to recover missed parts?

Finally I found the answer.
The region where disassembly breaks off with ?? is paged out memory region.
To "restore" the page I used the command:
.pagein /f /p <process_address> <page_start_address>
For my situation:
.pagein /f /p 0xffffbc4a4405efc0 0x7fff3d132000
This command loads memory pages from secondary storage and they become visible in disassembly.
References:
https://en.wikipedia.org/wiki/Memory_paging
https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/-pagein--page-in-memory-

Related

Why the DLL loaded in memory doesn't fully correspond to the original DLL file?

Please, correct me if I'm wrong anywhere...
What I want to do:
I want to find a certain function inside some DLL, which is being loaded by Windows service, during remote kernel debugging via WinDBG. (WinDBG plugin in IDA + VirtualKD + VMWare VM with Windows 10 x64).
I need to do it kernel mode, because I need to switch the processes and see all the memory
What I did:
I found an offset to the function in IDA (unfortunately, the DLL doesn't have debug symbols).
Connected to the VM in Kernel Mode.
Found the process of the service by iterating over the svchost-processes (!process 0 0 svchost.exe) and looking at CommandLine field in their PEBs (C:\Windows\system32\svchost.exe -k ...).
Switched to the process (.process /i <address>; g), refreshed the modules list (.reload)
Found the target DLL in user modules list and got its base address.
The problem:
The DLL loaded into memory doesn't fully correspond to the original DLL-file, so I can't find the function there.
When I jump to the address like <dll_base_address> + <function_offset> there is nothing there and around. But I found some other functions using this method, so it looks correct.
Then I tried to find the sequence of bytes belonging to the function according to the original DLL-file and also got nothing.
The function uses strings, which I found in data section, but there are no xrefs to them.
Looks like that function has completely disappeared...
What am I doing wrong?
P.S.: Also I dumped memory from <dll_start> to <dll_end> and compared it with the original file. Besides different jump addresses and offsets, sometimes the assembler code is completely missed...
It appeared that the memory pages were paged out. .pagein command did the trick
It appeared, that some memory pages were paged out (moved to secondary storage). This command loads the pages from secondary storage and they appear in disassembly:
.pagein /f /p <process_address> <memory_page_address>
See for more: The DLL is partly missed in remote kernel debugging

How does WinDbg itself work?

I have recently started windows driver development. I am wondering how does it actually debug my driver. The setup I have is --> Win7 as host, XP as guest on VMware, and I am debugging through serial port.
The research I have done:
I found only this link saying very few things that I am talking about.
I already know how debugger works on single OS, in that case debugger is also on the same OS, so it knows which process is running. That is understandable. But here, debugger is on entirely different OS, an entirely different environment. I just say file->open source files and I AM able to put breakpoints!! Moreover when I load driver, it actually breaks there. I mean why../How? How does XP's kernel comes to know(drivers are extension to kernel, atleast WDM, don't know about WDK) that there is source code of this driver? and that also outside its control(environment)? I mean I can have 10 files open with breakpoint in them, but it works beautifully, I am not able to fail/fool it.
So what I am thinking is like, whenever we add source to windbg on Win7, it creates the binary from that source, and whenever XP is going to load any binary, it checks if this is the binary that windbg is waiting for. what is confusing in above link is, Vikrant is saying that debugger asks kernel(XP) that it is willing to debug a process --> Bus HELLO... process is running on XP, and windbg on Win7 and does not know name or id of process. It has source code, but consider a case where there is a driver which is build out of 300 files, and just one, probably simplest file is open in windbg, how it matched that this source code is of the driver being run?
#Kjelll answer is correct. Here is the full scenario, including explanation to your comment:
PDB files have line information. This is a mapping from each (file,line) location to address (RVA - relative virtual address).
When you set a break point on a source file, WinDBG checks whether this source file correspond to a current address. If it is - it sets the breakpoint. Otherwise, it becomes a "future breakpoint" (not sure whether Microsoft uses this terminology).
When a new binary is a loaded, the agent on the client communicates with the host, informs it about the binary. At this point - WinDBG will try to allocate a PDB file.
WinDBG will start at the PDB location embedded within the file. You can see this value by using this command line: windbg -dump -pdbpath xxx.sys. This should explain how WinDBG will find a symbol file even if not on the .sympathy path (that I believe answers your comment to Kjell).
WinDBG will then search at the .sympathy.
Once symbol is find, it will look at all future breakpoint, and if applicable will set an actual breakpoint.
I think your link explain your question pretty well, but you have probably not realized what the mechanism of the pdb do for the debugger. The windbg on your host OS uses the pdb file to translate line nubers in the source files to addresses in your guest OS (xp) . Then the the debugger agent uses this address to set break points (Int 3) in the guest OS.This is much in the same way as a local debugger do to a local process.

ASLR and Windows System DLLs for non-aware executables?

From a Microsoft article:
Address Space Layout Randomization (ASLR)
ASLR moves executable images into random locations when a system
boots, making it harder for exploit
code to operate predictably. For a
component to support ASLR, all
components that it loads must also
support ASLR. For example, if A.exe
consumes B.dll and C.dll, all three
must support ASLR. By default, Windows
Vista and later will randomize system
DLLs and EXEs, but DLLs and EXEs
created by ISVs must opt in to support
ASLR using the /DYNAMICBASE linker
option.
I don't quite get it. Take the base system DLLs loaded by every process on WIndows: NtDll.dll and kernel32.dll.
If a have a non-aware executable, will these system DLLs use ASLR? That is, will they load at a different base address after every system reboot on Win 7 for this executable or will they always load at the same base address after system reboot like they do on Win XP?
To make it more clear what I mean: My typical dummy program's startup stack will look like this:
write_cons.exe!wmain() Line 8 C++
write_cons.exe!__tmainCRTStartup() Line 583 + 0x19 bytes C
write_cons.exe!wmainCRTStartup() Line 403 C
> kernel32.dll!_BaseProcessStart#4() + 0x23 bytes
Looking at the asm of BaseProcessStart, I see on my XP box here:
_BaseProcessStart#4:
7C817054 push 0Ch
7C817056 push 7C817080h
7C81705B call __SEH_prolog (7C8024D6h)
7C817060 and dword ptr [ebp-4],0
...
Now what interests me is the following:
On Windows XP, the address will always be 0x7C817054, regardless of how many times I reboot this machine. If I were on Win7 with ASLR, will this address change between reboots if the executable that loads kernel32.dll is not enabled for ASLR?
(Note: For me, atm., there is only one minor use-case this address would be useful for: In Visual Studio, I can only set a "Data Breakpoint" for assembly level functions, that is a breakpoint # 0x7... - If I want to break in a specific ntdll.dll or kernel32.dll function, in Windows XP I do not have to adjust my breakpoints between reboots. With ASLR kicking in (the scope of this question) I would have to change the Data Breakpoints between reboots.)
Technically whether the system dlls get relocated or not, it shouldn't matter, as the linker will bind to symbols, not addresses. These symbols are resolved by the runtime loader into to addresses for the instanced system dlls, thus your binary should be none the wiser. From what i've seen however, windows 7 will reset the base randomization every reboot, including system dlls(note: this is from debuging WOW64 apps on widows server 2008 R2). You can also do a system wide disabling of ASLR via some registery edits, but thats not really relevant...
Update:
the section on ASLR in this article explains what gets relocated and when.
it doesn't mention if the base will reset every reboot, but for system dlls, its never going to be guaranteed to load at the same address twice, reboot or no reboot.
the important thing is according to article, everything needs to opt-in to ASLR for system dll's to be relocated.
Your program will resolve calls into system DLLs wherever they happen to be loaded. But, unless your executable is linked with /DYNAMICBASE, it will not be given a randomized base address. In other words, your exe will always load at the same base address.
If you want your exe to load at a randomized address, then you have to link it with /DYNAMICBASE, and every DLL that it references must also have been linked with /DYANMICBASE. The system DLLs (starting in Vista) are all linked with /DYNAMICBASE.

WinDbg -- debugging mixed x64 managed/unmanaged code

I'm using WinDbg (Native x64 -- NOT Itanium) to debug an x64 (unmanaged) application that loads both managed an unmanaged DLLs.
I'm trying to set a breakpoint in one of the unmanaged DLLs. When the breakpoint is hit and I step through, the instructions displayed are totally different from what they should be. I verified with two different disassemblers that WinDbg is not displaying the correct disassembly as I step through.
When attaching to the application, I get a line like this:
ModLoad: 00000000`XXXXXXXX 00000000`YYYYYYYY C:\MyDLL.DLL
I adjusted the addresses in the two disassemblers to reflect the base address XXXXXXXX.
What could be the problem?
Does uf modname!FuncName return the correct results? You can sometimes trick WinDbg if you unassemble / breakpoint at weird places. Remember, that x86/x64 is a variable-width instruction set, so if you start reading halfway through an instruction, the disassembler gets confused.
Somewhere i've noticed info that this may be related to improper entry point in your DLL. But I have no clue what to do with this information (i'm beginner).

Does the VS disassembly window show the whole EXE?

A client is running my company's program and it is halting before it gets anywhere. They sent this information from the Windows Event Log:
faulting module program.exe, version 1.2.3.4, fault address 0x00054321.
We don't have much else to go on so as a last ditch effort I've been trying to see if I can find where that position is in a disassembler. I run the program through Visual Studio, pause it, look at the Disassembly window and try scrolling to that address but all I get there is this:
00054321 ???
00054322 ???
00054323 ???
00054324 ???
00054325 ???
00054326 ???
00054327 ???
00054328 ???
00054329 ???
0005432A ???
Would this be because Visual Studio only disassembles part of the EXE near the pause position or something? It's hard for me to look through how much is actually disassembled because the scrollbar doesn't work fully. (I can't grab and move the scroll position; I have to scroll by line or by page.)
Thanks for any insight you may have!
The fault address could also be caused from a stack corruption problem, ie. the return address could be compromised and jumped back to the wrong address # 0x54321.
Also, depending on the tecnology used (Java, .NET) the code could change it's position between runs.
Visual studio makes a disassembly of the whole process space. ???? means that the position is not accessible.
You'd better need a stack-frame to see what's happening, from a core dump.
WinDbg may be your friend here, there you can load your executable and the symbols (.pdb), if you can get a (mini)dump as QbProg says that would definitely ease the search. But I have had experiences when it was easier doing this in WinDbg.
What are you expecting to see in the disassembly window? This approach is not going to work. If you are able to rebuild the exact same build configuration of that your client is running then you can enable the /MAP option in the project's link options. This will create a file that maps symbols to addresses and will allow you to see which function was executing when the crash occurred. You may have to do a bit of calculation to offset the raw mapped address against the address the module was loaded at on the client's PC.
As Fredrik says, WinDbg may be able to help too, especially if you can get a crash dump from your client's PC.

Resources