SHOW:
|
|
- or go back to the newest paste.
| 1 | /* | |
| 2 | ||
| 3 | - | ______ ___ _____ ___.______ ________ _______ _________ ______ _____ ___. |
| 3 | + | ______ ___ _____ ___.______ ________ _______ _________ ______ _____ ___. |
| 4 | - | / ___/( /_\ \\ : \\ __ /_ _\ ___ // _ /__/ ___/__\ \\ : |
| 4 | + | / ___/( /_\ \\ : \\ __ /_ _\ ___ // _ /__/ ___/__\ \\ : |
| 5 | - | _\ _/ |\/ // . \ | _ \ _ \\ . /_____/__/ _\ _/ | . \ | |
| 5 | + | _\ _/ |\/ // . \ | _ \ _ \\ . /_____/__/ _\ _/ | . \ | |
| 6 | - | \ | / : | / \ / \ : | \_ \ | : | |
| 6 | + | \ | / : | / \ / \ : | \_ \ | : | |
| 7 | \______:__//____|____|_________/_______/ |____:__________\_______:____|____| | |
| 8 | - | /_____| |
| 8 | + | /_____| |
| 9 | ||
| 10 | ||
| 11 | KLPD Cybercrime Challenge 2013 -- Alternative solution for IRC C&C | |
| 12 | ||
| 13 | Instead of fishing the /passphrase/ from the memorydump, this utility | |
| 14 | searches for the raw 256bit key in memory. It simply treats every 32- | |
| 15 | byte block as a key, decrypts the given ciphertext and checks if the | |
| 16 | deciphered block consists of pure 7bit ascii characters. This is a | |
| 17 | pretty effective way to find "candidates" for possibly correct keys. | |
| 18 | To thwart some more false candidates we do a basic entropy check on | |
| 19 | the candidate key before letting it pass. | |
| 20 | ||
| 21 | This might sound quite expensive, but it churns to through the | |
| 22 | entire 512 megabyte memorydump within 2 minutes on an average desktop | |
| 23 | computer. Leaving you with only one candidate that matches all of | |
| 24 | the given basic constraints: the correct AES key :-) | |
| 25 | ||
| 26 | This AES key can be used to encrypt/decrypt any further messages! | |
| 27 | ||
| 28 | -- EINDBAZEN / 2013-03-31 | |
| 29 | ||
| 30 | ||
| 31 | sample run: | |
| 32 | $ gcc -o keyfinder keyfinder.c -lcrypto | |
| 33 | $ time ./keyfinder memory.raw \ | |
| 34 | `echo dfI8J5hkgaQ6vtYtKK2d7Qlou650S9m1FZ697bZ01TCOTnCTWtyCzqyZe9UV4bBHZN9nkm4j/2Py|base64 -d` | |
| 35 | 1ca16c00.. | |
| 36 | ||
| 37 | FOUND POSSIBLE KEY: 6c99160e2cdd68f68b9e09938453fc499ca6ab9df2eed14399663e1cb2461b40 --> 'supported comman' | |
| 38 | 20000000.. | |
| 39 | real 1m46.199s | |
| 40 | user 1m44.187s | |
| 41 | sys 0m1.004s | |
| 42 | ||
| 43 | */ | |
| 44 | #include <stdio.h> | |
| 45 | #include <string.h> | |
| 46 | #include <stdlib.h> | |
| 47 | - | #include <unistd.h> |
| 47 | + | #include <unistd.h> |
| 48 | #include <sys/types.h> | |
| 49 | #include <sys/stat.h> | |
| 50 | #include <openssl/aes.h> | |
| 51 | ||
| 52 | int decrypt(unsigned char *k, unsigned char *d, int dlen) {
| |
| 53 | AES_KEY aes_key; | |
| 54 | unsigned char iv[0x10], plaintext[0x20], ent_buf[256]; | |
| 55 | int i; | |
| 56 | ||
| 57 | memset(iv, 0, 16); | |
| 58 | ||
| 59 | AES_set_decrypt_key(k, 256, &aes_key); | |
| 60 | AES_cbc_encrypt(d, plaintext, 0x20u, &aes_key, iv, AES_DECRYPT); | |
| 61 | ||
| 62 | // all plaintext 7bit ascii? | |
| 63 | for(i = 0; i < 16; i++) {
| |
| 64 | if (plaintext[i] < 0x20 || plaintext[i] > 0x7e) | |
| 65 | return -1; | |
| 66 | } | |
| 67 | ||
| 68 | - | // somewhat legit entropy? |
| 68 | + | |
| 69 | printf("\n\nFOUND POSSIBLE KEY: ");
| |
| 70 | for(i=0;i<32;i++) {
| |
| 71 | printf("%02x", k[i]);
| |
| 72 | - | ent_buf[ k[i] ]++; |
| 72 | + | |
| 73 | ||
| 74 | printf(" --> '");
| |
| 75 | - | for (i=0;i<256;i++) {
|
| 75 | + | |
| 76 | - | if (ent_buf[i] > 2) |
| 76 | + | |
| 77 | printf("%c", plaintext[i]);
| |
| 78 | } | |
| 79 | ||
| 80 | printf("'\n");
| |
| 81 | ||
| 82 | return 0; | |
| 83 | } | |
| 84 | ||
| 85 | int main(int argc, char *argv[]) {
| |
| 86 | unsigned char *blob; | |
| 87 | FILE *fp; | |
| 88 | struct stat st; | |
| 89 | int pos=0, i, nonrandom=0; | |
| 90 | unsigned char ent_buf[256]; | |
| 91 | ||
| 92 | if (stat(argv[1], &st) < 0) {
| |
| 93 | perror("stat");
| |
| 94 | return -1; | |
| 95 | } | |
| 96 | ||
| 97 | fp=fopen(argv[1], "rb"); | |
| 98 | ||
| 99 | blob = malloc(st.st_size); | |
| 100 | fread(blob, st.st_size, 1, fp); | |
| 101 | - | int pos=0; |
| 101 | + | |
| 102 | ||
| 103 | memset(ent_buf, 0, 256); | |
| 104 | for(i=0;i<32;i++) {
| |
| 105 | if (++ent_buf[blob[i]] == 3) ++nonrandom; | |
| 106 | } | |
| 107 | ||
| 108 | while(pos < st.st_size) {
| |
| 109 | if (!nonrandom) {
| |
| 110 | decrypt(blob+pos, (unsigned char*)argv[2], 32); | |
| 111 | } | |
| 112 | for(i=0;i<4;i++) {
| |
| 113 | if (ent_buf[blob[pos]]-- == 3) --nonrandom; | |
| 114 | if (++ent_buf[blob[pos + 32]] == 3) ++nonrandom; | |
| 115 | - | decrypt(blob+pos, (unsigned char*)argv[2], 32); |
| 115 | + | ++pos; |
| 116 | - | pos += 4; |
| 116 | + | |
| 117 | if ((pos % (1024)) == 0) {
| |
| 118 | printf("%08x..\r", pos);
| |
| 119 | fflush(stdout); | |
| 120 | } | |
| 121 | } | |
| 122 | ||
| 123 | free(blob); | |
| 124 | ||
| 125 | return 0; | |
| 126 | } |