The-FLARE-On-Challenge-2015/Challenge-3
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):
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:
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
Keywords: reverse-engineering challenge flare fireeye