Stack Overflow Principle¶
Introduction¶
For an introduction to the stack, you can read the introduction in Linux Pwn.
Basic Example¶
Below is a typical example. In this example, a last-byte overflow exists due to the order of variable declarations and the size of the buffer declaration.
#include <stdio.h>
#include <string.h>
#define PASSWORD "666666"
int verify_password(char *password)
{
int authenticated;
char buffer[8];
authenticated = strcmp(password,PASSWORD);
strcpy(buffer,password);
return authenticated;
}
void main()
{
int valid_flag =0;
char password[128];
while(1)
{
printf("please input password: ");
scanf("%s",password);
valid_flag = verify_password(password);
if (valid_flag !=0)
{
printf("incorrect password!\n");
}
else
{
printf("Congratulation! You have passed the verification!\n");
break;
}
}
}
This is a simple password verification program that checks whether the input string is equal to 666666. Use vc6.0 to compile this program, and after a successful compilation, use winchecksec to check the enabled protections. We can see that GS is enabled, but this does not prevent our overflow.
C:\Users\CarlStar\Desktop>winchecksec.exe demo1.exe
Dynamic Base : false
ASLR : true
High Entropy VA : false
Force Integrity : false
Isolation : true
NX : true
SEH : true
CFG : false
RFG : false
SafeSEH : true
GS : true
Authenticode : false
.NET : true
Use OllyDbg to dynamically debug this program. Enter aaaaaa to observe the normal execution flow of the program. To facilitate understanding of the entire process, set a breakpoint after the strcmp function and after strcpy finishes executing.

Now we can let the program run. After entering aaaaaa, the program will hit our first breakpoint. Enter the strcmp function and observe its return value. Since the ASCII value of 'a' is greater than the ASCII value of '6', the function should return 1 as expected. In x86, the return value is stored in the EAX register. After the function returns normally, since the program still needs to use these registers to complete its remaining functionality, this return value will be saved on the stack at ss:[0012FEA0].


When execution reaches the second breakpoint, let's look at the stack structure. Here, 61 is the ASCII representation of the 'a' we entered, and 00 is the string terminator. The buffer is 8 bytes in size, so if we enter 8 a's, the final string terminator will overflow into 0012FEA0, overwriting the original value to 0. This allows us to change the program's execution flow and output "Congratulation! You have passed the verification!"
0012FE90 CCCCCCCC
0012FE94 CCCCCCCC
0012FE98 61616161
0012FE9C CC006161
0012FEA0 00000001
OK, let's first let the program continue running normally.

This time we enter 8 a's to verify whether it works as we expected: the string terminator will overflow into the return value of strcmp. We can see that the return value of strcmp is still 1.

Continue running to the second breakpoint and check the current stack values. The return value of strcmp has been successfully overflowed from 1 to 0.
0012FE90 CCCCCCCC
0012FE94 CCCCCCCC
0012FE98 61616161
0012FE9C 61616161
0012FEA0 00000000
Now let the program continue running. It successfully outputs the expected string.
