逆向工程 - GDB - Load Symbol File



參考資訊:
https://ephrain.net/gdb-%E8%BC%89%E5%85%A5%E6%9F%90%E5%80%8B-library-%E7%9A%84-symbol-file/

一般Release給客戶的檔案都是移掉Debug資訊的檔案,不過,在編譯Release檔案時,通常會額外編譯一份具有Debug Symbol的檔案,如何透過這份Debug檔案除錯,就是這次要介紹的東西

main.c

#include <stdio.h>

void test(int, char*);

int main(int argc, char** argv)
{
    test(1, "I am error !");
    return 0;
}

m.c

#include <stdio.h>
#include <stdlib.h>

void test(int a1, char* a2)
{
    printf("a1:%d, a2:%s\n", a1, a2);
}

編譯

$ gcc m.c -no-pie -fPIC -shared -o m.so
$ gcc m.c -no-pie -fPIC -shared -ggdb -o m.so.debug
$ gcc main.c -o main m.so

$ strip m.so
$ strip main

$ file main m.so m.so.debug
main:       ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, stripped
m.so:       ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, stripped
m.so.debug: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, with debug_info, not stripped

設定斷點在test()

$ gdb main
    Type "apropos word" to search for commands related to "word"...
    Reading symbols from main...(no debugging symbols found)...done.

(gdb) b test
    Breakpoint 1 at 0x1030

(gdb) r
    Starting program: /home/steward/Downloads/test/main
    Breakpoint 1, 0x00007ffff7fca109 in test () from ./m.so

由於沒有Debug Symbol,無法看到多餘資訊

(gdb) bt
    #0  0x00007ffff7fca109 in test () from ./m.so
    #1  0x0000555555555155 in ?? ()
    #2  0x00007ffff7de509b in __libc_start_main (main=0x555555555135, argc=1, argv=0x7fffffffe178, init=, fini=, rtld_fini=,
      stack_end=0x7fffffffe168) at ../csu/libc-start.c:308
    #3  0x000055555555507a in ?? ()

(gdb) list
    1	../sysdeps/x86/dl-procinfo.c: No such file or directory.

載入具有Debug Symbol的檔案

(gdb) add-symbol-file m.so.debug
    add symbol table from file "m.so.debug"
    (y or n) y
    Reading symbols from m.so.debug...done.

不過,竟然還是無法看到相關資訊

(gdb) bt
    #0  0x00007ffff7fca109 in test () from ./m.so
    #1  0x0000555555555155 in ?? ()
    #2  0x00007ffff7de509b in __libc_start_main (main=0x555555555135, argc=1, argv=0x7fffffffe178, init=, fini=, rtld_fini=,
      stack_end=0x7fffffffe168) at ../csu/libc-start.c:308
    #3  0x000055555555507a in ?? ()

(gdb) list
    1	in ../sysdeps/x86/dl-procinfo.c

仔細一看,竟然有兩個斷點,代表載入兩份程式

(gdb) info b
    Num     Type           Disp Enb Address            What
    1       breakpoint     keep y   
    breakpoint already hit 1 time
    1.1                         y     0x0000000000001105 in test at m.c:5
    1.2                         y     0x00007ffff7fca109 

接著移除Debug Symbol檔案

(gdb) symbol-file
    Discard symbol table from `/home/steward/Downloads/test/main'? (y or n) y
    No symbol file now.

列出m.so的位址

(gdb) info sharedlibrary
    From                To                  Syms Read   Shared Object Library
    0x00007ffff7fca050  0x00007ffff7fca131  No          ./m.so
    0x00007ffff7de3320  0x00007ffff7f2939b  No          /lib/x86_64-linux-gnu/libc.so.6
    0x00007ffff7fd6090  0x00007ffff7ff3b20  No          /lib64/ld-linux-x86-64.so.2

重新加載Debug Symbol的檔案到m.so的原本位址

(gdb) add-symbol-file m.so.debug 0x00007ffff7fca050
    add symbol table from file "m.so.debug" at
    .text_addr = 0x7ffff7fca050
    (y or n) y
    Reading symbols from m.so.debug...done.

重新設定斷點test()

(gdb) info b
    Num     Type           Disp Enb Address            What
    1       breakpoint     keep y   0x00007ffff7fca114 in test at m.c:6
    breakpoint already hit 1 time

(gdb) del 1

(gdb) b test
    Breakpoint 2 at 0x7ffff7fca114: file m.c, line 6.

(gdb) info b
    Num     Type           Disp Enb Address            What
    2       breakpoint     keep y   0x00007ffff7fca114 in test at m.c:6

重新執行main就可以看到除錯資訊

(gdb) r
    The program being debugged has been started already.
    Start it from the beginning? (y or n) y
    Starting program: /home/steward/Downloads/test/main

    Breakpoint 2, test (a1=1, a2=0x555555556004 "I am error !") at m.c:6
    6	  printf("a1:%d, a2:%s\n", a1, a2);

(gdb) list
    1	#include <stdio.h>
    2	#include <stdlib.h>
    3
    4	void test(int a1, char* a2)
    5	{
    6	  printf("a1:%d, a2:%s\n", a1, a2);
    7	}

(gdb) p a1
    $1 = 1

(gdb) p a2
    $2 = 0x555555556004 "I am error !"

(gdb) info f
    Stack level 0, frame at 0x7fffffffe080:
        rip = 0x7ffff7fca114 in test (m.c:6); saved rip = 0x555555555155
        called by frame at 0x7fffffffe088
        source language c.
        Arglist at 0x7fffffffe070, args: a1=1, a2=0x555555556004 "I am error !"
        Locals at 0x7fffffffe070, Previous frame's sp is 0x7fffffffe080
        Saved registers:
        rbp at 0x7fffffffe070, rip at 0x7fffffffe078