When I run process with GDB and the process is not running I always get same address for same function. However when I run the process I get different address every time.
How can I compare addresses from 2 runs of the same process? ( the binary does not contain debug symbols )
when process runs there is dynamic memory mapping that may change every time you run the process.
to watch it simply use the gdb command :
"info proc mapping"
another way to see memory mapping is bash "pmap" command.
each mapping region has start address and size , if you reduce the start address from the runtime address you will get the same address that you get when gdb is not running , which is always the same address.
little example:
mapping output looks like this :
*Start Addr End Addr Size Offset objfile
0x563d17d8c000 0x563d17fd2000 0x246000 0x0 /opt/redislabs/bin/dmcproxy
0x563d181d2000 0x563d181d8000 0x6000 0x246000 /opt/redislabs/bin/dmcproxy
0x563d181d8000 0x563d181ee000 0x16000 0x24c000 /opt/redislabs/bin/dmcproxy*
you get the address 0x0000563d17ed13fa on runtime.
in order to translate it to program address you should reduce its start address , start address is 0x563d17fd2000 so result address is 0x1453fa
--> this is the address you have in the binary code , if it is an address of a funtion you can see it using objdump or by running gdb without running the program.
if the binary you run is stripped and you have unstripped version of the same binary on different machine you can now use the calculated address to see details about the address you found by running gdb on the unstripped binary ( without running the process ) and use:
"info symbol 0x1453fa"
it will work even if you are in the middle of a function
( note that backtraces will give you the return address and not the function address which is usually different )
Related
I'm trying to get the physical address of a kernel symbol (because I need it to be read by a system that only accepts phys addr). So I'm using things like __pa(vaddr) and virt_to_phys(vaddr).
Problem is that the conversion is not correct everytime. Sometimes it is, sometimes it's not. How do I know that? Because I'm reading the value on the kernel module as well and comparing to value read using fmem and using my other system.
Ex:
my kernel symbol's address is 0xffffffffb3400000, so when I do
printk(KERN_INFO "Addr: 0x%lx , Value: 0x%lx\n", _stext, *_stext) I get => Addr: 0xffffffffb3400000 , Value: 0x4801e03f51258d48.
When it reads right I use fmem and the other system to read the physical address given by __pa and the value matches 0x4801e03f51258d48 in both cases. But sometimes it doesn't work, so the value is different. And how do I know the value itself hasn't changed? Because dereferencing the virtual address still gives me the result 0x4801e03f51258d48.
I know kernel code and data changes on every boot (including kernel symbols addresses), that's not a problem since I'm getting the kernel symbol's addr everytime. But I expected the virtual to phys mapping to be the same every time, shouldn't it be? I mean, what can I do to get the physical address of my kernel symbol correctly?
So right now I have
u64 _stext_pa = __pa(_stext_va)
printk(KERN_INFO "Value of _stext (va: 0x%lx | pa: 0x%x) = 0x%lx\n", _stext_va, _stext_pa, *_stext_va)
Addresses (virtual and physical) change every boot but the value is always the same. That's what I need.
I need a physical address paddr so that I can perform int value = *paddr; on my other system and get the same result I'm getting with the virtual address
Edit: this "other system" I'm refering to is an SMM driver, but that's not relevant, just in case you might be wondering "what is 'other system'"
I am building a Memory Scanner to find malware strings in a process.
Btw, when I was searching about the VirtualQueryEx dll, I saw that people starts its variable lpAdress ( which is supposed to be the Base Address of the process) with a NULL/0 value
LPVOID lpAdress = 0
and in each loop they increase the adress value by the size of the page they just read, so that way they go to the next page and can map all process virtual memory
lpAdress += mbi.RegionSize # mbi is a variable with MEMORY_BASIC_INFORMATION structure
So, is lpAdress the value of memory considering 0 as a start of the own process virtual memory and you dont need to get the actual base adress of the process in memory ? Sorry if my question looks dumb, but the MSDN documentation is confusing me.
Each process has it's own virtual address space that starts at 0. The various executable files (.exe / .dll / whatever) are loaded either at addresses specified in the file or more recently at random addresses for security purposes.
A process can easily have mapped memory regions at addresses lower than where the process executable is loaded. For this reason, if you want to examine a process' entire memory space you need to start at 0.
I have a "Hello World" program to which I've attached lldb. I'm trying to answer a few questions for myself about the results I get when I try to get the address of library functions:
(lldb) image lookup -n printf
1 match found in /usr/lib/system/libsystem_c.dylib:
Address: libsystem_c.dylib[0x000000000003f550] (libsystem_c.dylib.__TEXT.__text + 253892)
Summary: libsystem_c.dylib`printf
(lldb) image lookup -n scanf
1 match found in /usr/lib/system/libsystem_c.dylib:
Address: libsystem_c.dylib[0x000000000003fc69] (libsystem_c.dylib.__TEXT.__text + 255709)
Summary: libsystem_c.dylib`scanf
(lldb) expr &printf
(int (*)(const char *__restrict, ...)) $2 = 0x00007fff6f8c5550 (libsystem_c.dylib`printf)
(lldb) expr &scanf
error: unsupported expression with unknown type
I have three questions here:
What kind of address is 0x00007fff6f8c5550? I assume it is the function pointer to printf. Is this a virtual address that exists only in the mapped space of the current process? If yes, why does another program return the same address for printf?
Assuming it's some global shared address that is the same for every process, would modifying the contents of the data at this address (which I haven't been able to do yet) create a copy of the modified memory page and will the address change? (i'm on Mac OS and I assume one process cannot change shared memory for another process)
Why does expr &scanf not work, but expr &printf does?
What kind of address is 0x00007fff6f8c5550? I assume it is the function pointer to printf.
Yes, that's correct.
Is this a virtual address that exists only
in the mapped space of the current process?
Well, yes and no. It is a virtual address specific to your process and you should not assume it's valid in another process. But:
If yes, why does another
program return the same address for printf?
As an optimization, macOS uses a shared mapping for a lot of the system libraries. They are loaded once at boot and used by all processes. For a given boot, the address is constant across all such processes. However, the address is randomized each boot for security.
Assuming it's some global shared address that is the same for every process, would modifying the contents of the data at this address
(which I haven't been able to do yet) create a copy of the modified
memory page and will the address change?
Well, it is mapped copy-on-write. So, modifying it would create a copy. However, that wouldn't change its address. The OS would simply modify the mapping so that the memory around that address is private to your process.
(i'm on Mac OS and I assume
one process cannot change shared memory for another process)
Well, processes can cooperate to have writable shared memory. But, in general, you're correct that security precautions prevent unwanted modifications to a process's memory.
Why does expr &scanf not work, but expr &printf does?
Your program (presumably) doesn't use scanf, so there's no debugging information regarding it. The main thing lldb is missing is the type of scanf. If you use a cast expression, it can work:
(lldb) p scanf
error: 'scanf' has unknown type; cast it to its declared type to use it
(lldb) p &scanf
error: unsupported expression with unknown type
(lldb) p (int(*)(const char * __restrict, ...))scanf
(int (*)(const char *__restrict, ...)) $3 = 0x00007fffd7e958d4 (libsystem_c.dylib`scanf)
Conversely, it works for printf because your program does use it.
I tried to run inkscape-0.92.3 in gdb. Precisely, I tried to set a breakpoint on the first address of the .init section in its main shared library (i.e., /usr/lib/inkscape/libinkscape_base.so). The address is 0x7ffff6ebd9d0 based on the information returned by info files. But when I set the breakpoint on this address using b *0x7ffff6ebd9d0, I receive the following error:
Cannot insert breakpoint 1.
Cannot access memory at address 0x7ffff6ebd9d0
This address is the address of the _init function of this library. The same symbol, also, exists in other shared libraries. So I can put a breakpoint on this symbol using b _init, which leads to a lot of sub-breakpoints. This time all breakpoints work fine and I can c(ontinue) until I reach the _init symbol for the libinkscape shared library. Does anybody know the reason for the error in the raw address case?
Does anybody know the reason for the error in the raw address case?
The reason: this address isn't mapped yet (the library hasn't been loaded yet).
It works for break _init case because GDB can check whether any newly-loaded shared library defines that symbol. But it's not smart enough to check whether address 0x7ffff6ebd9d0 becomes breakpoint-able.
You can work around this by using (gdb) set stop-on-solib-events 1. GDB will then stop every time new shared libraries are loaded, before running their initializers.
Once libinkscape_base.so shows up, you will be able to use the address breakpoint as desired.
This is question on JTAG.
I am trying to set a read/write breakpoint in a range of addresses.
Command I give in b.set window is as follows(and selecting read/write)
A:0x8500000..0xd300000
But when i list it(b.list) it shows as follows :
AN:0x0:0x8500000--0xd300000
Why is 0x0 getting appended? So, is my original range of addresses at which i wanted to put the breakpoint is altered?
Additional Information : I am using Lauterbach Trace 32. CPU is ARm Krait
Thank you.
0x00 is the space ID. It is 0 for complete kernel space. For User spaces this space id is the process ID. Space Id's are nothing but Address space identifiers, used by TLB to differentiate the pagetable ebtries.