2016-08-27 12 views
1

во время сеанса fuzzing, протестированное приложение разбилось и я получил файл ядра. После открытия основного файла с gdb он говорит, что приложение не имеет отладочных символов.Разберите файл ядра в обратном порядке с помощью gdb

Команда трассировку показывает следующее:

Program terminated with signal 11, Segmentation fault. 
#0 0x0000000000000000 in ??() 
    (gdb) bt 
#0 0x0000000000000000 in ??() 
#1 0x00007f8749f065d3 in ??() 
#2 0x00007f874c6a9000 in ??() 
#3 0x00007f8749f06568 in ??() 
#4 0x00007f874c6ab9a0 in ??() 
#5 0x00007f874c6aaa00 in ??() 
#6 0x0000000000000001 in ??() 
#7 0x00007f8749f06664 in ??() 
#8 0x0000000000000000 in ??() 

Так что, когда я печатаю (GDB) disass 0x00007f8749f065d3, +1 тогда я получаю следующий результат:

Dump of assembler code from 0x7f8749f065d3 to 0x7f8749f065d4: 
    0x00007f8749f065d3: mov QWORD PTR [rbx+0x70],0x0 
End of assembler dump. 

И теперь мой вопрос:

Например, когда я на предыдущей строке (0x000 07f8749f065d3) и хотите проанализировать, скажем, две выполненные строки до 0x00007f8749f065d3, то что я должен набирать?

Примечание: Команда типа (gdb) disass 0x00007f8749f065d3, -2, которую я печатаю интуитивно, не помогла.

С наилучшими пожеланиями,

+0

Как вы ссылались на GDB? Как вы «открыли основной файл»? Скорее всего, вы не сделали это правильно. –

+0

Я набрал в командной оболочке «gdb/path_to_app/crashed_app_name/path_to_core_file/core». Итак, сначала gdb, а затем 1-й аргумент - путь к разбитому приложению, а в качестве второго аргумента - путь к файлу ядра. – user3097712

ответ

3

вы должны понять, как связать исходные строки с инструкциями ассемблера ли? Или вы имеете в виду, как разбирать инструкцию перед текущей инструкцией?

Вот ответы на оба вопроса.

Номера шестнадцатеричных чисел, отображаемые в команде backtrace, являются адресом счетчика программ для точки входа в функцию. Команда ассемблера по адресу будет одной инструкцией, такой как вызов или jmp.

Компилятор, такой как gcc, превратит исходный код в инструкции ассемблера. Компилятор будет включать информацию «DWARF» в исполняемом изображении. Информация DWARF будет использоваться для связывания набора инструкций ассемблера с конкретной строкой исходного кода.

Рассмотрим этот фрагмент C:

Использование disass /m демонстрирует, как GDB связывает исходные линии с ассемблером.

48   { 
    0x0000000000400bdf <+0>: push %rbp 
    0x0000000000400be0 <+1>: mov %rsp,%rbp 
    0x0000000000400be3 <+4>: add $0xffffffffffffff80,%rsp 
    0x0000000000400be7 <+8>: mov %edi,-0x74(%rbp) 
    0x0000000000400bea <+11>: mov %rsi,-0x80(%rbp) 
    0x0000000000400bee <+15>: mov %fs:0x28,%rax 
    0x0000000000400bf7 <+24>: mov %rax,-0x8(%rbp) 
    0x0000000000400bfb <+28>: xor %eax,%eax 

49    int s, tnum, opt, num_threads; 
50    struct thread_info *tinfo; 
51    pthread_attr_t attr; 
52    int stack_size; 
53    void *res; 
54 
55    /* The "-s" option specifies a stack size for our threads */ 
56 
57    stack_size = -1; 
    0x0000000000400bfd <+30>: movl $0xffffffff,-0x60(%rbp) 

58    while ((opt = getopt(argc, argv, "s:")) != -1) { 
    0x0000000000400c04 <+37>: jmp 0x400c56 <main+119> 
    0x0000000000400c56 <+119>: mov -0x80(%rbp),%rcx 
    0x0000000000400c5a <+123>: mov -0x74(%rbp),%eax 
    0x0000000000400c5d <+126>: mov $0x401002,%edx 
    0x0000000000400c62 <+131>: mov %rcx,%rsi 
    0x0000000000400c65 <+134>: mov %eax,%edi 
    0x0000000000400c67 <+136>: callq 0x400a00 <[email protected]> 
    0x0000000000400c6c <+141>: mov %eax,-0x5c(%rbp) 
    0x0000000000400c6f <+144>: cmpl $0xffffffff,-0x5c(%rbp) 
    0x0000000000400c73 <+148>: jne 0x400c06 <main+39> 

59     switch (opt) { 
    0x0000000000400c06 <+39>: mov -0x5c(%rbp),%eax 
    0x0000000000400c09 <+42>: cmp $0x73,%eax 
    0x0000000000400c0c <+45>: jne 0x400c2c <main+77> 

60     case 's': 
61      stack_size = strtoul(optarg, NULL, 0); 
    0x0000000000400c0e <+47>: mov 0x2014cb(%rip),%rax  # 0x6020e0 <[email protected]@GLIBC_2.2.5> 
    0x0000000000400c15 <+54>: mov $0x0,%edx 
    0x0000000000400c1a <+59>: mov $0x0,%esi 
    0x0000000000400c1f <+64>: mov %rax,%rdi 
    0x0000000000400c22 <+67>: callq 0x400a10 <[email protected]> 
    0x0000000000400c27 <+72>: mov %eax,-0x60(%rbp) 

62      break; 
    0x0000000000400c2a <+75>: jmp 0x400c56 <main+119> 

Некоторые из исходных строк являются одной инструкцией, в то время как другие состоят из нескольких инструкций. Обратите внимание, что адрес также не работает для некоторых строк.

Как вы можете видеть, без отладочной информации в исполняемом файле нет автоматизированного способа связывания команды ассемблера с исходной строкой. Самой целью отладочной информации является объединение этих двух.

Для архитектуры переменной длины, такой как x86, это не простой способ оглянуться назад для предыдущей инструкции. Лучшая стратегия в отладчике - это просто вычесть некоторое значение, например 16, и выполнить разборку. Если текущая инструкция отображается правильно, большая часть разборки верна. В моем примере давайте рассмотрим 0x0000000000400c06.

Итак, вычитая 16 (0x10), имеем 0x400bf6.

(gdb) disass 0x0000000000400bf6, +20 
Dump of assembler code from 0x400bf6 to 0x400c0a: 
    0x0000000000400bf6 <main+23>: add %cl,-0x77(%rax) 
    0x0000000000400bf9 <main+26>: rex.RB clc 
    0x0000000000400bfb <main+28>: xor %eax,%eax 
    0x0000000000400bfd <main+30>: movl $0xffffffff,-0x60(%rbp) 
    0x0000000000400c04 <main+37>: jmp 0x400c56 <main+119> 
    0x0000000000400c06 <main+39>: mov -0x5c(%rbp),%eax 
    0x0000000000400c09 <main+42>: cmp $0x73,%eax 

По сравнению с демонтажем, разборка правильная, начиная с инструкции «xor». Если вы знакомы с ассемблером, тогда вы заметите нечетные инструкции, такие как «rex».

Было бы разумно спросить, как gdb разбирает код. Ответ заключается в том, что он всегда начинается с первой инструкции функции и работает вниз.

Хороший вопрос!

+0

Привет, Мэтью. Спасибо за ответ. Я понимаю. Итак, вы берете конкретный адрес, вычитаете его с некоторым значением и затем разбираете его. Хорошо. Это была идея, но я подумал, что для нее может быть инструкция gdb. Я был неправ. Но мне нравится ваш подход. – user3097712

+0

Приветствую вас, спасибо за голосование. Если бы мой ответ был полезен, пожалуйста, примите его. Я пытаюсь создать свою репутацию. –

+0

Хорошо, я сделал это :) – user3097712