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!
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Insecure coding in C (and C++)
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. 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. 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. 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. 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. 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.
8.
9. 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...
10. 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
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. 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
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");
}
Here is a classic example of exploitable code
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()
Here is a classic example of exploitable code
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
Here is a classic example of exploitable code
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");
}
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
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");
}
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
18. 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");
}
19. 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. $ ./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.
21. $ ./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.
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");
}
Let's try executing the code
and see what happens.
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");
}
David
Let's try executing the code
and see what happens.
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
David
Let's try executing the code
and see what happens.
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
David
Let's try executing the code
and see what happens.
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
David
Let's try executing the code
and see what happens.
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
David
Let's try executing the code
and see what happens.
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 denied
Operation complete
$ ./launch
WarGames MissileLauncher v0.1
Secret:
David
Let's try executing the code
and see what happens.
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 denied
Operation complete
$ ./launch
WarGames MissileLauncher v0.1
Secret: Joshua
David
Let's try executing the code
and see what happens.
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
Access denied
Operation complete
$ ./launch
WarGames MissileLauncher v0.1
Secret: Joshua
David
Let's try executing the code
and see what happens.
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
Access denied
Operation complete
$ ./launch
WarGames MissileLauncher v0.1
Secret: Joshua
David
Let's try executing the code
and see what happens.
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
Access denied
Operation complete
$ ./launch
WarGames MissileLauncher v0.1
Secret: Joshua
David
Let's try executing the code
and see what happens.
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
Access denied
Operation complete
$ ./launch
WarGames MissileLauncher v0.1
Secret: Joshua
David
Let's try executing the code
and see what happens.
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
Access denied
Operation complete
$ ./launch
WarGames MissileLauncher v0.1
Secret: Joshua
David
Let's try executing the code
and see what happens.
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:
Access denied
Operation complete
$ ./launch
WarGames MissileLauncher v0.1
Secret: Joshua
David
Let's try executing the code
and see what happens.
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
Let's try executing the code
and see what happens.
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
Let's try executing the code
and see what happens.
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");
}
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.
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");
}
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. $ ./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.
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
Let's try executing the code
and see what happens.
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
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!
43. $ ./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!
44. $ ./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?
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
$
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. 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
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");
}
$ ./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
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");
}
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.
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.
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.
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.
high address
low address
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.
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()
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()
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 _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.
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");
}
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.
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");
}
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.
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");
} return address, next intruction in _start
pointer to stack frame for _start
high address
low address
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");
} return address, next intruction in _start
pointer to stack frame for _start
high address
low address
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
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()
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()
pointer to string "WarGames..."
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..."
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
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");
}
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()
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");
}
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)
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
pointer to string "WarGames..."
return address, next intruction in main
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
pointer to string "WarGames..."
return address, next intruction in main
The stack is restored and the next statement
will be executed.
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
The stack is restored and the next statement
will be executed.
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
The stack is restored and the next statement
will be executed.
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()
The stack is restored and the next statement
will be executed.
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
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.
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
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.
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
return address, next intruction in _main
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
Create a new stack frame, before allocating
space for the local variables on the stack.
return address, next intruction in _main
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
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
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
Create a new stack frame, before allocating
space for the local variables on the stack.
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)
Create a new stack frame, before allocating
space for the local variables on the stack.
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)
Create a new stack frame, before allocating
space for the local variables on the stack.
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)
Create a new stack frame, before allocating
space for the local variables on the stack.
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)
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.
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)
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.
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
return address, next intruction in _main
pointer to stack frame for _main
allowaccess (1 byte)
n_missiles (4 bytes)
response (8 bytes)
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
return address, next intruction in _main
pointer to stack frame for _main
allowaccess (1 byte)
n_missiles (4 bytes)
response (8 bytes)
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
allowaccess (1 byte)
n_missiles (4 bytes)
response (8 bytes)
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
pointer to string "Secret: "
allowaccess (1 byte)
n_missiles (4 bytes)
response (8 bytes)
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: "
allowaccess (1 byte)
n_missiles (4 bytes)
response (8 bytes)
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
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)
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
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)
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
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)
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
return address, next intruction in _main
pointer to stack frame for _main
allowaccess (1 byte)
n_missiles (4 bytes)
response (8 bytes)
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
allowaccess (1 byte)
n_missiles (4 bytes)
response (8 bytes)
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
allowaccess (1 byte)
n_missiles (4 bytes)
response (8 bytes)
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
allowaccess (1 byte)
n_missiles (4 bytes)
response (8 bytes)
Then the return address. Before jumping into
gets()
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
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()
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
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()
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");
} 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()
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");
} 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()
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)
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)
Here is the exact stack data I got one time
I executed the code on my machine.
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
Here is the exact stack data I got one time
I executed the code on my machine.
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
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.
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
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.
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. 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. 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
108. 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
109. 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