I'm currently learning about C and trying to find out more about how memory in a stack works, and how gdb can be used to help.
Below is a code snippet of my problem:
bool thisEvaluatesToFalse(char* something) {
return false;
}
void main() {
char something[10];
puts("My plan is to input a specific string over 10 characters than will achieve my goal:");
gets(something);
if (thisEvaluatesToFalse(something)) {
puts("If this runs, its a success!");
}
}
The idea is, my success message will never run unless I exploit gets to input a something over 10 characters, causing an overflow that overwrites the return address of the function to where the success message is.
I understand I'm supposed to take a look at the assembly code with gdb and look out for an address, but I'm not exactly sure how to do this.
Could anyone guide me or show me an example? Thanks!
Try this, hope it helps you figure this out. Good luck!
Consider moving gets into thisEvaluatesToFalse to overwrite the return address pushed by main so the return from thisEvaluatesToFalse will return to the puts of success.
Like this:
#include <stdio.h>
unsigned int thisEvaluatesToFalse() {
char something[10];
gets(something);
return 0xdeadbeef;
}
int main() {
puts("My plan is to input a specific string over 10 characters than will achieve my goal:");
if (thisEvaluatesToFalse()) {
puts("If this runs, its a success!");
}
return 0;
}
Here are the highlights of working w/ gdb.
gcc main.c -fno-stack-protector -ggdb
gdb a.out
(gdb) disass main
0x0000000100003eeb <+27>: call 0x100003eb0 <thisEvaluatesToFalse>
0x0000000100003ef0 <+32>: cmp $0x0,%eax
0x0000000100003ef3 <+35>: je 0x100003f05 <main+53>
0x0000000100003ef9 <+41>: lea 0x94(%rip),%rdi # 0x100003f94
0x0000000100003f00 <+48>: call 0x100003f14
# ORIG RETURN ADDRESS IS 0x0000000100003ef0
# EXPLOIT RETURN ADDRESS FOR SUCCESS IS 0x0000000100003ef9
(gdb) break thisEvaluatesToFalse
(gdb) run
(gdb) x/16x $sp
0x7ff7bfeff930: 0x000c8060 0x00000001 0x00003ed0 0x00000001
0x7ff7bfeff940: 0xbfeff960 0x00007ff7 0x00003ef0 0x00000001
0x7ff7bfeff950: 0x00000013 0x00000000 0x000c8060 0x00000000
0x7ff7bfeff960: 0xbfeffa70 0x00007ff7 0x0001552e 0x00000001
# NOTICE THE VALUE AT 0x7ff7bfeff948 IS 0x00003ef0 (ORIG RETURN)
# NOTICE THE VALUE AT 0x7ff7bfeff94C IS 0x00000001 (ORIG RETURN)
(gdb) s
warning: this program uses gets(), which is unsafe.
1234567890AAAABBBBCCCCDDDD
(gdb) x/16x $sp
0x7ff7bfeff930: 0x000c8060 0x32310001 0x36353433 0x30393837
0x7ff7bfeff940: 0x41414141 0x42424242 0x43434343 0x44444444
0x7ff7bfeff950: 0x00000000 0x00000000 0x000c8060 0x00000000
0x7ff7bfeff960: 0xbfeffa70 0x00007ff7 0x0001552e 0x00000001
# NOTICE THE VALUE AT 0x7ff7bfeff948 IS 0x43434343 (LETTER C)
# NOTICE THE VALUE AT 0x7ff7bfeff94C IS 0x44444444 (LETTER D)
(gdb) set *0x7ff7bfeff948 = 0x00003ef9
(gdb) set *0x7ff7bfeff94C = 0x00000001
(gdb) x/16x $sp
0x7ff7bfeff930: 0x000c8060 0x32310001 0x36353433 0x30393837
0x7ff7bfeff940: 0x41414141 0x42424242 0x00003ef9 0x00000001
(gdb) s
main () at main.c:17
17 puts("If this runs, its a success!");
(gdb) s
If this runs, its a success!
19 return 0;
Leaving it up to you to figure out how to input values for gets that perform the actions that replace C and D with the values you need.
If you can choose a different approach, then instead of using gets for the overflow try using memcpy and copy more than 10 bytes. Same impact, the stack gets modified.
Is it possible to get the current size of the stack in bytes with GDB (at a breakpoint)?
I didn't find anything regarding this on the Internet.
It's unclear whether you are asking "how much stack have my thread consumed so far", or "what is the maximum stack size this thread may consume in the future".
The first question can be trivially answered by using:
# go to the innermost frame
(gdb) down 100000
(gdb) set var $stack = $sp
# go to the outermost frame
(gdb) up 100000
(gdb) print $sp - $stack
To answer the second question, you would need libpthread that is built with debug symbols. If using GLIBC, you can do this:
# Go to frame which is `start_thread`
(gdb) frame 2
#2 0x00007ffff7d7eeae in start_thread (arg=0x7ffff7a4c640) at pthread_create.c:463
463 in pthread_create.c
(gdb) p pd.stackblock
$1 = (void *) 0x7ffff724c000 # low end of stack block
(gdb) p pd.stackblock_size
$1 = 8392704
Here you can see that the entire stack spans [0x7ffff724c000, 0x7ffff7a4d000] region. You can also confirm that $sp is in that region, near the high address end of the stack (which grows from high to low addresses on this system):
(gdb) p $sp
$9 = (void *) 0x7ffff7a4be60
I get the frame at 0xffffd3d0 and saveed eip = 0xf7e04e7e in stack level 0 while doing gdb debug.
(gdb) info frame
Stack level 0, frame at 0xffffd3d0:
eip = 0x8048452 in main (test.c:13); saved eip = 0xf7e04e7e
source language c.
Arglist at 0xffffd3b8, args:
Locals at 0xffffd3b8, Previous frame's sp is 0xffffd3d0
Saved registers:
ebp at 0xffffd3b8, eip at 0xffffd3cc
(gdb)
Here is my question about 3GB address space of userspace. Why it is showing frame pointer in out of 3GB address space ?
Normally, the address space of the user space is 0 to 0xc000000 in a 3: 1 virtual address distribution.
3GB limit does not apply to 64-bit processes
I am trying to do a buffer overflow for a project. The buffer needs to overflow to /bin/sh. I have found the correct return address, but I do not seem to be successfully getting an overflow.
Program received signal SIGSEGV, Segmentation fault.
0xb7fbc544 in msg (params) at myfile.c:167
167 msg_length = ctx->backend->send_msg_pre(msg, msg_length);
(gdb) backtrace
#0 0xb7fbc544 in msg (params) at myfile.c:167
#1 0xb7fbc869 in my_function(params) at myfile.c:912
#2 0xb7e4c190 in ?? () at ../sysdeps/unix/sysv/linux/system.c:76 from /lib/i386-linux-gnu/libc.so.6
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
To find the /bin/sh I followed this post:
(gdb) print &system
$15 = (<text variable, no debug info> *) 0xb7e4c190 <__libc_system>
(gdb) find &system,+9999999,"/bin/sh"
0xb7f6ca24
warning: Unable to access 16000 bytes of target memory at 0xb7fc292c, halting search.
1 pattern found.
(gdb)
I have found the return address and verified it is correct (if I replace it with a different function it calls that function). The original return address is bolded
0xbffff690: 0x90909090 0x90909090 0x90909090 0xb7e4c190
0xbffff6a0: 0xb7f6ca24 0x0804c050 0x0000004d 0x0804c158
The payload I sent was 0xb7e4c190 0xb7f6ca24 50
This overflow is a bit more tricky than others, because I need to do some padding to it in the front and the back. The way the item I am overflowing works is that it sets 6 bytes, so each set will take up a portion of one address and another.
I think the problem is that I have to overflow the last byte. I matched what it was originally, but that does not seem to work:
payload = payload + ['\x90'] + ['\xc1'] + ['\xe4'] + ['\xb7']
payload = payload + ['\x24'] + ['\xca'] + ['\xf6'] + ['\xb7'] + ['\x50']
Is there something I am missing here? Because the stack does not show the /bin/sh call in the overflow, I feel like that is not correct.
I'm new to reverse engeneering. I wrote the following C code to help me understand a bit more about stack frames.
#include <stdio.h>
int sum(int a, int b,int c)
{
return(a+b+c);
}
int media(int a, int b,int c)
{
int total;
total = a + b + c;
return (total/3);
}
int main ()
{
int num1,num2,num3;
char keypress[1];
num1 = 5;
num2 = 10;
num3 = 15;
printf ("\nCalling sum function\n");
sum(num1,num2,num3);
printf ("\nWaiting a keypress to call media function\n");
scanf ("%c",keypress);
media(num1,num2,num3);
printf ("\nWaiting a keypress to end\n");
scanf ("%c",keypress);
return(0);
}
As far as I know every time you call a function
a stack frame is created (see: ftp.gnu.org/old-gnu/Manuals/gdb/html_node/gdb_41.html). So, my goal with the above C code is to see, at least, three stack-frames.
1) main function - stack frame
2) sum function - stack frame
3) media function - stack frame
BTW: Those printfs are just to help me 'follow' the program in gdb. =)
So I guess if I compare the output of info frame after the program started with the output of info frame just after sum function is called I would get different output right? I did not got it as you can see:
Temporary breakpoint 1, main () at parastack.c:27
warning: Source file is more recent than executable.
27 num1 = 5;
(gdb) nexti
28 num2 = 10;
(gdb) info frame
Stack level 0, frame at 0x7fffffffdf00:
rip = 0x400605 in main (parastack.c:28); saved rip = 0x7ffff7a3c790
source language c.
Arglist at 0x7fffffffdef0, args:
Locals at 0x7fffffffdef0, Previous frame's sp is 0x7fffffffdf00
Saved registers:
rbp at 0x7fffffffdef0, rip at 0x7fffffffdef8
(gdb) nexti
29 num3 = 15;
(gdb) nexti
31 printf ("\nCalling sum function\n");
(gdb) nexti
0x0000000000400618 31 printf ("\nCalling sum function\n");
(gdb) nexti
Calling sum function
32 sum(num1,num2,num3);
(gdb) info frame
Stack level 0, frame at 0x7fffffffdf00:
rip = 0x40061d in main (parastack.c:32); saved rip = 0x7ffff7a3c790
source language c.
Arglist at 0x7fffffffdef0, args:
Locals at 0x7fffffffdef0, Previous frame's sp is 0x7fffffffdf00
Saved registers:
rbp at 0x7fffffffdef0, rip at 0x7fffffffdef8
(gdb) nexti
0x0000000000400620 32 sum(num1,num2,num3);
(gdb) info frame
Stack level 0, frame at 0x7fffffffdf00:
rip = 0x400620 in main (parastack.c:32); saved rip = 0x7ffff7a3c790
source language c.
Arglist at 0x7fffffffdef0, args:
Locals at 0x7fffffffdef0, Previous frame's sp is 0x7fffffffdf00
Saved registers:
rbp at 0x7fffffffdef0, rip at 0x7fffffffdef8
just after sum function is called
Your problem is that you never actually stopped inside of the sum function. You stopped after you printed that you are about to call it, and then you stepped a few instructions, but you never actually landed inside (it takes a few instructions to prepare arguments, one more to actually call, and few more inside the function to set up the frame).
You should start by setting breakpoints inside sum and media, and doing info frame when these breakpoints are hit. You'll notice that the breakpoint is set a few instructions after the beginning of the function (i.e. after function prolog). The skipped instructions are exactly the ones that set up the new frame.
After you understand how that works, you should progress to using step and next commands.
And after that you can graduate to using disas, stepi and nexti commands.
Based on my interpretation of your prose, your understanding of stack frames is slightly off. You are correct that when a function is called a stack frame is created, however, what you're missing is that when a function returns, the stack frame is popped. The stack is in the same state is was before the function began executing except that the program counter contains the address of the first instruction of the statement immediately following the function that just finished executing. So, you should not expect to see 3 stack frames after the two functions in main execute. You will only see one since you're only one frame deep into main().
As for the gdb session, as #Employed Russian points out, you never actually step into any function when printing the stack frame information.
Thanks for everyone that helped me. Below are the gdb session with shows that the stack-frame changed.
First I recompiled the C code: gcc -ggdb stack.c -o stack.bin
gdb stack.bin
(gdb) break sum
(gdb) start
(gdb) info frame
Stack level 0, frame at 0x7fffffffe1a0:
rip = 0x400653 in main (stack.c:26); saved rip 0x7ffff7a6fead
source language c.
Arglist at 0x7fffffffe190, args:
Locals at 0x7fffffffe190, Previous frame's sp is 0x7fffffffe1a0
Saved registers:
rbp at 0x7fffffffe190, rip at 0x7fffffffe198
(gdb) continue
Continuing.
Calling sum function
Breakpoint 1, sum (a=5, b=10, c=15) at stack.c:6
6 total = a + b + c;
(gdb) info frame
Stack level 0, frame at 0x7fffffffe180:
rip = 0x4005dd in sum (stack.c:6); saved rip 0x400684
called by frame at 0x7fffffffe1a0
source language c.
Arglist at 0x7fffffffe170, args: a=5, b=10, c=15
Locals at 0x7fffffffe170, Previous frame's sp is 0x7fffffffe180
Saved registers:
rbp at 0x7fffffffe170, rip at 0x7fffffffe178
Now I will search/learn more about the information in the output.