Как игнорировать выполнение какой-либо строки двоичного файла? - PullRequest
0 голосов
/ 16 июня 2020

Я хочу сделать свою программу более сильной перед хакерами, поэтому у меня есть класс program::validator, который проверяет мою среду по некоторым параметрам. I:

  • Скомпилировать program::validator разделяемую библиотеку.
  • Скомпилировать программу с использованием -O2 и --ffast-math и связать с libprogramvalidator.so.
  • Запустить программу с помощью GDB.
  • Найдите строку, которая действительно вызывает program::validator::is_valid_system().

, и я хочу знать, что могу игнорировать выполнение этой строки?

Ответы [ 2 ]

4 голосов
/ 17 июня 2020

Я просто хочу избежать вызова функции is_valid_system в моем исполняемом двоичном файле ELF.

Есть несколько простых способов. Для этого вы можете использовать команды GDB jump $address или return. Пример:

#include <stdio.h>

int is_valid_system()
{
  return 0;
}

int main()
{
  if (is_valid_system()) {
    printf("Life is good\n");
    return 0;
  }
  printf("Invalid system detected\n");
  return 1;
}

Как видите, запущенная выше программа всегда будет печатать Invalid system и завершать работу с кодом ошибки 1. Давайте подтвердим, что:

gcc t.c && gdb -q ./a.out
(gdb) run
Starting program: /tmp/a.out 
Invalid system detected
[Inferior 1 (process 180727) exited with code 01]

Хорошо, теперь давайте сделаем программа print Life is good. Сделаем это через return. Для этого установите точку останова на желаемой функции, установите регистр возврата ($rax на x86_64) на желаемое значение и return, чтобы функция немедленно вернулась:

(gdb) b is_valid_system
Breakpoint 1 at 0x1139
(gdb) run
Starting program: /tmp/a.out 

Breakpoint 1, 0x0000555555555139 in is_valid_system ()
(gdb) set $rax = 1
(gdb) return
#0  0x000055555555514e in main ()
(gdb) c
Continuing.
Life is good
[Inferior 1 (process 196141) exited normally]

В качестве альтернативы , вы можете "перепрыгнуть" через функцию. Отключите вызывающую программу, прервите команду CALL, установите регистр возврата на желаемое значение и перейдите к следующей инструкции:

(gdb) disas main
Dump of assembler code for function main:
   0x0000555555555140 <+0>:     push   %rbp
   0x0000555555555141 <+1>:     mov    %rsp,%rbp
   0x0000555555555144 <+4>:     mov    $0x0,%eax
   0x0000555555555149 <+9>:     callq  0x555555555135 <is_valid_system>
   0x000055555555514e <+14>:    test   %eax,%eax
   0x0000555555555150 <+16>:    je     0x555555555165 <main+37>
   0x0000555555555152 <+18>:    lea    0xeab(%rip),%rdi        # 0x555555556004
   0x0000555555555159 <+25>:    callq  0x555555555030 <puts@plt>
   0x000055555555515e <+30>:    mov    $0x0,%eax
   0x0000555555555163 <+35>:    jmp    0x555555555176 <main+54>
   0x0000555555555165 <+37>:    lea    0xea5(%rip),%rdi        # 0x555555556011
   0x000055555555516c <+44>:    callq  0x555555555030 <puts@plt>
   0x0000555555555171 <+49>:    mov    $0x1,%eax
   0x0000555555555176 <+54>:    pop    %rbp
   0x0000555555555177 <+55>:    retq   
End of assembler dump.
(gdb) b *0x0000555555555149
Breakpoint 2 at 0x555555555149
(gdb) run
Starting program: /tmp/a.out 

Breakpoint 2, 0x0000555555555149 in main ()
(gdb) set $rax = 1
(gdb) jump *0x000055555555514e
Continuing at 0x55555555514e.
Life is good
[Inferior 1 (process 205378) exited normally]

Вы также можете использовать GDB для временного или постоянного исправления is_valid_system. Подробности в этот ответ .

3 голосов
/ 16 июня 2020

Это еще один вариант распространенной ошибки «Думая, что вы можете доверять своей среде, даже если вы не можете доверять своей среде».

Вы безоговорочно верите, что компилятор - настоящий компилятор, компоновщик - реальный компоновщик, GDB - реальный GDB, а дизассемблер - настоящий дизассемблер. Вы дали хакерам не один, а четыре способа атаковать вашу программу.

...