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], vh@thc.org
*
* 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("sdmem %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("\nsdmem 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(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(int dummy) {
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);
}
|