Binaries are usually stripped. For ELF binaries, you can check it with file
command
$ file /bin/true
/bin/true: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0x73796652ea437df8ac7b3ba1864a7ac177e27600, stripped
Notice the stripped
at the end of file's result. It means, among other things, that symbols have been removed, so it won't find main
function.
In order to run the binary and stop the debugger right after the load, there is some kind of universal method that should almost always work (kind of universal, not 100%)
You have to find the entry point, retreived by this command :
$ readelf -h /bin/true | grep "Entry point"
Entry point address: 0x401264
Then load the binary into your favourite debugger (lldb, gdb, ...) and break on this address.
lldb :
$ lldb /bin/true
(lldb) target create "/bin/true"
Current executable set to '/bin/true' (x86_64).
(lldb) br s -a 0x401264
Breakpoint 1: address = 0x0000000000401264
(lldb) r
...
(lldb)
gdb :
$ gdb -q /bin/true
Reading symbols from /bin/true...(no debugging symbols found)...done.
gdb$ b *0x401264
Breakpoint 1 at 0x401264
gdb$ r
Breakpoint 1, 0x0000000000401264 in ?? ()
gdb$
Once you've loaded your binary and your breakpoint has been triggered, you can display following instructions that will be executed this way :
lldb :
(lldb) x -s4 -fi -c11 $pc
-> 0x401264: xor ebp,ebp
0x401266: mov r9,rdx
0x401269: pop rsi
0x40126a: mov rdx,rsp
0x40126d: and rsp,0xfffffffffffffff0
0x401271: push rax
0x401272: push rsp
0x401273: mov r8,0x403560
0x40127a: mov rcx,0x403570
0x401281: mov rdi,0x4011c0
0x401288: call 0x401060 <__libc_start_main@plt>
gdb :
gdb$ x/11i $pc
=> 0x401264: xor ebp,ebp
0x401266: mov r9,rdx
0x401269: pop rsi
0x40126a: mov rdx,rsp
0x40126d: and rsp,0xfffffffffffffff0
0x401271: push rax
0x401272: push rsp
0x401273: mov r8,0x403560
0x40127a: mov rcx,0x403570
0x401281: mov rdi,0x4011c0
0x401288: call 0x401060 <__libc_start_main@plt>
i
flag means instruction, and $pc
means Program Counter (equivalent of EIP/RIP for 32/64 bits architecures). You can see that __libc_start_main will be called at address 0x401288
. Its man page indicates its first argument is a pointer to binary main
function. 1st argument is here loaded in rdi
register, meaning that main
function is located at address 0x4011c0
.
You just have to finally place a breakpoint at this address (0x4011c0
) and you'll be at the beginning of your binary main function.
Further reading : How to handle stripped binaries with GDB? No source, no symbols and GDB only shows addresses?
Good luck and have fun !
gdb
, see: Stopping at the first machine code instruction in gdb at SO