root@dev:~$ gdb ./{executableFilename.out}
gef> info func
ALL defined functions:
File lab03.c
11: int f1();
26: void f2();
21: int f3(int, int, int);
5: void getNameLen();
35: int main();
Non-debugging symbols:
0x00001000 _init
0x00001080 _cxa_finalize@plt
0x00001090 printf@plt
...
* this displays user-defined functions, etc
- note that most malware doesn't have debug symbols turned on
#set breakpoints on ALL identified functions
gef> break *main
Breakpoint 1 at 0x132f: file lab03.c, line 35
gef> break *f1
Breakpoint 2 at 0x126d: file lab03.c, line 11
gef> break *f2
Breakpoint 3 at 0x12ed: file lab03.c, line 26
gef> break *f3
Breakpoint 4 at 0x12b4: file lab03.c, line 21
gef> break *getNameLen
Breakpoint 5 at 0x120d: file lab03.c, line 5
gef> info breakpoint
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000132f in main at lab03.c:35
2 breakpoint keep y 0x0000126d in f1 at lab03.c:11
3 breakpoint keep y 0x000012ed in f2 at lab03.c:26
4 breakpoint keep y 0x000012b4 in f3 at lab03.c:21
5 breakpoint keep y 0x0000120d in getNameLen at lab03.c:5
* display breakpoints that are enabled
RETRIEVING EBP
disassemble the main() to see how the stack is laid out and to get the EBP for the main(). be mindful that each function in a program has its own stack frame, and each of those stack frames includes its own base pointer. The base pointer register is used to reference local variables and parameters for the current function, providing a stable point of reference for accessing data in the stack.
gef> run
Starting program: /...lab03.out
...
$eax : 0xf7fac088 -> 0xffffd17c -> 0xffffd35a -> "SHELL=/bin/bash"
$ebx : 0x0
$ecx : 0xbe2e309b
$edx : 0xffffd104 -> 0x00000000
$esp : 0xffffd0dc -> 0xf7dd9ed5 -> <__libc_start_main+245> add esp, 0x10
$ebp : 0x0
$esi : 0xf7faa000 -> 0x001ead6c
$edi : 0xf7faa000 -> 0x001ead6c
$eip : 0x5655632f -> <main+0> endbr32
$eflags : ...
* this should hit the 1st breakpoint which is the main()
gef> disass
Dump of assembler code for function main:
=> 0x5655632f <+0>: endbr32
0x56556333 <+4>: lea ecx,[esp+0x4]
0x56556337 <+8>: and esp,0xfffffff0
...
* this displays the stack layout and begins at the function prologue
gef> step
gef> disass
Dump of assembler code for function main:
...
=> 0x5655634d <+30>: sub esp,0xc
0x56556350 <+33>: lea eax,[ebx-0x1f60]
0x56556356 <+39>: push eax
0x56556357 <+40>: call 0x565560a0 <puts@plt>
* after stepping this should bring you passed the main function's prologue
- now you can get the correct EBP address via "context regs" cmd
gef> context regs
$eax : ...
$ebx : ...
$ecx : ...
$edx : ...
$esp : ...
$ebp : 0xffffd0c8 -> 0x00000000
...
* note: EBP location doesn't change once the program is running
* keep "step"ing until the other function is reached
RETRIEVING VALUES & ADDRESS ON THE STACK
identify what's getting pushed onto the stack and what addresses those values are getting pushed on to
#start with the LOAD EFFECTIVE ADDRESS (LEA) and see what is getting put into eax
#e.g., lea eax, [ebp-0x10] //ebp-0x10 is getting put into eax
# push eax //eax is getting pushed onto the stack
* note: a stack has two cmds "PUSH" & "POP"
- this is your indication that the stack is being used
gef> si
$eax : 0xf7fac088 -> 0xffffd17c -> 0xffffd35a -> "SHELL=/bin/bash"
* this cmd "steps into" lea then the next step should be push eax
- you'll see what value is getting pushed from here
#find the first call to f1
gef> disass
...
push eax
call 0x565560a0 <puts@plt>
add esp, 0x10
call 0x5655620d <getNameLen>
call 0x5655626d <f1>
* remember: arguments gets pushed onto the stack in the reverse order that they are needed
- the last thing pushed onto the stack (0x5655620d <getNameLen> in this example is what f1 needs
- or is it push eax?
get> si
*
get> x /xw $ebp