DEBUGGING
Debugging is more of a method used during dynamic analysis and deobfuscation, rather than a separate or sequential step
The debugging process generally follows four main phases. First, you set breakpoints at strategic locations, such as function entries or critical instructions, to pause execution where closer inspection is needed. Next, you examine and analyze the program state by inspecting registers, memory, variables, and the stack to understand what is happening at that point in execution. From there, you step through the program—either instruction by instruction or line by line—to observe control flow, function calls, and how data changes in real time. Finally, you may modify the program’s state directly within the debugger, altering register values, memory contents, or execution flow to test hypotheses, apply quick patches, or bypass errors. Together, these phases provide a structured cycle for isolating bugs, understanding behavior, and experimenting with potential fixes.
STEP 1: VIEW FUNCTION / VARIABLE ADDRESS
STEP 2: SET BREAKPOINTS
This method can be done in two ways and depends whether the binary is stripped or not.
STEP 3: RUN THROUGH AND ANALYZE
gef> b _start
Breakpoint 1 at 0x401000
gef> r
Starting program: ./helloWorld
Breakpoint 1, 0x0000000000401000 in _start ()
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x0
$rbx : 0x0
$rcx : 0x0
$rdx : 0x0
$rsp : 0x00007fffffffe310 → 0x0000000000000001
$rbp : 0x0
$rsi : 0x0
$rdi : 0x0
$rip : 0x0000000000401000 → <_start+0> mov eax, 0x1
...SNIP...
───────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffe310│+0x0000: 0x0000000000000001 ← $rsp
0x00007fffffffe318│+0x0008: 0x00007fffffffe5a0 → "./helloWorld"
...SNIP...
─────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x400ffa add BYTE PTR [rax], al
0x400ffc add BYTE PTR [rax], al
0x400ffe add BYTE PTR [rax], al
→ 0x401000 <_start+0> mov eax, 0x1
0x401005 <_start+5> mov edi, 0x1
0x40100a <_start+10> movabs rsi, 0x402000
0x401014 <_start+20> mov edx, 0x12
0x401019 <_start+25> syscall
0x40101b <_start+27> mov eax, 0x3c
─────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "helloWorld", stopped 0x401000 in _start (), reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x401000 → _start()
────────────────────────────────────────────────────────────────────────────────────────────────────
* from here another breakpoint can be set
- e.g., if another breakpoint is required at "_start+10", use either
b *_start+10 or b *0x40100a
- use the "continue" or "c" command to continue to the next breakpoint
gef> b *0x40100a
...
gef> continue
...
gef> x/4ig $rip
=> 0x401000 <_start>: mov eax,0x1
0x401005 <_start+5>: mov edi,0x1
0x40100a <_start+10>: movabs rsi,0x402000
0x401014 <_start+20>: mov edx,0x12
* 4 refers to the count, i for the format, and g for the size
* use the following to perform manual analysis of values in registers and addresses
- format: x/FMT ADDRESS
- ADDRESS is the address or register to be examined
- FMT refers to the examine format
- FMT parts
- count: is the number of times to repeat the examination 2, 3, 10
- format representation: x(hex), s(string), i(instruction)
- size of memory to examine: b(byte), h(halfword), w(word),
g(giant, 8 bytes)
STEP 4: STEPPING
This steps through the program one instruction or line of code at a time. The stepi or si cmd will step through the assembly instructions one by one. It is the smallest level of steps possible while debugging
gef> si
0x0000000000401005 in _start ()
0x400fff add BYTE PTR [rax+0x1], bh
→ 0x401005 <_start+5> mov edi, 0x1
0x40100a <_start+10> movabs rsi, 0x402000
0x401014 <_start+20> mov edx, 0x12
0x401019 <_start+25> syscall
─────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "helloWorld", stopped 0x401005 in _start (), reason: SINGLE STEP
* the instruction shown with the -> symbol is where , and it has not yet
been processed
STEP 5: MODIFICATION
This step is used to modify values in registers and addresses at a certain point of execution. It assists in seeing how this would affect the execution of the program
ADDRESS
gef> b _start
Breakpoint 1 at 0x401000
gef> r
Starting program: ./helloWorld
Breakpoint 1, 0x0000000000401000 in _start ()
[ Legend: Modified register | Code | Heap | Stack | String ]
───────────────────────────────────────────────────────────────────────────────────── registers ────
$rax : 0x0
$rbx : 0x0
$rcx : 0x0
$rdx : 0x0
$rsp : 0x00007fffffffe310 → 0x0000000000000001
$rbp : 0x0
$rsi : 0x0
$rdi : 0x0
$rip : 0x0000000000401000 → <_start+0> mov eax, 0x1
...SNIP...
───────────────────────────────────────────────────────────────────────────────────────── stack ────
0x00007fffffffe310│+0x0000: 0x0000000000000001 ← $rsp
0x00007fffffffe318│+0x0008: 0x00007fffffffe5a0 → "./helloWorld"
...SNIP...
─────────────────────────────────────────────────────────────────────────────────── code:x86:64 ────
0x400ffa add BYTE PTR [rax], al
0x400ffc add BYTE PTR [rax], al
0x400ffe add BYTE PTR [rax], al
→ 0x401000 <_start+0> mov eax, 0x1
0x401005 <_start+5> mov edi, 0x1
0x40100a <_start+10> movabs rsi, 0x402000
0x401014 <_start+20> mov edx, 0x12
0x401019 <_start+25> syscall
0x40101b <_start+27> mov eax, 0x3c
0x401020 <_start+32> mov edi, 0x0
0x401025 <_start+37> syscall
─────────────────────────────────────────────────────────────────────────────────────── threads ────
[#0] Id 1, Name: "helloWorld", stopped 0x401000 in _start (), reason: BREAKPOINT
───────────────────────────────────────────────────────────────────────────────────────── trace ────
[#0] 0x401000 → _start()
────────────────────────────────────────────────────────────────────────────────────────────────────
gef> break *0x401019
Breakpoint 1 at 0x401019
gef> r
gef> patch string 0x402000 "Patched!\\x0a"
gef> c
Continuing.
Patched!
* in GDB, the "set" command is used to modify values. however, the "patch" command
in GEF makes this step much easier.
* the \x0a adds a new line to the string
REGISTER
Last updated