-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 843702d
Showing
6 changed files
with
311 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/** | ||
* error.c: Generic error/debug routines | ||
* author: Vassil Roussev | ||
*/ | ||
|
||
#include <errno.h> | ||
#include <stdint.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <stdlib.h> | ||
#include "util.h" | ||
|
||
|
||
/** | ||
* Allocate memory, check result, and print error (if necessary). | ||
*/ | ||
void *alloc_check( uint32_t alloc_type, uint64_t mem_bytes, const char *fun_name, const char *var_name, uint32_t error_action) { | ||
void *mem_chunk = NULL; | ||
|
||
switch( alloc_type) { | ||
case ALLOC_ONLY: | ||
mem_chunk = malloc( mem_bytes); | ||
break; | ||
case ALLOC_AUTO: | ||
mem_chunk = malloc( mem_bytes); | ||
break; | ||
case ALLOC_ZERO: | ||
mem_chunk = calloc( 1, mem_bytes); | ||
break; | ||
default: | ||
return NULL; | ||
} | ||
if( mem_chunk == NULL) { | ||
fprintf( stderr, "Could not allocate %dKB (%dMB) for %s in function %s(). System message: \"%s\".", | ||
(int)(mem_bytes >> 10), (int)(mem_bytes >> 20), var_name, fun_name, strerror( errno)); | ||
if( error_action == ERROR_EXIT) { | ||
fprintf( stderr, " Exiting.\n"); | ||
exit(-1); | ||
} | ||
} | ||
return mem_chunk; | ||
} | ||
void *realloc_check( void *buffer, uint64_t new_size) { | ||
void *mem_chunk = realloc( buffer, new_size); | ||
|
||
return mem_chunk; | ||
} | ||
|
||
/** | ||
* Print a 256-byte buffer | ||
*/ | ||
void print256( const uint8_t *buffer) { | ||
uint16_t i; | ||
fprintf( stderr, " "); | ||
for( i=0; i<32; i++) | ||
fprintf( stderr, "%02x ", i); | ||
fprintf( stderr, "\n"); | ||
|
||
for( i=0; i<256; i++) { | ||
if( i % 32 == 0) | ||
fprintf( stderr, "%04x: ", i); | ||
fprintf( stderr, "%02x ", buffer[i]); | ||
if( i % 32 == 31) | ||
fprintf( stderr, "\n"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
#include <errno.h> | ||
#include <fcntl.h> | ||
#include <stdio.h> | ||
#include <stdint.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include <sys/stat.h> | ||
#include <sys/types.h> | ||
#include <fstream> | ||
|
||
#include "util.h" | ||
|
||
using namespace std; | ||
|
||
/** | ||
* Open & read in a file (compile w/ -D_FILE_OFFSET_BITS=64) | ||
*/ | ||
processed_file_t *process_file(const char *fname) { | ||
processed_file_t *mfile = (processed_file_t *) alloc_check( ALLOC_ZERO, sizeof( processed_file_t), "map_file", "mfile", ERROR_EXIT); | ||
struct stat file_stat; | ||
ifstream *is= new ifstream(); | ||
|
||
if( stat( fname, &file_stat)) { | ||
fprintf( stderr, "Warning: Could not stat file '%s'. Skipping.\n", fname); | ||
return NULL; | ||
} | ||
is->open(fname,ios::binary); | ||
|
||
mfile->buffer = (uint8_t*)alloc_check(ALLOC_ZERO,sizeof(uint8_t)*file_stat.st_size, "read_file", "mfile", ERROR_EXIT); | ||
is->read((char*)mfile->buffer,file_stat.st_size); | ||
int res=is->gcount(); | ||
if( res != file_stat.st_size) { | ||
fprintf( stderr, "read failed: %s.\n", strerror( errno)); | ||
free( mfile); | ||
is->close(); | ||
return NULL; | ||
} | ||
mfile->name = (char*)fname; | ||
mfile->size = file_stat.st_size; | ||
is->close(); | ||
return mfile; | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
|
||
/** File: nullfinder.cc | ||
Author: Candice Quates | ||
Program: gpunullfinder | ||
Takes argument of a file of dumped gpu memory, attempts to divine structure | ||
by searching for blocks of nulls which have been added for padding. | ||
Default block of nulls to search for is 8. extracting is only for 8-null blocks. | ||
File parsing code lifted from sdhash, apache license (Roussev/Quates 2013) | ||
General structure and command line arguments lifted from zsniff. (apache license) | ||
*/ | ||
|
||
/* compile with: | ||
g++ -std=c++0x -o nullf nullfinder.cc map_file.cc error.cc | ||
*/ | ||
|
||
|
||
#include <vector> | ||
#include <cstddef> | ||
#include <iostream> | ||
#include <fstream> | ||
#include <sstream> | ||
#include <string> | ||
|
||
|
||
|
||
#define VERSION "nullfind 0.1 by Candice Quates May 2015" | ||
|
||
#include "util.h" | ||
|
||
|
||
int | ||
writeExtracted(std::vector<unsigned char> &image, std::string filename) { | ||
std::string outfilename = filename+".extract"; | ||
std::filebuf fb; | ||
fb.open (outfilename.c_str(),std::ios::out|std::ios::binary); | ||
if (fb.is_open()) { | ||
std::ostream os(&fb); | ||
os.write((const char *)image.data(), image.size()); | ||
fb.close(); | ||
return 0; | ||
} else { | ||
std::cerr << "nullfind: cannot write to " << outfilename << std::endl; | ||
return 1; | ||
} | ||
} | ||
|
||
// using null size default to 8 nulls | ||
// option for extract/noextract | ||
// null size changing does not work yet | ||
// other desired feature: use stringbuilder to make pretty hex address filenames | ||
int | ||
main(int argc, char *argv[]) | ||
{ | ||
bool extract = false; | ||
if (argc < 2 ) { | ||
std::cout << VERSION << std::endl << std::endl; | ||
std::cout << "Usage: "<< argv[0] << " [--extract] [--nulls 8] filename(s) " << std::endl; | ||
return 1; | ||
} | ||
bool nullsm=false; | ||
int nullssize=8; | ||
// look for extract and nulls size | ||
for (int i=0; i<argc; i++) { | ||
if (std::string("--extract").compare(std::string(argv[i]))==0) { | ||
extract=true; | ||
} | ||
if (nullsm==true) { | ||
if (isdigit(argv[i][0])) { | ||
nullssize=atoi(argv[i]); | ||
} else { | ||
std::cerr << "usage: "<< argv[0] << " [--extract] [--nulls 8] filename(s) " << std::endl; | ||
return 1; | ||
} | ||
nullsm=false; | ||
} | ||
if (std::string("--nulls").compare(std::string(argv[i]))==0) { | ||
nullsm=true; | ||
} | ||
} | ||
std::cout <<"null size "<< nullssize << std::endl; | ||
nullsm=false; | ||
//loop for multiple files here | ||
for (int i=1; i<argc; i++) { | ||
if (std::string("--extract").compare(std::string(argv[i]))==0) { | ||
continue; | ||
} | ||
// nulls marker to ignore argument after --block | ||
if (nullsm==true) { | ||
nullsm=false; | ||
continue; | ||
} | ||
if (std::string("--nulls").compare(std::string(argv[i]))==0) { | ||
nullsm=true; | ||
continue; | ||
} | ||
const char* filename = argv[i] ; | ||
|
||
//load files -- the sdhash methods reliably parse files with nulls | ||
processed_file_t *mfile=process_file(filename); | ||
if (mfile->size == 0) { | ||
std::cerr << "nullf: file " << filename << " empty or not found" << std::endl; | ||
return 1; | ||
} | ||
int error=0; | ||
std::cout << "nullf processing: "<< filename << std::endl; | ||
uint8_t current=0; | ||
// There is some integer size mismatching to be fixed here. | ||
int range=0; | ||
int nullcount=0; | ||
int startaddr=0; | ||
// I am well aware that there are prettier and more | ||
// elegant ways to do this, but this is much faster | ||
// than I expected it to be (ie, a few minutes on a VM for 2gb file) | ||
for (int n=0; n < mfile->size ; n++) { | ||
current=(uint8_t)*(mfile->buffer+n); | ||
if (n==0 && current != 0) | ||
std::cout<< std::hex <<n <<" data begin "; | ||
if (current == 0) { | ||
nullcount++; | ||
if (range != 1 && nullcount == 8) { | ||
std::cout<< std::hex <<n <<" ends" << std::endl; | ||
std::cout<< std::hex <<n-8 <<" nulls begin " ; | ||
// extract data | ||
if (extract) { | ||
std::vector<unsigned char> image; | ||
image.resize(n-7-startaddr); | ||
for (int x=0,y=startaddr; y<n-7; x++,y++) { | ||
image[x]=(unsigned char)*(mfile->buffer+y); | ||
} | ||
writeExtracted(image,std::string(filename)+std::to_string((int)startaddr)); | ||
} | ||
range=1; | ||
startaddr=0; | ||
} | ||
} else { | ||
// if we've changed state, note that. | ||
if (range == 1) { | ||
std::cout<< std::hex <<n <<" end "<< std::endl; | ||
std::cout<< std::hex <<n <<" data begin "; | ||
startaddr=n; | ||
} | ||
range=0; | ||
nullcount = 0; | ||
} | ||
} | ||
// If we've reached EOF and are in a block of data, | ||
// extract if asked. | ||
if (nullcount==0) { | ||
std::cout<< std::hex <<n<<" ends" << std::endl; | ||
if (extract) { | ||
std::vector<unsigned char> image; | ||
image.resize(n-7-startaddr); | ||
for (int x=0,y=startaddr; y<n-7; x++,y++) { | ||
image[x]=(unsigned char)*(mfile->buffer+y); | ||
} | ||
writeExtracted(image,std::string(filename)+std::to_string((int)startaddr)); | ||
} | ||
} | ||
} // loop for parsing multiple files | ||
return 0; | ||
} | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
* General definitions (Vassil Roussev) | ||
*/ | ||
#ifndef __UTIL_H | ||
#define __UTIL_H | ||
|
||
#include <stdio.h> | ||
#include <stdint.h> | ||
|
||
#define KB 1024 | ||
#define MB (KB*KB) | ||
#define GB (MB*KB) | ||
|
||
#define ALLOC_ONLY 1 | ||
#define ALLOC_ZERO 2 | ||
#define ALLOC_AUTO 3 | ||
|
||
#define ERROR_IGNORE 0 | ||
#define ERROR_EXIT 1 | ||
|
||
// Struct describing a mapped file | ||
typedef struct { | ||
char *name; | ||
int fd; | ||
FILE *input; | ||
uint64_t size; | ||
uint8_t *buffer; | ||
} processed_file_t; | ||
|
||
processed_file_t *process_file(const char *fname); | ||
|
||
void print256( const uint8_t *buffer); | ||
void *alloc_check( uint32_t alloc_type, uint64_t mem_bytes, const char *fun_name, const char *var_name, uint32_t error_action); | ||
void *realloc_check( void *buffer, uint64_t new_size); | ||
|
||
#endif |