grats to crp- for solving! greets to grainne for inspiring me to write this crackme.
well, in a nutshell, this crackme relies on some simple checks to trigger a cracked condition. i wrote it in c one very hot day while recovering from a sprained ankle. i’ll first explain some nonsense and after that, i’ll finally post the crackme listing for the benefit of everyone.
a) first it checks for a 5 byte file LiuYiFei_143 in the current directory
b) second, it does a simple checksum on argv[1].
here are a few assumptions/ideas that led me to design my crackme the way it’s designed now.
a) anti-ptrace protections are placed in an easily found area, that is, inside a function like main().
b) a lazy cracker can simply override weak functions like ptrace() and other library calls.
c) the strings utility can be used to print strings and i don’t want any cross references easily seen.
d) objdump and other “bfd” (binary file descriptor library) based tools rely on section headers.
e) luring them away from the real check as much as possbile sounds like a good plan.
f) i still don’t know enough to make a very hard crackme.
i tried approaching assumption a, “anti-ptrace in an easily found area” by using constructor attributes. gcc manual. what happens is that before control reaches the main() function, many other functions are called.. i won’t go into details about all those functions except the contructor functions. they are called just before main.
because of this merit, i thought it would be a good place to put protections. in comes your PTRACE_TRACEME trick. but, ptrace is a weak function. and any student of reverse engineering can simply go past this if he uses LD_PRELOAD. in comes the second protection. prevention of LD_PRELOAD overrides. this is for assumption b.
if there are constructor functions that resolve before main() there are also destructors that resolve after main(). i placed the check for the crack condition here. as they resolve automatically, i dont need to call them explicitly. so you wont find any actual link for the primary check condition and the the function to print the string cracked in the main() function.
now, for assumption c, the “strings” utility is a handy tool to print printable characters in files. it’s always used for preliminary forensics so i wanted to raise the bar a bit higher by preventing the “strings” utility from printing strings like the filename “LiuYiFei_143″, the string “Cracked!” and the string “LD_PRELOAD”. winding them with a simple xor operation did the trick. i had to therefore, unwind these strings before actually using them so i also included a string decryptor function. try running “strings” on the crackme to see for yourself.
assumption d is a bonus. i only corrupted the elf header sections, not the section themselves! i’ll remember to do that next time! also, i’ll really consider doing static linkage at the cost of binary size.
assumption e, is self explanatory.
idea f is impossible to achieve.
if you’ve reached this far! you must really be bored now! here’s the source code for my crackme as promised.
(more…)