Привет!

Сегодня ты сделаешь еще один шаг в деле
изучения Linux систем. Я расскажу об основных
приемах при работе с gdb. Овладев ими ты сможешь понять, как работает любая программа, писать свои эксплоиты. 

Вы, наверное, все слышали про такую вещь как отладчик, gdb – это и есть отладчик. GDB – GNU
Debugger. Это некое  подобие SoftICE для Windows (для тех кто не знает – самый популярный и, на мой взгляд, вообще лучший отладчик), только под
Linux системы. Дело в том, что в сети не так уж много документов, которые демонстрируют работу этой вещи и в свое время я его осваивал сам. Итак,
в документе будут описаны базовые команды gdb. Все это будет показано на примере. А в качестве примера я решил взять ненужную прогу yes. Для тех, кто не знает – это программа просто выводит символ ‘y’ до бесконечности, для начала я решил научить ее выводить не этот символ, а строку ‘XAKEP’, хоть веселее будет.

Ну а теперь все по порядку. Сам отладчик запускается так:

# gdb

Но можно вводить различные параметры, у нас это будет путь к исследуемой программе:

# gdb /usr/bin/yes 

Можно исследовать core файлы, для этого нужно ввести следует ввести следующее:

# gdb /usr/bin/yes core

Еще может понадобится команда для просмотра содержимого регистров:

(gdb) info registers

либо так (сокращенный вариант)

(gdb) i reg

Теперь рассмотрим как делать перехваты. Существуют
точки останова, точки перехвата и точки наблюдения. Более конкретно я бы хотел остановиться на точках останова. Их можно устанавливать на:

(gdb) break function — Остановить перед входом в функцию
(gdb) break *adress — Остановить перед выполнением инструкции по адресу.

После установок можно просмотреть все точки для этого воспользуйтесь командой:

(gdb) info break

А потом можно удалить эти точки:

(gdb) clear breakpoint — где break это название точки останова
(например, функция или адрес)

Очень необходимой вещью является возможность автоматического отображения различных значений при выполнении программы. Для этого существует команда display:

(gdb) display/format value , где format – это формат отображения, а value – само выражение которое нужно отобразить.

Для работы с отображением отведены следующие команды:

(gdb) info display — выдает инфу об отображениях
(gdb) delete num — где num – удалить элементы с индексом
num

Это был небольшой справочник по командам, чтобы понять основную идею.
Далее на примере хотелось бы продемонстрировать это и еще немного. И помните – здесь я дал лишь очень маленькую часть всех возможностей gdb, на самом деле у него их в сотни раз больше, поэтому читайте и учите.
Как я и обещал, берем ненужную прогу yes. Путь на вашей машине может не совпадать с моим, все зависит от операционки которой вы пользуетесь, если что воспользуйтесь поиском (команда
find).

[root@localhost /root]# gdb /usr/bin/yes

После запуска он говорит приветственное сообщение.

GNU gdb 19991004
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type «show copying» to see the conditions.
There is absolutely no warranty for GDB. Type «show warranty» for details.
This GDB was configured as «i386-redhat-linux»…
(no debugging symbols found)…

И появляется приглашение gdb. Дальше мы настраиваем вывод
так, чтобы при работе программы у нас каждый раз высвечивался
адрес команды, ее смещение и сама ассемблерная инструкция:
(gdb) display/i $pc

Так как yes выводит бесконечное число символов, то лучше бы их нам не видеть в отладчике, а вывод
программы можно направить на другую консоль. Откройте новый терминал, наберите who is i и вы получите имя консоли. Должно вылезти
что-то вроде этого:

localhost.localdomain!root pts/1 Apr 26 13:24

Вот теперь просто привязываем к ней.

(gdb) tty /dev/pts/1

А теперь ставим точку останова на функцию puts(), а чтобы было понятней вот вам man-справка об функции(команда man
puts)

#include <stdio.h>
int puts(const char *s);
puts() writes the string s and a trailing newline to std­
out.

Как видно, функция посылаем строку s на поток вывода. Вот она то нам и нужна. На ней то мы пока и остановимся.

(gdb) break puts
Breakpoint 1 at 0x8048698

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

(gdb) r
Starting program: /usr/bin/yes 
Breakpoint 1 at 0x4006d585: file ioputs.c, line 32.

Breakpoint 1, 0x4006d585 in _IO_puts (str=0x8048e59 «y») at ioputs.c:32
32 ioputs.c: No such file or directory.
1: x/i $eip 0x4006d585 <_IO_puts+21>: mov 0x8(%ebp),%esi

О, вот и произошло чудо, сработал breakpoint. Что мы видим – а видим мы ни что иное, как параметр функции, точнее адрес, по которому он лежит. Что теперь нужно
сделать? Правильно, подправить данные по этому адресу. При этом мы затрем еще пару символов своими. 

(gdb) set {char}0x8048e59=’X’
(gdb) set {char}0x8048e5a=’A’
(gdb) set {char}0x8048e5b=’K’
(gdb) set {char}0x8048e5c=’E’
(gdb) set {char}0x8048e5d=’P’

Ну а теперь посмотрим на наше творение. Что там лежит в памяти:

(gdb) x/3sw 0x8048e59
0x8048e59 <_IO_stdin_used+437>: «XAKEP\004\b»
0x8048e61 <_IO_stdin_used+445>: «»
0x8048e62 <_IO_stdin_used+446>: «»

Теперь удалим наш брякпоинт:

(gdb) info break
Num Type Disp Enb Address What
1 breakpoint keep y 0x4006d585 in _IO_puts at ioputs.c:32
breakpoint already hit 1 time
(gdb) clear puts
Deleted breakpoint 1 

И продолжим выполнение чтобы насладится результатом:

(gdb) c

Вот и все. Выходим.

(gdb) q
The program is running. Exit anyway? (y or n) y

[root@localhost /root]# 

На этом практика заканчивается, остальное изучайте сами и помните что главное в этой жизни – это УЧЕНЬЕ.
Вот еще некоторые примеры работы:

Присоединение к работающему процессу:

// launch gdb
hack@exploit:~ > gdb
GNU gdb 4.18
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i386-suse-linux".
(gdb) attach ‘pid’
(gdb) attach 1127 // example

Поиск в памяти:

(gdb) x/d or x ‘address’ show decimal
(gdb) x/100s ‘address’ show next 100 decimals
(gdb) x 0x0804846c show decimal at 0x0804846c
(gdb) x/s ‘address’ show strings at address
(gdb) x/105 0x0804846c show 105 strings at 0x0804846c
(gdb) x/x ‘address’ show hexadecimal address
(gdb) x/10x 0x0804846c show 10 addresses at 0x0804846c
(gdb) x/b 0x0804846c show byte at 0x0804846c
(gdb) x/10b 0x0804846c-10 show byte at 0x0804846c-10
(gdb) x/10b 0x0804846c+20 show byte at 0x0804846c+20
(gdb) x/20i 0x0804846c show 20 assembler instructions at address

Список всех секций в исполняемом файле:

(gdb) maintenance info sections // or
(gdb) mai i s

Executable file:
    `/home/hack/homepage/challenge/buf/basic’, file type
elf32-i386.
    0x080480f4->0x08048107 at 0x000000f4: .interp ALLOC
LOAD READONLY DATA HAS_CONTENTS
    0x08048108->0x08048128 at 0x00000108: .note.ABI-tag
ALLOC LOAD READONLY DATA HAS_CONTENTS
    0x08048128->0x08048158 at 0x00000128: .hash ALLOC
LOAD READONLY DATA HAS_CONTENTS
    0x08048158->0x080481c8 at 0x00000158: .dynsym ALLOC
LOAD READONLY DATA HAS_CONTENTS
    0x080481c8->0x08048242 at 0x000001c8: .dynstr ALLOC
LOAD READONLY DATA HAS_CONTENTS
    0x08048242->0x08048250 at 0x00000242: .gnu.version
ALLOC LOAD READONLY DATA
HAS_CONTENTS

Бряк на адрес:

(gdb) disassemble main
Dump of assembler code for function main:
0x8048400 <main>: push %ebp
0x8048401 <main+1>: mov %esp,%ebp
0x8048403 <main+3>: sub $0x408,%esp
0x8048409 <main+9>: add $0xfffffff8,%esp
0x804840c <main+12>: mov 0xc(%ebp),%eax
0x804840f <main+15>: add $0x4,%eax
0x8048412 <main+18>: mov (%eax),%edx
0x8048414 <main+20>: push %edx
0x8048415 <main+21>: lea 0xfffffc00(%ebp),%eax

(gdb) break *0x8048414 // example
Breakpoint 1 at 0x8048414
(gdb) break main // example
Breakpoint 2 at 0x8048409
(gdb)

И так далее 🙂

Оставить мнение

Check Also

Как Apple обходит стандарты, заставляя тебя платить. Колонка Олега Афонина

Иногда сложные вещи начинаются с простых: планшет iPad Pro 10.5 вдруг перестал заряжаться …