how to make it uncrackable?
the first problem is, that the license key is inside the binary.
we can use 'strings license_1' to extract all stings, and we find the key. (or hexdump)
our first attempt to make it secure would be not have the key inside by writing an algorithm that scrambles the key.
source code : license_2.c
#include <string.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
if(argc==2) {
printf("Checking License: %s\n", argv[1]);
int sum = 0;
for (int i = 0; i < strlen(argv[1]); i++) {
sum+= (int)argv[1][i];
}
if(sum==916) {
printf("Access Granted!\n");
} else {
printf("WRONG!\n");
}
} else {
printf("Usage: <key>\n");
}
return 0;
}
radare2:
keygen.py :
import random
import sys
def check_key(key):
char_sum = 0
for c in key:
char_sum += ord(c)
sys.stdout.write("{0:3} | {1} \r".format(char_sum, key))
sys.stdout.flush()
return char_sum
key = ""
while True:
key += random.choice("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_")
s = check_key(key)
if s > 916:
key = ""
elif s==916:
print "Found valid key: {0}".format(key)
Programs like gdb and radare2 have to parse the executable to be able to disassemble and debug it.
So could you modify the executable in a way, that you can still execute it with linux, but gdb and radare2 tell you something is broken?
What we are looking for is a parser differential.
Fuzzing
fuzz.py
import random
import os
os.system("cp license_2 license_2_fuzz")
def flip_byte(in_bytes):
i = random.randint(0,len(in_bytes))
c = chr(random.randint(0,0xFF))
return in_bytes[:i]+c+in_bytes[i+1:]
def copy_binary():
with open("license_2", "rb") as orig_f, open("license_2_fuzz", "wb") as new_f:
new_f.write(flip_byte(orig_f.read()))
def compare(fn1, fn2):
with open(fn1) as f1, open(fn2) as f2:
return f1.read()==f2.read()
def check_output():
os.system("(./license_2_fuzz ; ./license_2_fuzz AAAA-Z10N-42-OK) > fuzz_output")
return compare("orig_output", "fuzz_output")
def check_gdb():
os.system("echo disassemble main | gdb license_2_fuzz > fuzz_gdb")
return compare("orig_gdb", "fuzz_gdb")
def check_radare():
os.system('echo -e "aaa\ns sym.main\npdf" | radare2 license_2_fuzz > fuzz_radare')
return compare("orig_radare", "fuzz_radare")
while True:
copy_binary()
if check_output() and not check_gdb() and not check_radare():
print "FOUND POSSIBLE FAIL\n\n\n"
os.system("tail fuzz_gdb")
os.system("tail fuzz_radare")
raw_input()