If a process has loaded a certain dll in its address space, how can I determine where the dll 's base address is? I have tried using depends.exe but the address it gives is not authentic. The method I am using now is to write a simple WinAPI program, disassemble it and check the address in the call instruction. However this method is quite time consuming...
Thanks!
Related
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
I'm in the process of porting an existing win32 application to x64.
In one of the modules, I see a fixed based address passed to MapViewOfFileEx() as "lpBaseAddress" argument. The value passed is 0x20000000.
In one of the porting guidelines, I read that we should stay away from such "magic numbers" while porting to x64.
But, the code using the base address 0x20000000 is a legacy one and is called from lots of other modules for shared memory allocation. So, I'm hesitant to change the value of this address while porting to x64.
I'd like to know if the code ported to x64 will work well with the same base address?
As a side note, I also see the current (x86) code links, ie invokes the linker with /base option value of 0x1C000000, ie -base:0x1C000000.
Does this have any relation to the valid value of base address we can request from MapViewOfFileEx()?
Any insight/ideas will be greatly appreciated.
Edit:
To clarify, this question doesn't pertain to any addresses per se. What I want to know is whether a 32-bit constant address passed to MapViewOfFileEx() can be reused while porting to x64 platform. The reference to linker option "base" was to ask if the address specified as the base address while linking has any relation to the address lpBaseAddress we pass to MapViewOfFileEx().
This is a bit of a non-question. The real issue is why the file must be mapped at that address, and I'm having a tough time believing that changing the 'legacy' code to be more flexible is completely off the table.
Calling MapViewOfFileEx with a specific base address is really, really dangerous. There is never any guarantee that Windows will be able to honour that request, since, even if it's only one time in a hundred (which is the worst kind of bug, no?), that address will already be occupied. ASLR is a case in point, or Windows might have put the heap there, or whatever.
So, tl;dr: don't do that. Just don't. Find another way.
I'm studying Windows system internals and the question is just a guess.
I learn that DLL is a form of shared libraries, so at least the code section of the same DLL is shared between processes using it. (By adding the same page entries into the page table of these processes) The code section usually has something like jump tables, which need to be relocated (i.e. write the run-time virtual address to fix the pointer) before it's ready to be executed.
Assume that the same DLL aa.dll is mapped in two different processes at different virtual addresses. (e.g. a.exe 0x00400000 b.exe 0x00410000) The same pointer (at .text+0x100) will be fixed into different addresses. (e.g. a.exe 0x00400100 b.exe 0x004100100). So we have to make a copy of the code section and change it to adapt one process. Then how can the code section be shared?
Am I right?
Answering my own question. The first time a DLL is loaded, Windows would try to load it at the Preferred address which would not require relocation (i.e. fixing addresses due to the fact that code segment is located at x). If it cannot be loaded at the preferred address, it would be allocated virtual pages at a free address backed up by the DLL file itself (not swap file) but marked as Copy-On-Write. Now Windows has to go and fix up the assembly code using the relocation table. Hopefully only a small percentage of code needs to be fixed up and each code segment that is changed would be copied on write and put into physical memory somewhere.
Each time a process cannot load a DLL at the preferred address, I believe this process would happen. This is why sometimes popular DLLs need to be rebased so that their preferred addresses don't conflict.
Last time I described my problem badly.
Now I'll try to explain my problem clearer.
I'm trying to make HDD serial checking to prevent distribution of the program. I don't have its src, so I found some space in .code section and injected code there.
You can see intermodular calls. For example, call kernel32.GetDriveTypeA matches call 75738D98. BUT after reboot this address changes. However my code calls incorrect 75738D98 address.
I need to fix it (resolve new GetDriveTypeA address and replace 75738D98 with correct address)
LoadLibrary and GetProcAddress will give you the address to a DLL function. The next natural question is: how can you call LoadLibrary and GetProcAddress if you don't know their address?
All user processes have kernel32 loaded. You don't need to dynamically load anything in kernel32.
Normally your linker & the OS loader does this all for you by linking to an import library (kernel32.lib for example). This will tell the OS that you want kernel32 loaded with your DLL. Your DLL has a import address table which contains a bunch of stubs to the real imported functions. When your module is loaded, the OS patches these stubs to point to the real function address.
You should probably be doing it this way too. Your app can even be detected as malware if you try to get too hackery.
Do you have a good reason not to just link to the import lib?
I always thought .dll is working the same way as .so in linux,
but some article says not.
Does windows ensure that memory will contain only one copy the same dll as in linux?
I don't have a clue to check it myself in windows,so I can only ask here.
UPDATE
Anyone knows how do verify this manually?
Here's a short description: DLL Hell, basically in modern Windows it use a technique called Memory Mapping where the DLL is loaded once, if both processes try to load the DLL from the same directory. So to answer your question, it is working the same was as in Linux.
If the DLL can be loaded at the same base virtual address in two processes then there will only be one copy of the DLL in physical memory.
Since Windows does not use position independent code, if a DLL cannot load at its preferred base address it will be rebased and thus not be able to share physical memory with other instances.