Gdb how to use

Gdb how to use

GDB Tutorial for Reverse Engineers: Breakpoints, Modifying Memory and Printing its Contents

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

GDB is THE debugger for Linux programs. It’s super powerful. But its user-friendliness or lack thereof can actually make you throw your PC out of the window. But what’s important to understand about GDB is that GDB is not simply a tool, it’s a debugging framework for you to build upon. In this video, I’m gonna walk you through GDB setup for reverse engineering and show you all of the necessary commands and shortcuts for your debugging workflow.

GDB Setup With Plugins

The most common mistake I see is that people perceive GDB as a standalone debugger tool. I suggest you think of GDB as a debugger framework that allows you to build your own tools. Or you can use premade tools. My GDB-based tool of choice is Peda. It’s pretty easy to install, just follow installation instructions from Peda repository: https://github.com/longld/peda

Program example

I’ll be using this simple program as our debugging target:

This code creates local variable X on the stack, prints its value to the console, then adds 5 to X, and prints its value again. Pretty simple, just what we need for our learning example.

First Steps with Debugging a Program

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Now if I issue run command, the execution conveniently stops at the beginning of the “main” function. And just to save us some time we can use command start which comes from Peda instead of doing all of this. This command will do all this work for us.

And if you like to do single-stepping a lot, note, that pressing ‘Return’ on an empty line will make GDB execute the previous command you entered once more. Also, you can use command next to single step without entering function calls.

Modifying Registers

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

By the way, with Peda you have a faster way to skip instructions without executing them with skipi command.

Modifying Memory

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Print xprint hexdump hexprint

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

By changing the second x to i you can print memory as instructions.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

The full list of supported modifiers you can find in the documentation:

You can use the command x (for “examine”) to examine memory in any of several formats, independently of your program’s data types.

x/nfu addrx addrx Use the x command to examine memory.

n, f, and u are all optional parameters that specify how much memory to display and how to format it; addr is an expression giving the address where you want to start displaying memory. If you use defaults for nfu, you need not type the slash ‘/’. Several commands set convenient defaults for addr.

n, the repeat countThe repeat count is a decimal integer; the default is 1. It specifies how much memory (counting by units u) to display. If a negative number is specified, memory is examined backward from addr.f, the display formatThe display format is one of the formats used by print (‘x’, ‘d’, ‘u’, ‘o’, ‘t’, ‘a’, ‘c’, ‘f’, ‘s’), and in addition ‘i’ (for machine instructions). The default is ‘x’ (hexadecimal) initially. The default changes each time you use either x or print .u, the unit sizeThe unit size is any of b Bytes. h Halfwords (two bytes). w Words (four bytes). This is the initial default. g Giant words (eight bytes).

Also, Peda provides you with a convenient hexdump address /count (dump “count” lines, 16-bytes each) command which you can use… well, to display hex dump.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Final Thoughts

So today we’ve seen a glimpse of GDB functionality. To sum up, I want you to take home 3 things:

use Peda or a different GDB plugin that suits you

use ‘break’ and ‘delete’ commands to control breakpoints

use ‘x’ command to print memory contents

If you have any further questions on GDB, please leave a comment below. Like the article, if you want more content like this. And happy hacking, you guys.

As always, instead of reading this article, you can watch the full video (bonus outtakes and cats included):

Как пользоваться gdb

В сегодняшней статье мы рассмотрим как пользоваться gdb для отладки и анализа выполнения программ, написанных на Си. Попытаемся разобраться с основными возможностями программы.

Как пользоваться gdb

1. Установка gdb

Обычно, отладчик устанавливается вместе с другими инструментами для сборки программного обеспечения. Для установки всего необходимого в Ubuntu или Debian достаточно выполнить:

sudo apt install build-essential

Для того чтобы установить отладчик отдельно, выполните:

sudo apt install gdb

В CentOS или Fedora команда установки будет выглядеть следующим образом:

sudo dnf install gdb

А для Arch Linux надо выполнить:

Теперь отладчик gdb установлен и вы можете его использовать.

2. Компиляция программы

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

#include
int main() <
int var1 = 0;
int var2 = 2;
char greeting[] = «Hello from losst\n»;
printf(«%s», greeting);
>

Затем вы можете её выполнить:

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

3. Запуск отладчика

Для того чтобы запустить программу достаточно передать путь к ней отладчику. Какие-либо опции указывать не обязательно:

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

4. Запуск программы

Для того чтобы запустить программу надо воспользоваться командой run в консоли gdb. Просто выполните:

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

И программа будет запущена и выполнена. Если вам надо передать программе какие-либо аргументы, то следует их передать команде run, например:

(gdb) run arg1 arg2

Если программа завершилась с ошибкой, вы можете вывести стек вызовов функций для того чтобы узнать в какой именно функции возникла ошибка:

Программа сообщает на какой строчке исходного кода возникла проблема. Чтобы посмотреть весь исходник выполните команду list:

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Для того чтобы вызвать ошибку Segmentation Fault и проверить как это работает можете добавить в программу такие строки и перекомпилировать её:

char *buffer = malloc(sizeof(char) * 10);
while(1) <
*(++buffer) = ‘c’;
>

Тут мы выделяем из памяти массив символов размером 10 элементов и заполняем его и память, которая находится за ним символами «с», пока программа не упадёт.

5. Точки останова

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

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

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Например, давайте установим точку останова на восьмой строчке исходника:

Теперь, когда вы запустите программу на выполнение она остановиться в указанной точке:

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Для того чтобы выполнить следующую строчку без входа в функцию используйте команду next:

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Тогда выполнится следующая строка кода в программе. Если надо войти в функцию и посмотреть что в ней происходит следует использовать команду step:

Для отладки циклов можно устанавливать точки останова на основе условия, например, на 11-той строке, если значение переменной var1 будет 20:

(gdb) break 11 if var1==20

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Чтобы этот пример заработал добавьте в код цикла следующую строчку, как на снимке:

Посмотреть все установленные точки останова можно такой командой:

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

6. Вывод информации

(gdb) info locals

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

А для вывода значений аргументов функции:

Вывести значение определённой переменной можно с помощью print:

Интересно, что с помощью print можно выполнять арифметические операции и их результат не только выводится на экран, но и присваивается внутренней переменной, таким образом его можно будет вывести ещё раз позже или использовать в других вычислениях. Например:

(gdb) print var1+30

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Таким образом вы можете анализировать состояние программы, на каждой точке останова и искать ошибки.

7. Изменение информации

С помощью команды set можно изменить значение переменной прямо во время выполнения программы. Например:

(gdb) break 7
(gdb) run
(gdb) set var2 = 20
(gdb) print var2

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

8. Вывод типа

С помощью команды ptype вы можете вывести тип переменной. Например:

(gdb) break 7
(gdb) run
(gdb) ptype var2

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

9. Просмотр адресов

Ещё интереснее исследовать как программы на Си работают с памятью. Команда print может выводить не только выводить значения переменных, но и их адреса в памяти. Приведите программу к такому виду и перекомпилируйте её:

#include
#include
#include
int main(int argc, char *argv[]) <
int var1 = 0;
int var2 = 2;
char *buffer = malloc(sizeof(char) * 10);
while(var1

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

Теперь вы можете вывести адреса всех переменных в памяти с помощью символа &. Например:

(gdb) print &argc
(gdb) print &var1
(gdb) print &buffer
(gdb) print buffer

10. Просмотр памяти

С помощью команды x или eXamine можно посмотреть содержимое памяти, по определённому адресу. Например, смотрим содержимое переменной var2:

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Если вы не знаете адрес переменной, можно передать её имя с оператором &, он извлечет её адрес. Программа выводит шеснадцатиричное значение, и оно обычно мало о чём нам может сообщить. Для того чтобы улучшить ситуацию можно воспользоваться опциями форматирования. Можно указать тип выводимых данных с помощью таких модификаторов:

Также можно указать размер выводимого блока:

Мы пытались вывести переменную типа int. Она занимает обычно четыре байта. Для её корректного вывода используйте такие параметры:

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Ещё можно указать количество блоков, которые надо выводить, например два:

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Но поскольку там уже не наша переменная, эти данные не имеют смысла. Аналогично всё работает с строками, символами и другими значениями. Только обратите внимание, что если вы будете выводить переменную не одним блоком, то на результат повлияет порядок расположения байт. Значение будет выводиться задом на перед.

11. Справка по программе

Мы рассмотрели основные возможности отладчика gdb. Но если этого вам не достаточно, вы можете посмотреть справку по любой команде программы в самой программе. Для этого используйте команду help. Например, для команды exemine:

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Выводы

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

gnebbia/gdb_tutorial

Use Git or checkout with SVN using the web URL.

Work fast with our official CLI. Learn more.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

Debugging is the art and science of finding and eliminating bugs in software. Bugs can be simple functional issues or in some cases have security implications. gdb is a famous debugger included in many UNIX or UNIX-like systems. Let’s see in these notes, how to use gdb properly in order to effectively debug software.

In order to open a program with gdb we do:

Once we are in GDB we can run the program by doing:

if the program was compiled with the so called «debugging symbols», we will will have useful information about variables, functions, and other stuff. Debug symbols can either be integral part of the binary file or can be placed in a separate file.

We can disassemble a program by doing:

we can attach gdb to a running process by doing:

we can also attach to an existing process by launching gdb in quiet mode, so that the boilerplate initial information does not appear in the output by doing:

if the program crashes we can run:

We need to be explicitly mention the intention to create debug symbols at compile time, we have different kind of debug symbol file types:

we have two options with gcc in order to compile with debug symbols:

In a practical compilation scenario we can include debug symbold by doing:

The information provided by debug files and debug symbols can be summarized as follows:

In order to detach (or strip) symbols from a binary file and save them in a separate file we can do:

we can attach debug symbols to a binary by doing:

we can simply strip debug symbols from a binary by doing:

Anyway, remember that also after doing this removal operation there will still be additional informations that can be used by reverse engineers.

We can delete everything which is unnecessary by doing:

so in order to not let other view my code and make the life of reverse engineers harder we can use the second strip command, this will also make the binary smaller.

So summarizing with debugging symbols we can:

Loading a symbol file in GDB

In order to load a symbol file in GDB we do:

Inspecting Symbols with «nm»

The program «nm» will list symbols contained in an object file, so we can inspect symbols related to a file by doing:

By default the list will be composed by 3 rows where:

For symbol types we have:

Symbol TableMeaning
Aabsolute symbol
Bin the uninitialized data section (BSS)
Din the initialized data section
Ndebugging symbol
Tin the text section
Usymbol undefined right now

We moreover can encounter both «uppercase» or «lowercase» symbols:

Other nm examples

— this can be useful if we want to find a specific function to which executable is owned

— this can be useful even by specifying a specific symbol type instead of function name

The «strace» tool will help us understand how our program interacts with the OS, this tool traces all system calls made by the program, it even tells us about arguments passed and has great filtering capabilities. Let’s see some examples:

We can even attach «strace» to a running process:

we can get even list and statistics of system calls used, in this case we do:

all of this is important because when we are in GDB we can set «breakpoints» on one of these system calls.

Breakpoints, Registers and Memory

A breakpoint is a technique used to «pause» the program during execution based on certain criteria, these criteria can be for example «before to execute a specific instruction» (which we want to examine).

There are different ways to set a breakpoint:

once a breakpoint is set, we can run the program with:

once the program is frozen we can inspect various informations, for example using:

we can see the list of active breakpoints with:

we can enable/disable breakpoints once we have seen the id number by doing:

we can continue the execution after a breakpoint with the instructions:

Sometimes we want to use breakpoints only if certain conditions are met, these conditional breakpoints could be very handy for example in case of loops. Let’s see some example, let’s say we put a breakpoint on line «10» of our code for example with:

we can now view its id number with:

now let’s say our breakpoint has as id number «1» we can do:

let’s see another example:

We can even set breakpoints when certain events happen, for example when a variable is written/read or written or read from it, let’s see some example:

In order to examine memory we use the commands:

the «x» command has a very specific format which has to follow, the general format is:

GDB — Basics

Introduction to basic usage of gdb

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

A lot of people like reading or browsing code and given the convenience of sublime or any other IDEs/tools like cscope, the navigation is simple. The real complexity arises when you have to :

This is where the IDEs come in and provide you some powerful tools and visual buttons to step through code and see the live action. But, if you are one of command line crowd that never uses a graphical IDE or visual debuggers with step-in/step-out buttons, welcome to the beautiful and simple world of GDB (GNU Debugger) 😊

Some uses of gdb:

So, here’s what we are going to do in this article:

Specifications of the machine used for this article:

If you need a refresher on gcc and it’s usage, here is a great page to help you get started: GCC and Make

How to get gdb on Ubuntu

Make sure gdb was installed correctly using return code check ($?)

How to compile a program to use with gdb

Learn the basic information provided by gdb

Let’s use a simple C program example.c to see the basic information provided by gdb

The program finds the factorial of 5. Let’s compile this program and see the information provided by gdb.

I would first start with a command that tells me what information is available to me:

There we go! A neatly sorted list of commands to get information.
Here is a list of some interesting commands in help, and a description of what a few of the info commands do:

Well, the information gets more interesting once we start debugging our binary file. Let’s run our program. Oh wait! The whole purpose of coming to gdb was to pause, observe and proceed. There is no point in running a program without a breakpoint! Simplest way of putting a breakpoint is using the function name or a line number.

Or get the list of functions in the program and break on a particular function.

Forgot the list of breakpoints? Need to delete a breakpoint? Here is how you do it:

Now, let’s run our program with a sample argument just to demonstrate how to run a program in gdb with arguments

We are at the breakpoint 3 (in main() function) and we are able to see that our program has received 3 arguments. How to see what were the arguments? Use the ‘print’ command.

You could also print the values in hex/binary/octal/other formats.

How to expand macros? ‘macro expand’ to our rescue!

NOTE: The program has to be run before expanding macros.

At any point in the program, you can use the ‘ list|l’ command to view the next lines gdb is going to execute.

And if you need any help in knowing the options of a command:

next|n: Proceed to the next line of execution (Doesn’t step into a function call in the current line)

step|s: Step into the function call in the line being executed (even if there is no breakpoint for that function)

continue|c: Continue execution till the next break point or end of program
finish: Finish execution of the current function

Of course this is just the basic usage of these commands. Feel free to explore more options using :

Let’s say you’ve a pointer or an iterator in a function and you obviously do not want to spend time on using the ’n’ command until the iterator reaches a value or the loop reaches a certain state. Conditional breakpoints to the rescue!

You may also choose to add a condition to a breakpoint after you’ve set the breakpoint.

Usually, the header files containing the struct definitions and function signatures are written in separate files. What if we would want to know the type of a variable? What if it is a struct and has more data types? What if we want to know the signature of a function? ‘ ptype’ to our rescue.
ptype prints the definition of the type specified. Let’s say we have the following struct:

We have some source code that creates a pointer to an instance of type EVP_CIPHER. Give the pointer to the ptype command and prepare to be amazed!

Just to complete the basics 😄, here is how we quit gdb:

Well, I hope the title was justified and now you are armed with the commands and tools necessary to dissect a C program using the basic commands of gdb.

GDB (Step by Step Introduction)

GDB stands for GNU Project Debugger and is a powerful debugging tool for C(along with other languages like C++).It helps you to poke around inside your C programs while they are executing and also allows you to see what exactly happens when your program crashes. GDB operates on executable files which are binary files produced by compilation process.

For demo purpose, below example is executed on a Linux machine with below specs.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Let’s learn by doing:-

1. Go to your Linux command prompt and type “gdb”.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Gdb open prompt lets you know that it is ready for commands. To exit out of gdb, type quit or q.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

2. Below is a program that shows undefined behavior when compiled using C99.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

Note: If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate, where the indeterminate value is either an unspecified value or a trap representation.

3. Now compile the code. (here test.c).
g flag means you can see the proper names of variables and functions in your stack frames, get line numbers and see the source as you step around in the executable.
-std=C99 flag implies use standard C99 to compile the code.
-o flag writes the build output to an output file.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

4. Run gdb with the generated executable.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

5.Now, type “l” at gdb prompt to display the code.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

6. Let’s introduce a break point, say line 5.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use
If you want to put breakpoint at different lines, you can type “b line_number“.By default “list or l” display only first 10 lines.

7.In order to see the breakpoints, type “info b”.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

8. Having done above, let’s say you changed your mind and you want to revert.
Type “disable b”.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

As marked in the blue circle, Enb becomes n for disabled.

9. To re-enable the recent disabled breakpoint. Type “enable b”.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

10. Run the code by typing “run or r”.If you haven’t set any breakpoints, run command will simply execute the full program.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

11. To see the value of variable, type “print variable_name or p variable_name“.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use
The above shows the values stored at x at time of execution.

12. To change the value of variable in gdb and continue execution with changed value, type “set variable_name“.

13. Below screenshot shows the values of variables from which it’s quite understandable the reason why we got a garbage value as output. At every execution of ./test we will be receiving different output.

Exercise:Try using set x = 0 in gdb at first run and see the output of c.

Gdb how to use. Смотреть фото Gdb how to use. Смотреть картинку Gdb how to use. Картинка про Gdb how to use. Фото Gdb how to use

GDB offers many more ways to debug and understand your code like examining stack, memory, threads, manipulating the program, etc. I hope the above example helps you get started with gdb.

Источники информации:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *