This question already has an answer here:
I wrote a really simple program:
ebrahim@ebrahim:~/test$ cat main.c
int main() {
int i = 0;
return i;
}
And the I compiled it with -s
for stripped mode:
ebrahim@ebrahim:~/test$ gcc -s main.c -o f3
ebrahim@ebrahim:~/test$ file f3
f3: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=4dc6b893fbae8b418ca41ddeef948df1fcb26d3d, stripped
Now, I'm trying to find out the main function start address using GDB:
ebrahim@ebrahim:~/test$ gdb -nh f3
GNU gdb (Ubuntu 7.11.90.20161005-0ubuntu2) 7.11.90.20161005-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from f3...(no debugging symbols found)...done.
As there is no Symbol info inside the file, I need to put a break at the file entry point and the disassemble it and find the start address of main
function. So I used info file
command to find the file entry point
address:
(gdb) info file
Symbols from "/home/ebrahim/test/f3".
Local exec file:
`/home/ebrahim/test/f3', file type elf64-x86-64.
Entry point: 0x530 <<<<=============
0x0000000000000238 - 0x0000000000000254 is .interp
0x0000000000000254 - 0x0000000000000274 is .note.ABI-tag
0x0000000000000274 - 0x0000000000000298 is .note.gnu.build-id
0x0000000000000298 - 0x00000000000002b4 is .gnu.hash
0x00000000000002b8 - 0x0000000000000360 is .dynsym
0x0000000000000360 - 0x00000000000003f1 is .dynstr
0x00000000000003f2 - 0x0000000000000400 is .gnu.version
0x0000000000000400 - 0x0000000000000420 is .gnu.version_r
0x0000000000000420 - 0x00000000000004f8 is .rela.dyn
0x00000000000004f8 - 0x000000000000050f is .init
0x0000000000000510 - 0x0000000000000520 is .plt
0x0000000000000520 - 0x0000000000000528 is .plt.got
0x0000000000000530 - 0x00000000000006e2 is .text
0x00000000000006e4 - 0x00000000000006ed is .fini
0x00000000000006f0 - 0x00000000000006f4 is .rodata
0x00000000000006f4 - 0x0000000000000728 is .eh_frame_hdr
0x0000000000000728 - 0x000000000000081c is .eh_frame
0x0000000000200de0 - 0x0000000000200de8 is .init_array
0x0000000000200de8 - 0x0000000000200df0 is .fini_array
0x0000000000200df0 - 0x0000000000200df8 is .jcr
0x0000000000200df8 - 0x0000000000200fb8 is .dynamic
0x0000000000200fb8 - 0x0000000000201000 is .got
0x0000000000201000 - 0x0000000000201010 is .data
0x0000000000201010 - 0x0000000000201018 is .bss
As we expected the entry point is the start of .text
section. So I put a breakpoint on this address:
(gdb) b *0x0000000000000530
Breakpoint 1 at 0x530
(gdb) r
Starting program: /home/ebrahim/test/f3
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x530
(gdb)
The question is why GDB cannot insert this breakpoint?
Debugging stripped code is probably very much useless (except for reverse engineering), but you can cause
gdb
to stop at the very first instruction, and you are already doing this accidentally. If the address of a breakpoint cannot be mapped,gdb
stops and tells you the error. As a side effect, your program is stopped at its first instruction. An address that's guaranteed to be unmappable is0
, so just do the following:Here you see the
PC
sits at0x00007ffff7ffffd190
. So this is your entry point at runtime.In order to be able to continue (or: single-step for example), you have to delete the offending breakpoint:
Credits for this answer go to this answer on reverse engineering
The problem is that you're attempting to debug a shared object as though it were an executable. In particular your
file
reported:Because it's a shared object rather than an executable, you will probably need to start with an actual program. In this particular case, you would need to link that shared object file with another program of your own making. For example, I've created a simple shared object:
snoot.c
Compile with
Now we have the equivalent of your stripped shared library. If we do
objdump -T libsnoot.so
we get this:The only two symbols in the
.text
section are the two functions we defined. Unfortunately, there's no general way to determine how to call the functions (that is, no way to recover the original C function prototype) but we can simply guess. If we guess wrong, the stack will be off. For example, let's try to link tosquare
with this program:testsnoot.c
Assuming the
so
file is in the same directory, we can compile and link like so:Now we can debug normally, since this test driver is under our control:
Note that we need to set
LD_LIBRARY_PATH
or else the library we're working with won't be loaded and execution will terminate.Now you can see the disassembly of the function and see what it's doing. In this case, since we see that there is a reference to
-0x4(%rbp)
it's clear that this function is actually expecting an argument although we don't really know what kind.We can rewrite the test drive function and iteratively approach debugging until we gain an understanding of what the stripped library is doing.
I'm assuming you can take it from there, now that I've showed the general procedure.