Переключение вызовов методов внутри исполняемого файла - PullRequest
0 голосов
/ 26 февраля 2019

Интересно, как переключить вызов другой функции внутри исполняемого файла (в моем случае .exe)

Вот код, с которым я пытаюсь поиграть

#include <stdio.h>

void hello()
{
    printf("Hello world!");
}

void investigate()
{
    printf("Investigate all the things!");
}

main()
{
    hello();
}

Один разЯ скомпилировал приведенный выше код (с помощью gcc) и получил из него исполняемый файл (.exe), я хочу переключить вызов "hello" на "исследовать".

- Правка -

Моя среда: Windows 10 (64-разрядная версия), mingw с gcc / g ++ 4.8.1

- Edit 2 -

Я в порядке с ответом Linux (любой Ubuntu или любым OpenSuseи любая архитектура), так как для меня очень важно иметь подтверждение концепции.

1 Ответ

0 голосов
/ 26 февраля 2019

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

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

Если ваш компилятор пропустил мертвую функцию, вы не можете переключить функцию (одна отсутствует).

Если ваш компилятор встроил вызов, вы не можете переключить функцию (нет вызова).Вы можете работать против компилятора и переписать код на сайте вызова (в исходном коде C), это называется исправлением.

Если ваш компилятор использовал PLT, вам нужно изменить запись GOT, используемую заглушкой PLT.Возможно, вам придется немного документировать себя, но изменение связанной процедуры на самом деле является особенностью механизма PLT.

Если ваш компилятор ничего не сделал, это должно быть в случае такого простого источника, когда оптимизация не включена, вы можете использовать objdump -d <file>, чтобы найти сайт вызова и адрес новой функции:

000000000040051d <hello>:
  40051d:   55                      push   %rbp
  40051e:   48 89 e5                mov    %rsp,%rbp
  400521:   bf f0 05 40 00          mov    $0x4005f0,%edi
  400526:   b8 00 00 00 00          mov    $0x0,%eax
  40052b:   e8 d0 fe ff ff          callq  400400 <printf@plt>
  400530:   5d                      pop    %rbp
  400531:   c3                      retq   

0000000000400532 <investigate>:
  400532:   55                      push   %rbp
  400533:   48 89 e5                mov    %rsp,%rbp
  400536:   bf fd 05 40 00          mov    $0x4005fd,%edi
  40053b:   b8 00 00 00 00          mov    $0x0,%eax
  400540:   e8 bb fe ff ff          callq  400400 <printf@plt>
  400545:   5d                      pop    %rbp
  400546:   c3                      retq   

0000000000400547 <main>:
  400547:   55                      push   %rbp
  400548:   48 89 e5                mov    %rsp,%rbp
  40054b:   b8 00 00 00 00          mov    $0x0,%eax
  400550:   e8 c8 ff ff ff          callq  40051d <hello>
  400555:   b8 00 00 00 00          mov    $0x0,%eax
  40055a:   5d                      pop    %rbp
  40055b:   c3                      retq   
  40055c:   0f 1f 40 00             nopl   0x0(%rax)

Затем измените непосредственное значение инструкции call с разницей между целевым адресом и адресом после окончания инструкции call (не имеет значения, где длина источникакак это одинаково для обоих адресов).

Target = 400532 
After the end of call = 400555
Difference = 400532 - 400555 = -23 = 0xFFFFFFDD

Change from:
400550: e8 c8 ff ff ff
to:
400550: e8 dd ff ff ff

Обратите внимание, что непосредственные значения являются младшими знаками конца.
Вы можете использовать гекседитор для редактирования кода, чтобы найти смещение в файле, вы можете использовать эльф-ридер и немного по математике.Вы сами или можете просто искать байты инструкции вызова (проверьте также байты вокруг вызова).

После редактирования был исправлен бинарный файл:

 0000000000400532 <investigate>:
  400532:   55                      push   %rbp
  400533:   48 89 e5                mov    %rsp,%rbp
  400536:   bf fd 05 40 00          mov    $0x4005fd,%edi
  40053b:   b8 00 00 00 00          mov    $0x0,%eax
  400540:   e8 bb fe ff ff          callq  400400 <printf@plt>
  400545:   5d                      pop    %rbp
  400546:   c3                      retq   

0000000000400547 <main>:
  400547:   55                      push   %rbp
  400548:   48 89 e5                mov    %rsp,%rbp
  40054b:   b8 00 00 00 00          mov    $0x0,%eax
  400550:   e8 dd ff ff ff          callq  400532 <investigate>
  400555:   b8 00 00 00 00          mov    $0x0,%eax
  40055a:   5d                      pop    %rbp
  40055b:   c3                      retq   
...