Reading Time : 9min
Crackme: flag_eater_crackme KeyGen
Author: wh1t3r0se
Difficulty: 2.7/6.0
Platform: Unix/Linux
Language: C/C++
Architecture: X86_64
Description by Author: The elves are hungry to eat flag cookies. It’s your duty to bake all of them.
Aslam o Alaikum (Greetings) Everyone In this blog post I am changing things a little bit. instead of showing you IDA Disassembly code I will decompile this software using Ghidra ( I have commented and renamed variables in ghidra decompiler so they make more sense ) and using that I am going to write its source code in Python, I will also explain how it is working along the way.
this program is mainly consist of 4 parts
main function : it shows greeting messages and take input from user, then it pass this input to a function I call “main_code“
main_code : this function calls two more function “remainder_zero_or_not” and “compare_function” and shows the correct or wrong message as feedback
remainder_zero_or_not : in this function calculations are performed on value of each character provided as input
compare_function : this function compares data generated by if condition in result of “remainder_zero_or_not” return value with (data) provided inside “main_code” and return value 1 or 0 if they matched or not accordingly.
This program is 64bit ELF binary file
This is how it looks when running and provided a wrong key.
Urdu/ Hindi -----> English meaning
------------------------------------------------------
"chal flag de: " -----> means "enter the flag: "
"ye diya hai tune: " -----> means "this is your input: "
main function
here is decompiled(ghidra) code snippet for main() function
here program is taking input and passing it as an argument in “main_code” function
this function is taking one character from user input and passing its ASCII integer value to “remainder_zero_or_not” function which perform basically a modulus operation on it, if it is an even number the function returns 0 or 1 if it is odd and in response to the return value, in case of 0 return the shr(shift bitwise right) operation will be performed 4 time on said chracter value or 1 time if it returns 1 and the modified value will be saved in a memory location i named (generated_data).
after that the generated_data and data values will be compared in “compare_function” and result will determine either you will be present with wrong or correct message.
This function is performing modulus operation and checking if character is even or odd, if even then it will return 0 and if odd then it will return 1.
Global Variable “DATA” memory location in Ghidra
here program is comparing each value inside (generated_data) and Data Variable, if every value matches then it will return 1 and if not then it will return 0
which will then be used to show correct and wrong message as mentioned above.
This is Python3 script I wrote that does the same thing as actual program.
# Python3 Script for wh1t3r0se's flag_eater_crackme KeyGen
# Written by Mr. Manj
# created with Python3 if you want to run on Python2 replace input() with raw_input()
DATA = [0x6,0x6,0x30,0x33,0x7,0x7,0x3,0x7,0x32,0x6,0x3,0x5,0x35,0x3,0x5,0x7,0x7,0x7,0x6,0x36,0x7,0x5,0x6,0x6,0x3,0x5,0x3,0x7,0x30,0x7]
input_array = []
generated_data = []
print("\t\tHello")
input_flag = input("chal flag de: ") #if using python2 replace input with raw_input
print("ye diya hai tune: \n",input_flag)
for char in input_flag:
input_array.append(char)
counter = 0
while counter < 0x1e:
character = ord(input_array[counter])
ret1 = character % 2 #here instead of using remainder_zero_or_not function i replaced it with
#this one line code that does the same thing
if ret1 == 0:
shifted_value = character >> 4
generated_data.append(shifted_value)
else:
shifted_value = character >> 1
generated_data.append(shifted_value)
counter = counter +1
if generated_data == DATA: #here we don't need to extract each character to compare
#python does it for us by replacing compare_function with this If condition
print('correct')
else:
print('wrong')
This is how i create password generator script in python.
we saw in Ghidra that DATA array is being compared with our generated_array and if our generated_array matches with DATA array only then we get success message.
so lets head to our generated_array and how it is being created, here is our python snippet for it
counter = 0
while counter < 0x1e:
character = ord(input_array[counter])
return_value = character % 2 #here instead of using remainder_zero_or_not function i replaced it
#with simple mod operation that does the same thing
if return_value == 0:
shifted_value = character >> 4
generated_data.append(shifted_value)
else:
shifted_value = character >> 1
generated_data.append(shifted_value)
counter = counter +1
so if even our character is being shifted right 4 times and if odd then it is being shifted right 1 time, let modify this code a bit
character = 0x30
while character <= 0x7e:
return_value = character % 2
if return_value == 0:
shifted_value = character >> 4
print(chr(character),"is even and giving = ",hex(shifted_value))
else:
shifted_value = character >> 1
print(chr(character),"is odd and giving = ",hex(shifted_value))
character = character +1
by running it i got this output
0 is even and giving = 0x3
1 is odd and giving = 0x18
2 is even and giving = 0x3
3 is odd and giving = 0x19
4 is even and giving = 0x3
5 is odd and giving = 0x1a
6 is even and giving = 0x3
7 is odd and giving = 0x1b
8 is even and giving = 0x3
9 is odd and giving = 0x1c
: is even and giving = 0x3
; is odd and giving = 0x1d
< is even and giving = 0x3
= is odd and giving = 0x1e
> is even and giving = 0x3
? is odd and giving = 0x1f
@ is even and giving = 0x4
A is odd and giving = 0x20
B is even and giving = 0x4
C is odd and giving = 0x21
D is even and giving = 0x4
E is odd and giving = 0x22
F is even and giving = 0x4
G is odd and giving = 0x23
H is even and giving = 0x4
I is odd and giving = 0x24
J is even and giving = 0x4
K is odd and giving = 0x25
L is even and giving = 0x4
M is odd and giving = 0x26
N is even and giving = 0x4
O is odd and giving = 0x27
P is even and giving = 0x5
Q is odd and giving = 0x28
R is even and giving = 0x5
S is odd and giving = 0x29
T is even and giving = 0x5
U is odd and giving = 0x2a
V is even and giving = 0x5
W is odd and giving = 0x2b
X is even and giving = 0x5
Y is odd and giving = 0x2c
Z is even and giving = 0x5
[ is odd and giving = 0x2d
\ is even and giving = 0x5
] is odd and giving = 0x2e
^ is even and giving = 0x5
_ is odd and giving = 0x2f
` is even and giving = 0x6
a is odd and giving = 0x30
b is even and giving = 0x6
c is odd and giving = 0x31
d is even and giving = 0x6
e is odd and giving = 0x32
f is even and giving = 0x6
g is odd and giving = 0x33
h is even and giving = 0x6
i is odd and giving = 0x34
j is even and giving = 0x6
k is odd and giving = 0x35
l is even and giving = 0x6
m is odd and giving = 0x36
n is even and giving = 0x6
o is odd and giving = 0x37
p is even and giving = 0x7
q is odd and giving = 0x38
r is even and giving = 0x7
s is odd and giving = 0x39
t is even and giving = 0x7
u is odd and giving = 0x3a
v is even and giving = 0x7
w is odd and giving = 0x3b
x is even and giving = 0x7
y is odd and giving = 0x3c
z is even and giving = 0x7
{ is odd and giving = 0x3d
| is even and giving = 0x7
} is odd and giving = 0x3e
~ is even and giving = 0x7
Here lets look at DATA array and how it is formed.
DATA = [0x6,0x6,0x30,0x33,0x7,0x7,0x3,0x7,0x32,0x6,0x3,0x5,0x35,0x3,0x5,0x7,0x7,0x7,0x6,0x36,0x7,0x5,0x6,0x6,0x3,0x5,0x3,0x7,0x30,0x7]
you see 0x6, 0x6 0x30 etc? lets use this as our base and extract the corresponding characters from the above output
position shifted_value = characters that gave this result
01 0x6 = ' b d f h j l n
02 0x6 = ' b d f h j l n
03 0x30 = a a is odd and giving = 0x30
04 0x33 = g g is odd and giving = 0x33 - etc
05 0x7 = p r t v x z | ~
06 0x7 = p r t v x z | ~
07 0x3 = 0 2 4 6 8 : < >
08 0x7 = p r t v x z | ~
09 0x32 = e
10 0x6 = ' b d f h j l n
11 0x3 = 0 2 4 6 8 : < >
12 0x5 = P R T V X Z \ ^
13 0x35 = k
14 0x3 = 0 2 4 6 8 : < >
15 0x5 = P R T V X Z \ ^
16 0x7 = p r t v x z | ~
17 0x7 = p r t v x z | ~
18 0x7 = p r t v x z | ~
19 0x6 = ' b d f h j l n
20 0x36 = m
21 0x7 = p r t v x z | ~
22 0x5 = P R T V X Z \ ^
23 0x6 = ' b d f h j l n
24 0x6 = ' b d f h j l n
25 0x3 = 0 2 4 6 8 : < >
26 0x5 = P R T V X Z \ ^
27 0x3 = 0 2 4 6 8 : < >
28 0x7 = p r t v x z | ~
29 0x30 = a
30 0x7 = p r t v x z | ~
now lets use this information to write our key-gen
I am only using alphanumeric characters for this keygen, as they do the job and are easy to deal with.
# This is python3 keygen for wh1t3r0se's flag_eater_crackme KeyGen
# Written by Mr. Manj
import random
flag = []
def hex_three():
set = ('0', '2', '4', '6', '8') #, ':', '<', '>'
randchar = random.choice(set)
flag.append(randchar)
def hex_five():
set = ('P', 'R', 'T', 'V', 'X', 'Z') #'\\', '^',
randchar = random.choice(set)
flag.append(randchar)
def hex_six():
set = ('b', 'd', 'f', 'h', 'j', 'l', 'n') #'`',
randchar = random.choice(set)
flag.append(randchar)
def hex_seven():
set = ('p', 'r', 't', 'v', 'x', 'z') # '|', '~'
randchar = random.choice(set)
flag.append(randchar)
hex_six()
hex_six()
flag.append('a')
flag.append('g')
hex_seven()
hex_seven()
hex_three()
hex_seven()
flag.append('e')
hex_six()
hex_three()
hex_five()
flag.append('k')
hex_three()
hex_five()
hex_seven()
hex_seven()
hex_seven()
hex_six()
flag.append('m')
hex_seven()
hex_five()
hex_six()
hex_six()
hex_three()
hex_five()
hex_three()
hex_seven()
flag.append('a')
hex_seven()
print(''.join(flag))
Here are some flags i generated using our Keygen
bfagzt2ref8Pk8XxvrbmxPjl4Z8zap
bdagzv6reb8Rk6RxzvfmtTjl8V0zat
blagtv6tef8Xk2XvpvbmxRnl6P2zax
Lets check these
3 out of 3! Nice.