[Reverse] 3DS - W32.killah


W32.killah - 487 Points

Caution.. “The flag is over there..”

Password: “infected!”

WARNING! DON’T EXECUTE THIS SAMPLE IN YOUR OWN PERSONAL MACHINE!!!

Another malware problem, all malware problems were practically the same the writer of this challenge should have at least make it different from the others, as in Ransomware we have to decrypt more obfuscated strings but this time the encryption function is more difficult to understand, it does a summation before a xor, and uses 8 bit based operations (8 bit registers), we can see the beginning of start function we are actually decrypting a string:

As I explained previously in Ransomware ecx is storing the string length, al is the single byte used to encrypt the string and edx is where is stored the encrypted string.

Analysing the encryption function sub_4011A9, we can see it doesn’t only uses xor but it uses an addition operation before that:

We know that a character must be between 0 to 255, the additions will break this range, I’m not so sure about this but I think in assembly when there is an 8 bit operation if an overflow occurs, it returns back to 0 and that’s what I tried to write in python :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import struct

def xor_encrytion(al, ecx, edx):
c = ''
for i in range(ecx):
n = chr((((ord(edx[i]) + ord(al))%256) ^ ord(al)) %256)
s = chr(ord(edx[i]) ^ ord(al))
#print n,s
if s in string.printable:
c += s
else:
c += n
#print c
return c
buf = struct.pack ("17B", *[
0xC6,0xb4,0xc6,0xca,0xf2,0xe3,0xe9,0xf3,0xf9,0xfb,0xf6,
0xde,0xe8,0xf3,0xec,0xff,0xaa])

Well this actually worked for the first encrypted string:

1
2
$ python w32killah.py
3DS{m4lw@r3_1

And we got the first part of the flag… while searching in IDA I didn’t initially found the other encryption code until I started searching and found some code that wasn’t present in the function window:

Once again we need to decrypt that string but this time the function I wrote in python didn’t really work, outputed me a bunch of non printable characters, so I may misunderstood how actually 8 bit operations work in assembly, but I still managed to solve this by trying a bunch of other key bytes:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import struct
import string

def xor_encrytion(al, ecx, edx):
c = ''
for i in range(ecx):
n = chr((((ord(edx[i]) + ord(al))%256) ^ ord(al)) %256)
s = chr(ord(edx[i]) ^ ord(al))
#print n,s
if s in string.printable:
c += s
else:
c += n
#print c
return c

for i in range(1,0xff):
print xor_encrytion(al=chr(i),ecx=0x10-1,edx=struct.pack ("15B", *[
0xb3,0xdf,0xa6,0xb5,0xa3,0xcb,0xa9,0xae,0xc7,0xdf,0xa6,
0xb5,0xae,0xe1,0xbd])), i

A there we go the key to decrypt the flag with the function I wrote was 96 in hex is 0x60:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
$ python w32.killah.py | grep '}'
s_fucKinG_fun!} 96
w#jugOirK#jur!} 98
s'n}cKivO'n}v!E 100
}!nmUkvI!nv#G 101
#j}oWirK#j}r!E 102
}!j{mUwrI!j{r/C 103
M!~O}U{vY!~Ov#G 109
M!zK}UwrY!zKr?C 111
/C:)?W52[C:)2}! 156
s_fuc
inG_fun!} 192
{on}k[afGon}f)u 200
}ch{mWg` ch{`/s 206
`
ufpMz}I
uf}2n 211
g
rawK}zO
raz5i 212
ha}nx}ruya}nu:f 219
mcxk}wwp{cxkp?c 222

The flag was 3DS{m4lw@r3_1s_fucKinG_fun!}