exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

keyfinder.c

keyfinder.c
Posted Feb 18, 2005
Authored by van Hauser, thc | Site thc.org

THC Keyfinder analyses files for public/private keys and encrypted or compressed data. It identifies such areas by measuring the entropy, arithmetical mean and counter checking, and dumps the encrypted/compressed file sections.

SHA-256 | 35a9a7d340627b6885d74cb98d01849cc87a8deda546b6155dd85efc2df56ee5

keyfinder.c

Change Mirror Download
/*
* Keyfinder - finds crypto keys, encrypted data and compressed data in files
* by analyzing the entropy of parts of the file.
*
* (c) 2005 by van Hauser / THC <vh@thc.org> www.thc.org
* The GPL 2.0 applies to this code.
*
* Based on the paper "Playing hide and seek with stored keys" by Shamir and
* van Someren. www.ncipher.com/products/files/papers/anguilla/keyhide2.pdf
*
* In my experiments I went however a different route to identify keys which
* seems to be better when identifying keys.
* The paper evaluates 60 byte chunks on their entropy, and depending on the
* number of consecutive chunks with high entropies, this could be the key.
* This tool evalutes the full key size for the entropy, increasing by an
* approx 10% of the key size windows. Hence if the key is 1024 bit = 128 byte
* long, the window size is 10, and the file size is 500 bytes, it looks at
* the randomness from bytes 0-128, then 10-138, next 20-148 etc.
* Additionally to measuring the entropy, I added checking for the
* arithmetical mean, and detecting couting bytes up- and downwards in the
* beginning, middle or end of the file.
* By having three randomness checks and evaluating the full key size with a
* sliding window, the best keyfinding measures are in place, and much better
* than in the described paper.
*
* However still beware: you will 1) receive some false positives, and 2)
* Keyfinder can not find the exact start/end region of the key, it will
* usually be some bytes before or after the reported file area.
*
* For usage hints, type "keyfinder -h"
*
* To compile: gcc -o keyfinder keyfinder.c -lm
*
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

#define MINIMUM_RANDOMNESS 85
#define KEY_SIZE 128
#define WINDOW_SIZE 10
#define DUMP_ROWS 16

int minimal_randomness = MINIMUM_RANDOMNESS;
char *prg;
int ext_entropy;
int ext_mean;
int debug = 0;

void help() {
printf("Keyfinder v1.0 (c) 2005 by van Hauser / THC <vh@thc.org> www.thc.org\n");
printf("\nSyntax: %s [-k KEY_SIZE] [-w WINDOW_SIZE] [-r MINIMUM_RANDOMNESS] FILE\n", prg);
printf("\nOptions:\n");
printf(" -k KEY_SIZE Key size to look for (default: %d byte [%d bit])\n", KEY_SIZE, KEY_SIZE * 8);
printf(" -w WINDOW_SIZE Window size to check (default: %d byte)\n", WINDOW_SIZE);
printf(" -r MINIMUM_RANDOMNESS Minimum %% of randomness for keys (default: %d%%)\n", MINIMUM_RANDOMNESS);
printf(" -d Print debug output\n");
printf("\nFinds binary crypto keys, crypto data and compressed data in files.\n");
printf("The result is an indicator where the key could be, not a byte exact match.\n");
printf("The randomness is calculated by the entropy, the arithmetic mean value and a\n");
printf("counting check. Read more information in the header of the keyfinder.c file.\n");
printf("Note: If -k is specified but not -w, -w will be 10%% of -k.\n");
printf("Hints: (1) the smaller -k, the smaller should be -r\n");
printf(" (2) the smaller -r the more false positives\n");
printf(" (3) -w should be 1/8 to 1/20 of -k\n");
printf(" (4) -k values are 128/256/512 byte for RSA/asymmetric keys\n");
printf(" (5) -k 512 -> -r 95; -k 128 -> -r 85 \n");
exit(-1);
}

/* Why is log2() in libm not working?? what a fucking #!+~$$!! */
#define log2of10 3.32192809488736234787
static double log2_(double x) {
return (log2of10 * (log10(x)));
}

void calculate_randomness(unsigned char *buf, int buflen) {
double ent = 0.0;
double mean = 0.0;
double datasum = 0.0;
unsigned long ccount[256];
double prob[256];
int i, j = 0;

for (i = 0; i < 256; i++)
ccount[i] = 0;

for (i = 0; i < buflen; i++)
ccount[buf[i]]++;

for (i = 0; i < 256; i++) {
prob[i] = (double) ccount[i] / buflen;
datasum += ((double) i) * ccount[i]; /**/
}

for (i = 0; i < 256; i++) {
if (prob[i] > 0.0) {
ent += prob[i] * log2_((1.0 / prob[i]));
// printf("%f += %f * %f\n", ent, prob[i], log2_((1.0 / prob[i])));
}
}

mean = datasum / buflen; /**/
ext_mean = (mean - 127.5) / 1.275;
if (ext_mean < 0)
ext_mean = ext_mean * -1;
ext_mean = 100 - ext_mean;

ext_entropy = (ent * 100) / 8;

if (debug) {
printf("Entropy: %f bits (8 is totally random)\n", ent);
printf("Mean: %1.4f (127.5 is totally random)\n", mean);
}

if (ext_entropy + ext_mean >= minimal_randomness) {
/* check for counting in the beginning */
for (i = 0; i < 8 && j == 0; i++)
if (buf[i] + 1 != buf[i + 1])
j = 1;
if (j == 0)
j = 2;
if (j == 1)
j = 0;
for (i = 0; i < 8 && j == 0; i++)
if (buf[i] - 1 != buf[i++ + 1])
j = 1;
if (j == 0)
j = 2;
if (j == 1)
j = 0;

/* check for counting in the middle */
for (i = 0; i < 8 && j == 0; i++)
if (buf[((buflen/2) - i) - 4] != buf[((buflen/2) - i) - 3] + 1)
j = 1;
if (j == 0)
j = 2;
if (j == 1)
j = 0;
for (i = 0; i < 8 && j == 0; i++)
if (buf[((buflen/2) - i) - 4] != buf[((buflen/2) - i) - 3] - 1)
j = 1;
if (j == 0)
j = 2;
if (j == 1)
j = 0;

/* check for counting in the end */
for (i = 1; i <= 8 && j == 0; i++)
if (buf[buflen - i] != buf[(buflen - i) - 1] + 1)
j = 1;
if (j == 0)
j = 2;
if (j == 1)
j = 0;
for (i = 1; i <= 8 && j == 0; i++)
if (buf[buflen - i] != buf[(buflen - i) - 1] - 1)
j = 1;
if (j == 0)
j = 2;
if (j == 1)
j = 0;

if (j == 2) {
if (debug)
printf("Counting detected, false positive, ignoring...\n");
ext_mean = 0;
ext_entropy = 0;
}
}
}

void dump_asciihex(unsigned char *string, int length, unsigned int offset) {
unsigned char *p = (unsigned char *) string;
unsigned char lastrow_data[16];
unsigned int rows = length / DUMP_ROWS;
unsigned int lastrow = length % DUMP_ROWS;
unsigned int i, j;

for (i = 0; i < rows; i++) {
printf("%08hx: ", i * 16 + offset);
for (j = 0; j < DUMP_ROWS; j++) {
printf("%02x", p[(i * 16) + j]);
if (j % 2 == 1)
printf(" ");
}
printf(" [ ");
for (j = 0; j < DUMP_ROWS; j++) {
if (isprint(p[(i * 16) + j]))
printf("%c", p[(i * 16) + j]);
else
printf(".");
}
printf(" ]\n");
}
if (lastrow > 0) {
memset(lastrow_data, 0, sizeof(lastrow_data));
memcpy(lastrow_data, p + length - lastrow, lastrow);
printf("%08hx: ", i * 16 + offset);
for (j = 0; j < lastrow; j++) {
printf("%02x", p[(i * 16) + j]);
if (j % 2 == 1)
printf(" ");
}
while(j < DUMP_ROWS) {
printf(" ");
if (j % 2 == 1)
printf(" ");
j++;
}
printf(" [ ");
for (j = 0; j < lastrow; j++) {
if (isprint(p[(i * 16) + j]))
printf("%c", p[(i * 16) + j]);
else
printf(".");
}
while(j < DUMP_ROWS) {
printf(" ");
j++;
}
printf(" ]\n");
}
}

void dump_found(char *buf, int key_size, unsigned int block_count, int entropy, int mean) {
printf("Found at block %u (Entropy is %d%% | Mean Deviation is %d%% = %d%%):\n", block_count * 64, entropy, mean, (entropy + mean) / 2);
dump_asciihex(buf, key_size, block_count * 64);
printf("\n");
}

int main(int argc, char *argv[]) {
int key_size = KEY_SIZE;
int window_size = 0;
char *fn;
FILE *f;
char *buf;
int i;
int reading;
unsigned int block_count = 0;

prg = argv[0];

if (argc < 2 || strcmp(argv[1], "-h") == 0 || strncmp(argv[1], "--h", 3) == 0)
help();

while ((i = getopt(argc, argv, "dw:r:k:")) >= 0) {
switch(i) {
case 'd':
debug = 1;
break;
case 'w':
window_size = atoi(optarg);
break;
case 'r':
minimal_randomness = atoi(optarg);
break;
case 'k':
key_size = atoi(optarg);
break;
default:
help();
}
}

if (key_size != KEY_SIZE) {
if (window_size == 0)
window_size = (key_size / 10) - 1;
} else
window_size = WINDOW_SIZE;

if (key_size < 20 || key_size > 65535 || window_size < 1 || window_size >= key_size || minimal_randomness < 1 || minimal_randomness > 99) {
fprintf(stderr, "Error: Wrong Values! Limits: 20 < key_size < 65535; 1 < window_size < key_size; 1 < minimal_randomness < 100\n");
exit(-1);
}

if (key_size < window_size * 8)
fprintf(stderr, "Warning: The window size is too large, -w should be 1/8 to 1/16 of -k\n");

if (optind + 1 != argc)
help();

fn = argv[argc - 1];

if ((f = fopen(fn, "r")) == NULL) {
fprintf(stderr, "Error: Can not open file %s\n", fn);
exit(-1);
}

if ((buf = malloc(key_size + window_size)) == NULL) {
fprintf(stderr, "Error: malloc() failed\n");
exit(-1);
}
memset(buf, 0, key_size + window_size);

printf("Analyzing %s:\n", fn);
// if (debug)
printf("[Key Size: %d byte/%d bit, Window Size: %d byte, Minimal Randomness: %d%%]\n", key_size, key_size * 8, window_size, minimal_randomness);

minimal_randomness = minimal_randomness * 2;

if ((reading = fread(buf, 1, key_size, f)) > 0) {
calculate_randomness(buf, reading);
if ((ext_entropy + ext_mean) >= minimal_randomness && reading == key_size)
dump_found(buf, key_size, block_count, ext_entropy, ext_mean);
if (reading == key_size)
reading = window_size;
while (!feof(f) && reading == window_size) {
if ((reading = fread(buf + key_size, 1, window_size, f)) > 0) {
++block_count;
memmove(buf, buf + reading, key_size);
calculate_randomness(buf, key_size);
if ((ext_entropy + ext_mean) >= minimal_randomness)
dump_found(buf, key_size, block_count, ext_entropy, ext_mean);
}
}
}

return 0;
}
Login or Register to add favorites

File Archive:

September 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Sep 1st
    261 Files
  • 2
    Sep 2nd
    17 Files
  • 3
    Sep 3rd
    38 Files
  • 4
    Sep 4th
    52 Files
  • 5
    Sep 5th
    23 Files
  • 6
    Sep 6th
    27 Files
  • 7
    Sep 7th
    0 Files
  • 8
    Sep 8th
    1 Files
  • 9
    Sep 9th
    16 Files
  • 10
    Sep 10th
    38 Files
  • 11
    Sep 11th
    21 Files
  • 12
    Sep 12th
    40 Files
  • 13
    Sep 13th
    18 Files
  • 14
    Sep 14th
    0 Files
  • 15
    Sep 15th
    0 Files
  • 16
    Sep 16th
    21 Files
  • 17
    Sep 17th
    51 Files
  • 18
    Sep 18th
    23 Files
  • 19
    Sep 19th
    48 Files
  • 20
    Sep 20th
    36 Files
  • 21
    Sep 21st
    0 Files
  • 22
    Sep 22nd
    0 Files
  • 23
    Sep 23rd
    0 Files
  • 24
    Sep 24th
    0 Files
  • 25
    Sep 25th
    0 Files
  • 26
    Sep 26th
    0 Files
  • 27
    Sep 27th
    0 Files
  • 28
    Sep 28th
    0 Files
  • 29
    Sep 29th
    0 Files
  • 30
    Sep 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2024 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close