Reading Time : 9min

Linux Wh1t3r0ses Flag_eater_crackme Keygen Crackme Solution


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.


Key Hints in this Crackme :

  • function calls
  • conditional loops
  • bitwise shift operation
  • ASCII table

Lets try something new

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.

About this program

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.

Testing the program

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: "

Ghidra Decompiled C code

main function

here is decompiled(ghidra) code snippet for main() function

Ghidra Decompilation of main() function

here program is taking input and passing it as an argument in “main_code” function

main_code function

IDA Disassembly tree of 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.

remainder_zero_or_not function

IDA Disassembly of remainder_zero_or_not function

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.

compare_function

Global Variable “DATA” memory location in Ghidra

DATA memory location keep it in mind

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.

Python Script

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')

Python Keygen

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.

Keygen

# 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.