radare2/libr/search/rsakey.c
pancake 696961d15d * Cleanup for rsakey (still unused)
* Move sflib into libr/include
* Added r_file_size()

--HG--
rename : binr/ragg2/d/sflib/common/sfsocketcall.h => libr/include/sflib/common/sfsocketcall.h
rename : binr/ragg2/d/sflib/common/sftypes.h => libr/include/sflib/common/sftypes.h
rename : binr/ragg2/d/sflib/darwin-x86-32/sflib.h => libr/include/sflib/darwin-x86-32/sflib.h
rename : binr/ragg2/d/sflib/darwin-x86-32/sfsyscall.h => libr/include/sflib/darwin-x86-32/sfsyscall.h
rename : binr/ragg2/d/sflib/darwin-x86-32/sfsysnr.h => libr/include/sflib/darwin-x86-32/sfsysnr.h
rename : binr/ragg2/d/sflib/linux-x86-32/sflib.h => libr/include/sflib/linux-x86-32/sflib.h
rename : binr/ragg2/d/sflib/linux-x86-32/sfsyscall.h => libr/include/sflib/linux-x86-32/sfsyscall.h
rename : binr/ragg2/d/sflib/linux-x86-32/sfsysnr.h => libr/include/sflib/linux-x86-32/sfsysnr.h
rename : binr/ragg2/d/sflib/linux-x86-64/sflib.h => libr/include/sflib/linux-x86-64/sflib.h
rename : binr/ragg2/d/sflib/linux-x86-64/sfsyscall.h => libr/include/sflib/linux-x86-64/sfsyscall.h
rename : binr/ragg2/d/sflib/linux-x86-64/sfsysnr.h => libr/include/sflib/linux-x86-64/sfsysnr.h
2011-12-01 10:53:02 +01:00

154 lines
4.2 KiB
C

// RSAKeyFinder 1.0 (2008-07-18)
// By Nadia Heninger and J. Alex Halderman
// Contribution to r2 by @santitox
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <err.h>
#include <r_search.h>
// Baby BER parser, just good enough for RSA keys.
//
// This is not robust to errors in the memory image, but if we added
// some entropy testing and intelligent guessing, it could be made to be.
//
// Parses a single field of the key, beginning at start. Each field
// consists of a type, a length, and a value. Puts the type of field
// into type, the number of bytes into len, and returns a pointer to
// the beginning of the value.
ut8* r_parse_next(ut8* start, ut32 *type, ut32 *len) {
ut8 *val = NULL;
*type = start[0];
*len = 0;
if ((start[1] & 0x80) == 0) {
*len = start[1];
*val = start[2];
} else {
int i;
int lensize = start[1] & 0x7F;
for (i=0; i < lensize; i++)
*len = (*len << 8) | start[2+i];
*val = start[2+lensize];
}
return val;
}
// Sets output to a string displaying len bytes from buffer
void r_output_bytes(ut8* buffer, int len, char* output) {
char *output_aux;
int i,j;
for (i=0; i<len; i++) {
char tmp[4];
snprintf(tmp, sizeof(tmp), "%02x ",buffer[i]);
for (j=0;j<4;j++)
*output++ = tmp[j];
if ((i < len-1) && i % 16 == 15) *output++ = '\n';
}
*output = '\n';
output = output_aux;
}
// Field names in private and public keys
char *private_fields[10] = {"version", "modulus", "publicExponent",
"privateExponent","prime1","prime2",
"exponent1", "exponent2","coefficient", ""};
char *public_fields[3] = {"modulus", "publicExponent", ""};
// Sets output to a string listing the fields from a BER-encoded
// record, beginning at start, with the fields named according to the
// array of strings (returns true iff a valid encoding was found)
boolt r_print_fields(ut8* start, char *fields[], char *output) {
ut32 len=0, type;
int i;
output = NULL;
start = r_parse_next (start,&type,&len); // skip sequence field
for (i = 0; fields[i] != ""; i++) {
start = r_parse_next (start,&type,&len);
if (start == NULL || len == 0 || len > 1000)
return R_FALSE;
//XXX: spagueti?
// XXX asprintf is not portable
asprintf(&output, "%s = \n", fields[i]);
r_output_bytes (start,len,output);
start += len;
}
return R_TRUE;
}
// Returns a pointer to the beginning of a BER-encoded key by working
// backwards from the given memory map offset, looking for the
// sequence identifier (this is not completely safe)
ut8 *r_find_key_start(ut8 *map, int offset) {
int k;
for (k = offset; k >= 0 && k > offset-20; k--)
if (map[k] == 0x30)
return &map[k];
return NULL;
}
// Finds and prints private (or private and public) keys in the memory
// map by searching for given target pattern
void r_find_keys(ut8 *image, int isize, ut8 *target, int target_size, boolt find_public) {
int i;
for (i = 0; i < isize - target_size; i++) {
if (memcmp (&image[i], target, target_size))
continue;
ut8 *key = r_find_key_start(image, i);
if (!key)
continue;
char *output;
if (r_print_fields(key,private_fields,output)) {
printf("FOUND PRIVATE KEY AT %x\n", (ut32)(key-image));
printf("%s\n",output);
} else if (find_public &&
r_print_fields(key,public_fields,output)) {
printf("FOUND PUBLIC KEY AT %x\n", (ut32)(key-image));
printf("%s\n",output);
}
}
}
#if TEST
static void r_usage() {
fprintf(stderr, "USAGE: rsakeyfind MEMORY-IMAGE [MODULUS-FILE]\n"
"Locates BER-encoded RSA private keys in MEMORY-IMAGE.\n"
"If MODULUS-FILE is specified, it will locate private and public keys"
"matching the hex-encoded modulus read from this file.\n");
}
int main(int argc, char *argv[]) {
RMmap *img;
if (argc < 2 || argc > 3) {
r_usage();
exit(1);
}
img = r_file_mmap (argv[1], 0);
if (argc == 3) {
// method 1: searching for modulus
ut32 mlen;
ut8 *modulus = r_file_slurp (argv[2], &mlen);
if (modulus)
r_find_keys (
img->buf, img->len,
modulus, mlen, R_TRUE);
} else {
// method 2: searching for versionmarker
ut8 versionmarker[4] = {0x02, 0x01, 0x00, 0x02};
r_find_keys (img->buf, img->len,
versionmarker, sizeof (versionmarker), R_FALSE);
}
r_file_mmap_free (img);
return 0;
}
#endif