Hi all,

So it's time to write a little about iscisc 2015 ransomware quests, due to lack of time i just write a brief writeup, so i can update it soon. this is a related link to the contest.

We are given an archive named final-stp.7z, decompressing it shows i should deal with 3 files. Ok. step3.pdf is the doc, but the main part is the other two files: FinalStep.exe and Result.txt. According to the doc Result.txt is the encrypted file. So the process is pretty obvious; Reversing FinalStep.exe.

At first attempt FinalStep.exe is a packed binary, so i need to unpack it. But remember to use some behaviour analysis principle before go to detail on malware and ransomware, so you can take some idea to continue.

I used SysInternal procmon and i can see the targeted file is Result.txt. but is it possible to continue without unpacking? of course use OllyDbg Phantom and other plugins and set a breakpoint on CreateFile API, on hitting this breakpoint we are in the middle of binary and if we were lucky enough we don't need any stepping back. I did this and after using multiple F9 it worked. I hit the bp with Filename Result.txt, now it's time to recognize the algorithms and reverse the binary.

I don't go to detail now, but this section will be updated soon.

You can see a standalone solution to this step bellow:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/python

# ISCISC & Padvish Ransomware Contest 2015 :: Step3 
# HAMIDx9 :: me@hamidx9.ir :: http://hamidx9.ir

from Crypto.Cipher import AES
from hexdump import hexdump
from base64 import b64decode
from Crypto.PublicKey import RSA

def swap(table, i, j):
    c = table[i]
    table[i] = table[j]
    table[j] = c

def create_xor_table():
    chall = [ord(c) ^ 0x44 for c in list("',%(%*#!")]
    table = []
    for i in range(0x100):
        table.append(i)
    bef_char = 0
    for counter in range(0x100):
        a = table[counter]
        b = bef_char + table[counter]
        j = counter % 7
        c = chall[j]
        cur_char = b + c
        cur_char &= 0xff
        if a == 0x4c:
            cur_char = counter
        swap(table, cur_char, counter)
        bef_char = cur_char 
    return table

def aes_decrypt(cipher):
    key = 'rj\|GVppohbV~F^\\'
    iv = "\0"*16
    aes = AES.new(key, AES.MODE_ECB, iv )
    return aes.decrypt(''.join(cipher))


def reset_permutation(encoded_b64):

    chal_table = create_xor_table()
    b64_list = [ord(c) for c in list(encoded_b64)]

    bef_char = 0

    xor_table = []

    for i in range(1, 0x8c0):
        bef_char += chal_table[i & 0xff]
        bef_char &= 0xff
        swap(chal_table, i & 0xff, bef_char)
        tc = chal_table[i & 0xff]
        b = chal_table[bef_char]
        s = (tc + b) & 0xff
        xor_table.append(chal_table[s])

    rv_b64 = ""
    for i in range(0x8c0 - 1):
        b64_list[i] ^= xor_table[i]
        rv_b64 += chr(b64_list[i])

    return rv_b64

def xor_c7_blocks(block_to_enc):

    enc = [ord(c) for c in block_to_enc[::-1]]
    bx = 0x30
    return_block = []

    for i in range(len(enc)):
        dx = bx
        dx &= 0x3
        ax = enc[i]
        ah = 0x1 << dx
        ax -= ah 
        ax -= 1
        ax &= 0xff
        ax ^= 0xc7
        bx += enc[i]
        return_block.append(chr(ax))

    return return_block

def write_to_list(l, data, start, size):

    for i in range(size):
        l[start+i] = data[i]


with open("./Result.txt", "rb") as enc_file:
    encrypted_file = enc_file.read()

#encrypted_file = list(encrypted_file)    

encrypted_privekey = list(encrypted_file[:0x8c0])
encrypted_result = encrypted_file[0x8c0:0x8c0+0x100]

# Step 1: XOR-C7...
block1_fix = xor_c7_blocks(encrypted_privekey[:0x32])
write_to_list(encrypted_privekey, block1_fix, 0, 0x32)

block2_fix = xor_c7_blocks(encrypted_privekey[0x64:0x64+0x32])
write_to_list(encrypted_privekey, block2_fix, 0x64, 0x32)

block3_fix = xor_c7_blocks(encrypted_privekey[0xc8:0xc8+0x32])
write_to_list(encrypted_privekey, block3_fix, 0xc8, 0x32)

# Step 2: decrypt all encrypted privatekey (aes)
aes_decrypted_privkey = aes_decrypt(encrypted_privekey)

# Step 3: reset permutation
b64_privkey = reset_permutation(aes_decrypted_privkey)

# Step 4: decode b64 and construct RSA for decryption
rsa_privkey = RSA.importKey(b64decode(b64_privkey[:b64_privkey.rfind("LS0t")+4]+"LQ=="))

print "The flag is:", rsa_privkey.decrypt(encrypted_result).split(",")[-1]

You should just run the code, (place the Result.txt beside of the script)

hamidx9@KernelsCallMe:~/iscisc2015/step3$ python step3-solve.py 
The flag is: Congratulations!
Call us at padvish-quest@amnpardaz.com

If there is any question, please let me know.

Regards,

Hamid Zamani

Comments