The-FLARE-On-Challenge-2015/Challenge-3

From aldeid
Jump to navigation Jump to search
You are here
Challenge 3

File

Uncompress 3BD127AEDB12472EB288DAAFDEE76953.zip (password is "flare") and you will get a file named elfie with following properties:

MD5 8f0400fe6d897ddbcef2aaf9f9dbd0a4
SHA1 750e299842c89900fdb2532c0e7fd089bbf9e626
SHA256 6b82463eaa13aba88aab9050f08bcc7658067f4dc4d6ca04f49bbda2201cc70b
File type PE32 executable (console) Intel 80386, for MS Windows

The strings command reveals a lot of hints that we have to deal with python:

Error loading Python DLL: %s (error code %d)
Error detected starting Python VM.
PYTHONHOME
PYTHONPATH
Cannot GetProcAddress for Py_SetPythonHome
Py_SetPythonHome
bpython27.dll
bpyside-python2.7.dll
bshiboken-python2.7.dll
python27.dll

Also the icon shows the python logo (actually the pyinstaller icon):

Flare-on-challenge-2015-l3-python-icon.png

Moreover, the execution of the executable drops several python libraries (Qt, PySide, ...). A quick search on the Internet leads to pyinstaller, a utility that makes an executable from python code. Let's try to extract the content with pyinstxtractor.

Code extraction

C:\_malware>pyinstxtractor.py elfie.exe
Successfully extracted Pyinstaller archive : elfie.exe

Now use Easy Python Decompiler v1.1 to decompile the pyc files
Choose Uncompyle2 as the decompiler engine as the other engine
is unstable and can crash although it is very fast.

It results in many files, one of which seems to be interesting: elfie. Below is a extract of the content of this file:

O0OO0OO00000OOOO0OOOOO0O00O0O0O0 = 'IRGppV0FJM3BRRlNwWGhNNG'
OO0O0O00OO00OOOOOO0O0O0OOO0OOO0O = 'UczRkNZZ0JVRHJjbnRJUWlJV3FRTkpo'
OOO0000O0OO0OOOOO000O00O0OO0O00O = 'xTStNRDJqZG9nRCtSU1V'
OOO0000O0OO0OOOOO000O00O0OO0O00O += 'Rbk51WXI4dmRaOXlwV3NvME0ySGp'
OOO0OOOOOOOO0000O000O00O0OOOO00O = 'ZnJvbSBQeVNpZGUgaW1wb3J'
O0000OO00000000OO000O0OOO000OO00 = 'z'
O00O0O00OO0O0OO00O0OO0O00O0O00OO = 'OFJVT1d0TTJZTUppSWhVNWFQbDI3MkJVMlNLVWMvYVh'
O0O0OO0OO0O0OOO0O0OOO00O0OOOOO00 = 'aZzV1bFJPQnpIS1F5SWZuSDBMWUw0NGRGQ1lVeVF'
O000OOOOOOOOOO0O0OO0OO000OO000O0 = 'RC9XQXdIQ3FmcGxoK1owYlB4M2xQeGxoT2lvMllRaTI5dnJ5WDdx'
OO00OOO0O00OO0OO0OOOO000OO0000OO = 'hoOHBRUTFRWWttQklySmJDVWxaeTU4RWRQYXdFQktMUjl5VzJ6U'
O0O0OO000OOO00000OO0OOOO0OO00000 = 'tnbVJJbHBaZVh3SmlKZ1FYTER'
OO0O0OOOO0O000OOOO00O0O00O0O0O0O = 'ejc2YjFq'
OOOO000OOOOO00000O000OO0O00O0O0O = '9tUHJ1b0xMUFJObVpNWWxiWW91MGNvZWNwRjZhUFQ3RWVrZXo5MGRCdTFSb'
OOOO000O0OOOOO0O0O0000O0O0OO00O0 = '2cFVOa0lwMjlSSFV4TDFSSG4ySTBz'
OOOOO0OO0O00OOOOOO00O00000O0OO0O = 'WUExiQ2IyUXdDY1VmQ3luQU42cXVQQlplZ0N'
O0O0OOO000O000OO0O0O0OOOOO0OO000 = 'hTUhJWnNISVpNSExlMG5LWnM5VmVFaS94cWppbUIvVVJpL014aThJSnhR'
OOO00O0OOOOO00OO0OOOOO0O0O00O0O0 = 'MUFUL0ZEdnhYVVM4SzlvRlIyZXpDdVo3VGFTenprRWEzVGlFUWxD'
OO00OOO00OO0OOO000O000000O0O0000 = 'NHBBMUJBTVErRzF'
OO0O00OO0OO00O0O000O0000O0OOOOO0 = 'akZQNTFycjJiOUdhcnZVU09iMjJTeV'
OO00OOO00OO0OOO000O000000O0O0000 += 'FS3NEUUlURnFmSkVLaE'
O0OOO00OOOO0OO0OO0O000O0OO0OO000 = '2lUVGdwME83T1ZCbVBGa080aG14TElUZnhkcFA2OHg3UkhZall5M2xUa2xneitLc'
OO0OOOO0O00OOOO0OOOO0O0OOO0OO0O0 = 'I0dG'
O0OO00000OOOOO0OOO000O00000OOO00 = 'vRm4waFY0anNVaEY3ZEhub1U5MVhOSW'
O0000O0OOOO00OO0OOO00OO000O0000O = 'VlN21GamYvNGtLMnNkNTRSVDcrMHFtUyt'
OO0OOOO0O00OOOO0OOOO0O0OOO0OO0O0 += 'V5U01ZaDZ0YXFTWjhhNUhsQ09WdW1QYlJCc1hINzUwZkdLZi9aU2wrejI5WnJMO'
O00000O0OO00O0OO00000O000OOO00O0 = 'qKzVDeEtYbDY4V3pz'

# [REMOVED] #

import base64
exec(base64.b64decode(OOO0OOOOOOOO0000O000O00O0OOOO00O + O0O00OO0OO00OO00OO00O000OOO0O000 + O00OO0000OO0OO0OOO00O00000OO0OO0 + O00OO00000O0OOO0OO0O0O0OO0OOO0O0 + 

# [REMOVED] #

Decoding

It looks like obfuscated code. Let's try to decrypt the content of this file by replacing the exec instruction with print. We then rename this file obfuscated.py and we run the following command:

$ python obfuscated.py > decoded-01.py

It leads to another obfuscation layer:

from PySide import QtGui, QtCore
import base64
OOO00O00OO0OO000OOOO00000000OOO0 = ''.join((OOOO00OO0OOO000OOOO00O00O0OOOOOO for OOOO00OO0OOO000OOOO00O00O0OOOOOO in reversed('CCmQuSkTFlEAAAAA86w1BWpRYgSD/jo9
cbbt1bcxoWhYyzlGb2haSMI09gkb3ItDMuAq51wbk5qG/MlLxgLZtgA1xCHlQG/aspAjE6czvD51m4czG/lXTnATTHHiN6hpP10wcRyWB6VnigtS2ajee4TI90195FdaT1m3tVpTxtoUw4oKZmnrAtqiInKSq4+
dmZfQVmArBDUDwwzI6Wa0vaDI9uUmBZ1lXyorxjV1nQMwmij0g8zxqIQx+L/s8FI+aEPqsRmJEjuV6qkZKUsnbdQVQPmCkadL1Yk1PjnmeMhIM4LzxixKKcgmhEqjpZVkBgrrOLBa6J2kEBOsmqM+2mtjACBzuj
5hZg6vSsMj2JL3rhn5Plxx2rrNPNyxL774zn+8zfdcWHcfNadljqZ8dqayTT8QHj8xOBiJamIQyiJZhnTtmFSq7Vzu+5zAWX+ue3x1h/TcB/

# [REMOVED] #

vi/+W69a9/qr+gVWY6q/vaq+9r6fE9+ZOPJDIj2NT319on/zrNBMzOr237r79MQJ+ZcXCBIK5u7iHQIIIBHQIOloAVLu5u7u7eCwh2IBBCEQnEBibJnn/7vd7v+XTFe11LpehHVBRUSB+PAAA1lmz4MuAjL0ACd
l5mL05WahBHAlJXY3RnZvNFdYVEdYAAAAwvfdLdASsAAAIxCAAwcZhEcJAAAAUQY8vwjxCAAB1UQnRAAAAQ6c4srAI0RSNXAAAAAdHTDlCAAAIACiFAAAglAAAgUEhUSNAAAAogGK0wROBVi')))

class OO00O0O00OOO00OOOO0O00O0000OOOOO(getattr(QtGui, 'tidEtxeTQ'[::-1])):
    def __init__(self, OO0O0O0O0OO0OO00000OO00O0O0000O0, OO00O00O00OO00OO0OO0OO000O0O00OO, OO0OOO00O00O0OO00000OO0000OO0OOO):
        super(OO00O0O00OOO00OOOO0O00O0000OOOOO, self).__init__(OO0O0O0O0OO0OO00000OO00O0O0000O0)
        self.OO0O0O0O0OO0OO00000OO00O0O0000O0 = OO0O0O0O0OO0OO00000OO00O0O0000O0
        self.OO00O00O00OO00OO0OO0OO000O0O00OO = OO00O00O00OO00OO0OO0OO000O0O00OO
        self.OO0OOO00O00O0OO00000OO0000OO0OOO = OO0OOO00O00O0OO00000OO0000OO0OOO
        self.OOOOOOOOOO0O0OOOOO000OO000OO0O00 = False

    def O000OOOOOO0OOOO00000OO0O0O000OO0(self):
        O0O0O0000OOO000O00000OOO000OO000 = getattr(self, 'txeTnialPot'[::-1])()
        if (O0O0O0000OOO000O00000OOO000OO000 == ''.join((OO00O00OOOO00OO000O00OO0OOOO0000 for OO00O00OOOO00OO000O00OO0OOOO0000 in reversed('[email protected]')))):
                self.OO0O0O0O0OO0OO00000OO00O0O0000O0.setWindowTitle('!sseccus taerg'[::-1])
                self.OOOOOOOOOO0O0OOOOO000OO000OO0O00 = True
                self.OO0O0O0O0OO0OO00000OO00O0O0000O0.setVisible(False)
                self.OO0O0O0O0OO0OO00000OO00O0O0000O0.setVisible(True)

    def keyPressEvent(self, OO000O0O0OOOOOO0OO0OO00O0OOO00OO):
        if ((OO000O0O0OOOOOO0OO0OO00O0OOO00OO.key() == getattr(QtCore, 'tQ'[::-1]).Key_Enter) or (OO000O0O0OOOOOO0OO0OO00O0OOO00OO.key() == getattr(QtCore, 'tQ'[::-1]).Key_Return)):
            self.O000OOOOOO0OOOO00000OO0O0O000OO0()
        else:
            super(OO00O0O00OOO00OOOO0O00O0000OOOOO, self).keyPressEvent(OO000O0O0OOOOOO0OO0OO00O0OOO00OO)

    def paintEvent(self, OO000O0O0OOOOOO0OO0OO00O0OOO00OO):
        OOOOOOOOOO00O00O0OO0OO00OOO0OOO0 = getattr(self, 'tropweiv'[::-1])()
        O000OOO000O0OO00O00OO0O00O0

Solution

Without going much further in the analysis of this code, we can quickly identify:

  • that strings are reversed (string[::-1])
  • there is what seems to be an email address in reverse order: [email protected])

This email in reverse order is:

>>> '[email protected]'[::-1]
'[email protected]'

We can check it in the program:

Flare-on-challenge-2015-l3-solution.png

When you send an email to this address, you receive the following answer along with a 10.4KB file attached.

Very good. I am most pleased with your progress. Attached is the next challenge and the password to the zip archive is "flare" again.

Despite what they say about you, I think you're doing great.

Always be sure to run the challenge on the command line to confirm that it is actually doing what you think it's doing.

-FLARE

Comments

blog comments powered by Disqus

Keywords: reverse-engineering challenge flare fireeye