Photo by Florian Krumm on Unsplash
The ASCII table has a few special characters that are unprintable. This can be an issue when you need to enter a memory address of a function or variable that consists of these special characters.
In this article, I will guide you through the process of converting hexadecimal memory addresses to ASCII and using them as keyboard inputs when using the GDB debugger.
Setup
In this article, we will be using the gdb debugger. As an example, the task 7 program named func-pointer in the TryHackMe room Buffer Overflow will be used.
Start GDB, and set up your debugging environment.
gdb func-pointer
...
[redacted-for-brevity]
...
(gdb) set exec-wrapper env -u LINES -u COLUMNS
Function address
Finding where to point the return address
Typically, a buffer overflow will make the function's return address point to somewhere else that it was intended to return to. So instead of returning to the address in memory after the address that called the exploitable function, we want to go to the address at the beginning of a desired function.
To find the address of our desired function you should preferably know what function you want to call. If you know the function name in a compiled C program this can be found by running this command:
(gdb) disassemble special
Dump of assembler code for function special:
0x0000000000400567 <+0>: push %rbp
0x0000000000400568 <+1>: mov %rsp,%rbp
0x000000000040056b <+4>: mov $0x400680,%edi
0x0000000000400570 <+9>: callq 0x400460 <puts@plt>
0x0000000000400575 <+14>: mov $0x40069d,%edi
0x000000000040057a <+19>: callq 0x400460 <puts@plt>
0x000000000040057f <+24>: nop
0x0000000000400580 <+25>: pop %rbp
0x0000000000400581 <+26>: retq
End of assembler dump.
The first row of the function has the address 0x0000000000400567. This is the address we need to pass as the return address in our exploitable function.
The ASCII problem
Invisible characters...
The ASCII table has a few invisible control characters, these are used for various functions such as carriage return, backspace, etc. A perfect example of tricky ASCII characters is the one found on the hex number x05 that is used in our function address.
x05 is an "enquiry" character. In other words, we cannot simply paste that character into our terminal when trying to perform a buffer overflow attack.
Typing raw ASCII
To type in the raw ASCII characters into your terminal you have to first press Ctrl+Shift+u, then the hex number, like "05", then press enter to confirm the entered ASCII character.
To make my life as simple as possible I use CyberChef to convert as much as the address to typeable ASCII, and then I fill in the rest by hand.
Because x86 is "little-endian", the address has to be entered byte-by-byte as ASCII in reverse order.
Using CyberChef to covert from hex to ASCII
As an example of a buffer overflow, we first fill the buffer with A's and then start entering the desired return address. The address only consists of a regular ASCII "g" and "@" characters. the 05, and the 00's have to be typed in using the keyboard technique.
Once typed in, it will look like this in your terminal:
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/user1/overflow-2/func-pointer
AAAAAAAAAAAAAAg^E@
That's it, folks! You now know how to type invisible ASCII characters in the GDB debugger. 🎉