Tags: md5 kernel-module
Rating:
**Description**
> This your last chance. After this there is no turning back. You take the blue pill, the story ends. You wake up in your bed and believe whatever you want to. You take the red pill, you stay in Wonderland, and I show you how deep the rabbit hole goes. Remember, all I'm offering is the truth. Nothing more. This challenge was sponsored by ATEA! If you are a local student player you are eligible to turn in the flag at the ATEA booth for a prize!
**Files given**
- `bluepill.tar.gz` - archive containing
- `bluepill.ko`
- `init`
- `run.sh`
- `tiny.kernel`
**Solution**
A kernel object is given, which I am not very familiar with, however, `pill_choice` is the critical function, obviously.
The basic logic is to get input from function `strncpy_from_user`, and test the input.
```c
v5 = file_open("/proc/version");
if ( v5 )
{
v6 = v5;
file_read(v5, (unsigned __int8 *)magic, 0x1F4u);
v7 = v6;
v8 = &choice_35697;
filp_close(v7, 0LL);
if ( strlen((const char *)&choice_35697) > 0xB )
{
v9 = checks_35680;
while ( 1 )
{
v10 = 0LL;
memset(&v21, 0, 0x19uLL);
*(_QWORD *)digest = 0LL;
v19 = 0LL;
s2 = 0LL;
calc(v8, 4uLL, digest); //calculate md5 for 4 bytes
do
{
v11 = magic[v10];
v12 = digest[v10];
v13 = 2 * v10++;
sprintf((char *)&s2 + v13, "%02x", v11 ^ v12);
}
while ( v10 != 16 );
if ( memcmp(v9, &s2, 0x20uLL) )
break;
v8 += 4;
v9 += 33;
if ( v8 == &choice_35697 + 12 )
{
printk(&success);
//...
```
The length of string must be larger than 11, and then only 12 bytes are useful, which are grouped as 4 bytes and their md5 are calculated. To know `calc` is calculating md5, simply inspect the constants and global array data used and search them on google. However, in some other reverse challenges the hash algorithm may be modified, so this approach can't be 100% sure.
Then the md5 hashes will be `xor` with the content from `/proc/version`, then compare with the
```assembly
.data:0000000000000800 checks_35680 db '40369e8c78b46122a4e813228ae8ee6e',0
.data:0000000000000821 aE4a75afe114e44 db 'e4a75afe114e4483a46aaa20fe4e6ead',0
.data:0000000000000842 a8c3749214f4a91 db '8c3749214f4a9131ebc67e6c7a86d162',0
```
so to get md5 hashes, simply `xor` the hex above with content in `/proc/version`, as shown.
```python
import hashlib
from pwn import *
proc_version = "Linux version 4.17.0-rc4+ (likvidera@ubuntu) (gcc version 7.2.0 (Ubuntu 7.2.0-8ubuntu3.2)) #9 Sat May 12 12:57:01 PDT 2018"
# obtained from cat /proc/version within the kernel given
keys = ["40369e8c78b46122a4e813228ae8ee6e", "e4a75afe114e4483a46aaa20fe4e6ead", "8c3749214f4a9131ebc67e6c7a86d162"]
def get_hashes():
ret = []
for i in xrange(0,3):
one_hashes = ""
hex_data = keys[i].decode("hex")
for i in xrange(0,len(hex_data)):
one_hashes += chr(ord(proc_version[i]) ^ ord(hex_data[i]))
ret.append(one_hashes)
return ret
def md5(string):
m = hashlib.md5()
m.update(string)
return m.digest()
hashes = get_hashes()
for i in xrange(0, 3):
print "".join("{:02x}".format(ord(c)) for c in hashes[i])
#0c5ff0f900941747d69b7a4de4c8da40
#a8ce348b696e32e6d619c34f906e5a83
#c05e2754376ae75499b5170314a6e54c
#crack the md5 using this website https://cmd5.org/
#g1Mm3Th3r3D1
```
However, this is not the flag, obtain the flag by accessing the kernel object.
```bash
$ echo "g1Mm3Th3r3D1" > /proc/bluepill
$ cat flag
```