-
Notifications
You must be signed in to change notification settings - Fork 8
/
smem.c
209 lines (185 loc) · 6.23 KB
/
smem.c
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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/* Secure MEMORY cleaner - by van Hauser / [THC], [email protected]
*
* Note that this program is beta. It was tested with linux, solaris and
* openbsd but I can't tell for other platforms.
*
* Secure MEMORY overwrites all data in your memory it gets.
* The any -l option this does a real security wipe for 38 times, flushing
* the caches after every write. The wipe technique was proposed by Peter
* Gutmann at Usenix '96 and includes 10 random overwrites plus 29 special
* defined characters. Take a look at the paper of him, it's really worth
* your time.
* If run with one -l option, it wipes the memory twice, first with null
* bytes, then with random values.
* If run with two -l options, it wipes the memory only once with null bytes.
*
* Note that it is *very* slow. You might run it with "-llf"
*
* Read the manual for limitations.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "sdel.h"
#ifdef BLOCKSIZE
#undef BLOCKSIZE
#endif
#define BLOCKSIZE 65536
char buf[BLOCKSIZE+2];
int slow = 1;
extern FILE *devrandom;
void help() {
printf("smem %s (c) 1997-2003 by %s <%s>\n\n", VERSION, AUTHOR, EMAIL);
printf("Syntax: %s [-flv]\n\n", prg);
printf("Options:\n");
printf("\t-f fast (and insecure mode): no /dev/urandom.\n");
printf("\t-l lessens the security (use twice for total insecure mode).\n");
printf("\t-v is verbose mode.\n");
printf("\nsmem does a secure overwrite of the memory (RAM), because memory contents can\n");
printf("be recovered even after a shutdown! Default is secure mode (38 writes).\n");
printf("You can find updates at %s\n", WEB);
exit(1);
}
int smash_it(int mode) {
unsigned char write_modes[27][3] = {
{"\x55\x55\x55"}, {"\xaa\xaa\xaa"}, {"\x92\x49\x24"}, {"\x49\x24\x92"},
{"\x24\x92\x49"}, {"\x00\x00\x00"}, {"\x11\x11\x11"}, {"\x22\x22\x22"},
{"\x33\x33\x33"}, {"\x44\x44\x44"}, {"\x55\x55\x55"}, {"\x66\x66\x66"},
{"\x77\x77\x77"}, {"\x88\x88\x88"}, {"\x99\x99\x99"}, {"\xaa\xaa\xaa"},
{"\xbb\xbb\xbb"}, {"\xcc\xcc\xcc"}, {"\xdd\xdd\xdd"}, {"\xee\xee\xee"},
{"\xff\xff\xff"}, {"\x92\x49\x24"}, {"\x49\x24\x92"}, {"\x24\x92\x49"},
{"\x6d\xb6\xdb"}, {"\xb6\xdb\x6d"}, {"\xdb\x6d\xb6"}
};
int turn;
unsigned int counter = 0;
unsigned char buffers[27][BLOCKSIZE+2];
char *ptr;
struct rlimit rlim;
if (verbose) {
switch (mode) {
case 0 : printf("Wipe mode is insecure (one pass with 0x00)\n");
break;
case 1 : printf("Wipe mode is insecure (two passes [0x00/random])\n"); break;
default: printf("Wipe mode is secure (38 special passes)\n");
}
}
if (slow && mode)
if ((devrandom = fopen(RANDOM_DEVICE, "r")) != NULL)
if (verbose)
printf("Using %s for random input.\n", RANDOM_DEVICE);
/* We set a new ulimit, so we can grab all memory ... */
#ifdef RLIM_INFINITY
rlim.rlim_cur = RLIM_INFINITY;
rlim.rlim_max = RLIM_INFINITY;
#ifdef RLIMIT_DATA
if (setrlimit(RLIMIT_DATA, &rlim) != 0)
fprintf(stderr, "Warning: Could not reset ulimit for data.\n");
#endif
#ifdef RLIMIT_STACK
if (setrlimit(RLIMIT_STACK, &rlim) != 0)
fprintf(stderr, "Warning: Could not reset ulimit for stack.\n");
#endif
#ifdef RLIMIT_RSS
if (setrlimit(RLIMIT_RSS, &rlim) != 0)
fprintf(stderr, "Warning: Could not reset ulimit for rss.\n");
#endif
#ifdef RLIMIT_MEMLOCK
if (setrlimit(RLIMIT_MEMLOCK, &rlim) != 0)
fprintf(stderr, "Warning: Could not reset ulimit for mem locked.\n");
#endif
#ifndef RLIMIT_DATA
#ifndef RLIMIT_STACK
#ifndef RLIMIT_RSS
#ifndef RLIMIT_MEMLOCK
fprintf(stderr, "Warning: Not compiled with support for resetting ulimits for memory\n");
#endif
#endif
#endif
#endif
#else
fprintf(stderr, "Warning: Not compiled with support for resetting ulimits for memory\n");
#endif
if (mode > 1) {
for (turn=0; turn<27; turn++) {
__sdel_fill_buf((char *)write_modes[turn], BLOCKSIZE + 2, buf);
memcpy(buffers[turn], buf, BLOCKSIZE);
}
}
alarm(600); /* needed to prevent mem caching */
while ( (ptr = calloc(4096, 16)) != NULL) {
if (mode > 0) {
for (turn=0; turn<=36; turn++) {
if ((mode == 1) && (turn > 0)) break;
if ((turn>=5) && (turn<=31)) {
memcpy(ptr, buffers[turn-5], BLOCKSIZE);
} else {
__sdel_random_buf(BLOCKSIZE + 2, buf);
memcpy(ptr, buf, BLOCKSIZE);
}
}
}
if (verbose && (counter > 8)) { /* every 512kb */
printf("*");
counter = 0;
} else counter++;
}
if (devrandom)
fclose(devrandom);
if (verbose)
printf(" done\n");
return 0;
}
void cleanup() {
fprintf(stderr,"Terminated by signal. Clean exit.\n");
if (devrandom)
fclose(devrandom);
fflush(stdout);
fflush(stderr);
exit(1);
}
int main (int argc, char *argv[]) {
int secure = 2;
int result;
prg = argv[0];
if (argc == 2)
if ( (strncmp(argv[1],"-h", 2) == 0) || (strcmp(argv[1],"-?") == 0) )
help();
while (1) {
result = getopt(argc, argv, "FfLlSsVvZz");
if (result<0) break;
switch (result) {
case 'F' :
case 'f' : slow = 0;
break;
case 'L' :
case 'l' : if (secure) secure--;
break;
case 'S' :
case 's' : secure++;
break;
case 'V' :
case 'v' : verbose++;
break;
case 'Z':
case 'z': break;
default : help();
}
}
if (optind < argc)
help();
printf("Starting Wiping the memory, press Control-C to abort earlier. Help: \"%s -h\"\n", prg);
(void) setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGINT, cleanup);
signal(SIGTERM, cleanup);
signal(SIGHUP, cleanup);
signal(SIGALRM, cleanup);
smash_it(secure);
/* thats all */
exit(0);
}