{"id":15584,"date":"2018-06-12T10:00:39","date_gmt":"2018-06-12T09:00:39","guid":{"rendered":"https:\/\/www.riskinsight-wavestone.com\/?p=15584"},"modified":"2021-06-02T17:26:42","modified_gmt":"2021-06-02T16:26:42","slug":"malwarebytes-challenge-write-up","status":"publish","type":"post","link":"https:\/\/www.riskinsight-wavestone.com\/en\/2018\/06\/malwarebytes-challenge-write-up\/","title":{"rendered":"Malwarebytes challenge write-up"},"content":{"rendered":"<div class=\"separator\" style=\"clear: both; text-align: center;\">\n<figure id=\"post-15585 media-15585\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-15585 aligncenter\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png\" alt=\"\" width=\"320\" height=\"150\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png 320w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1-71x33.png 71w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/figure>\n<\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: left;\"><span style=\"text-align: justify;\">Malwarebytes published on April 27th a new reverse engineering challenge, an executable mixing malware behavior with a traditional crackme look. It came in the form of a Windows executable<\/span><\/div>\n<p>This document describes the solving step of the challenge.<\/p>\n<h2><span style=\"text-align: center;\">Lightweight analysis of \u201cmb_crackme_2.exe\u201d<\/span><\/h2>\n<div style=\"text-align: justify;\">\n<p>As we would do with any real malware, we start by performing some basic information gathering on the provided executable. Even if the static and dynamic approaches gave us similar conclusions on the executable\u2019s nature (see 2.4), the different methods have been described nonetheless in the following sections.<\/p>\n<h3>Basic static information gathering<\/h3>\n<p>Using <b>Exeinfo PE<\/b>, a maintained successor of the renowned (but outdated) <b>PEiD<\/b> software, gives us some basic information about the binary:<\/p>\n<ul>\n<li>\u00a0The program is a <b>32 bits Portable Executable<\/b> (PE), meant to be run in console (no GUI);<\/li>\n<li>\u00a0It seems to be compiled from C++ using Microsoft Visual C++ 8;<\/li>\n<li>\u00a0No obvious sign of packing is detected by the tool.<\/li>\n<\/ul>\n<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">\n<div style=\"text-align: justify;\">\n<div style=\"text-align: center;\">\n<figure id=\"post-15587 media-15587\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15587 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I2.png\" alt=\"\" width=\"518\" height=\"255\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I2.png 518w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I2-388x191.png 388w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I2-71x35.png 71w\" sizes=\"auto, (max-width: 518px) 100vw, 518px\" \/><\/figure>\n<p><i><span style=\"font-size: x-small;\">Output of Exeinfo PE<\/span><\/i>\n<\/div>\n<p>Looking for printable strings in the binary already gives us some hints about the executable\u2019s nature:\n<\/p><\/div>\n<div style=\"background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><span style=\"font-family: inherit;\"><span style=\"font-size: small;\">$ strings -n 10 mb_crackme_2.exe_\r\n[...]\r\n<span style=\"color: red;\"><b>pyi<\/b><\/span>-windows-manifest-filename\r\n[...]\r\n<span style=\"color: red;\"><b>Py<\/b><\/span>_IgnoreEnvironmentFlag\r\nFailed to get address for <b><span style=\"color: red;\">Py<\/span><\/b>_IgnoreEnvironmentFlag\r\n<span style=\"color: red;\"><b>Py<\/b><\/span>_NoSiteFlag\r\nFailed to get address for <span style=\"color: red;\"><b>Py<\/b><\/span>_NoSiteFlag\r\nPy_NoUserSiteDirectory\r\n[...]\r\nm<span style=\"color: red;\"><b>pyi<\/b><\/span>mod01_os_path\r\nm<span style=\"color: red;\"><b>pyi<\/b><\/span>mod02_archive\r\nm<span style=\"color: red;\"><b>pyi<\/b><\/span>mod03_importers\r\ns<span style=\"color: red;\"><b>pyi<\/b><\/span>boot01_bootstrap\r\ns<span style=\"color: red;\"><b>pyi<\/b><\/span>_rth__tkinter\r\nbCrypto.Cipher._AES.<span style=\"color: red;\"><b>pyd<\/b><\/span>\r\nbCrypto.Hash._SHA256.<span style=\"color: red;\"><b>pyd<\/b><\/span>\r\nbCrypto.Random.OSRNG.winrandom.<span style=\"color: red;\"><b>pyd<\/b><\/span>\r\nbCrypto.Util._counter.<span style=\"color: red;\"><b>pyd<\/b><\/span>\r\nbMicrosoft.VC90.CRT.manifest\r\nbPIL._imaging.<span style=\"color: red;\"><b>pyd<\/b><\/span>\r\nbPIL._imagingtk.<span style=\"color: red;\"><b>pyd<\/b><\/span>\r\n[...]\r\no<span style=\"color: red;\"><b>pyi<\/b><\/span>-windows-manifest-filename another.exe.manifest\r\n[...]\r\nzout00-PYZ.<span style=\"color: red;\"><b>pyz<\/b><\/span>\r\n<span style=\"color: red;\"><b>python27.dll<\/b><\/span><\/span><\/span>\r\n<\/pre>\n<\/div>\n<p>Many references to <b>Python libraries<\/b>, <b>PYZ<\/b> archives and \u201c<b>pyi<\/b>\u201d substring indicates the use of the <b>PyInstaller<\/b> utility to build a PE executable from a Python script.<\/p>\n<h3>Basic dynamic information gathering<\/h3>\n<p>Running the executable (in a sandboxed environment) gives us the following message:<\/p>\n<figure id=\"post-15672 media-15672\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15672 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I3-1.png\" alt=\"\" width=\"454\" height=\"785\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I3-1.png 454w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I3-1-110x191.png 110w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I3-1-23x39.png 23w\" sizes=\"auto, (max-width: 454px) 100vw, 454px\" \/><\/figure>\n<figure id=\"post-15589 media-15589\" class=\"align-none\"><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<p>Using <b>Process Monitor<\/b>, from <a href=\"https:\/\/docs.microsoft.com\/en-us\/sysinternals\/\">SysInternals Tools Suit<\/a><a href=\"https:\/\/www.blogger.com\/null\">e<\/a> , allows us to quickly get a glimpse of the actions performed by the executable:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15591 size-full\" style=\"text-align: center;\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I4.png\" alt=\"\" width=\"640\" height=\"328\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I4.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I4-373x191.png 373w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I4-71x36.png 71w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/p>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<p>A temporary directory named \u201c<b>_MEI5282<\/b>\u201d is created under user\u2019s \u201c<b>%temp%<\/b>\u201d directory, and filled with <b>Python-related resources<\/b>. In particular, \u201c<b>python27.dll<\/b>\u201d and \u201c<b>*.pyd<\/b>\u201d libraries are written and later loaded by the executable.<\/p>\n<p>This behavior is typical of executables generated by PyInstaller.\n<\/p><\/div>\n<div style=\"text-align: justify;\">\n<div style=\"text-align: justify;\">\n<figure id=\"post-15593 media-15593\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15593 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I5.png\" alt=\"\" width=\"640\" height=\"312\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I5.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I5-392x191.png 392w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I5-71x35.png 71w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<\/div>\n<h3 style=\"text-align: justify;\">Error-handling analysis<\/h3>\n<div style=\"text-align: justify;\">Without tools, it is often possible to quickly get information about a binary\u2019s internals by <b>testing its error handling<\/b>. For example, inserting an <b>EOF<\/b> (End-Of-File) signal in the terminal (\u201cCtrl+Z + Return\u201d on Windows Command Prompt) makes the program crash, printing the following information:<\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\">\n<figure id=\"post-15595 media-15595\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15595 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I6.png\" alt=\"\" width=\"461\" height=\"262\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I6.png 461w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I6-336x191.png 336w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I6-69x39.png 69w\" sizes=\"auto, (max-width: 461px) 100vw, 461px\" \/><\/figure>\n<\/div>\n<div style=\"text-align: justify;\">\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Python stack trace printed after a crash<\/span><\/i><\/div>\n<p>This allows us to identify the presence of a Python program embedded inside the executable and gives us the name of the main script:<b> another.py.<\/b> The error message \u201c[$PID] Failed to execute script $scriptName\u201d is typical of <b>PyInstaller<\/b>-produced programs.\n<\/div>\n<h3 style=\"text-align: justify;\">Python files extraction and decompilation<\/h3>\n<div style=\"text-align: justify;\">Every lightweight analysis presented previously points out that the executable has been built using <b>PyInstaller<\/b>.<br \/>\nThe <a href=\"https:\/\/0xec.blogspot.fr\/2017\/11\/pyinstaller-extractor-updated-to-v19.html\"><b>PyInstaller Extractor<\/b><\/a>\u00a0 program can be used to extract python-compiled resources from the executable.<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>$ python pyinstxtractor.py mb_crackme_2.exe\r\n[*] Processing mb_crackme_2.exe\r\n[*] Pyinstaller version: 2.1+\r\n[*] Python version: 27\r\n[*] Length of package: 8531014 bytes\r\n[*] Found 931 files in CArchive\r\n[*] Beginning extraction...please standby\r\n[+] Possible entry point: pyiboot01_bootstrap\r\n[+] Possible entry point: pyi_rth__tkinter\r\n[+] Possible entry point: <b><span style=\"color: red;\">another<\/span><\/b>\r\n[*] Found 440 files in PYZ archive\r\n[*] Successfully extracted pyinstaller archive: mb_crackme_2.exe\r\n\r\nYou can now use a python decompiler on the pyc files within the extracted directory<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div style=\"text-align: justify;\">As previously seen, the most interesting file is \u201c<b>another<\/b>\u201d, as it should contain the \u201cmain\u201d function.<\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\">\n<figure id=\"post-15597 media-15597\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15597 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I7.png\" alt=\"\" width=\"400\" height=\"88\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I7.png 400w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I7-71x16.png 71w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/figure>\n<\/div>\n<div style=\"text-align: justify;\">\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Files extracted by PyInstaller Extractor<\/span><\/i><\/div>\n<p>&nbsp;\n<\/p><\/div>\n<div style=\"text-align: justify;\">A quick <a href=\"https:\/\/hshrzd.wordpress.com\/2018\/01\/26\/solving-a-pyinstaller-compiled-crackme\/\">Internet search<\/a>\u00a0 informs us that in a PYZ archive, the main file is in fact a *<b>.pyc file<\/b> (Python bytecode) from which the<b> first 8 bytes<\/b>, containing its signature, <b>have been removed<\/b>. Looking the hex dump of <b>another *.pyc <\/b>file of the archive confirms this statement and gives us the correct signature for Python 2.7 bytecode files (in purple).<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>$ hexdump -C another | head -n 3\r\n00000000  <span style=\"color: red;\"><b>63 00 00 00 00 00 00 00  00 03 00 00 00 40 00 00<\/b><\/span>  |c............@..|\r\n00000010  00 73 03 02 00 00 64 00  00 5a 00 00 64 01 00 5a  |.s....d..Z..d..Z|\r\n00000020  01 00 64 02 00 5a 02 00  64 03 00 64 04 00 6c 03  |..d..Z..d..d..l.|\r\n$ hexdump -C out00-PYZ.pyz_extracted\/cmd.pyc | head -n 3\r\n00000000  <b><span style=\"color: purple;\">03 f3 0d 0a 00 00 00 00<\/span><\/b>  <span style=\"color: red;\"><b>63 00 00 00 00 00 00 00<\/b><\/span>  |.\u00f3......c.......|\r\n00000010  <span style=\"color: red;\"><b>00 03 00 00 00 40 00 00<\/b><\/span>  00 73 4c 00 00 00 64 00  |.....@...sL...d.|\r\n00000020  00 5a 00 00 64 01 00 64  02 00 6c 01 00 5a 01 00  |.Z..d..d..l..Z..|<\/pre>\n<\/div>\n<p>Restoring the file\u2019s signature produces a correct Python bytecode file.<\/p>\n<div style=\"background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>$ cat &lt;(printf \"\\x03\\xf3\\x0d\\x0a\\x00\\x00\\x00\\x00\") another &gt; another.pyc\r\n$ file another.pyc\r\nanother.pyc: python 2.7 byte-compiled<\/pre>\n<\/div>\n<\/div>\n<div style=\"text-align: justify;\">\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"text-align: justify;\">Using the <a href=\"https:\/\/github.com\/rocky\/python-uncompyle6\">uncompyle6<\/a>\u00a0 decompilation tool, we can easily recover the original source code of <b>another.py<\/b>.<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>$ uncompyle6 another.pyc &gt; another.py<\/pre>\n<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<h1 style=\"text-align: justify;\">Stage 1: login<\/h1>\n<div style=\"text-align: justify;\">Looking at the <b>main()<\/b> function of <b>another.py<\/b>, we see that the first operations are performed by the <b>stage1_login()<\/b> function.<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><span style=\"color: blue;\">def<\/span> <span style=\"color: magenta;\">main<\/span>():\r\n    key = <span style=\"color: red;\">stage1_login<\/span>()\r\n    <span style=\"color: blue;\">if not<\/span> check_if_next(key):\r\n        <span style=\"color: blue;\">return<\/span>\r\n    <span style=\"color: blue;\">else<\/span>:\r\n        content = decode_and_fetch_url(key)\r\n        <span style=\"color: blue;\">if <\/span>content <span style=\"color: blue;\">is None<\/span>:\r\n            <span style=\"color: blue;\">print <\/span><span style=\"color: #666666;\">'Could not fetch the content'<\/span>\r\n            <span style=\"color: blue;\">return <\/span>-<span style=\"color: red;\">1<\/span>\r\n        decdata = get_encoded_data(content)\r\n        <span style=\"color: blue;\">if not <\/span>is_valid_payl(decdata):\r\n            <span style=\"color: blue;\">return <\/span>-<span style=\"color: red;\">3<\/span>\r\n        <span style=\"color: blue;\">print <\/span>colorama.Style.BRIGHT + colorama.Fore.CYAN\r\n        <span style=\"color: blue;\">print <\/span><span style=\"color: #666666;\">'Level #2: Find the secret console...'<\/span>\r\n        <span style=\"color: blue;\">print <\/span>colorama.Style.RESET_ALL\r\n        <span style=\"color: #6aa84f;\">#load_level2(decdata, len(decdata))<\/span>\r\n        dump_shellcode(decdata, len(decdata))\r\n        user32_dll.MessageBoxA(<span style=\"color: blue;\">None<\/span>, <span style=\"color: #666666;\">'You did it, level up!'<\/span>, 'Congrats!', <span style=\"color: red;\">0<\/span>)\r\n        <span style=\"color: blue;\">try<\/span>:\r\n            <span style=\"color: blue;\">if <\/span>decode_pasted() == <span style=\"color: blue;\">True<\/span>:\r\n                user32_dll.MessageBoxA(<span style=\"color: blue;\">None<\/span>, <span style=\"color: #666666;\">'''Congratulations! Now save your flag\r\nand send it to Malwarebytes!'''<\/span>, <span style=\"color: #666666;\">'You solved it!'<\/span>, <span style=\"color: red;\">0<\/span>)\r\n                <span style=\"color: blue;\">return <\/span><span style=\"color: red;\">0<\/span>\r\n            user32_dll.MessageBoxA(<span style=\"color: blue;\">None<\/span>, <span style=\"color: #666666;\">'See you later!'<\/span>, <span style=\"color: #666666;\">'Game over'<\/span>, <span style=\"color: red;\">0<\/span>)\r\n        <span style=\"color: blue;\">except<\/span>:\r\n            <span style=\"color: blue;\">print <\/span>'Error decoding the flag'\r\n        <span style=\"color: blue;\">return<\/span><\/pre>\n<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre><span style=\"color: blue;\">def <\/span><span style=\"color: magenta;\">stage1_login<\/span>():\r\n    show_banner()\r\n    <span style=\"color: blue;\">print <\/span>colorama.Style.BRIGHT + colorama.Fore.CYAN\r\n    <span style=\"color: blue;\">print <\/span><span style=\"color: #666666;\">'Level #1: log in to the system!'<\/span>\r\n    <span style=\"color: blue;\">print <\/span>colorama.Style.RESET_ALL\r\n    login = raw_input('login: ')\r\n    password = getpass.getpass()\r\n    <span style=\"color: blue;\">if not <\/span>(<span style=\"color: red;\">check_login<\/span>(login) <span style=\"color: blue;\">and <\/span><span style=\"color: red;\">check_password<\/span>(password)):\r\n        <span style=\"color: blue;\">print <\/span><span style=\"color: #666666;\">'Login failed. Wrong combination username\/password'<\/span>\r\n        <span style=\"color: blue;\">return <\/span>None\r\n    <span style=\"color: blue;\">else<\/span>:\r\n        PIN = raw_input('PIN: ')\r\n        <span style=\"color: blue;\">try<\/span>:\r\n            key = <span style=\"color: red;\">get_url_key<\/span>(int(PIN))\r\n        <span style=\"color: blue;\">except<\/span>:\r\n            <span style=\"color: blue;\">print <\/span><span style=\"color: #666666;\">'Login failed. The PIN is incorrect'<\/span>\r\n            <span style=\"color: blue;\">return None<\/span>\r\n        <span style=\"color: blue;\">if not <\/span><span style=\"color: red;\">check_key<\/span>(key):\r\n            <span style=\"color: blue;\">print <\/span><span style=\"color: #666666;\">'Login failed. The PIN is incorrect'<\/span>\r\n            <span style=\"color: blue;\">return None<\/span>\r\n        <span style=\"color: blue;\">return <\/span>key<\/pre>\n<\/div>\n<p>Three user inputs are successively checked: the user\u2019s <b>login<\/b>, <b>password <\/b>and <b>PIN <\/b>code.<\/p>\n<h3>Finding the login<\/h3>\n<div style=\"text-align: justify;\">The check_login() function&#8217;s code is completely transparent :<\/div>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><span style=\"color: blue;\">def <\/span><span style=\"color: magenta;\">check_login<\/span>(login):\r\n    <span style=\"color: blue;\">if <\/span>login == <span style=\"color: red;\">'hackerman'<\/span>:\r\n        <span style=\"color: blue;\">return True<\/span>\r\n    <span style=\"color: blue;\">return False<\/span><\/pre>\n<\/div>\n<p>We have found the login, let&#8217;s search for the password.<\/p>\n<figure id=\"post-15599 media-15599\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-15599 aligncenter\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I8.jpg\" alt=\"\" width=\"320\" height=\"180\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I8.jpg 320w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I8-69x39.jpg 69w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Expected login<\/span><\/i><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: left;\"><\/div>\n<\/div>\n<h3>Finding the password<\/h3>\n<p>The <b>check_password<\/b>() function hashes user\u2019s input using the <b>MD5 <\/b>hash function, and compares the result with an hardcoded string:<\/p>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><span style=\"color: blue;\">def <\/span><span style=\"color: magenta;\">check_password<\/span>(password):\r\n    my_md5 = hashlib.md5(password).hexdigest()\r\n    <span style=\"color: blue;\">if <\/span>my_md5 == '42f749ade7f9e195bf475f37a44cafcb':\r\n        <span style=\"color: blue;\">return True<\/span>\r\n    <span style=\"color: blue;\">return False<\/span><\/pre>\n<\/div>\n<p>A quick Internet search of this string gives us the corresponding cleartext password: <b>Password123<\/b>.<\/p>\n<figure id=\"post-15601 media-15601\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15601 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I9.png\" alt=\"\" width=\"640\" height=\"240\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I9.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I9-437x164.png 437w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I9-71x27.png 71w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Finding the password on a search engine<\/span><\/i><\/div>\n<h3>Finding the PIN code<\/h3>\n<p>The PIN code is read from standard input, converted into an<b> integer<\/b> (cf. stage1_login()<b> <\/b>function), and passed to the <b>get_url_key() <\/b>function:<\/p>\n<div style=\"text-align: justify;\"><\/div>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre><span style=\"color: blue;\">def<\/span> <span style=\"color: magenta;\">get_url_key<\/span>(my_seed):\r\n\u00a0\u00a0\u00a0 random.seed(my_seed)\r\n\u00a0\u00a0\u00a0 key = \u2018\u2019\r\n\u00a0\u00a0\u00a0 <span style=\"color: blue;\">for <\/span>I <span style=\"color: blue;\">in <\/span>xrange(0, 32):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 id = random.randint(0, 9)\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 key += str(id)\r\n\u00a0\u00a0\u00a0 <span style=\"color: blue;\">return <\/span>key<\/pre>\n<\/div>\n<p>This function derives a<b> pseudo-random 32 digits<\/b> key from the PIN code, using it as a <b>seed <\/b>for Python\u2019s PRNG. The generated key is then verified using the <b>check_key()<\/b> function, where its MD5 sum is checked against another hardcoded value.<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre><span style=\"color: blue;\">def <\/span><span style=\"color: magenta;\">check_key<\/span>(key):\r\n\u00a0\u00a0\u00a0 my_md5 = hashlib.md5(key).hexdigest()\r\n\u00a0\u00a0\u00a0 <span style=\"color: blue;\">if <\/span>my_md5 == '<span style=\"color: red;\">fb4b322c518e9f6a52af906e32aee955<\/span>':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <span style=\"color: blue;\">return <\/span>True\r\n\u00a0\u00a0\u00a0 <span style=\"color: blue;\">return <\/span>False<\/pre>\n<\/div>\n<p>The key space is obviously <b>too large to be brute-forced<\/b>, as a 32-digits string corresponds to 10^32 (~2^106) possible combinations. However, <b>we can brute-force the PIN<\/b> code, being an integer, using the following code:<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre><span style=\"color: blue;\">from <\/span>another <span style=\"color: blue;\">import <\/span>get_url_key, check_key\r\nPIN = 0\r\n<span style=\"color: blue;\">while True<\/span>:\r\n\u00a0\u00a0\u00a0 key = get_url_key(PIN)\r\n\u00a0\u00a0\u00a0 <span style=\"color: blue;\">if <\/span>check_key(key):\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <span style=\"color: blue;\">print <\/span>PIN\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 <span style=\"color: blue;\">break<\/span>\r\n\u00a0\u00a0\u00a0 PIN += 1<\/pre>\n<\/div>\n<p>The solution is obtained in a few milliseconds:<\/p>\n<div style=\"background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>$ python bruteforcePIN.py\r\n9667<\/pre>\n<\/div>\n<h3>Testing credentials<\/h3>\n<p>Using the credentials found in the previous step completes the first stage of the challenge.<\/p>\n<figure id=\"post-15603 media-15603\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15603 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I10.png\" alt=\"\" width=\"400\" height=\"148\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I10.png 400w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I10-71x26.png 71w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Validating stage 1<\/span><\/i><\/div>\n<p>Clicking \u201cYes\u201d makes the executable pause after printing the following message in the console:<\/p>\n<div class=\"separator\" style=\"clear: both; text-align: center;\">\n<figure id=\"post-15605 media-15605\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15605 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I11.png\" alt=\"\" width=\"320\" height=\"96\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I11.png 320w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I11-71x21.png 71w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/figure>\n<\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Waiting for us to find a &#8220;secret console&#8221;<\/span><\/i><\/div>\n<p>Let\u2019s find that secret console!<\/p>\n<h1>Stage 2: the secret console<\/h1>\n<h3>Payload download and decoding<\/h3>\n<p>Continuing our analysis of the main() function, the next function to be called after credentials verification is <b>decode_and_fetch_url()<\/b>, with the previously calculated 32-digits key given as argument:<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre><span style=\"color: blue;\">def <\/span><span style=\"color: magenta;\">decode_and_fetch_url<\/span>(key):\r\n    <span style=\"color: blue;\">try<\/span>:\r\n        encrypted_url = <span style=\"color: #444444;\">'\\xa6\\xfa\\x8fO\\xba\\x7f\\x9d\\[...]\\xfe'<\/span>\r\n        aes = AESCipher(bytearray(key))\r\n        output = aes.decrypt(encrypted_url)\r\n        full_url = output\r\n        content = fetch_url(full_url)\r\n    <span style=\"color: blue;\">except<\/span>:\r\n        <span style=\"color: blue;\">return None<\/span>\r\n    <span style=\"color: blue;\">return <\/span>content<\/pre>\n<\/div>\n<p>A URL is decrypted using an <b>AES <\/b>cipher and the 32-digits key. The resource at this URL is then downloaded and its content returned by the function.<br \/>\nTo get the decrypted URL, we simply add some <b>logging<\/b> instructions to the original code of another.py, which can be run independently of mb_crackme_2.exe (given that the required dependencies are present on our machine).<\/p>\n<div style=\"background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>[...]\r\n        full_url = output\r\n        print \"DEBUG : URL fetched is : %s \" % full_url #added from original code\r\n        content = fetch_url(full_url)\r\n[...]<\/pre>\n<\/div>\n<p>The result execution is the following:<\/p>\n<div style=\"background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre>login: hackerman\r\nPassword:\r\nPIN: 9667\r\n<span style=\"color: red;\">DEBUG : URL fetched is : https:\/\/i.imgur.com\/dTHXed7.png<\/span><\/pre>\n<\/div>\n<p>The decrypted URL hosts the PNG image displayed bellow:<\/p>\n<figure id=\"post-15607 media-15607\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15607 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12.png\" alt=\"\" width=\"267\" height=\"267\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12.png 267w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-191x191.png 191w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-39x39.png 39w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-32x32.png 32w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-64x64.png 64w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-96x96.png 96w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-128x128.png 128w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-70x70.png 70w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-175x175.png 175w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-130x130.png 130w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-115x115.png 115w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I12-30x30.png 30w\" sizes=\"auto, (max-width: 267px) 100vw, 267px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Image downloaded by the executable<\/span><\/i><\/div>\n<p>The \u201cmalware\u201d then reads the <b>Red, Green and Blue components of each of the image\u2019s pixels<\/b>, interprets them as <b>bytes <\/b>and constructs a buffer from their concatenation.<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><span style=\"color: blue;\">def <\/span><span style=\"color: magenta;\">get_encoded_data<\/span>(bytes):\r\n    imo = Image.open(io.BytesIO(bytes))\r\n    rawdata = list(imo.getdata())\r\n    tsdata <span style=\"color: blue;\">= <\/span>''\r\n    <span style=\"color: blue;\">for <\/span>x <span style=\"color: blue;\">in <\/span>rawdata:\r\n        <span style=\"color: blue;\">for <\/span>z <span style=\"color: blue;\">in <\/span>x:\r\n            tsdata += chr(z)\r\n    <span style=\"color: blue;\">del <\/span>rawdata\r\n    <span style=\"color: blue;\">return <\/span>tsdata<\/pre>\n<pre><\/pre>\n<\/div>\n<p>This technique is sometimes used by real malware to download malicious code <b>without raising suspicion of traffic-analysis tools<\/b>, hiding the real nature of the downloaded resource.<br \/>\nUsing the \u201cExtract data\u2026\u201d function of the <b>Stegsolve<\/b> tool\u00a0 allows to quickly preview the data encoded in the image, which appears to be a PE file (and more specifically, a DLL):<\/p>\n<figure id=\"post-15609 media-15609\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15609 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I13.png\" alt=\"\" width=\"640\" height=\"494\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I13.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I13-247x191.png 247w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I13-51x39.png 51w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I13-156x121.png 156w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I13-155x120.png 155w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Output of the stegsolve tool<\/span><\/i><\/div>\n<p>The function <b>is_valid_payl()<\/b> is then used to check whether the decoded payload is correct:<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre><span style=\"color: blue;\">def <\/span><span style=\"color: magenta;\">is_valid_payl<\/span>(content):\r\n    <span style=\"color: blue;\">if <\/span>get_word(content) != <span style=\"color: red;\">23117<\/span>:\r\n        <span style=\"color: blue;\">return False<\/span>\r\n    next_offset = get_dword(content[<span style=\"color: red;\">60<\/span>:])\r\n    next_hdr = content[next_offset:]\r\n    <span style=\"color: blue;\">if <\/span>get_dword(next_hdr) != <span style=\"color: red;\">17744<\/span>:\r\n        <span style=\"color: blue;\">return False<\/span>\r\n    <span style=\"color: blue;\">return True<\/span><\/pre>\n<\/div>\n<p>The<b> 23117 and 17744<\/b> constants represent the \u201cMZ\u201d and \u201cPE\u201d magic bytes present in the headers of a PE.<\/p>\n<div style=\"background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre>&gt;&gt;&gt; import struct\r\n&gt;&gt;&gt; struct.pack(\"&lt;H\", 23117)\r\n'MZ'\r\n&gt;&gt;&gt; struct.pack(\"&lt;H\", 17744)\r\n'PE'<\/pre>\n<\/div>\n<p>The decoded file is then passed to the<b> load_level2()<\/b> function, which is a wrapper around <b>prepare_stage()<\/b>.<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><span style=\"color: blue;\">def <\/span><span style=\"color: magenta;\">load_level2<\/span>(rawbytes, bytesread):\r\n    <span style=\"color: blue;\">try<\/span>:\r\n        <span style=\"color: blue;\">if <\/span>prepare_stage(rawbytes, bytesread):\r\n            <span style=\"color: blue;\">return True<\/span>\r\n    <span style=\"color: blue;\">except<\/span>:\r\n        <span style=\"color: blue;\">return False<\/span><\/pre>\n<\/div>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre><span style=\"color: blue;\">def <\/span><span style=\"color: magenta;\">prepare_stage<\/span>(content, content_size):\r\n    virtual_buf = kernel_dll.VirtualAlloc(0, content_size, 12288, 64)\r\n    <span style=\"color: blue;\">if <\/span>virtual_buf == 0:\r\n        <span style=\"color: blue;\">return False<\/span>\r\n    <span style=\"color: blue;\">res <\/span>= memmove(virtual_buf, content, content_size)\r\n    <span style=\"color: blue;\">if <\/span>res == 0:\r\n        <span style=\"color: blue;\">return False<\/span>\r\n    MR = WINFUNCTYPE(c_uint)(virtual_buf + 2)\r\n    MR()\r\n    <span style=\"color: blue;\">return True<\/span><\/pre>\n<\/div>\n<p>This function starts by allocating enough space to store the downloaded code, using the VirtualAlloc API function call. The allocated space is <b>readable, writable and executable<\/b>, as the provided arguments reveal (12288 being equal to \u201cMEM_COMMIT | MEM_RESERVE\u201d, and 64 to PAGE_EXECUTE_READWRITE).<br \/>\nThe downloaded code is then written in the allocated space using the memmove function, and executed like a shellcode from offset 2.<\/p>\n<p>To get a clean dump of the downloaded code (once decrypted), we <b>add a piece of code in the prepare_stage()<\/b> function, as follows:<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><span style=\"color: blue;\">def <\/span><span style=\"color: magenta;\">prepare_stage<\/span>(content, content_size):\r\n    <span style=\"color: blue;\">with <\/span>open(\"dumped_pe.dll\", \"wb\") as f:\r\n        f.write(content[:content_size])\r\n        print \"DEBUG : File dumped in dumped_pe.dll\"\r\n    virtual_buf = kernel_dll.VirtualAlloc(0, content_size, 12288, 64)\r\n    <span style=\"color: blue;\">if <\/span>virtual_buf == 0:\r\n        return False\r\n    res = memmove(virtual_buf, content, content_size)\r\n    <span style=\"color: blue;\">if <\/span>res == 0:\r\n        <span style=\"color: blue;\">return <\/span>False\r\n    MR = WINFUNCTYPE(c_uint)(virtual_buf + 2)\r\n    MR()\r\n    <span style=\"color: blue;\">return True<\/span><\/pre>\n<\/div>\n<p>After re-executing the program, we observe that the obtained file is indeed a valid 32 bits Windows DLL:<\/p>\n<div style=\"background-color: black; border: 1px solid white; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>$ file dumped_pe.dll\r\ndumped_file.ext: PE32 executable (DLL) (console) Intel 80386, for MS Windows<\/pre>\n<\/div>\n<p>Time for us to open our favorite disassembler !<\/p>\n<h2>Downloaded DLL\u2019s reverse-engineering<\/h2>\n<p><b>Reflective loading<\/b><br \/>\nFrom the offset 2 of the file, a little shellcode located in the DOS headers<b> transfers the execution<\/b> to another code that implements <b>Reflective DLL injection<\/b>. This technique is used to load the library itself from memory, instead of normally loading the DLL from disk using the LoadLibrary API call.<br \/>\n&nbsp;<\/p>\n<figure id=\"post-15611 media-15611\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15611 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I14.png\" alt=\"\" width=\"640\" height=\"118\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I14.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I14-437x81.png 437w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I14-71x13.png 71w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Disassembly of the first bytes of the downloaded DLL<\/span><\/i><\/div>\n<p>The reflective loader\u2019s code, located at 0x6E0, is documented in Stephen Fewer\u2019s GitHub\u00a0 and will not be described in this write-up. Since, in the end, the library is loaded by this mechanism as it would be after a normal LoadLibrary call, this downloaded file will be analyzed like a standard DLL in the rest of this write-up.<\/p>\n<p>The list of exported functions being empty (except for the DllEntryPoint function), we start our analysis at the <b>entry point of the DLL<\/b>.<\/p>\n<figure id=\"post-15613 media-15613\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15613 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I15.png\" alt=\"\" width=\"400\" height=\"43\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I15.png 400w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I15-71x8.png 71w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Exports list<\/i><\/span><\/div>\n<p><b>Entry point<\/b><br \/>\nOur first goal is to search for the <b>DllMain()<\/b> function from the entry point. If the reverser is not used to analyzing Windows DLLs, a simple way to start would be to open any random non-stripped 32bit DLL, which (with a little luck) would be compiled with the same compiler (Visual C++ ~7.10 here), and which would have a similar CFG structure for the DllEntryPoint function.<br \/>\nAn example of CFG comparisons between the analyzed DLL (left) and another non-stripped 32bit DLL (right) is presented below:<br \/>\n&nbsp;<\/p>\n<figure id=\"post-15615 media-15615\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15615 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I16.png\" alt=\"\" width=\"640\" height=\"298\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I16.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I16-410x191.png 410w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I16-71x33.png 71w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><i><\/i><\/figure>\n<div style=\"text-align: center;\"><i><span style=\"font-size: x-small;\">DLLEntryPoints in our DLL v\/s another non-stripped DLL<\/span><\/i><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<figure id=\"post-15617 media-15617\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15617 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I17.png\" alt=\"\" width=\"640\" height=\"451\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I17.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I17-271x191.png 271w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I17-55x39.png 55w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<div style=\"text-align: center;\"><i><span style=\"font-size: x-small;\">DllMainCTRStartup in our DLL \/ in another non-stripped DLL<\/span><\/i><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<p>This technique allows us to quickly find the DllMain function in our DLL, here being located at 0x10001170.<br \/>\n<b>DllMain (0x10001170)<\/b><br \/>\nThe function starts by checking if it has been called during the first load of the DLL by a process, by comparing the value of the fdwReason argument\u00a0 against the DLL_PROCESS_ATTACH constant.<br \/>\nThe DllMain() function then <b>registers two exception handlers<\/b> using the AddVectoredExceptionHandler\u00a0 API call. The handlers are named <b>\u201cHandler_0\u201d and \u201cHandler_1\u201d<\/b> in the screenshot below:<\/p>\n<figure id=\"post-15619 media-15619\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15619 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I18.png\" alt=\"\" width=\"640\" height=\"453\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I18.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I18-270x191.png 270w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I18-55x39.png 55w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I18-345x245.png 345w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>DllMain function<\/i><\/span><\/div>\n<p>An exception is then manually raised using the \u201cint 3\u201d interruption instruction, triggering the execution of Handler_0.<br \/>\n<b>Interlude: debugging a DLL in IDA Pro<\/b><br \/>\nTo make the reverse-engineering of some functions easier, debugging the code to observe function inputs and outputs can be an effective method.<br \/>\nOne simple way to <b>debug a DLL inside IDA <\/b>is to load the file as usual, then go to \u201cDebugger -&gt;Process options&#8230;\u201d and modify the following value:<\/p>\n<ul>\n<li>Application:\n<ul>\n<li>\u00a0On a 64 bits version of Windows:\n<ul>\n<li>\u00a0 \u201cC:\\Windows\\SysWOW64\\rundll32.exe\u201d to debug a 32 bits library<\/li>\n<li>\u00a0 \u201cC:\\Windows\\System32\\rundll32.exe\u201d to debug a 64 bits library<\/li>\n<\/ul>\n<\/li>\n<li>\u00a0On a 32 bits version of Windows:\n<ul>\n<li>\u00a0 \u201cC:\\Windows\\System32\\rundll32.exe\u201d to debug a 32 bits library<\/li>\n<li>\u00a0 Obviously, you cannot run (therefore debug) a 64 bits library on a 32 bits version of Windows<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<li>\u00a0Parameters:\n<ul>\n<li>\u00a0 \u201cPATH_OF_YOUR_DLL\u201d,functionToCall [function parameters if any]<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Note: The file extension <b>must be \u201c*.dll\u201d <\/b>for rundll32.exe to accept it.<\/p>\n<figure id=\"post-15621 media-15621\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15621 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I19.png\" alt=\"\" width=\"320\" height=\"179\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I19.png 320w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I19-71x39.png 71w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>IDA &#8220;Process options&#8230;&#8221; menu<\/i><\/span><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<p>To test the configuration, just place a <b>breakpoint <\/b>at the entry point of the DLL:<\/p>\n<figure id=\"post-15623 media-15623\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15623 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I20.png\" alt=\"\" width=\"640\" height=\"353\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I20.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I20-346x191.png 346w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I20-71x39.png 71w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Placing a breakpoint on the entry point<\/i><\/span><\/div>\n<p>Run your debugger (F9). If configured correctly, your debugger should break at the DLL entry point, allowing you to debug any DLL function<\/p>\n<p><b>Handler_0 (0x10001260)<\/b><br \/>\nLooking at Handler_0\u2019s CFG (given below), we see that the function calls <b>two unknown functions <\/b>(0x100092C0 and 0x1000E61D). To quickly identify these functions, let\u2019s debug the DLL, and look at the functions inputs\/outputs:<\/p>\n<p><u>sub_100092C0<\/u><\/p>\n<figure id=\"post-15625 media-15625\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15625 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I21.png\" alt=\"\" width=\"178\" height=\"91\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I21.png 178w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I21-71x36.png 71w\" sizes=\"auto, (max-width: 178px) 100vw, 178px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Function sub_100092C0() call<\/span><\/i><\/div>\n<p>The function seems to take 3 arguments:<\/p>\n<ul>\n<li>A buffer (here named \u201cValue\u201d);<\/li>\n<li>A value (here 0);<\/li>\n<li>The size of the buffer (here 0x104).<\/li>\n<\/ul>\n<p>Let&#8217;s look at the buffer\u2019s content <b>before and after the function call<\/b>:<\/p>\n<figure id=\"post-15627 media-15627\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15627 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I22.png\" alt=\"\" width=\"320\" height=\"134\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I22.png 320w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I22-71x30.png 71w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>&#8220;Value&#8221; buffer before and after the call<\/i><\/span><\/div>\n<p>The function prototype and its side effects correspond to the <b>memset <\/b>function.<u><br \/>\n<\/u><br \/>\n<u>sub_1000E61D<\/u><\/p>\n<figure id=\"post-15629 media-15629\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15629 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I23.png\" alt=\"\" width=\"207\" height=\"110\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I23.png 207w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I23-71x39.png 71w\" sizes=\"auto, (max-width: 207px) 100vw, 207px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Function sub_1000E61D() call<\/i><\/span><\/div>\n<p>The function seems to take 4 arguments:<\/p>\n<ul>\n<li>An <b>integer <\/b>(here the PID of the process);<\/li>\n<li>A <b>buffer <\/b>(here named \u201cValue\u201d);<\/li>\n<li>The <b>size of the buffer<\/b> (here 0x104);<\/li>\n<li>A <b>value <\/b>(here 0xA, or 10).<\/li>\n<\/ul>\n<p>Looking at the provided buffer\u2019s content after the function call, we see that the representation in base 10 of the first integer passed in parameter is written in the provided buffer.<\/p>\n<figure id=\"post-15631 media-15631\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15631 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I24.png\" alt=\"\" width=\"214\" height=\"168\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I24.png 214w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I24-50x39.png 50w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I24-156x121.png 156w\" sizes=\"auto, (max-width: 214px) 100vw, 214px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Value buffer after the call<\/i><\/span><\/div>\n<p>The function prototype and its side effects correspond to the <b>_itoa_s<\/b> function .<\/p>\n<p><u>Handler_0 whole CFG and pseudo-code<\/u><br \/>\nHere is the graph of the Handler_0 function:<\/p>\n<figure id=\"post-15633 media-15633\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15633 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I25.png\" alt=\"\" width=\"400\" height=\"365\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I25.png 400w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I25-209x191.png 209w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I25-43x39.png 43w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/figure>\n<figure id=\"post-15633 media-15633\" class=\"align-none\">\n<figure id=\"post-15633 media-15633\" class=\"align-none\">\n<figure id=\"post-15675 media-15675\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15675 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I25bis.png\" alt=\"\" width=\"400\" height=\"255\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I25bis.png 400w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I25bis-300x191.png 300w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I25bis-61x39.png 61w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/figure>\n<\/figure>\n<\/figure>\n<figure id=\"post-15635 media-15635\" class=\"align-none\"><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>CFG of function Handler_0()<\/i><\/span><\/div>\n<p>This corresponds to the following pseudo code:<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>if isloaded(\u201cpython.dll\u201d):\r\n   pid = getpid()\r\nelse:\r\n   pid = 0\r\nsetEnvironmentVariable(\u201cmb_chall\u201d, str(pid))\r\nreturn EXCEPTION_CONTINUE_SEARCH<\/pre>\n<\/div>\n<p>The function<b> checks the presence of the python27.dll<\/b> library (normally loaded by the main program mb_crackme_2.exe) in the process address space, and sets the <b>\u201cmb_chall\u201d environment variable <\/b>consequently.<br \/>\nThis may be seen as an \u201canti-debug\u201d trick, because running the DLL independently in a debugger makes the execution follow a different path.<\/p>\n<p><b>Handler_1 (0x100011D0)<\/b><br \/>\nThe code of this handler is quite self-explanatory, being similar to the previous handler\u2019s code:<\/p>\n<figure id=\"post-15635 media-15635\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15635 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I26.png\" alt=\"\" width=\"400\" height=\"350\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I26.png 400w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I26-218x191.png 218w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I26-45x39.png 45w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\">\n<figure id=\"post-15677 media-15677\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-15677 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I26bis.png\" alt=\"\" width=\"400\" height=\"248\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I26bis.png 400w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I26bis-308x191.png 308w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I26bis-63x39.png 63w\" sizes=\"auto, (max-width: 400px) 100vw, 400px\" \/><\/figure>\n<\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<p>Once again, this corresponds to the following pseudo code:<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>if getpid() == int(getenv(\u201cmb_chall\u201d):\r\n   tmp = 6\r\nelse:\r\n   tmp = 1\r\nexceptionInfo-&gt;Context._Eip += tmp\r\nreturn EXCEPTION_CONTINUE_EXECUTION<\/pre>\n<\/div>\n<p>After this handler, execution restarts at the address of original interruption (\u201cint 3\u201d) +1 or +6 (as presented in the pseudo-code above), whether performed checks pass or not.<\/p>\n<figure id=\"post-15637 media-15637\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15637 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I27.png\" alt=\"\" width=\"640\" height=\"150\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I27.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I27-437x102.png 437w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I27-71x17.png 71w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<p>We thus continue the analysis at the <b>not_fail function<\/b> (0x100010D0).<\/p>\n<p><b>not_fail (0x100010D0)<\/b><br \/>\nThe function only starts a thread and waits for it to terminate.<\/p>\n<figure id=\"post-15639 media-15639\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15639 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I28.png\" alt=\"\" width=\"319\" height=\"231\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I28.png 319w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I28-264x191.png 264w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I28-54x39.png 54w\" sizes=\"auto, (max-width: 319px) 100vw, 319px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>CFG of not_fail() function<\/i><\/span><\/div>\n<p>The created thread executes the <b>MainThread<\/b> (0x10001110) function, where our analysis continues.<\/p>\n<p><b>MainThread (0x10001110)<\/b><br \/>\nThe function loops and calls the <b>EnumWindows<\/b>\u00a0 API every second, which in turn calls the provided callback function (<b>EnumWindowsCallback<\/b>) on every window present on the desktop.<br \/>\n<b><br \/>\n<\/b><\/p>\n<figure id=\"post-15641 media-15641\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15641 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I29.png\" alt=\"\" width=\"284\" height=\"400\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I29.png 284w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I29-136x191.png 136w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I29-28x39.png 28w\" sizes=\"auto, (max-width: 284px) 100vw, 284px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>CFG of MainThread() function<\/i><\/span><\/div>\n<p><b>EnumWindowsCallback function (0x10005750)<\/b><br \/>\nThe function, called on each window, uses the <b>SendMessageA<\/b>\u00a0 API with the WM_GETTEXT message to retrieve the window\u2019s title.<\/p>\n<figure id=\"post-15643 media-15643\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15643 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I30.png\" alt=\"\" width=\"320\" height=\"175\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I30.png 320w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I30-71x39.png 71w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>SendMessageA() call in MainThread()<\/i><\/span><\/div>\n<p>After being converted to C++ std::string, the substrings <b>\u201cNotepad\u201d<\/b> and <b>\u201csecret_console\u201d<\/b> are searched in the window\u2019s title.<\/p>\n<div class=\"separator\" style=\"clear: both; text-align: center;\">\n<figure id=\"post-15645 media-15645\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15645 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I31.png\" alt=\"\" width=\"363\" height=\"404\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I31.png 363w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I31-172x191.png 172w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I31-35x39.png 35w\" sizes=\"auto, (max-width: 363px) 100vw, 363px\" \/><\/figure>\n<\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Strings &#8220;Notepad&#8221; and &#8220;secret_console&#8221; searched for in window title<\/i><\/span><\/div>\n<p>If both substrings are present, the window\u2019s title is replaced by the hardcoded string <b>\u201cSecret Console is waiting for the commands&#8230;\u201d<\/b>, using the SendMessageA API along with the WM_SETTEXT message. The window is placed to the <b>foreground,<\/b> using the ShowWindow API call.<\/p>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\">\n<figure id=\"post-15647 media-15647\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15647 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I32.png\" alt=\"\" width=\"295\" height=\"330\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I32.png 295w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I32-171x191.png 171w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I32-35x39.png 35w\" sizes=\"auto, (max-width: 295px) 100vw, 295px\" \/><\/figure>\n<p><span style=\"font-size: x-small;\"><i>Modification of the window&#8217;s title using SendMessageA()<\/i><\/span>\n<\/div>\n<p>The PID of the process corresponding to the window is then written in the \u201cmalware\u201d\u2019s console, and sub-windows of this window are enumerated, using the EnumChildWindows\u00a0 API.The function <b>EnumChildWindowsCallback<\/b> (0x100034C0) is thus called on every sub-window.<\/p>\n<figure id=\"post-15649 media-15649\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15649 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I33.png\" alt=\"\" width=\"438\" height=\"309\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I33.png 438w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I33-271x191.png 271w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I33-55x39.png 55w\" sizes=\"auto, (max-width: 438px) 100vw, 438px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>EnumChildWindows() function call<\/i><\/span><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>\u00a0<\/i><\/span><\/div>\n<p><b>EnumChildWindowsCallback function (0x100034C0)<\/b><br \/>\nThis function gets the content of the sub-window using the SendMessageA API call:<\/p>\n<figure id=\"post-15651 media-15651\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15651 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I34.png\" alt=\"\" width=\"436\" height=\"222\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I34.png 436w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I34-375x191.png 375w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I34-71x36.png 71w\" sizes=\"auto, (max-width: 436px) 100vw, 436px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>SendMessageA() call in EnumChildWindowsCallback() function<\/i><\/span><\/div>\n<p>The substring <b>\u201cdump_the_key\u201d<\/b> is then searched in the retrieved content:<\/p>\n<figure id=\"post-15653 media-15653\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15653 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I35.png\" alt=\"\" width=\"328\" height=\"254\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I35.png 328w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I35-247x191.png 247w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I35-50x39.png 50w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I35-156x121.png 156w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I35-155x120.png 155w\" sizes=\"auto, (max-width: 328px) 100vw, 328px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Search for &#8220;dump_the_key&#8221;<\/i><\/span><\/div>\n<p>If this string is found, this function calls a decryption routine <b>decrypt_buffer()<\/b> (0x100016F0) on a buffer (encrypted_buff), using the string \u201cdump_the_key\u201d as argument.<\/p>\n<figure id=\"post-15655 media-15655\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15655 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I36.png\" alt=\"\" width=\"514\" height=\"251\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I36.png 514w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I36-391x191.png 391w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I36-71x35.png 71w\" sizes=\"auto, (max-width: 514px) 100vw, 514px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Decrypting a hardcoded buffer using &#8220;dump_the_key&#8221; as key<\/i><\/span><\/div>\n<p>Then, the \u201cmalware\u201d loads the <b>actxprxy.dll <\/b>library into the process memory space. The first 4096 bytes (i.e. the first memory page) of the library is made writable using the VirtualProtect API call, and the decrypted payload is written at this location.<\/p>\n<figure id=\"post-15657 media-15657\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15657 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I37.png\" alt=\"\" width=\"640\" height=\"395\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I37.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I37-309x191.png 309w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I37-63x39.png 63w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Loading a library and writing the decrypted buffer at its location<\/i><\/span><\/div>\n<p>Since the actxprxy.dll library is not used anywhere in the analyzed DLL after being re-written, it may be seen as a <b>covert communication channel <\/b>between the analyzed DLL and the main program mb_crackme_2.exe. After this, the function clears every allocated memory and exits. The created thread (see 4.2.6) therefore also exits, and the DllEntryPoint function call terminates, giving the control back to the main python script.<\/p>\n<h3>Triggering the secret console<\/h3>\n<p>As seen in the DLL analysis, to trigger the required conditions, a file named<b> \u201csecret_console \u2013 Notepad\u201d<\/b> is opened in a text editor. As such, the window title contains the mentioned substrings:<\/p>\n<figure id=\"post-15659 media-15659\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15659 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I38.png\" alt=\"\" width=\"320\" height=\"219\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I38.png 320w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I38-279x191.png 279w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I38-57x39.png 57w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Opening a file named &#8220;secret_console_Notepad.txt&#8221; on Notepad++<\/span><\/i><\/div>\n<p>As expected, the title of the window is changed to \u201cSecret Console is waiting for the commands\u2026\u201d by the malware. Writing \u201cdump_the_key\u201d in the window validates the second stage.<\/p>\n<figure id=\"post-15661 media-15661\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15661 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I39.png\" alt=\"\" width=\"320\" height=\"242\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I39.png 320w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I39-253x191.png 253w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I39-52x39.png 52w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Writing &#8220;dump_the_key&#8221; in the text editor<\/i><\/span><\/div>\n<h1>Stage 3: the colors<\/h1>\n<p>After validating the previous step, a message is printed on the console, asking the user to \u201cguess a color\u201d:<\/p>\n<figure id=\"post-15663 media-15663\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15663 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I40.png\" alt=\"\" width=\"640\" height=\"67\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I40.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I40-437x46.png 437w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I40-71x7.png 71w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Level 3 Message<\/i><\/span><\/div>\n<p>The <b>three components (R, G and B) of a specific color<\/b>, with values going from 0 to 255, need to be entered to validate this step.<\/p>\n<figure id=\"post-15665 media-15665\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15665 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I41.png\" alt=\"\" width=\"320\" height=\"144\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I41.png 320w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I41-71x32.png 71w\" sizes=\"auto, (max-width: 320px) 100vw, 320px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><span style=\"font-size: x-small;\"><i>Level 3 failed guess message<\/i><\/span><\/div>\n<h3>Understanding the code<\/h3>\n<p>Looking back at the another.py\u2019s main() function code, it seems that the corresponding operations are performed inside the <b>decode_pasted()<\/b> function.<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre>def main():\r\n   [...]\r\n      load_level2(decdata, len(decdata))\r\n      user32_dll.MessageBoxA(None, 'You did it, level up!', 'Congrats!', 0)\r\n      try:\r\n         if decode_pasted() == True:\r\n            user32_dll.MessageBoxA(None, '''Congratulations! Now save your flag and \r\nsend it to Malwarebytes!''', 'You solved it!', 0)\r\n            return 0<\/pre>\n<\/div>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>def decode_pasted():\r\n    my_proxy = kernel_dll.GetModuleHandleA('actxprxy.dll')\r\n    if my_proxy is None or my_proxy == 0:\r\n        return False\r\n    else:\r\n        char_sum = 0\r\n        arr1 = my_proxy\r\n        str = ''\r\n        while True:\r\n            val = get_char(arr1)\r\n            if val == '\\x00':\r\n                break\r\n            char_sum += ord(val)\r\n            str = str + val\r\n            arr1 += 1\r\n\r\n        print char_sum\r\n        if char_sum != 52937:\r\n            return False\r\n        colors = level3_colors()\r\n        if colors is None:\r\n            return False\r\n        val_arr = zlib.decompress(base64.b64decode(str))\r\n        final_arr = dexor_data(val_arr, colors)\r\n        try:\r\n            exec final_arr\r\n        except:\r\n            print 'Your guess was wrong!'\r\n            return False\r\n\r\n        return True<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre>def dexor_data(data, key):\r\n    maxlen = len(data)\r\n    keylen = len(key)\r\n    decoded = ''\r\n    for i in range(0, maxlen):\r\n        val = chr(ord(data[i]) ^ ord(key[i % keylen]))\r\n        decoded = decoded + val\r\n    return decoded<\/pre>\n<\/div>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre>def level3_colors():\r\n    colorama.init()\r\n    print colorama.Style.BRIGHT + colorama.Fore.CYAN\r\n    print '''Level #3: Your flag is almost ready! But before it will be revealed\r\n, you need to guess it's color (R,G,B)!'''\r\n    print colorama.Style.RESET_ALL\r\n    color_codes = ''\r\n    while True:\r\n        try:\r\n            val_red = int(raw_input('R: '))\r\n            val_green = int(raw_input('G: '))\r\n            val_blue = int(raw_input('B: '))\r\n            color_codes += chr(val_red)\r\n            color_codes += chr(val_green)\r\n            color_codes += chr(val_blue)\r\n            break\r\n        except:\r\n            print 'Invalid color code! Color code must be an integer (0,255)'\r\n    print 'Checking: RGB(%d,%d,%d)' % (val_red, val_green, val_blue)\r\n    return color_codes<\/pre>\n<\/div>\n<p>According to the decode_pasted() function, the decrypted buffer stored at the start of actxprxy.dll\u2019s address space is read and:<br \/>\nbase64-decoded;<\/p>\n<ul>\n<li>zlib-decompressed;<\/li>\n<li>XOR\u2019ed against the user-provided colors values;<\/li>\n<li>Executed by the Python exec function.<\/li>\n<\/ul>\n<p>To start our cryptanalysis, we <b>modify the decode_pasted() function<\/b> to dump the val_arr buffer before the dexor_data() operation, and rerun another.py, providing all required credentials:<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre>[...]\r\nif colors is None:\r\n   return False\r\nval_arr = zlib.decompress(base64.b64decode(str))\r\nwith open(\"val_arr.bin\", \"wb\") as f:\r\n   f.write(val_arr)\r\n   print \"val_arr dumped !\"\r\nexit()\r\nfinal_arr = dexor_data(val_arr, colors)\r\n[...]<\/pre>\n<\/div>\n<p>&nbsp;<\/p>\n<figure id=\"post-15667 media-15667\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15667 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I42.png\" alt=\"\" width=\"213\" height=\"118\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I42.png 213w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I42-71x39.png 71w\" sizes=\"auto, (max-width: 213px) 100vw, 213px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Dumping the XOR&#8217;ed array<\/span><\/i><\/div>\n<h3>Decrypting the val_arr buffer<\/h3>\n<p>Knowing that the buffer is a string passed to the \u201cexec\u201d Python statement after being decrypted, it should represent a <b>valid Python source code<\/b>.<br \/>\nTo find the right key, the na\u00efve solution would be to run a brute-force attack on all the possible \u201c(R, G, B)\u201d combinations, and look for printable solutions. This solution would need to perform 256^3 = 16\u2019777\u2019216 dexor_data() calls, which is feasible but <b>inefficient<\/b>.<br \/>\nInstead, we perform 3 independent brute-force attacks on each R, G and B component, therefore performing 256 x 3 = 768 dexor_data() calls. The 3 brute-force attacks are performed on different \u201cslices\u201d of the val_arr string (of each of stride 3). We then test each combination of potential values previously found for each component.<br \/>\nFor example, if our 3 brute-force attacks indicate that:<\/p>\n<ul>\n<li>R can take values 2 and 37,<\/li>\n<li>G can take values 77 and 78,<\/li>\n<li>and B can only take the value 3,<\/li>\n<\/ul>\n<p>Then we test the combinations (2,77, 3), (37,77, 3), (2,78, 3) and (37,78, 3).<\/p>\n<p>The following code implements our attack:<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre>import string\r\nimport itertools\r\nfrom colorama import *\r\nfrom another import dexor_data\r\n\r\nwith open(\"val_arr.bin\", \"rb\") as f:\r\n    val_arr = f.read()\r\n\r\n#lists of possible values for R, G and B\r\npotential_solutions = [list(), list(), list()]\r\nfor color in range(3): # separate bruteforce on R, G and B\r\n    for xor_value in range(256): #testing all potential values\r\n        valid = True\r\n        for b in val_arr[color::3]: #extracting one every 3 characters, from index \r\n        # \"color\" (i.e. extracting all characters xored by the same \"color\" value)\r\n            if chr(ord(b) ^ xor_value) not in string.printable:\r\n                valid = False\r\n                break\r\n        if valid:\r\n            potential_solutions[color].append(xor_value)\r\n\r\nprint \"Possible values for R, G and B :\", potential_solutions\r\n\r\nfor colors in itertools.product(*potential_solutions):\r\n    print \"Testing \", colors\r\n    plaintext = dexor_data(val_arr, map(chr, colors))\r\n    print repr(plaintext)\r\n    if not raw_input(\"Does it seems right ? [Y\/n]\\n\").startswith(\"n\"):\r\n       print \"Executing payload :\"\r\n       exec plaintext\r\n       break<\/pre>\n<\/div>\n<p>Executing this code gives us the solution instantly:<\/p>\n<figure id=\"post-15669 media-15669\" class=\"align-none\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-15669 size-full\" src=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I43.png\" alt=\"\" width=\"640\" height=\"199\" srcset=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I43.png 640w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I43-437x136.png 437w, https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I43-71x22.png 71w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/figure>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><\/div>\n<div class=\"separator\" style=\"clear: both; text-align: center;\"><i><span style=\"font-size: x-small;\">Decrypting the payload<\/span><\/i><\/div>\n<p>The final flag appears in the console:<\/p>\n<div style=\"background-color: #dfd2ee; border: 1px solid black; padding-left: 1%; padding-right: 1%; width: 100%;\">\n<pre><\/pre>\n<pre>flag{\"Things are not always what they seem; the first appearance \r\ndeceives many; the intelligence of a few perceives what has been \r\ncarefully hidden.\" - Phaedrus}<\/pre>\n<\/div>\n<h2>Conclusion<\/h2>\n<p>This challenge was very interesting to solve, because apart from being an original crackme, it also included various topics that could be found during a real malware analysis. These topics included:<\/p>\n<ul>\n<li>DLL-rewriting techniques, here used as a kind of covert communication channel between a DLL and its main process;<\/li>\n<li>\u201cNon-obvious\u201d anti-debugging tricks, like checking the presence of a known library in the process\u2019 memory space to identify standalone DLL debugging;<\/li>\n<li>Concealed malware downloading, using \u00ab harmless \u00bb formats (like PNG) to hide an executable payload from basic traffic analysis;<\/li>\n<li>PyInstaller-based malware, (yes, sometimes malware writers can be lazy).<\/li>\n<\/ul>\n<p>Thanks MalwareBytes for this entertaining challenge!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Malwarebytes published on April 27th a new reverse engineering challenge, an executable mixing malware behavior with a traditional crackme look. It came in the form of a Windows executable This document describes the solving step of the challenge. Lightweight analysis&#8230;<\/p>\n","protected":false},"author":1416,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"page-templates\/tmpl-one.php","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[36,3854,3225],"tags":[641,265],"coauthors":[3896],"class_list":["post-15584","post","type-post","status-publish","format-standard","hentry","category-cybersecurity-digital-trust","category-deep-dive","category-ethical-hacking-indicent-response","tag-hackers","tag-malware"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Malwarebytes challenge write-up - RiskInsight<\/title>\n<meta name=\"description\" content=\"Malwarebytes published on April 27th a new reverse engineering challenge, an executable mixing malware behavior with a traditional crackme look. It came in the form of a Windows executableThis document describes the solving step of the challenge.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Malwarebytes challenge write-up - RiskInsight\" \/>\n<meta property=\"og:description\" content=\"Malwarebytes published on April 27th a new reverse engineering challenge, an executable mixing malware behavior with a traditional crackme look. It came in the form of a Windows executableThis document describes the solving step of the challenge.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/\" \/>\n<meta property=\"og:site_name\" content=\"RiskInsight\" \/>\n<meta property=\"article:published_time\" content=\"2018-06-12T09:00:39+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-06-02T16:26:42+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png\" \/>\n<meta name=\"author\" content=\"Maxime Meignan\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Maxime Meignan\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"22 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/\"},\"author\":{\"name\":\"Maxime Meignan\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/person\/7cb6f70eb43bca0ed40d795d10f42c9a\"},\"headline\":\"Malwarebytes challenge write-up\",\"datePublished\":\"2018-06-12T09:00:39+00:00\",\"dateModified\":\"2021-06-02T16:26:42+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/\"},\"wordCount\":2961,\"publisher\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png\",\"keywords\":[\"hackers\",\"malware\"],\"articleSection\":[\"Cybersecurity &amp; Digital Trust\",\"Deep-dive\",\"Ethical Hacking &amp; Incident Response\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/\",\"name\":\"Malwarebytes challenge write-up - RiskInsight\",\"isPartOf\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png\",\"datePublished\":\"2018-06-12T09:00:39+00:00\",\"dateModified\":\"2021-06-02T16:26:42+00:00\",\"description\":\"Malwarebytes published on April 27th a new reverse engineering challenge, an executable mixing malware behavior with a traditional crackme look. It came in the form of a Windows executableThis document describes the solving step of the challenge.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#primaryimage\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png\",\"contentUrl\":\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Accueil\",\"item\":\"https:\/\/www.riskinsight-wavestone.com\/en\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Malwarebytes challenge write-up\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#website\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/en\/\",\"name\":\"RiskInsight\",\"description\":\"The cybersecurity &amp; digital trust blog by Wavestone&#039;s consultants\",\"publisher\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.riskinsight-wavestone.com\/en\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#organization\",\"name\":\"Wavestone\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/en\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/08\/Monogramme\u2013W\u2013NEGA-RGB-50x50-1.png\",\"contentUrl\":\"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/08\/Monogramme\u2013W\u2013NEGA-RGB-50x50-1.png\",\"width\":50,\"height\":50,\"caption\":\"Wavestone\"},\"image\":{\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/person\/7cb6f70eb43bca0ed40d795d10f42c9a\",\"name\":\"Maxime Meignan\",\"url\":\"https:\/\/www.riskinsight-wavestone.com\/en\/author\/maxime-meignan\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Malwarebytes challenge write-up - RiskInsight","description":"Malwarebytes published on April 27th a new reverse engineering challenge, an executable mixing malware behavior with a traditional crackme look. It came in the form of a Windows executableThis document describes the solving step of the challenge.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/","og_locale":"en_US","og_type":"article","og_title":"Malwarebytes challenge write-up - RiskInsight","og_description":"Malwarebytes published on April 27th a new reverse engineering challenge, an executable mixing malware behavior with a traditional crackme look. It came in the form of a Windows executableThis document describes the solving step of the challenge.","og_url":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/","og_site_name":"RiskInsight","article_published_time":"2018-06-12T09:00:39+00:00","article_modified_time":"2021-06-02T16:26:42+00:00","og_image":[{"url":"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png","type":"","width":"","height":""}],"author":"Maxime Meignan","twitter_misc":{"Written by":"Maxime Meignan","Est. reading time":"22 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#article","isPartOf":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/"},"author":{"name":"Maxime Meignan","@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/person\/7cb6f70eb43bca0ed40d795d10f42c9a"},"headline":"Malwarebytes challenge write-up","datePublished":"2018-06-12T09:00:39+00:00","dateModified":"2021-06-02T16:26:42+00:00","mainEntityOfPage":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/"},"wordCount":2961,"publisher":{"@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#organization"},"image":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#primaryimage"},"thumbnailUrl":"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png","keywords":["hackers","malware"],"articleSection":["Cybersecurity &amp; Digital Trust","Deep-dive","Ethical Hacking &amp; Incident Response"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/","url":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/","name":"Malwarebytes challenge write-up - RiskInsight","isPartOf":{"@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#primaryimage"},"image":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#primaryimage"},"thumbnailUrl":"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png","datePublished":"2018-06-12T09:00:39+00:00","dateModified":"2021-06-02T16:26:42+00:00","description":"Malwarebytes published on April 27th a new reverse engineering challenge, an executable mixing malware behavior with a traditional crackme look. It came in the form of a Windows executableThis document describes the solving step of the challenge.","breadcrumb":{"@id":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#primaryimage","url":"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png","contentUrl":"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/04\/I1.png"},{"@type":"BreadcrumbList","@id":"https:\/\/www.riskinsight-wavestone.com\/2018\/06\/malwarebytes-challenge-write-up\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Accueil","item":"https:\/\/www.riskinsight-wavestone.com\/en\/"},{"@type":"ListItem","position":2,"name":"Malwarebytes challenge write-up"}]},{"@type":"WebSite","@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#website","url":"https:\/\/www.riskinsight-wavestone.com\/en\/","name":"RiskInsight","description":"The cybersecurity &amp; digital trust blog by Wavestone&#039;s consultants","publisher":{"@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.riskinsight-wavestone.com\/en\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#organization","name":"Wavestone","url":"https:\/\/www.riskinsight-wavestone.com\/en\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/logo\/image\/","url":"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/08\/Monogramme\u2013W\u2013NEGA-RGB-50x50-1.png","contentUrl":"https:\/\/www.riskinsight-wavestone.com\/wp-content\/uploads\/2021\/08\/Monogramme\u2013W\u2013NEGA-RGB-50x50-1.png","width":50,"height":50,"caption":"Wavestone"},"image":{"@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.riskinsight-wavestone.com\/en\/#\/schema\/person\/7cb6f70eb43bca0ed40d795d10f42c9a","name":"Maxime Meignan","url":"https:\/\/www.riskinsight-wavestone.com\/en\/author\/maxime-meignan\/"}]}},"_links":{"self":[{"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/posts\/15584","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/users\/1416"}],"replies":[{"embeddable":true,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/comments?post=15584"}],"version-history":[{"count":5,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/posts\/15584\/revisions"}],"predecessor-version":[{"id":15894,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/posts\/15584\/revisions\/15894"}],"wp:attachment":[{"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/media?parent=15584"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/categories?post=15584"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/tags?post=15584"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.riskinsight-wavestone.com\/en\/wp-json\/wp\/v2\/coauthors?post=15584"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}