Insecure coding in C (and C++)
Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C...
Insecure coding in C (and C++)
Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C...
Insecure coding in C (and C++)
Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C...
Insecure coding in C (and C++)
Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C...
Insecure coding in C (and C++)
Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C...
Insecure coding in C (and C++)
Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C...
When I refer to "my machine" it is a fairly up-to-date Ubuntu
distro (13.10) running inVirtualBox with x86-32 Linux kernel...
I will briefly discuss the following topics:
•stack buffer overflow (aka stack smashing)
•call stack (aka activation frames)...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
$ ./launch
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void auth...
$ ./launch
WarGames MissileLauncher v0.1
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: imple...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
$ ./launch
WarGames MissileLauncher v0.1
Secret:
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TOD...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
void launch_missiles(int n)
{
printf("Launching %d missilesn", n);
// TODO: implement this function
}
void authenticate_an...
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Insecure coding in C (and C++)
Upcoming SlideShare
Loading in...5
×

Insecure coding in C (and C++)

4,719

Published on

Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C++ with serious security vulnerabilities that can be "easily" exploited. Then you need to know about things like stack smashing, shellcode, arc injection, return-oriented programming. You also need to know about annoying protection mechanisms such as address space layout randomization, stack canaries, data execution prevention, and more. These slides will teach you the basics of how to deliberately write insecure programs in C and C++.

A PDF version of the slides can be downloaded from my homepage: http://olvemaudal.com/talks

Here is a video recording of me presenting these slides at NDC 2014: http://vimeo.com/channels/ndc2014/97505677

Enjoy!

Published in: Software, Technology
0 Comments
37 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,719
On Slideshare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
254
Comments
0
Likes
37
Embeds 0
No embeds

No notes for slide

Insecure coding in C (and C++)

  1. 1. Insecure coding in C (and C++) Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C++ with serious security vulnerabilities that can be "easily" exploited.Then you need to know about things like stack smashing, shellcode, arc injection, return-oriented programming. You also need to know about annoying protection mechanisms such as address space layout randomization, stack canaries, data execution prevention, and more. This session will teach you the basics of how to deliberately write insecure programs in C and C++. a 60 minute presentation Norwegian Developer Conference Oslo, June 5 2014, 16:20-17:20 Olve Maudal Update:A recording of this talk is available at http://vimeo.com/channels/ndc2014/97505677
  2. 2. Insecure coding in C (and C++) Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C++ with serious security vulnerabilities that can be "easily" exploited.Then you need to know about things like stack smashing, shellcode, arc injection, return-oriented programming. You also need to know about annoying protection mechanisms such as address space layout randomization, stack canaries, data execution prevention, and more. This session will teach you the basics of how to deliberately write insecure programs in C and C++. a 60 minute presentation Norwegian Developer Conference Oslo, June 5 2014, 16:20-17:20 Olve Maudal
  3. 3. Insecure coding in C (and C++) Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C++ with serious security vulnerabilities that can be "easily" exploited.Then you need to know about things like stack smashing, shellcode, arc injection, return-oriented programming. You also need to know about annoying protection mechanisms such as address space layout randomization, stack canaries, data execution prevention, and more. This session will teach you the basics of how to deliberately write insecure programs in C and C++. a 60 minute presentation Norwegian Developer Conference Oslo, June 5 2014, 16:20-17:20 Olve Maudal Level: Introduction Advanced Expert
  4. 4. Insecure coding in C (and C++) Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C++ with serious security vulnerabilities that can be "easily" exploited.Then you need to know about things like stack smashing, shellcode, arc injection, return-oriented programming. You also need to know about annoying protection mechanisms such as address space layout randomization, stack canaries, data execution prevention, and more. This session will teach you the basics of how to deliberately write insecure programs in C and C++. a 60 minute presentation Norwegian Developer Conference Oslo, June 5 2014, 16:20-17:20 Olve Maudal Level: Introduction Advanced Expert
  5. 5. Insecure coding in C (and C++) Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C++ with serious security vulnerabilities that can be "easily" exploited.Then you need to know about things like stack smashing, shellcode, arc injection, return-oriented programming. You also need to know about annoying protection mechanisms such as address space layout randomization, stack canaries, data execution prevention, and more. This session will teach you the basics of how to deliberately write insecure programs in C and C++. a 60 minute presentation Norwegian Developer Conference Oslo, June 5 2014, 16:20-17:20 Olve Maudal Level: Introduction Advanced Expert
  6. 6. Insecure coding in C (and C++) Let's turn the table. Suppose your goal is to deliberately create buggy programs in C and C++ with serious security vulnerabilities that can be "easily" exploited.Then you need to know about things like stack smashing, shellcode, arc injection, return-oriented programming. You also need to know about annoying protection mechanisms such as address space layout randomization, stack canaries, data execution prevention, and more. This session will teach you the basics of how to deliberately write insecure programs in C and C++. a 60 minute presentation Norwegian Developer Conference Oslo, June 5 2014, 16:20-17:20 Olve Maudal Level: Introduction Advanced Expert
  7. 7. When I refer to "my machine" it is a fairly up-to-date Ubuntu distro (13.10) running inVirtualBox with x86-32 Linux kernel (3.11) and gcc (4.8.1) - there is nothing special here...
  8. 8. I will briefly discuss the following topics: •stack buffer overflow (aka stack smashing) •call stack (aka activation frames) •writing exploits •arc injection (aka return to lib-c) •code injection (aka shell code) •data execution protection (aka DEP, PAE/NX,W^X) •address space layout randomization (ASLR) •stack protection (aka stack canaries) •return-oriented programming (ROP) •writing code with "surprising" behavior •layered security •information leakage •patching binaries •summary - a few tricks for insecure coding
  9. 9. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Here is a classic example of exploitable code
  10. 10. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Here is a classic example of exploitable code
  11. 11. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Here is a classic example of exploitable code
  12. 12. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } This program is bad in so many ways, but the main weakness we are going to have fun with is of course the use of gets() Here is a classic example of exploitable code
  13. 13. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } This program is bad in so many ways, but the main weakness we are going to have fun with is of course the use of gets() gets() is a function that will read characters from stdin until a newline or end-of-file is reached, and then a null character is appended. In this case, any input of more than 7 characters will overwrite data outside of the allocated space for the buffer Here is a classic example of exploitable code
  14. 14. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } This program is bad in so many ways, but the main weakness we are going to have fun with is of course the use of gets() gets() is a function that will read characters from stdin until a newline or end-of-file is reached, and then a null character is appended. In this case, any input of more than 7 characters will overwrite data outside of the allocated space for the buffer I never use gets() Here is a classic example of exploitable code
  15. 15. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } This program is bad in so many ways, but the main weakness we are going to have fun with is of course the use of gets() gets() is a function that will read characters from stdin until a newline or end-of-file is reached, and then a null character is appended. In this case, any input of more than 7 characters will overwrite data outside of the allocated space for the buffer I never use gets() That's nice to hear, and gets() has actually been deprecated and removed from latest version of the language.We use it anyway here just to make it easier to illustrate the basics. In C and C++ there are plenty of ways to accidentally allow you to poke directly into memory - we will mention some of those later later. But for now... Here is a classic example of exploitable code
  16. 16. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); }
  17. 17. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Let's try executing the code and see what happens.
  18. 18. $ ./launch void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Let's try executing the code and see what happens.
  19. 19. $ ./launch WarGames MissileLauncher v0.1 void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Let's try executing the code and see what happens.
  20. 20. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Let's try executing the code and see what happens.
  21. 21. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } David Let's try executing the code and see what happens.
  22. 22. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access denied David Let's try executing the code and see what happens.
  23. 23. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access denied Operation complete David Let's try executing the code and see what happens.
  24. 24. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access denied Operation complete $ ./launch David Let's try executing the code and see what happens.
  25. 25. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 David Let's try executing the code and see what happens.
  26. 26. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: David Let's try executing the code and see what happens.
  27. 27. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Let's try executing the code and see what happens.
  28. 28. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access granted Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Let's try executing the code and see what happens.
  29. 29. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access granted Launching 2 missiles Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Let's try executing the code and see what happens.
  30. 30. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access granted Launching 2 missiles Operation complete Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Let's try executing the code and see what happens.
  31. 31. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access granted Launching 2 missiles Operation complete $ ./launch Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Let's try executing the code and see what happens.
  32. 32. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Let's try executing the code and see what happens.
  33. 33. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Let's try executing the code and see what happens.
  34. 34. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Let's try executing the code and see what happens.
  35. 35. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Access granted Let's try executing the code and see what happens.
  36. 36. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Access granted Launching 1869443685 missiles Let's try executing the code and see what happens.
  37. 37. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Access granted Launching 1869443685 missiles Access denied Let's try executing the code and see what happens.
  38. 38. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Operation complete Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Access granted Launching 1869443685 missiles Access denied Let's try executing the code and see what happens.
  39. 39. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Operation complete $ Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Access granted Launching 1869443685 missiles Access denied Let's try executing the code and see what happens.
  40. 40. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Operation complete $ Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Access granted Launching 1869443685 missiles Access denied Let's try executing the code and see what happens. Due to an overflow we seem to have changed the value of allowaccess and the value of n_missiles. Interesting!
  41. 41. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Operation complete $ Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Access granted Launching 1869443685 missiles Access denied Huh? Let's try executing the code and see what happens. Due to an overflow we seem to have changed the value of allowaccess and the value of n_missiles. Interesting!
  42. 42. $ ./launch WarGames MissileLauncher v0.1 Secret: void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } Operation complete $ Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua David Access granted Launching 1869443685 missiles Access denied Huh? Let's try executing the code and see what happens. Due to an overflow we seem to have changed the value of allowaccess and the value of n_missiles. Interesting! ... but why did it also print Access denied?
  43. 43. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } $ ./launch WarGames MissileLauncher v0.1 Secret: David Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access granted Launching 1869443685 missiles Access denied Operation complete $
  44. 44. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } $ ./launch WarGames MissileLauncher v0.1 Secret: David Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access granted Launching 1869443685 missiles Access denied Operation complete $ What we just saw was an example of stack buffer overflow, aka stack smashing.When overwriting the response buffer we also changed the memory location used by variable allowaccess and n_missiles
  45. 45. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } $ ./launch WarGames MissileLauncher v0.1 Secret: David Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access granted Launching 1869443685 missiles Access denied Operation complete $ C and C++ are languages that are mostly defined by its behavior.The standards says very little about how things should be implemented. Indeed, while it is common to hear discussions about call stack when talking about C and C++, it is worth noting that the standards does not mention the concept at all. What we just saw was an example of stack buffer overflow, aka stack smashing.When overwriting the response buffer we also changed the memory location used by variable allowaccess and n_missiles
  46. 46. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } $ ./launch WarGames MissileLauncher v0.1 Secret: David Access denied Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: Joshua Access granted Launching 2 missiles Operation complete $ ./launch WarGames MissileLauncher v0.1 Secret: globalthermonuclearwar Access granted Launching 1869443685 missiles Access denied Operation complete $ C and C++ are languages that are mostly defined by its behavior.The standards says very little about how things should be implemented. Indeed, while it is common to hear discussions about call stack when talking about C and C++, it is worth noting that the standards does not mention the concept at all. We can learn a lot about C and C++ by studying what happens when it executes. Here is a detailed explanation about what actually happened on my machine. Let's start from the beginning... What we just saw was an example of stack buffer overflow, aka stack smashing.When overwriting the response buffer we also changed the memory location used by variable allowaccess and n_missiles
  47. 47. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); }
  48. 48. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } main() is the entry point for the program.
  49. 49. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } main() is the entry point for the program.
  50. 50. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } main() is the entry point for the program. At this point, a call stack has been set up for us.
  51. 51. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } main() is the entry point for the program. At this point, a call stack has been set up for us. high address low address
  52. 52. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } main() is the entry point for the program. At this point, a call stack has been set up for us. high address low address The calling function has pushed the address of its next instruction to be executed on the stack, just before it made a jmp into main()
  53. 53. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } main() is the entry point for the program. At this point, a call stack has been set up for us. return address, next intruction in _starthigh address low address The calling function has pushed the address of its next instruction to be executed on the stack, just before it made a jmp into main()
  54. 54. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } main() is the entry point for the program. At this point, a call stack has been set up for us. return address, next intruction in _starthigh address low address The calling function has pushed the address of its next instruction to be executed on the stack, just before it made a jmp into main() The first thing that happens when entering main(), is that the current base pointer is pushed on to the stack.
  55. 55. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } main() is the entry point for the program. At this point, a call stack has been set up for us. return address, next intruction in _starthigh address low address The calling function has pushed the address of its next instruction to be executed on the stack, just before it made a jmp into main() The first thing that happens when entering main(), is that the current base pointer is pushed on to the stack. Then the base pointer and stack pointer is changed so main() get's it's own activation frame.
  56. 56. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } main() is the entry point for the program. At this point, a call stack has been set up for us. return address, next intruction in _start pointer to stack frame for _start high address low address The calling function has pushed the address of its next instruction to be executed on the stack, just before it made a jmp into main() The first thing that happens when entering main(), is that the current base pointer is pushed on to the stack. Then the base pointer and stack pointer is changed so main() get's it's own activation frame.
  57. 57. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address
  58. 58. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address
  59. 59. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } The first statement in main() is to call puts() with a string. return address, next intruction in _start pointer to stack frame for _start high address low address
  60. 60. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } The first statement in main() is to call puts() with a string. return address, next intruction in _start pointer to stack frame for _start high address low address A pointer to the string is pushed on the stack, this is the argument to puts()
  61. 61. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } The first statement in main() is to call puts() with a string. return address, next intruction in _start pointer to stack frame for _start high address low address A pointer to the string is pushed on the stack, this is the argument to puts() pointer to string "WarGames..."
  62. 62. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } The first statement in main() is to call puts() with a string. return address, next intruction in _start pointer to stack frame for _start high address low address A pointer to the string is pushed on the stack, this is the argument to puts() Then we push the return address, a memory address pointing to the next instruction in main() pointer to string "WarGames..."
  63. 63. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } The first statement in main() is to call puts() with a string. return address, next intruction in _start pointer to stack frame for _start high address low address A pointer to the string is pushed on the stack, this is the argument to puts() Then we push the return address, a memory address pointing to the next instruction in main() pointer to string "WarGames..." return address, next intruction in main
  64. 64. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } The first statement in main() is to call puts() with a string. return address, next intruction in _start pointer to stack frame for _start high address low address A pointer to the string is pushed on the stack, this is the argument to puts() Then we push the return address, a memory address pointing to the next instruction in main() pointer to string "WarGames..." return address, next intruction in main The puts() function will do whatever it needs to do, just making sure that the base pointer is restored before using the return address to jump back to the next instruction in main()
  65. 65. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } The first statement in main() is to call puts() with a string. return address, next intruction in _start pointer to stack frame for _start high address low address A pointer to the string is pushed on the stack, this is the argument to puts() Then we push the return address, a memory address pointing to the next instruction in main() pointer to string "WarGames..." return address, next intruction in main The puts() function will do whatever it needs to do, just making sure that the base pointer is restored before using the return address to jump back to the next instruction in main() (whatever puts() needs to do)
  66. 66. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address pointer to string "WarGames..." return address, next intruction in main
  67. 67. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address pointer to string "WarGames..." return address, next intruction in main The stack is restored and the next statement will be executed.
  68. 68. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address The stack is restored and the next statement will be executed.
  69. 69. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address The stack is restored and the next statement will be executed.
  70. 70. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address Now we prepare for calling authenticate_and_launch() by pushing the return address of the next statement to be executed in main() , and then we jump into authenticate_and_launch() The stack is restored and the next statement will be executed.
  71. 71. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address Now we prepare for calling authenticate_and_launch() by pushing the return address of the next statement to be executed in main() , and then we jump into authenticate_and_launch() return address, next intruction in _main The stack is restored and the next statement will be executed.
  72. 72. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address Now we prepare for calling authenticate_and_launch() by pushing the return address of the next statement to be executed in main() , and then we jump into authenticate_and_launch() return address, next intruction in _main The stack is restored and the next statement will be executed.
  73. 73. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main
  74. 74. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address Create a new stack frame, before allocating space for the local variables on the stack. return address, next intruction in _main
  75. 75. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address Create a new stack frame, before allocating space for the local variables on the stack. return address, next intruction in _main pointer to stack frame for _main
  76. 76. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main Create a new stack frame, before allocating space for the local variables on the stack.
  77. 77. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) Create a new stack frame, before allocating space for the local variables on the stack.
  78. 78. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) n_missiles (4 bytes) Create a new stack frame, before allocating space for the local variables on the stack.
  79. 79. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes) Create a new stack frame, before allocating space for the local variables on the stack.
  80. 80. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes) Hey, wait a minute... should not the stack variables be allocated in correct order? Create a new stack frame, before allocating space for the local variables on the stack.
  81. 81. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes) There is no "correct order" here. In this case, the compiler is free to store objects of automatic storage duration (the correct name for "stack variables") in any order. Indeed, it can keep all of them in registers or ignore them completely as long as the external behavior of the program is the same. Hey, wait a minute... should not the stack variables be allocated in correct order? Create a new stack frame, before allocating space for the local variables on the stack.
  82. 82. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes)
  83. 83. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes)
  84. 84. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address Then we call printf() with an argument. return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes)
  85. 85. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address Then we call printf() with an argument. return address, next intruction in _main pointer to stack frame for _main pointer to string "Secret: " allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes)
  86. 86. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address Then we call printf() with an argument. return address, next intruction in _main pointer to stack frame for _main return address, authenticate_and_launch() pointer to string "Secret: " allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes)
  87. 87. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address Then we call printf() with an argument. return address, next intruction in _main pointer to stack frame for _main return address, authenticate_and_launch() pointer to string "Secret: " (whatever printf() needs to do) allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes)
  88. 88. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address Then we call printf() with an argument. return address, next intruction in _main pointer to stack frame for _main return address, authenticate_and_launch() pointer to string "Secret: " (whatever printf() needs to do) After the prompt has been written to the standard output stream.The stack is cleaned up and we get ready to execute the next statement. allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes)
  89. 89. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes) return address, authenticate_and_launch() pointer to string "Secret: " (whatever printf() needs to do)
  90. 90. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes)
  91. 91. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address First the pointer to the response buffer is pushed on stack. return address, next intruction in _main pointer to stack frame for _main allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes)
  92. 92. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address First the pointer to the response buffer is pushed on stack. return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes)
  93. 93. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address First the pointer to the response buffer is pushed on stack. return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes) Then the return address. Before jumping into gets()
  94. 94. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address First the pointer to the response buffer is pushed on stack. return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes) Then the return address. Before jumping into gets()
  95. 95. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address First the pointer to the response buffer is pushed on stack. return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes) Then the return address. Before jumping into gets()
  96. 96. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address First the pointer to the response buffer is pushed on stack. return address, next intruction in _main pointer to stack frame for _main gets() will wait for input from the standard input stream. Each character will be poked sequentally into the response buffer until a newline character, end-of-line or some kind of error occurs.Then, before returning it will append a '0' character to the buffer. pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes) Then the return address. Before jumping into gets()
  97. 97. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } return address, next intruction in _start pointer to stack frame for _start high address low address First the pointer to the response buffer is pushed on stack. return address, next intruction in _main pointer to stack frame for _main gets() will wait for input from the standard input stream. Each character will be poked sequentally into the response buffer until a newline character, end-of-line or some kind of error occurs.Then, before returning it will append a '0' character to the buffer. pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) If the input is 8 characters or more, then the response buffer allocated on the stack is not big enough, and in this case the data storage of the other variables will be overwritten. allowaccess (1 byte) n_missiles (4 bytes) response (8 bytes) Then the return address. Before jumping into gets()
  98. 98. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } allowaccess (1 byte) response (8 bytes) n_missiles (4 bytes) return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do)
  99. 99. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } allowaccess (1 byte) response (8 bytes) n_missiles (4 bytes) return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) Here is the exact stack data I got one time I executed the code on my machine.
  100. 100. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } allowaccess (1 byte) response (8 bytes) n_missiles (4 bytes) return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) 0x50 0xfa 0xff 0xbf 0x00 0x40 0xfc 0xb7 0x00 0x00 0x00 0x00 0x00 0x39 0xe1 0xb7 0x88 0xfa 0xff 0xbf 0xa0 0x29 0xff 0xb7 0x02 0x00 0x00 0x00 0x00 0x40 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x88 0xfa 0xff 0xbf 0x5b 0x85 0x04 0x08 0xbffffa40 0xbffffa6c Here is the exact stack data I got one time I executed the code on my machine.
  101. 101. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } allowaccess (1 byte) response (8 bytes) n_missiles (4 bytes) return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) 0x50 0xfa 0xff 0xbf 0x00 0x40 0xfc 0xb7 0x00 0x00 0x00 0x00 0x00 0x39 0xe1 0xb7 0x88 0xfa 0xff 0xbf 0xa0 0x29 0xff 0xb7 0x02 0x00 0x00 0x00 0x00 0x40 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x88 0xfa 0xff 0xbf 0x5b 0x85 0x04 0x08 0xbffffa40 0xbffffa6c Here is the exact stack data I got one time I executed the code on my machine. A lot of this is just padding due to alignment issues.
  102. 102. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } allowaccess (1 byte) response (8 bytes) n_missiles (4 bytes) return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) 0x50 0xfa 0xff 0xbf 0x00 0x40 0xfc 0xb7 0x00 0x00 0x00 0x00 0x00 0x39 0xe1 0xb7 0x88 0xfa 0xff 0xbf 0xa0 0x29 0xff 0xb7 0x02 0x00 0x00 0x00 0x00 0x40 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x88 0xfa 0xff 0xbf 0x5b 0x85 0x04 0x08 0xbffffa40 0xbffffa6c A lot of this is just padding due to alignment issues. Here is the exact stack data I got one time I executed the code on my machine.
  103. 103. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } allowaccess (1 byte) response (8 bytes) n_missiles (4 bytes) return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) 0x50 0xfa 0xff 0xbf 0x00 0x40 0xfc 0xb7 0x00 0x00 0x00 0x00 0x00 0x39 0xe1 0xb7 0x88 0xfa 0xff 0xbf 0xa0 0x29 0xff 0xb7 0x02 0x00 0x00 0x00 0x00 0x40 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x88 0xfa 0xff 0xbf 0x5b 0x85 0x04 0x08 0xbffffa40 0xbffffa6c
  104. 104. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } allowaccess (1 byte) response (8 bytes) n_missiles (4 bytes) return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) 0x50 0xfa 0xff 0xbf 0x00 0x40 0xfc 0xb7 0x00 0x00 0x00 0x00 0x00 0x39 0xe1 0xb7 0x88 0xfa 0xff 0xbf 0xa0 0x29 0xff 0xb7 0x02 0x00 0x00 0x00 0x00 0x40 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x88 0xfa 0xff 0xbf 0x5b 0x85 0x04 0x08 0xbffffa40 0xbffffa6c
  105. 105. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } allowaccess (1 byte) response (8 bytes) n_missiles (4 bytes) return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) 0x50 0xfa 0xff 0xbf 0x00 0x40 0xfc 0xb7 0x00 0x00 0x00 0x00 0x00 0x39 0xe1 0xb7 0x88 0xfa 0xff 0xbf 0xa0 0x29 0xff 0xb7 0x02 0x00 0x00 0x00 0x00 0x40 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x88 0xfa 0xff 0xbf 0x5b 0x85 0x04 0x08 0xbffffa40 0xbffffa6c
  106. 106. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } allowaccess (1 byte) response (8 bytes) n_missiles (4 bytes) return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) 0x50 0xfa 0xff 0xbf 0x00 0x40 0xfc 0xb7 0x00 0x00 0x00 0x00 0x00 0x39 0xe1 0xb7 0x88 0xfa 0xff 0xbf 0xa0 0x29 0xff 0xb7 0x02 0x00 0x00 0x00 0x00 0x40 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x88 0xfa 0xff 0xbf 0x5b 0x85 0x04 0x08 0xbffffa40 0xbffffa6c
  107. 107. void launch_missiles(int n) { printf("Launching %d missilesn", n); // TODO: implement this function } void authenticate_and_launch(void) { int n_missiles = 2; bool allowaccess = false; char response[8]; printf("Secret: "); gets(response); if (strcmp(response, "Joshua") == 0) allowaccess = true; if (allowaccess) { puts("Access granted"); launch_missiles(n_missiles); } if (!allowaccess) puts("Access denied"); } int main(void) { puts("WarGames MissileLauncher v0.1"); authenticate_and_launch(); puts("Operation complete"); } allowaccess (1 byte) response (8 bytes) n_missiles (4 bytes) return address, next intruction in _start pointer to stack frame for _start high address low address return address, next intruction in _main pointer to stack frame for _main pointer to the response buffer return address, authenticate_and_launch() (whatever gets() needs to do) 0x50 0xfa 0xff 0xbf 0x00 0x40 0xfc 0xb7 0x00 0x00 0x00 0x00 0x00 0x39 0xe1 0xb7 0x88 0xfa 0xff 0xbf 0xa0 0x29 0xff 0xb7 0x02 0x00 0x00 0x00 0x00 0x40 0xfc 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x88 0xfa 0xff 0xbf 0x5b 0x85 0x04 0x08 0xbffffa40 0xbffffa6c
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×