-
Notifications
You must be signed in to change notification settings - Fork 0
/
BufferOverflow.cpp
executable file
·170 lines (145 loc) · 5.41 KB
/
BufferOverflow.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
#define _CRT_SECURE_NO_WARNINGS
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "memory.h"
#include <iostream>
#include <iomanip>
using namespace std;
// Note: GCC and MSVC uses different memory alignment
// Try "12345678DevilEvecosia" as a password for gcc build
// Try "1234567812345678Devil I am. Ha Ha" as a password for MSVC debug x86 build.
// If doesn't work, investigate why :)
void demoBufferOverflowData() {
int unused_variable = 30;
#define NORMAL_USER 'n'
#define ADMIN_USER 'a'
int userRights = NORMAL_USER;
#define USER_INPUT_MAX_LENGTH 8
char userName[USER_INPUT_MAX_LENGTH];
char passwd[USER_INPUT_MAX_LENGTH];
// print some info about variables
printf("%-20s: %p\n", "userName", userName);
printf("%-20s: %p\n", "passwd", passwd);
printf("%-20s: %p\n", "unused_variable", &unused_variable);
printf("%-20s: %p\n", "userRights", &userRights);
printf("%-20s: %p\n", "demoBufferOverflowData", demoBufferOverflowData);
// problem
printf("\n");
// Get user name
memset(userName, 1, USER_INPUT_MAX_LENGTH);
memset(passwd, 2, USER_INPUT_MAX_LENGTH);
printf("login as: ");
fflush(stdout);
//gets(userName); // use scanf("%s", userName); if gets fails with identifier not found
scanf("%s", userName);
// Get password
printf("%[email protected]: ", userName);
fflush(stdout);
//gets(passwd);
scanf("%s", passwd); // use scanf("%s", passwd); if gets fails with identifier not found
// Check user rights (set to NORMAL_USER and not changed in code)
if (userRights == NORMAL_USER) {
printf("\nWelcome, normal user '%s', your rights are limited.\n\n", userName);
fflush(stdout);
}
if (userRights == ADMIN_USER) {
printf("\nWelcome, all mighty admin user '%s'!\n", userName);
fflush(stdout);
}
// How to FIX:
//memset(userName, 0, USER_INPUT_MAX_LENGTH);
//fgets(userName, USER_INPUT_MAX_LENGTH - 1, stdin);
//gets_s(userName, USER_INPUT_MAX_LENGTH - 1);
//memset(passwd, 0, USER_INPUT_MAX_LENGTH);
//fgets(passwd, USER_INPUT_MAX_LENGTH - 1, stdin);
}
void demoAdjacentMemoryOverflow(char* userName, char* password) {
// See more at http://www.awarenetwork.org/etc/alpha/?x=5
// Once string is not null terminated, a lot of functions will behave wrongly:
// sprintf, fprintf, snprintf, strcpy, strcat, strlen, strstr, strchr, read...
// memcpy, memmove - if length to copy is computed via strlen(string)
char message[100];
char realPassword[] = "very secret password nbusr123";
char buf[8];
// print some info about variables
printf("%-20s: %p\n", "message", message);
printf("%-20s: %p\n", "userName", userName);
printf("%-20s: %p\n", "password", password);
printf("%-20s: %p\n", "realPassword", &realPassword);
printf("%-20s: %p\n", "buf", &buf);
printf("\n");
memset(buf, 0, sizeof(buf));
memset(message, 1, sizeof(message));
strncpy(buf, userName, sizeof(buf)); // We will copy only characters which fits into buf
// Now print username to standard output - nothing sensitive, right?
sprintf(message, "Checking '%s' password\n", buf);
printf("%s", message);
if (strcmp(password, realPassword) == 0) {
printf("Correct password.\n");
}
else {
printf("Wrong password.\n");
}
// FIX: Do not allow to have non-terminated string
// Clear buffer for text with zeroes (terminating zero will be there)
// strncpy(buf,arg1,sizeof(buf) - 1);
}
typedef struct _some_structure {
float someData[1000];
} some_structure;
void demoDataTypeOverflow(int totalItemsCount, some_structure* pItem, int itemPosition) {
// See http://blogs.msdn.com/oldnewthing/archive/2004/01/29/64389.aspx
some_structure* data_copy = NULL;
int bytesToAllocation = totalItemsCount * sizeof(some_structure);
printf("Bytes to allocation: %d\n", bytesToAllocation);
data_copy = (some_structure*)malloc(bytesToAllocation);
if (itemPosition >= 0 && itemPosition < totalItemsCount) {
memcpy(&(data_copy[itemPosition]), pItem, sizeof(some_structure));
}
else {
printf("Out of bound assignment");
return;
}
free(data_copy);
}
int main() {
printf("%-20s: %p\n", "main", main);
printf("\n");
//
// Let's play with buffer overflow - change internal data
// VS, Debug mode
//
printf("\n\n#### demoBufferOverflowData ####\n");
demoBufferOverflowData();
demoBufferOverflowData();
/**/
//
// More on buffer overflow - reveal sensitive data.
// Try to login as admin. Password is hardcoded in the application.
//
// VS, Debug mode
/*
printf("\n\n#### demoAdjacentMemoryOverflow ####\n");
demoAdjacentMemoryOverflow("admin", "I don't know the password");
demoAdjacentMemoryOverflow("adminxxxx", "I still don't know the password");
demoAdjacentMemoryOverflow("admin", "very secret password nbu123");
/**/
//
// And more on buffer overflow - run different function or user code!
// Eclipse, Debug - work
// VS, Release - stack protection nonce example - does not work due to canary word
// demoBufferOverunFunction();
//
// Not only arrays may overflow - integers as well
//
//
/*
// printf("\n\n#### demoDataTypeOverflow ####\n");
some_structure data;
memset(&data, 1, sizeof(some_structure));
demoDataTypeOverflow(10, &data, 5); // Correct operation
demoDataTypeOverflow(1073742, &data, 5); // 1073742 * 4000 => only 704 B allocated
/**/
return 0;
}