GDB Cannot insert breakpoint, Cannot access memory at address XXX? [duplicate]

可紊 提交于 2019-11-29 07:31:01

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 is 0, so just do the following:

(gdb) b *0
Breakpoint 1 at 0x0
(gdb) r
Starting program: [...]
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x0

(gdb) disas
Dump of assembler code for function _start:
=> 0x00007ffff7ddd190 <+0>: mov    %rsp,%rdi
   0x00007ffff7ddd193 <+3>: callq  0x7ffff7de0750 <_dl_start>

Here you see the PC sits at 0x00007ffff7ddd190. 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:

(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) c
Continuing.

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:

ELF 64-bit LSB shared object

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

#include <stdio.h>

int square(int test) {
    return test*test;
}

int func() {
    n = 7;
    printf("The answer is %d\n", square(n)-5);
}

Compile with

gcc -shared -fpic snoot.c -o libsnoot.so
strip libsnoot.so

Now we have the equivalent of your stripped shared library. If we do objdump -T libsnoot.so we get this:

libsnoot.so:     file format elf64-x86-64

DYNAMIC SYMBOL TABLE:
0000000000000580 l    d  .init  0000000000000000              .init
0000000000000000  w   D  *UND*  0000000000000000              _ITM_deregisterTMCloneTable
0000000000000000      DF *UND*  0000000000000000  GLIBC_2.2.5 printf
0000000000000000  w   D  *UND*  0000000000000000              __gmon_start__
0000000000000000  w   D  *UND*  0000000000000000              _Jv_RegisterClasses
0000000000000000  w   D  *UND*  0000000000000000              _ITM_registerTMCloneTable
0000000000000000  w   DF *UND*  0000000000000000  GLIBC_2.2.5 __cxa_finalize
0000000000201028 g    D  .got.plt   0000000000000000  Base        _edata
00000000000006e0 g    DF .text  0000000000000010  Base        square
0000000000201030 g    D  .bss   0000000000000000  Base        _end
0000000000201028 g    D  .bss   0000000000000000  Base        __bss_start
0000000000000580 g    DF .init  0000000000000000  Base        _init
0000000000000724 g    DF .fini  0000000000000000  Base        _fini
00000000000006f0 g    DF .text  0000000000000032  Base        func

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 to square with this program:

testsnoot.c

extern void square(void);

int main() {
    square();
}

Assuming the so file is in the same directory, we can compile and link like so:

gcc testsnoot.c -o testsnoot -L. -lsnoot

Now we can debug normally, since this test driver is under our control:

LD_LIBRARY_PATH="." gdb ./testsnoot

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.

(gdb) b square
Breakpoint 1 at 0x400560
(gdb) r
Starting program: /home/edward/test/testsnoot 
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.24-4.fc25.x86_64

Breakpoint 1, 0x00007ffff7bd56e4 in square () from ./libsnoot.so
(gdb) x/20i $pc
=> 0x7ffff7bd56e4 <square+4>:   mov    %edi,-0x4(%rbp)
   0x7ffff7bd56e7 <square+7>:   mov    -0x4(%rbp),%eax
   0x7ffff7bd56ea <square+10>:  imul   -0x4(%rbp),%eax
   0x7ffff7bd56ee <square+14>:  pop    %rbp
   0x7ffff7bd56ef <square+15>:  retq   
   0x7ffff7bd56f0 <func>:   push   %rbp
   0x7ffff7bd56f1 <func+1>: mov    %rsp,%rbp
   0x7ffff7bd56f4 <func+4>: sub    $0x10,%rsp
   0x7ffff7bd56f8 <func+8>: movl   $0x7,-0x4(%rbp)
   0x7ffff7bd56ff <func+15>:    mov    -0x4(%rbp),%eax
   0x7ffff7bd5702 <func+18>:    mov    %eax,%edi
   0x7ffff7bd5704 <func+20>:    callq  0x7ffff7bd55b0 <square@plt>
   0x7ffff7bd5709 <func+25>:    sub    $0x5,%eax
   0x7ffff7bd570c <func+28>:    mov    %eax,%esi
   0x7ffff7bd570e <func+30>:    lea    0x18(%rip),%rdi        # 0x7ffff7bd572d
   0x7ffff7bd5715 <func+37>:    mov    $0x0,%eax
   0x7ffff7bd571a <func+42>:    callq  0x7ffff7bd55c0 <printf@plt>
   0x7ffff7bd571f <func+47>:    nop
   0x7ffff7bd5720 <func+48>:    leaveq 
   0x7ffff7bd5721 <func+49>:    retq   

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!