Segfault при прыжке с PLT - PullRequest
       38

Segfault при прыжке с PLT

0 голосов
/ 12 января 2020

Я пытаюсь найти причину segfault и сузил ее до PLT, используя btrace gdb. Segfault происходит во время перехода от PLT к GOT, что я интерпретирую, чтобы показать, что PLT был поврежден во время выполнения. На основании анализа, представленного ниже, является ли эта интерпретация правильной? Каковы вероятные виновники коррупции в PLT? Переполнение стека? Я считаю, что установка точки наблюдения на GOT-адрес может быть полезна в этом случае. watch -l 0x55555562f048 будет правильным подходом? Другие идеи для отладки приветствуются.


Для контекста, segfault происходит во время вызова strlen в функции foo:

int foo(char * path, ...) {
    ...
    if (strlen(path) >= PATH_MAX) {

Соответствующие строки сборки :

0x58114 <foo+212>    cmpq   $0x0,-0x4c8(%rbp)
0x5811c <foo+220>    jne    0x5812a <foo+234>
0x5811e <foo+222>    lea    0xb96fb(%rip),%rdi        # 0x111820
0x58125 <foo+229>    callq  0x376c0 <__ubsan_handle_nonnull_arg@plt>
0x5812a <foo+234>    mov    -0x4c8(%rbp),%rax
0x58131 <foo+241>    mov    %rax,%rdi
0x58134 <foo+244>    callq  0x37090 <strlen@plt>

Во-первых, path сравнивается с NULL (cmpq $0x0,-0x4c8(%rbp)), который, как я полагаю, в данном случае добавляется исключительно для убсановских приборов. За этой ветвью не последовало, и программа перешла на <foo+234>, где она установила для вызова strlen, переместив path на rax, а затем rdi и, наконец, вызвав strlen@plt. Выполнение record btrace в gdb непосредственно перед тем, как это произвело эту историю команд:

(gdb) record btrace
(gdb) c
136        0x00005555555ac114 <foo+212>:        cmpq   $0x0,-0x4c8(%rbp)
137        0x00005555555ac11c <foo+220>:        jne    0x5555555ac12a <foo+234>
138        0x00005555555ac12a <foo+234>:        mov    -0x4c8(%rbp),%rax
139        0x00005555555ac131 <foo+241>:        mov    %rax,%rdi
140        0x00005555555ac134 <foo+244>:        callq  0x55555558b090 <strlen@plt>
141        0x000055555558b090 <strlen@plt+0>:   jmpq   *0xa3fb2(%rip)  # 0x55555562f048 <strlen@got.plt>

Здесь мы видим, что path не был нулевым, и поэтому программа перепрыгнула на <foo+234> и настроила для вызова strlen (mov, mov, callq <strlen@plt>). Последняя выполненная инструкция была jmpq *0xa3fb2(%rip) для записи для strlen в GOT (strlen@got.plt), после чего программа потерпела крах и GDB потеряла контекст (сообщив, что она Cannot find bounds of current function).

...