{"id":17968,"date":"2020-03-17T20:38:47","date_gmt":"2020-03-18T04:38:47","guid":{"rendered":"http:\/\/www.palada.net\/index.php\/2020\/03\/17\/news-11701\/"},"modified":"2020-03-17T20:38:47","modified_gmt":"2020-03-18T04:38:47","slug":"news-11701","status":"publish","type":"post","link":"https:\/\/www.palada.net\/index.php\/2020\/03\/17\/news-11701\/","title":{"rendered":"\u201cDouble agent\u201d: a MacOS bundleware installer that acts like a spy"},"content":{"rendered":"<p><strong>Credit to Author: Sergei Shevchenko| Date: Tue, 17 Mar 2020 08:00:58 +0000<\/strong><\/p>\n<div class=\"entry-content\">\n<p>Security software frequently blocks \u201cbundleware\u201d installers &#8211; software distribution tools that bundle their advertised applications with (usually undesired) additional software &#8211; as potentially undesirable applications. But one widely-used software distribution tool for MacOS applications goes to great lengths to avoid being blocked as \u201cbundleware\u201d &#8211; using a number of anti-forensics techniques that are more common in malware code. The installer is from a legitimate company, which claims to reach over 1 billion users per month with its various downloaders and adware platforms.<\/p>\n<p>This software attempts to evade blocking by endpoint protection systems with anti-debugging code, strings and API encryption, runtime decompression and virtual machine detection. Its developers went as far as to embed a full backdoor-like component into the installer that allows remote injection of new code into the installer &#8211; granting it capabilities that extend far beyond what one might expect from a piece of installation software.<\/p>\n<p>This particular bundleware has potential access to a large number of Macs around the world. The power given to the installer practically enables full control over the target system. Even if this was done so that the company behind it would have &#8216;advanced analytics&#8217; or the ability to push any third-party software it wants, given the amount of power it aggregates, what happens if this power is abused?<\/p>\n<p>We&#8217;re not naming the company or the installer here because of its wide distribution; this research is entirely focused on technical aspects of the reverse-engineered software. The developers have been contacted by researchers, but have shown no interest in changing what they see as a feature of their installer, as long as it allows them to monetize the installations of their software.<\/p>\n<h3>The allure of bundleware<\/h3>\n<p>MacOS application developers use third-party installers for a number of reasons. One of the reasons often given is the desire to improve the overall &#8220;user experience&#8221; of software installation. Many developers turn to application installation platforms because they promise enhanced installation analytics, an optimized footprint, and a guaranteed smoothness of installation.<\/p>\n<p>But these installers offer another attraction that is more important to many developers: the promise of monetization. Developers or websites distributing freeware (such as free games) or software based on open source components may not be able to charge for the applications, but they can capture some revenue by teaming with a third-party installation tool.<\/p>\n<p>Some of these application installation platforms bundle the title application with third-party software such as adware or browser toolbars, leading to a setup that the end-user might find unwanted. Once the target application is installed, users often encounter undesirable consequences, such as installed browser hijackers that modify the search engine for their web browser. In some cases, these inject messages for &#8220;scare-ware&#8221; removers that prompt the user to pay for the removal of non-exist threats.<\/p>\n<p>Apple actively combats these types of unethical applications, which the company labels as &#8221; <a href=\"https:\/\/developer.apple.com\/support\/protecting-users-from-suspicious-software\/\">suspicious software<\/a> .&#8221; In 2019, starting with macOS 10.14.5 (Mojave), Apple began requiring application developers to submit their code for &#8221; <a href=\"https:\/\/developer.apple.com\/news\/?id=04102019a\">notarization<\/a> &#8220;, and blocking applications without notarisation or with revoked developer signatures by macOS&#8217;s <a href=\"https:\/\/support.apple.com\/en-us\/HT202491\">Gatekeeper<\/a> . Apple can revoke notarisation and the developer accounts associated with applications that are found to be abusive. But bundleware installers may not get flagged as &#8220;suspicious&#8221; in the notarization process.<\/p>\n<p>Detecting bundleware is almost never a problem for endpoint protection systems &#8211; it&#8217;s a much more simplistic breed, so to speak, than malware. But the bundleware package we examine here, already blocked by a number of endpoint protection tools as a potentially unwanted application, adopts many anti-forensics and counter-detection techniques that have in the past been found mostly in malware.<\/p>\n<h3>The Application<\/h3>\n<p>The bundleware described in this post is a Cocoa application &#8211; an application built with the <a href=\"https:\/\/developer.apple.com\/documentation\/appkit\">AppKit<\/a> framework, and is distributed as an <a href=\"https:\/\/developer.apple.com\/library\/archive\/documentation\/CoreFoundation\/Conceptual\/CFBundles\/AboutBundles\/AboutBundles.html\">application bundle<\/a> .\u00a0From sample to sample, the name of the main executable varies. For example, it can be named as <code>radiosurgical<\/code>or <code>Herculid<\/code>.<\/p>\n<p>The digital signature used to sign the app varies, as this is generated by the developer packaging the application with the installer. Some observed installers are signed by \u201cOwen Bell\u201d. Some other installers were found to be signed by \u201cRuiQing Software Technology Beijing Inc.\u201d or \u201cAVSoftware EOOD\u201d.<\/p>\n<h3>The main executable<\/h3>\n<p>Compiled as Mach-O (the native executable file format for macOS), the main executable relies on Objective-C runtime <code>libobjc.dylib<\/code>. When the kernel first loads the main executable, it makes sure that the executable is a valid Mach-O file, and then examines its <code>mach_header<\/code>structure.<\/p>\n<p>Next, it loads the dynamic linker to load all the shared libraries that the main executable links against.\u00a0The dynamic linker then initializes the Objective-C runtime, and then calls the program&#8217;s <em>main ()<\/em> function.<\/p>\n<p>However, the main executable&#8217;s entry point starts from garbage bytes &#8211; that is, it has no valid code to execute:<\/p>\n<pre style=\"background-color: #000064;line-height: 125%;color: silver;padding-top: 1em;padding-bottom: 1em\">__text: 0000000100001150 <span style=\"color: white\">04 <\/span>     <span style=\"color: yellow\">start<\/span>     db     <span style=\"color: cyan\">4<\/span>    __text: 0000000100001151 <span style=\"color: white\">4A<\/span>                db     <span style=\"color: cyan\">4Ah<\/span> ; J   __text: 0000000100001152 <span style=\"color: white\">3E<\/span>                db     <span style=\"color: cyan\">3Eh<\/span> ; &gt;<\/pre>\n<p>With no valid code at the entry point, how does it run without crashing?\u00a0The answer lays in Objective-C&#8217;s concept of <em>non-lazy<\/em> (&#8216;eager&#8217;) and <em>lazy<\/em> (&#8216;on-demand&#8217;) implementation of classes.<\/p>\n<p><em>Non-lazy<\/em> classes are realized when the program starts up. These classes will always implement <em>+ load<\/em> method.\u00a0Contrary to that, <em>lazy<\/em> classes (classes without <em>+ load<\/em> method) do not have to be realized immediately, but only when they receive a message for the first time (hence the term &#8216;lazy&#8217;).<\/p>\n<p>Let&#8217;s check out Objective-C Runtime&#8217;s own <a href=\"https:\/\/opensource.apple.com\/source\/objc4\/objc4-532\/runtime\/objc-runtime-new.mm\">source,<\/a> found in <code>objc-runtime-new.mm<\/code> file.\u00a0The snippet below realizes the <em>non-lazy<\/em> classes, retrieved with <em>_getObjc2NonlazyClassList ()<\/em> call:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\"><span style=\"color: #008000\">\/\/ Realize non-lazy classes (for + load methods and static instances) <\/span>  <span style=\"color: #0000ff\">for<\/span> (EACH_HEADER) {       <span style=\"color: #2b91af\">classref_t<\/span> * classlist = _getObjc2NonlazyClassList (hi, &amp; count);      <span style=\"color: #0000ff\">for<\/span> (i = 0; i &lt;count; i ++) {           realizeClass (remapClass (classlist [i]));       }   }  <\/pre>\n<p>Looking at the Objective-C Runtime&#8217;s <a href=\"https:\/\/github.com\/opensource-apple\/objc4\/blob\/master\/runtime\/objc-file.mm\">source<\/a> in <code>objc-file.mm<\/code>, one can see that <em>_getObjc2NonlazyClassList ()<\/em> function collects <em>non-lazy<\/em> classes from the <code>__objc_nlclslist<\/code>data section:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\">GETSECT (_getObjc2NonlazyClassList,    <span style=\"color: #008000\">\/\/ function name <\/span>           <span style=\"color: #2b91af\">classref_t<\/span> ,                  <span style=\"color: #008000\">\/\/ content type <\/span>           <span style=\"color: #a31515\">\"__objc_nlclslist\"<\/span> );         <span style=\"color: #008000\">\/\/ section name - 'nl' stands for non-lazy<\/span>  <\/pre>\n<p>In the case of our bundleware executable, the <code>__objc_nlclslist<\/code>data section of the main binary is very small. It enlists only two <em>non-lazy<\/em> classes: <code>ListedUpaithric<\/code>and <code>__ARCLite__<\/code>:<\/p>\n<pre style=\"background-color: #000064;line-height: 125%;color: silver;padding-top: 1em;padding-bottom: 1em\">__objc_nlclslist: 0001000692C8     <span style=\"color: yellow\">__objc_nlclslist segment para public 'DATA' use64<\/span>    __objc_nlclslist: 0001000692C8 dq offset <span style=\"color: yellow\">_OBJC_CLASS _ $ _ ListedUpaithric<\/span>    __objc_nlclslist: 0001000692D0 dq offset <span style=\"color: yellow\">_OBJC_CLASS _ $ ___ ARCLite__<\/span>    __objc_nlclslist: 0001000692D0     <span style=\"color: yellow\">__objc_nlclslist ends<\/span><\/pre>\n<p>The <code>ListedUpaithric<\/code>name, like many of the other class names in the executable, is random. For example, in another sample this class is called <code>HoundingHusky<\/code>.<\/p>\n<p>These two non-lazy classes will be called in the order they&#8217;re listed, realized by their <em>+ load\u00a0<\/em> method.\u00a0\u00a0However, at first glance the <em>+ load<\/em> method of the <code>__ARCLite__<\/code>class contains no valid code, because it is located within the <code>__text<\/code>section of the executable &#8211; which is encrypted.<\/p>\n<h3>Finding a secret agent<\/h3>\n<p>The <em>+ load<\/em> method of the <code>ListedUpaithric<\/code>class is physically located in a section of the executable that has a random name, such as <code>__amorpha<\/code>or <code>__mottled<\/code>. Once run, the <em>+ load<\/em> method will take a 32-byte XOR key hard-coded in the body and then use that key to decrypt the <code>__text<\/code>section (around 15KB in size) of the executable, including the <em>+ load<\/em> method of the <code>__ARCLite__<\/code>class.<\/p>\n<p>The decryption routine relies on a special anchor stored in the <code>__text<\/code>section. The virtual address of this anchor is used to describe the virtual address and virtual size of the encrypted <code>__text<\/code>section.<\/p>\n<p>For example, in this particular sample, the anchor can be located at the virtual address <code>0x100001CF0<\/code>, as shown below:<\/p>\n<pre style=\"background-color: #000064;line-height: 125%;color: silver;padding-top: 1em;padding-bottom: 1em\">__text: 000100001CF0 23        <span style=\"color: yellow\">anchor <\/span>      <span style=\"color: cyan\">db 23h<\/span> ; #      <span style=\"color: cyan\">; DATA XREF: decrypt_code + 101<\/span>    __text: 000100001CF1 2B                     <span style=\"color: cyan\">db 2Bh<\/span> ; +   ...<\/pre>\n<p>The decryptor uses the address of the anchor to describe the parameters of the <code>__text<\/code> section. In the snippet below, the decryptor makes the <code>__text<\/code> section writable and executable, by assigning a new protection to it. To do that, it takes the address of the anchor <code>0x100001CF0<\/code> and subtracts <code>0xBA0<\/code> from it to locate the start of the <code>__text<\/code> section &#8211; <code>0x100001150<\/code>:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\">vm_protect (mach_task_self (),          <span style=\"color: #008000\">\/\/ decoded stings: 'vm_protect', 'mach_task_self_'<\/span>                ( <span style=\"color: #2b91af\">char<\/span> *) &amp; anchor - 0xBA0,    <span style=\"color: #008000\">\/\/ 0x100001150 -&gt; start of the __text section<\/span>                0x37F2,                    <span style=\"color: #008000\">\/\/ size of the entire __text section: 14,322 bytes<\/span>               0 ,               VM_PROT_ALL)               <span style=\"color: #008000\">\/\/ assign read, write, and execute access rights<\/span>  <\/pre>\n<p>Once the entire <code>__text<\/code>section is decrypted, the anchor shown above gets decrypted into the following text:<\/p>\n<pre style=\"background-color: #000064;line-height: 125%;color: silver;padding-top: 1em;padding-bottom: 1em\">__text: 000100001CF0 MaximMaximovicIsayev db ' <span style=\"color: #00ff00\">Maxim Maximovich Isayev<\/span> ', <span style=\"color: #00ff00\">0<\/span><\/pre>\n<p>The resulting text is the same across all the samples we&#8217;ve looked at, and is quite interesting by itself.\u00a0Maxim Maximovich Isayev (\u041c\u0430\u043a\u0441\u0438\u043c \u041c\u0430\u043a\u0441\u0438\u043c\u043e\u0432\u0438\u0447 \u0418\u0441\u0430\u0435\u0432) is the Russian name of Max Otto von Stierlitz, the lead <a href=\"https:\/\/en.wikipedia.org\/wiki\/Stierlitz\">character<\/a> in a popular Russian book series written in the 1960s, and of the most popular Soviet television series ever, <em>Seventeen Moments of Spring<\/em> .<\/p>\n<p><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/image1.jpeg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-54150\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/image1.jpeg?w=300\" alt=\"\" width=\"300\" height=\"223\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/image1.jpeg 640w, https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/image1.jpeg?resize=300,223 300w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a>A Soviet James <a href=\"http:\/\/www.bbc.com\/news\/magazine-39862225\">Bond<\/a> , Stierlitz takes a key role in SS Reich Main Security Office in Berlin during World War II. Working as a deep undercover agent within SS, he diverts the German nuclear &#8220;Vengeance Weapon&#8221; research program into a fruitless dead-end.<\/p>\n<p>Leaving a hidden marker like that could indicate an intentionally planted false flag. Regardless of the intention, this marker stays constant across the entire family of this bundleware.<\/p>\n<p>After the <code>ListedUpaithric<\/code> class is called and decrypts the text, being next in line, the <em>+ load<\/em> method of the <code>__ARCLite__<\/code> <em>non-lazy<\/em> class is called to perform further initialization. The decrypted <code>__text<\/code> section is quite small &#8211; it&#8217;s a valid code section containing a valid entry point in it, and it consists of another layer of decryptor and decompressor:<\/p>\n<pre style=\"background-color: #000064;line-height: 125%;color: silver;padding-top: 1em;padding-bottom: 1em\">__text: 0000000100001150             <span style=\"color: yellow\">public start<\/span>    __text: 0000000100001150      <span style=\"color: yellow\">start proc near<\/span>    __text: 0000000100001150 push    <span style=\"color: cyan\">0<\/span>   __text: 0000000100001152 mov rbp, rsp   __text: 0000000100001155 and rsp, <span style=\"color: cyan\">0FFFFFFFFFFFFFFF0h<\/span>    __text: 0000000100001159 mov rdi, [rbp + <span style=\"color: cyan\">8<\/span> ]<\/pre>\n<p>With both <em>non-lazy<\/em> classes realized, the entry point above receives control. From there, the <em>main ()<\/em> function of the executable is called, followed with <em>_exit ()<\/em> .<\/p>\n<h3>The main () function<\/h3>\n<p>Once the entry point within <code>__text<\/code>section is called, the <em>main ()<\/em> function that follows it will read an internal chunk of data with the size of ~ 300KB.<\/p>\n<p>This encrypted data is stored in a separate section of the executable.<\/p>\n<p>The data will be read, its CRC32-based hash validated, then decrypted and further decompressed into a buffer, allocated with <em>vm_allocate ()<\/em> function.<\/p>\n<p>The decompression is achieved by dynamically loading <code>libz.1.dylib<\/code> library, and calling <em>uncompress ()<\/em> API from it.<\/p>\n<p>The decompressed data has a size of ~ 800Kb, having a format of Mach-O executable ( <code>MH_BUNDLE<\/code> type). This data is loaded from memory as a plugin with the help of <em>NSCreateObjectFileImageFromMemory ()<\/em> and <em>NSLinkModule ()<\/em> APIs.<\/p>\n<p>This method is equivalent to dynamic DLL loading on Windows. It is described on macOS man <a href=\"http:\/\/mirror.informatimago.com\/next\/developer.apple.com\/documentation\/Darwin\/Reference\/ManPages\/man3\/NSModule.3.html\">page<\/a> as a way to programmatically load <a href=\"http:\/\/mirror.informatimago.com\/next\/developer.apple.com\/documentation\/Darwin\/Reference\/ManPages\/man3\/NSObjectFileImage.3.html\">plugins<\/a> after a program starts executing.<\/p>\n<h3>The Engine<\/h3>\n<p>The loaded module represents itself an engine driven by the JavaScript files.<\/p>\n<p>Some of the scripts reside in the app&#8217;s Resources directory in an encrypted form, forming an SDK. Other JavaScript files are fetched from a remote server as tasks (internally called &#8216;offers&#8217; as they are designed to offer \/ advertise other products).<\/p>\n<p><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/engine_schema.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-63212\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/engine_schema.png\" alt=\"\" width=\"640\" height=\"242\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/engine_schema.png 1720w, https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/engine_schema.png?resize=300,113 300w, https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/engine_schema.png?resize=768,290 768w, https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/engine_schema.png?resize=1024,387 1024w, https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/engine_schema.png?resize=1536,580 1536w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>The downloaded tasks rely on high-level function calls from the SDK. This allows composing tasks with a very flexible logic.<\/p>\n<p>There are several classes exposed by the engine to the SDK, such as:<\/p>\n<ul>\n<li>System controller<\/li>\n<li>Install<\/li>\n<li>Screenshot controller<\/li>\n<li>Task manager<\/li>\n<li>Collector info system<\/li>\n<li>Event reporter<\/li>\n<li>Application manager<\/li>\n<li>File downloader<\/li>\n<\/ul>\n<p>The engine itself is executed on macOS platform natively.<\/p>\n<p>For example, a JavaScript task may attempt to elevate the privilege level with the following call:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\">function relaunchWithRoot () {       installer.relaunchingWithRoot = true;       var successR = installer.elevatePrivilegedTask ();<\/pre>\n<p>The <em>elevatePrivilegedTask ()<\/em> call in JavaScript has a corresponding method in the engine&#8217;s class, such as <code>tr54jds23<\/code>. The engine exposes this method to JavaScript code so that it can be called directly from the engine.<\/p>\n<p>When <code>tr54jds23<\/code> -&gt; <em>elevatePrivilegedTask ()<\/em> is executed, the engine calls another method: <code>ICTaskManager<\/code> -&gt; <em>elevatePrivilegedTask ()<\/em> .<\/p>\n<p>That will, in turn, create a task <code>ICTaskManager<\/code>-&gt; <em>root_Task<\/em> . The task will then create an authorization with the <code>system.privilege.admin<\/code>flag. Next, the task is executed with the <em>AuthorizationExecuteWithPrivileges ()<\/em> call.<\/p>\n<p>In practice, this may invoke a dialog asking for admin password so that the task can be executed as root.<\/p>\n<h3>String \/ API Encryption<\/h3>\n<p>The engine module stores the names of all critical functions and most critical strings encoded. In one of the analyzed samples, there are 1,228 encoded strings, decoded with 1,055 different functions. That is, some strings are decoded with the same function.<\/p>\n<p>All the string decoding functions use different keys, but they implement one of the following 3 algorithms:<\/p>\n<ul>\n<li>Simple XOR key<\/li>\n<li>Simple key subtraction<\/li>\n<li>Auto-incremented XOR key<\/li>\n<\/ul>\n<p>One of the string decryption routines can be demonstrated with the anti-debugging trick explained in the next section.<\/p>\n<h3>Anti-debugging Trick<\/h3>\n<p>An attempt to attach to or run the bundleware app under a debugger produces the following error:<\/p>\n<pre style=\"background-color: #27292c;line-height: 125%;color: silver;padding-top: 1em;padding-bottom: 1em\"><span style=\"color: cyan\">mac: \/ user $ sudo lldb \/Users\/user\/Installer\/Installer.app  (lldb) target create \"\/Users\/user\/Installer\/Installer.app\"  Current executable set to '\/Users\/user\/Installer\/Installer.app' (x86_64).  (lldb) r  Process 1280 launched:  '\/Users\/user\/Installer\/Installer.app\/Contents\/MacOS\/radiosurgical' (x86_64)  <span style=\"color: yellow\">Process 1280 exited with status = 45 (0x0000002d)<\/span><\/span><\/pre>\n<p>The anti-debugging defense is provided with <em>ptrace ()<\/em> request named <code>PT_DENY_ATTACH<\/code>( <code>0x1F<\/code>), called from the function below:<\/p>\n<pre style=\"background-color: #000064;line-height: 125%;color: silver;padding-top: 1em;padding-bottom: 1em\"><span style=\"color: cyan\">ptrace = 0x515D5A5D;                       <span style=\"color: #00ff00\">\/\/ encrypted 'ptrace' string: 5D 5A 5D 51   <span style=\"color: cyan\">ptrace_plus_4 = 0x5752;                    <span style=\"color: #00ff00\">\/\/ 52 57   <span style=\"color: cyan\">ptrace_plus_6 = 0x33;                      <span style=\"color: #00ff00\">\/\/ 33   <span style=\"color: cyan\">ptrace [0] = <span style=\"color: white\">add_2D_xor (0x5D, 0);           <span style=\"color: #00ff00\">\/\/ decrypt 1st char (5D ^ (2D + 0))   <span style=\"color: cyan\">i = 1;                                     <span style=\"color: #00ff00\">\/\/ start loop from the 2nd char  do  {                                           <span style=\"color: #00ff00\">\/\/ decrypt the rest       <span style=\"color: cyan\">ptrace [ <span style=\"color: cyan\">i ] = <span style=\"color: white\">add_2D_xor ( <span style=\"color: cyan\">ptrace [ <span style=\"color: cyan\">i ], <span style=\"color: cyan\">i );  <span style=\"color: #00ff00\">\/\/ ptrace [i] ^ = 2D + i       <span style=\"color: cyan\">i ++;  }  while ( <span style=\"color: cyan\">i ! = 6);                            <span style=\"color: #00ff00\">\/\/ 6 characters from the 2nd char, including \/ 0   <span style=\"color: cyan\">fn_ptrace = <span style=\"color: cyan\">dlsym (RTLD_NEXT, &amp; <span style=\"color: cyan\">ptrace );     <span style=\"color: #00ff00\">\/\/ get proc address from the linked dylibs   return <span style=\"color: cyan\">fn_ptrace ( <span style=\"color: yellow\">PT_DENY_ATTACH , 0, 0, 0); <span style=\"color: #00ff00\">\/\/ call ptrace () by pointer, deny tracing<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/pre>\n<p>If the process is being debugged, as defined in man <a href=\"http:\/\/mirror.informatimago.com\/next\/developer.apple.com\/documentation\/Darwin\/Reference\/ManPages\/man2\/ptrace.2.html\"><code>ptrace<\/code><\/a>, it will exit with the exit status of <code>ENOTSUP<\/code>( <code>45<\/code>), <em>&#8216;error, not supported&#8217;<\/em> . Otherwise, it sets a flag that denies future traces &#8211; an attempt to debug it with this flag set will result in a segmentation violation exception.<\/p>\n<p>By stepping over a call into the function that denies tracing (or NOP-ing the 5 bytes of the call), the anti-debugging trick above can be easily circumvented:<\/p>\n<pre style=\"background-color: #27292c;line-height: 125%;color: silver;padding-top: 1em;padding-bottom: 1em\">-&gt;   <span style=\"color: orange\">0x103dd1ff5 &lt;+25&gt;: callq 0x103e30cd3                ; <\/span>call the function with ptrace ()      0x103dd1ffa &lt;+30&gt;: callq 0x103de03aa; ICCrashLogger :: sharedLogger ()      0x103dd1fff &lt;+35&gt;: movq% rax,% rdi  (lldb) <span style=\"color: yellow\">re w pc `$ pc + 5`       <span style=\"color: #00ff00\">; <\/span>step over the call by adding 5 bytes to $ pc   (lldb) <span style=\"color: yellow\">x \/ 2i $ pc              <span style=\"color: #00ff00\">; <\/span>now $ pc (pseudo-name for RIP) points to the next instruction  -&gt; 0x103dd1ffa: e8 ab e3 00 00 callq 0x103de03aa; <\/span>ICCrashLogger :: sharedLogger ()      0x103dd1fff: 48 89 c7 movq% rax,% rdi<\/span><\/pre>\n<h3>Obfuscation Variations<\/h3>\n<p>Some samples of this bundleware family contain variations in the string encryption algorithm.<\/p>\n<p>For example, a hard-coded integer number <code>6<\/code>within a decryption function can be encoded with a separate function, as shown below:<\/p>\n<pre style=\"background-color: #000064;line-height: 125%;color: silver;padding-top: 1em;padding-bottom: 1em\"><span style=\"color: yellow\">get_6 proc near          push rbp          mov rbp, rsp          mov al, <span style=\"color: cyan\">3          <span style=\"color: #00ff00\">; <\/span>al = 3           shl al, <span style=\"color: cyan\">2          <span style=\"color: #00ff00\">; <\/span>al = 12           movsx ecx, al        <span style=\"color: #00ff00\">; <\/span>ecx = 12           mov eax, <span style=\"color: cyan\">65        <span style=\"color: #00ff00\">; <\/span>eax = 65           xor edx, edx       <span style=\"color: #00ff00\">; <\/span>edx = 0           idiv ecx            <span style=\"color: #00ff00\">; <\/span>65\/12, eax = 5           mul cl             <span style=\"color: #00ff00\">; <\/span>eax = 60           mov cl, <span style=\"color: cyan\">65         <span style=\"color: #00ff00\">; <\/span>cl = 65           sub cl, al         <span style=\"color: #00ff00\">; <\/span>cl = 65 - 60 = 5           inc cl             <span style=\"color: #00ff00\">; <\/span>cl = 6           movsx eax, cl        <span style=\"color: #00ff00\">; <\/span>result = 6          pop rbp          retn  <span style=\"color: yellow\">get_6 endp<\/span><\/span><\/span><\/span><\/span><\/span><\/pre>\n<p>The same function is collapsed by the Hex-Rays Decompiler into:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\">signed __int64 get_6 ()  {      return 6;  }<\/pre>\n<h3>VM Evasion<\/h3>\n<p>Because of their advertising-based business model, the developers of this bundleware installer go to great lengths to prevent fraud by those looking to pump up the monetization of their apps using large numbers of virtual machine installs. The engine is able to detect the presence of a virtual environment through the method <em>checkPossibleFraud ()<\/em> . This method is exposed to JavaScript, where it can be called as:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\">var isVm = system.checkPossibleFraud ()&gt; 0? 1: 0;<\/pre>\n<p>To achieve that, the engine compiles a so called &#8216;fraud&#8217; report that consists of the following details:<\/p>\n<ul>\n<li><code>MAC_L<\/code><br \/> MAC and IP addresses for all network interfaces, to recognize sandboxes that rely on a common network setup.<\/li>\n<li><code>vmVendor<\/code><br \/> The engine checks if the MAC address starts from an address that is common for a given VM manufacturer. For example, if the MAC address starts from <code>00:1C:42<\/code>, the installer determines that it&#8217;s running under a <em>Parallels<\/em> VM.<br \/> Using this trick for over 35 known MAC prefixes, it reports the following VM vendors (the vendor names are shown exactly as the installer reports them):<\/p>\n<ul>\n<li>Parallels ID.<\/li>\n<li>Egenera, Inc.<\/li>\n<li>First Virtual Corporation<\/li>\n<li>linux kernal virtual machine (kvm)<\/li>\n<li>Virtual Iron Software, Inc. (was: Katana Technology)<\/li>\n<li>Paravirtual Corporation (was: Accenia, Inc.)<\/li>\n<li>Virtual Conexions<\/li>\n<li>Virtual Computer Inc.<\/li>\n<li>virtual access, ltd.<\/li>\n<li>Virtual Instruments<\/li>\n<li>Virtualtek. Co. Ltd<\/li>\n<li>VMware, Inc.<\/li>\n<li>Microsoft Corporation (was: Connectix)<\/li>\n<li>Microsoft Corp.<\/li>\n<li>Microsoft Network Load Balancing Service Heartbeat<\/li>\n<li>Microsoft XCG<\/li>\n<li>Oracle Corporation (was: Virtual Iron Software)<\/li>\n<li>Oracle Corporation (was: Xsigo Systems, Inc.)<\/li>\n<li>Oracle Corporation (was: Sun Microsystems, Inc)<\/li>\n<li>CADMUS COMPUTER SYSTEMS<\/li>\n<\/ul>\n<\/li>\n<li><code>Host UUID<\/code><br \/> Reported by <em>gethostuuid ()<\/em> , to recognise common sandboxes.<\/li>\n<li><code>hddName<\/code><br \/> The engine collects data reported by <em>DADiskCreateFromBSDName ()<\/em> for <code>\/dev\/disk0<\/code>device, to recognise HDD presumably common for some sandbox installations.<\/li>\n<li><code>usbFraud<\/code><br \/> A list of USB devices, presumably common for certain VMs, as reported by calling:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\">ioreg -l | grep -e 'USB Vendor Name'<\/pre>\n<\/li>\n<li><code>dispRats<\/code><br \/> Report display ratio, to recognize display ratios used in common sandboxes.<\/li>\n<li><code>lastMove<\/code><br \/> Report mouse position since the last mouse movement event, to see if a VM was restored from a clean snapshot.<\/li>\n<li><code>lastRbt<\/code><br \/> Gets system up-time, since last reboot, to recognize a VM restored from a snapshot.<\/li>\n<li><code>dmgLoc<\/code>, <code>fromDMG<\/code><br \/> Gets full path filename of the DMG file, in case it&#8217;s executed by a sandbox under a generic name, such as using file hash.<\/li>\n<li><code>wndPos<\/code><br \/> Gets position and size of the app&#8217;s window.<\/li>\n<li><code>msePos<\/code><br \/> Gets mouse position, to see if mouse is in use.<\/li>\n<\/ul>\n<h3>Crash Logger<\/h3>\n<p>The crash logger in the samples we examined sends a GET request to a remote script, disguised as a PNG file:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\">http [: \/\/] ec2-54-191-37-103.us-west-2.compute.amazonaws [.] com \/ black.png<\/pre>\n<p>The stats it submits to the remote script are encoded as URL parameters:<\/p>\n<ul>\n<li><code>crash=1<\/code><\/li>\n<li><code>os=mac<\/code><\/li>\n<li><code>appkit=%APP_KIT%<\/code><\/li>\n<li><code>ver=%VERSION%<\/code><\/li>\n<li><code>ldebug=%LIVE_DEBUG%<\/code><\/li>\n<li><code>backtrace=%CALL_BACKTRACE%<\/code><\/li>\n<\/ul>\n<h3>Configuration<\/h3>\n<p>The installer uses two configuration files. The first one is dynamically extracted from an unused cavity of the installer&#8217;s own DMG file. This configuration is written into the DMG file (a process internally called &#8216;injection&#8217;) after the DMG file is built, and is encrypted with AES-128 algorithm.<\/p>\n<p>To locate the encrypted config within the DMG file, the installer module parses the contents of the file. For each pair of bytes, it subtracts one byte from another, until if locates the following signature that consists of 7 64-bit integers, such as:<\/p>\n<pre style=\"background-color: #000064;line-height: 125%;color: silver;padding-top: 1em;padding-bottom: 1em\">__const: 0000000103E51C40    <span style=\"color: white\">signature    dq <span style=\"color: cyan\">0Fh , <span style=\"color: cyan\">9 , <span style=\"color: cyan\">3Eh , <span style=\"color: cyan\">23h , <span style=\"color: cyan\">7 , <span style=\"color: cyan\">86h , <span style=\"color: cyan\">0Ch<\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/span><\/pre>\n<p>Once located, the config is then extracted and decrypted. As shown in the example below, the extracted configuration specifies the URL of an application to download and install:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\"><span style=\"color: #900\"><strong>PRODUCT_TITLE<\/strong><\/span> = Duolingo% 202017  <span style=\"color: #900\"><strong> PRODUCT_DESCRIPTION<\/strong><\/span> = To% 20install% 20Duolingo% 202017% 20for% 20Mac% 20click% 20Continue.  <span style=\"color: #900\"><strong>PRODUCT_VERSION<\/strong><\/span> = Mac  <span style=\"color: #900\"><strong> PRODUCT_PUBLIC_DATE<\/strong><\/span> = 2017  <span style=\"color: #900\"><strong> PRODUCT_FILE_NAME<\/strong><\/span> = Duolingo% 20% 20Setup  <span style=\"color: #900\"><strong> PRODUCT_FILE_SIZE<\/strong><\/span> = 260.8% 20MB  <span style=\"color: #900\"><strong> CHNL<\/strong><\/span> = download7-Duolingo  <span style=\"color: #900\"><strong> DOWNLOAD_URL<\/strong><\/span> = http% 3A% 2F% 2Fcdn.downloadfree2.com% 2Fmacsoftware% 2FBlueStacks Installer.dmg  <span style=\"color: #900\"><strong> PRODUCT_LOGO_URL<\/strong><\/span> = http% 3A% 2F% 2Fwww.download7.co% 2Fgamegraphics% 2F90.png  <span style=\"color: #900\"><strong> ROOT_IF_INSTALLED<\/strong><\/span> = com.bluestacks.BlueStacks  <span style=\"color: #900\"><strong> APP_NAME<\/strong><\/span> = BlueStacks  <span style=\"color: #900\"><strong> TOS_URL<\/strong><\/span> = http% 3A% 2F% 2Fwww.download7.co% 2Feula.html  <span style=\"color: #900\"><strong>TYP<\/strong><\/span> = http% 3A% 2F% 2Fpiroga.space% 2Fpages% 2FDM% 2FDMTYP.html% 3Foffers% 3D  <span style=\"color: #900\"><strong> EXIT_PAGE_URL<\/strong><\/span> = http% 3A% 2F% 2Fpiroga.space% 2Fpages% 2FDM% 2FDMInter.html  <span style=\"color: #900\"><strong> PRIVACY_URL<\/strong><\/span> = http% 3A% 2F% 2Fwww.download7.co% 2Fprivacy.html  <span style=\"color: #900\"><strong> ISPBROWSER<\/strong><\/span> = ch  <span style=\"color: #900\"><strong> % 40REPORT_ADD_PARAMS<\/strong><\/span> = IRONBRO_ID% 253D9309% 2526INST_GUID% 253D4136ef6c-c79c-49b3 -...  <span style=\"color: #900\"><strong> INST_GUID<\/strong><\/span> = 4136ef6c3e -794<\/pre>\n<p>The 2nd configuration file is provided as a JavaScript file, and is decrypted with the other SDK files from the app&#8217;s Resources directory.<\/p>\n<p>This configuration defines multiple operational parameters, such as report and ad servers:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\"><span style=\"color: #0000ff\">var appInfo = {      report: <span style=\"color: #a31515\">'http: \/\/ rp. [REMOVED] .com' ,      ad_url: <span style=\"color: #a31515\">\u2019http:\/\/os.[REMOVED].com\/MacDarwenDLM\/?v=5.0\u2019<\/span>,      requires_root: <span style=\"color: #0000ff\">false<\/span>,      root_if_installed: [<span style=\"color: #a31515\">\u2019\u2019<\/span>],      skip_vm_check: <span style=\"color: #0000ff\">false<\/span>,      ...  <\/span><\/span><\/pre>\n<h3>Report Server<\/h3>\n<p>The report server from the configuration is used to receive posted reports.<\/p>\n<p>The example below demonstrates what data is posted to the report server:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\"><span style=\"color: #900\"><strong>AC<\/strong><\/span> = DarwenDLM  <span style=\"color: #900\"><strong>PrID<\/strong><\/span> = MacDarwenDLM  <span style=\"color: #900\"><strong>PrSub<\/strong><\/span> = MacDarwenDLM  <span style=\"color: #900\"><strong>RS<\/strong><\/span> = Q  <span style=\"color: #900\"><strong>IRVER<\/strong><\/span> = 106.1712  <span style=\"color: #900\"><strong>CHNL<\/strong><\/span> = download7-Duolingo  <span style=\"color: #900\"><strong>PROD_TITLE<\/strong><\/span> = Duolingo 2017  <span style=\"color: #900\"><strong>schemeName<\/strong><\/span> = MacDarwenDLM  <span style=\"color: #900\"><strong>OSName<\/strong><\/span> = OSX  <span style=\"color: #900\"><strong>OSVer<\/strong><\/span> = 10.12  <span style=\"color: #900\"><strong>OSLang<\/strong><\/span> = en  <span style=\"color: #900\"><strong>_makeDate<\/strong><\/span> = 201711091722  <span style=\"color: #900\"><strong>SDT<\/strong><\/span> = 20181004195204931  <span style=\"color: #900\"><strong>UID<\/strong><\/span> = 9C0C266E-266D-4D98-B83C-BCB2A3018EB7  <span style=\"color: #900\"><strong>BRW<\/strong><\/span> = Safari  <span style=\"color: #900\"><strong>OSPlat<\/strong><\/span> = 2  <span style=\"color: #900\"><strong>MAC_L<\/strong><\/span> = [REMOVED]000000000000%3A127.0.0.1%3A24%3A0  <span style=\"color: #900\"><strong>hddSize<\/strong><\/span> = 107374182400  <span style=\"color: #900\"><strong>_makerver<\/strong><\/span> = total20171107115116  <span style=\"color: #900\"><strong>Isuseradmin<\/strong><\/span> = 1  <span style=\"color: #900\"><strong>isVmDef<\/strong><\/span> = 1  <span style=\"color: #900\"><strong>inst_flv<\/strong><\/span> = no_injection_106.1712  <span style=\"color: #900\"><strong>dwa.SrcNo<\/strong><\/span> = 1  <span style=\"color: #900\"><strong>QuitPage<\/strong><\/span> = welcomePage  <span style=\"color: #900\"><strong>RepCnt<\/strong><\/span> = 1  <span style=\"color: #900\"><strong>ofrClPrm<\/strong><\/span> = 266E-266D-4D98-B83C-BCB2A3018EB7<\/pre>\n<p>As seen in the example, the data it posts contains basic system information, such as macOS version number (<code>OSVer<\/code>), language (<code>OSLang<\/code>), MAC and IP addresses for all network interfaces (<code>MAC_L<\/code>), default browser name (<code>BRW<\/code>), HDD size, whether a VM was detected or not (<code>isVmDef<\/code>), whether user is admin (<code>isuseradmin<\/code>), and some other parameters.<\/p>\n<p>The collected data is assembled into a text, then encrypted with AES-128, and posted to the server:<\/p>\n<p><a href=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/image3.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-54175\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/image3.png?w=640\" alt=\"\" width=\"640\" height=\"171\" srcset=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/image3.png 661w, https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/image3.png?resize=300,80 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<h3>Tasks<\/h3>\n<p>Remote tasks are received encrypted from the ad server, as shown below:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\">POST <span style=\"color: #05b\">os.[REMOVED].com\/MacDarwenDLM\/?v=5.0<\/span>  USER-AGENT: <span style=\"color: #05b\">ICMAC<\/span>  Response:      Header: X-ICSCT-SERVER-NAME: <span style=\"color: #05b\">ads-slave-1111-production-us-west-2-i-07e9c6437616f3e49<\/span>      Data: 85,368 bytes binary [<span style=\"color: #d04000\">6c ec 6c 99...<\/span>]<\/pre>\n<p>When the received task is decrypted, its data is split into named sections. Each section is surrounded with the following comments:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\"><span style=\"color: #05b\">var<\/span> namestartstr = \u2019<span style=\"color: #d04000\">&lt;!--SECTION NAME=\"<\/span>\u2019;  <span style=\"color: #05b\">var<\/span> nameendstr = \u2019<span style=\"color: #d04000\">\"--&gt;<\/span>\u2019;  <span style=\"color: #05b\">var<\/span> sectionendstr = \u2019&lt;<span style=\"color: #d04070\">!--\/SECTION--&gt;<\/span>\u2019;<\/pre>\n<p>The parser extracts JavaScript code from those sections. That code will then rely on APIs exposed by the SDK, to drive the engine that exposes its own API interface to the SDK.<\/p>\n<p>The nature of the received tasks may depend on the presence of VM (a condition, internally called \u2019fraud\u2019).<\/p>\n<p>An analysis of the tasks received from the ad server reveals no malicious activity.<\/p>\n<h3>Engine Capabilities<\/h3>\n<p>The bundleware\u2019s engine consists of the several components, capable of doing the following:<\/p>\n<ul>\n<li style=\"list-style-type: none\">\n<ul>\n<li>Browser manager\n<ul style=\"list-style-type: square\">\n<li>detects supported browsers, such as Safari, Google Chrome, Firefox<\/li>\n<li>terminates browser process<\/li>\n<li>sets new home page<\/li>\n<li>reads Chrome preferences<\/li>\n<li>clears Chrome cache<\/li>\n<li>reads Firefox preferences<\/li>\n<\/ul>\n<\/li>\n<li>Logger\n<ul style=\"list-style-type: square\">\n<li>takes full screen snapshot<\/li>\n<li>takes installer window\u2019s snapshot<\/li>\n<li>submits \u2019live debug\u2019 information to the remote server<\/li>\n<\/ul>\n<\/li>\n<li>Screenshot controller\n<ul style=\"list-style-type: square\">\n<li>takes full screen snapshot with the mouse location<\/li>\n<li>collects a set of screenshots<\/li>\n<li>takes snapshot of a given window<\/li>\n<\/ul>\n<\/li>\n<li>Task manager\n<ul style=\"list-style-type: square\">\n<li>downloads and execute new tasks\n<ul style=\"list-style-type: circle\">\n<li>submits task execution output<\/li>\n<li>runs tasks with the privilege level elevated to root<\/li>\n<\/ul>\n<\/li>\n<li>creates authorisation for tasks, using given credentials<\/li>\n<\/ul>\n<\/li>\n<li>System controller\n<ul style=\"list-style-type: square\">\n<li>collects system OS version<\/li>\n<li>collects mac address and IP for all interfaces<\/li>\n<li>collects all cookies from Safari, Google Chrome, Firefox<\/li>\n<li>collects the list of all installed applications<\/li>\n<li>collects the list of running applications<\/li>\n<li>checks the presence of VM<\/li>\n<li>gets home page for all supported browsers<\/li>\n<li>gets system default browser<\/li>\n<li>adds\/removes applications to\/from dock<\/li>\n<li>adds applications to dock<\/li>\n<li>checks if user is admin<\/li>\n<li>checks if a given process runs as admin<\/li>\n<li>gets user name<\/li>\n<li>gets user locale\/language<\/li>\n<li>gets free space of start-up volume<\/li>\n<li>gets info about connected iOS devices:\n<ul style=\"list-style-type: circle\">\n<li>device class (iPod\/iPad\/iPhone)<\/li>\n<li>device identifier<\/li>\n<li>device serial number<\/li>\n<\/ul>\n<\/li>\n<li>builds \u2019fraud\u2019 report (info about detected VM)<\/li>\n<li>collects the following lists:\n<ul style=\"list-style-type: circle\">\n<li>running processes<\/li>\n<li>keyboard input sources<\/li>\n<li>graphics card names<\/li>\n<li>USB devices<\/li>\n<li>apps launched automatically on login<\/li>\n<li>launch daemons and agents<\/li>\n<li>user launch agents<\/li>\n<li>Google Chrome extension names<\/li>\n<li>Safari extension names<\/li>\n<li>Firefox extension names<\/li>\n<\/ul>\n<\/li>\n<li>searches for files in the specified directory<\/li>\n<li>checks if the specified application is running<\/li>\n<li>terminates specified applications<\/li>\n<li>encrypts\/decrypts data<\/li>\n<li>gets user paths, such as local applications, download paths<\/li>\n<li>checks if an application is installed by the specified name<\/li>\n<li>reads key values from user defaults<\/li>\n<li>gets default apps for all available extensions<\/li>\n<li>adds an app to dock as persistent item<\/li>\n<li>removes all persistent apps from dock for specified path<\/li>\n<li>reads text files<\/li>\n<li>copies given directory to a new location<\/li>\n<li>deletes the specified directory<\/li>\n<li>run specified script with <code>\u2019\/bin\/sh\u2019<\/code>, as root<\/li>\n<li>checks if the specified file exists<\/li>\n<li>gets detailed HDD information<\/li>\n<li>collects network information<\/li>\n<li>downloads files<\/li>\n<li>reads\/sets window title for running apps<\/li>\n<li>reads mouse position<\/li>\n<li>displays alerts<\/li>\n<li>launches tasks\/applications as root<\/li>\n<li>copies\/moves files<\/li>\n<li>opens URLs<\/li>\n<li>saves data to files<\/li>\n<li>checks if path is writable<\/li>\n<li>creates\/deletes directories<\/li>\n<li>gets specified file size\/attributes<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h3>CI\/CD pipeline<\/h3>\n<p>The authors of the bundleware have apparently adopted <a href=\"https:\/\/jenkins.io\/\">Jenkins<\/a>, an open source tool for building Continuous Integration and Continuous Delivery (CI\/CD) pipelines.<\/p>\n<p>This fact is evident from the full path names of the source files that are still visible in the compiled engine module, such as:<\/p>\n<pre style=\"background-color: white;line-height: 125%;padding-top: 1em;padding-bottom: 1em\">\/Users\/[REMOVED]-ai\/jenkins\/workspace\/AI_Mac_Release_Production\/continuous-integration\/mac_team_repo\/Sources\/[REMOVED]Utils.mm<\/pre>\n<p>With Continuous Integration in place, every commit made to the source code in the Git repository is pulled and built automatically. If it results in a bug, the developers can quickly identify the responsible commit.<\/p>\n<p>Continuous Integration pipeline also allows automated testing and deployment. Apart from reducing the length of time it takes to release new PUA builds, it also allows to increase their quality.<\/p>\n<h3>Conclusion<\/h3>\n<p>Being a legitimate distribution platform, the techniques employed by this popular bundleware product conceal a very powerful engine.<\/p>\n<p>When viewed from a certain angle, this engine resembles a backdoor as it unlocks full access to the system.<\/p>\n<p>The sheer power of the engine is made covert with the wisely engineered trickery. Some of its methods, such as loading code from memory, are known from the \u201cThe Mac Hacker\u2019s <a href=\"https:\/\/www.amazon.com\/Mac-Hackers-Handbook-Charlie-Miller\/dp\/0470395362\">Handbook<\/a>\u201d, and rightly belong to the world of malware.<\/p>\n<p>Given that the engine is driven by symmetrically encrypted remote tasks, any researcher who pays attention to detail couldn\u2019t help but wonder what would happen if the control of its engine was intercepted.<\/p>\n<p>Careful analysis of these techniques also demonstrates a disturbing trend we\u2019re witnessing \u2013 the continued \u2019spill\u2019 of the traditional <em>Windows<\/em> malicious techniques, such as run-time packing, strings\/API obfuscation, memory injection into the <em>Mac<\/em> world.<\/p>\n<p>Even though the installer itself is legitimate, an analysis of state-of-art code where these techniques are honed to perfection is vitally important for the researchers to understand what opportunities exist on the <em>macOS<\/em> platform, to be better prepared for the challenges that lay ahead of us.<\/p>\n<p><em>This report is based on research <a href=\"https:\/\/www.virusbulletin.com\/conference\/vb2019\/abstracts\/never-had-stierlitz-been-so-close-failure\">previously presented at Virus Bulletin&#8217;s VB2019 conference<\/a> .<\/em><\/p>\n<\/p><\/div>\n<p><a href=\"http:\/\/feedproxy.google.com\/~r\/sophos\/dgdY\/~3\/n8Txqmat4RA\/\" target=\"bwo\" >http:\/\/feeds.feedburner.com\/sophos\/dgdY<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p><img decoding=\"async\" src=\"https:\/\/news.sophos.com\/wp-content\/uploads\/2018\/11\/image1.jpeg?w=300\"\/><\/p>\n<p><strong>Credit to Author: Sergei Shevchenko| Date: Tue, 17 Mar 2020 08:00:58 +0000<\/strong><\/p>\n<p>Security software frequently blocks \u201cbundleware\u201d installers &amp;#8211; software distribution tools that bundle their advertised applications with (usually undesired) additional software &amp;#8211; as potentially undesirable applications. But one widely-used software distribution tool for MacOS applications goes to great lengths to avoid being blocked as \u201cbundleware\u201d &amp;#8211; using a number of anti-forensics techniques that are more common [&amp;#8230;]&lt;img src=&#8221;http:\/\/feeds.feedburner.com\/~r\/sophos\/dgdY\/~4\/n8Txqmat4RA&#8221; height=&#8221;1&#8243; width=&#8221;1&#8243; alt=&#8221;&#8221;\/&gt;<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"colormag_page_container_layout":"default_layout","colormag_page_sidebar_layout":"default_layout","footnotes":""},"categories":[10378,10377],"tags":[10379,10383,18513],"class_list":["post-17968","post","type-post","status-publish","format-standard","hentry","category-security","category-sophos","tag-corporate","tag-sophoslabs","tag-sophoslabs-uncut"],"_links":{"self":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/17968","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/comments?post=17968"}],"version-history":[{"count":0,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/posts\/17968\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/media?parent=17968"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/categories?post=17968"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.palada.net\/index.php\/wp-json\/wp\/v2\/tags?post=17968"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}