68 GB Stolen From a Philippine Government Agency’s Overseas-Employment Databases, Exposed by the Operator’s Own Open Directory

68 GB Stolen From a Philippine Government Agency’s Overseas-Employment Databases, Exposed by the Operator’s Own Open Directory

Published on

Over 68 GB of Philippine Overseas-Employment Database Backups Copied From an Exposed Staging Server

Disclosure note: Hunt.io notified the relevant national CERT prior to publication. No personal records or credentials from the affected systems appear in this report.


An operator copied 68.837 GiB of a Philippine government agency's database backups, logged the transfer for themselves, and then left that log open on the internet. We captured the directory while it was still serving.

The copy finished in under 24 minutes on 6 September 2026, 27 SQL Server backups whose names match the agency's overseas-employment and migrant-worker systems. Beside the log sat the operator's toolkit, a rebranded GodPotato build, a PowerShell stager, two payloads and a full Impacket environment.

The access log shows that tooling pulled the same evening, which establishes distribution from this server and nothing past it. How the operator got in, and whether any payload ran, are not in the capture.

Key Findings

We reverse-engineered the payload, traced the operator's logs, and pivoted the certificates to the agency itself. The key takeaways:

  • A staging host at UpCloud Ltd (AS202053) left the operator's working folder open through an unauthenticated HTTP directory on port 80, including the operator's own transfer and access logs

  • Completed 68.837 GiB copy of 27 SQL Server backups, transferred in 23m 46s at a tool-reported 20.238 MiB/s that does not reconcile with the volume and duration

  • Backup filenames matching the case-management systems of a Philippine overseas-employment and migrant-worker administration, including POEA and OFW variants

  • A rebranded GodPotato .NET build staged as Wrqsnx.dll and Wrqsnx_portal.dll, with the RPC pipe, namespace and assembly metadata renamed and internal identifiers left untouched

  • Two builds from two different compilers, the second compiled 6m 43s before it was retrieved

  • An eight-line PowerShell stager that rebuilds the payload in memory from base64 fragments, so no DLL touches disk

  • A full Impacket environment with no signs of modification, including LDAP and MSSQL relay checks and a tool targeting Windows Server 2025 domain controllers

  • No initial access vector, no command-and-control channel and no confirmed payload execution appear in the recovered data

The exposed staging server

Each point above traces back to a file the operator left in the open. We start with the server that served them.

The host 213.163.205[.]35:80 ran a Python HTTP server on port 80 with directory listing enabled, and it served the operator's working folder to anyone who asked. No defender found the exposure: the directory was captured while it was open. The access log records 543 requests from 76 distinct addresses across a 16-hour, 9-minute window on 6 and 7 September 2026.

Figure 01Figure 01: The capture in Hunt.io: the staging directory, served from 213.163.205[.]35:80 at UpCloud Ltd (AS202053), Singapore.

The operator's environment is identifiable from the recovered files, not from the host itself. The Impacket environment records its own path in its activation script: /tmp/imp. That places the toolkit in a temporary directory on the staging server, and it fits an operator working from a rented Linux host rather than a maintained workstation.

Most of the traffic against the directory was scanner noise with no link to the operation. The six addresses assessed below were selected for their retrieval of operational files; the remaining 70 requested only directory listings or common exploit paths. A WordPress and PHP RCE sweeper sent 49 requests and received 404 or 501 on every one.

A handful of addresses did more than scan, and they downloaded files. Their roles are assessed separately from their activity in the indicators section, because taking a file from an open directory establishes neither that the requester is the operator nor that it is a victim.

What the host exposed was the operator's working folder, not a finished deployment: more than a hundred files, including a payload builder and its source tree, two compiled payloads, a PowerShell stager, a complete Impacket environment, a small Python upload receiver, and the operator's own logs.

Figure 02Figure 02: The staging directory was captured: the payloads, the stager, the transfer logs and the Impacket environment, all in the open.

The upload receiver is a small Python service that binds port 8888 and writes request bodies to disk. Its companion log is zero bytes, but the handler contains no logging call, so the empty log is not evidence of disuse, and no received file was recovered. Whether the endpoint was ever used cannot be determined from this capture.

The logs are the most consequential files in the directory, and they are treated in their own section below.

Wrqsnx: a rebranded GodPotato

The payload is the most detailed piece in the directory, so we start there.

The payload is GodPotato, a publicly available .NET tool. It turns the rights of a service account into full SYSTEM control through DCOM and RPC, and it needs no Windows vulnerability to do it. The operator rebuilt it under the name Wrqsnx and renamed the namespace, the context classes, the pipe path and the assembly metadata, while leaving the source file names and some internal field names unchanged. That gap is a fingerprint: the tool is public, and the copy is lightly edited.

Microsoft's platform detects the payload as Trojan:MSIL/GodPotato.FF!MTB. That corroborates the lineage independently of our code reading. Everything below is read from the recovered files; none of it was observed running.

Rebuilding the payload in memory

The stager runs the payload without ever writing a DLL to disk. It is eight lines of PowerShell. It collects the base64 fragments named p_*.b64 from C:\Users\Public in filename order, joins them, strips whitespace, decodes the result in memory, loads it as a .NET assembly and calls its Main method.

The design has two weak points the operator accepted. The join depends on fixed-width fragment names, and the script never checks this. And the completion marker, POTATO_FIRED, only shows that the stager reached its last line: failures inside the payload are caught and swallowed, so the marker says nothing about SYSTEM.

Figure 03Figure 03: portalload.ps1 as served and no DLL touches disk.

Nothing in the stager validates the fragments, so whatever the files contain is what gets loaded.

Finding the target in memory

The payload takes over one decision inside Windows RPC. Hardcoding the location of that decision would work on a single Windows build, so the payload finds it at runtime instead. It copies the combase.dll module image into memory and searches for a short byte pattern: the size of the structure it wants followed by a known interface identifier.

From the first match, it follows the structure's own records to the dispatch table and learns how many arguments the routine it wants to replace takes, between four and fourteen. That count changes between Windows versions, and the payload reads it instead of assuming it.

Figure 04Figure 04: Finding combase.dll at runtime and building the 20-byte search pattern.

The second figure carries the walk on from the match to the pointer the payload replaces.

Figure 05Figure 05: Walking RPC_SERVER_INTERFACE and MIDL_SERVER_INFO to reach the dispatch table pointer.

The walk reads the layout Windows ships, so the same code reaches the routine on any build.

Taking over the RPC lookup

When Windows needs to reach an interface, one routine answers a single question: which transport does it use? The payload takes that routine over. It makes the dispatch table writable, replaces the first entry, the transport chooser, with a pointer to its own function, and stores the original pointer to put back later.

One thing is never put back. The memory page was made writable and stays writable after the process exits. No code is injected, and the change is four bytes wide, so it escapes tools that scan for injected code. It is the clearest trace the tool leaves on a host.

Figure 06Figure 06: HookRPC makes the page writable; Restore rewrites the pointer but not the page protection.

The two functions sit beside each other in the source, and the page permission is the only thing they disagree on.

Pulling in a SYSTEM connection

For the technique to work, a SYSTEM service has to connect to the payload. The payload creates the named pipe \.\pipe\Wrqsnx\pipe\epmapper with a descriptor that grants Everyone full control. That looks careless but is required, because a named pipe created normally would refuse the SYSTEM-context connection the technique depends on.

Figure 07Figure 07: The pipe is created with Everyone Full Control, a condition of the attack.

The payload then builds a genuine-looking COM object reference for a local object, rewrites its destination to point at the same machine with NTLM authentication, and hands it to CoUnmarshalInterface. combase asks the hooked lookup how to reach the interface, receives the pipe instead of a network address, and the DCOM resolver inside RPCSS, which runs as SYSTEM, opens the pipe. That is where the SYSTEM client comes from.

Figure 08Figure 08: The hooked routine answers combase with the pipe endpoint instead of a network address.

The answer the resolver receives is a pipe on the local machine, which is the connection the payload wants.

Stealing a SYSTEM token

With a SYSTEM client attached, the pipe thread impersonates the connected client, reads the system-wide handle table through NtQuerySystemInformation, and duplicates a token that matches three conditions: the local system SID S-1-5-18, an impersonation level of at least Impersonation, and System integrity or higher.

No memory corruption is involved at any point, and no vulnerability is exploited. Every call uses a permission the process already holds. The escalation works because a SYSTEM token is reachable in the table and the caller has the right to duplicate it.

Figure 09Figure 09: Reading the system handle table with NtQuerySystemInformation.

The search walks the table entry by entry, and the three conditions are the whole of the check.

Running the command

The payload runs one command as SYSTEM. It reads a base64 command from C:\Users\Public\ptcmd.txt, decodes it, runs it as cmd.exe /c under the stolen token, and pipes the output back to its own console. It prints the stolen identity with the result.

The child process is created without a window. That hides the console and nothing else: the creation event, the command line and the parent-child link are all recorded. The command file is not in the capture, so what ran as SYSTEM is not known.

Figure 10Figure 10: The stolen identity is printed, ptcmd.txt is read and decoded, the command runs as SYSTEM, and SHELL_DONE is written.

The output between the two markers belongs to the command, printed under the stolen identity.

Cleanup

The payload restores the original function pointer, connects to its own pipe and writes a single byte to release the waiting thread, then exits. Everything is reversed except the page protection from the third stage.

Two builds, one program

Two payloads were recovered. They are the same program from two different compilers, and the differences are the evidence. One build comes from Mono's mcs compiler and the other from Microsoft's Roslyn, based on three signals that agree: the compiler-generated class names, the image base, and the way field initialisers are placed.

The two builds differ in exactly one place, a stray dollar sign in an error message that never executes. The second build was compiled at 22:48:01 on 6 September and retrieved at 22:54:44, under seven minutes later. A fresh hash against hash-based blocking is the plausible reason, but no log states it.

The source tree and the served archive are byte-identical copies of the same eleven files, and the tree does not build. It calls a helper class named Sunday that ships in no file in the archive, and its project file declares an older .NET version than the binaries it produced. The tree matches the second build, not the first.

Figure 11Figure 11: The gp_build source tree: Program.cs, SharpToken.cs and the GodPotato project files.

The tree is the operator's build directory, and it is the last of the files left in the open.

The staged toolkit

The payload and its build tree were not the only tooling left in the open. The directory held a full Impacket environment, the standard toolkit for working with Windows networks from Linux. We swept all 69 Python scripts for hardcoded addresses, embedded data and added code, and found nothing. We did not diff them against upstream line by line, so a careful single-line edit could pass this check.

Two scripts check whether LDAP or MSSQL relay is viable against a target, and one filters domain controllers for Windows Server 2025. Those read as per-target checks rather than a spray.

The rest is the standard Active Directory attack surface, from secretsdump to five remote-execution methods. No tool in the set was observed in use, and the capture holds no command history, no tool output and no execution telemetry.

The exfiltration

The operator's own logs carry more weight than the payloads, because the operator wrote them for private use, not for an audience. The transfer log records a completed copy of 68.837 GiB across 27 files in 23 minutes 46 seconds.

2026/09/06 01:26:50 INFO  : POEA_EServices.bak: Multi-thread Copied (new)
Transferred:  68.837 GiB / 68.837 GiB, 100%, 20.238 MiB/s, ETA 0s
Transferred:  27 / 27, 100%
Elapsed time: 23m46.3s

                
Copy

Its counterpart records a failed attempt fourteen hours later against a source path of /data/chunk that no longer existed. That indicates the collection was assembled separately from the transfer and subsequently cleared.

The log does not name the source host or the destination remote. The volume and the displayed rate also do not reconcile: 68.837 GiB over 23 minutes 46 seconds averages approximately 49.4 MiB/s, while the summary line reads 20.238 MiB/s. Rclone's summary speed is a rolling average at completion, not total bytes divided by elapsed time, which accounts for the gap. We report both as logged.

The ordering of the transfer against the payload matters more than either figure. The transfer completed at 01:26:50 on 6 September and the first payload was fetched at 21:41:33 the same day, which the logs place approximately twenty hours later. So the payload was not the mechanism of the theft, and whatever access the operator held when the backups were copied was already sufficient.

That is as far as the operator's own files take us. The rest comes from what our platform already recorded about the host.

Infrastructure Analysis

The staging directory was served over port 80 from 213.163.205[.]35, a Linux host at UpCloud Ltd (AS202053) in Singapore. The Impacket virtual environment path, /tmp/imp, is recorded in the environment's own activation script. A separate Python service on the host binds port 8888 and accepts push uploads, though no received file was recovered and its use is not established. The transfer destination does not appear in the indicators, because the log does not name it. The staging address does appear: it is the same address published in the Hunt.io AttackCapture report covering this capture, so a defender who needs it for blocking has two sources for it.

Figure 12Figure 12: The staging host, flagged for the malicious open directory on 7 September 2026.

An automated capability check was run against the first payload as a cross-check and reported virtualisation and sandbox evasion, which we do not consider supported: the match derives from two token-enumeration names in a bundled third-party library, and no environment detection exists anywhere in the payload or that library. The same check reported no process injection and no event-triggered execution, which agrees with our own reading.

Our AttackCapture platform indexed the staging directory on 7 September 2026, and the same platform keeps the scan telemetry, the certificates and the directory listings behind it. We queried our tables for every address in the log, so each statement below rests on a record and can be reproduced with the query printed beside it.

The staging host

Our record for 213.163.205[.]35 gives the operator's platform: UpCloud Ltd (AS202053), Singapore, in the range 213.163.192[.]0/20, behind the PTR 213-163-205-35.sg-sin1.upcloud.host. The platform carries one warning on the address and nothing else: a potential malicious open directory, dated 7 September 2026.

Figure 13Figure 13: The staging host listening on port 80, running a SimpleHTTP/0.6 Python/3.13.5 under the title Directory listing for

The open ports confirm the capture's own story and add one detail. Port 80 answered with SimpleHTTP/0.6 Python/3.13.5 under the title Directory listing for /, which is Python's built-in server, started by hand. Port 887 carried a self-signed *.aapanel.com certificate valid to November 2035, and 887 is aaPanel's default port, so the VPS was run through that panel. The same port 80 had answered as WebSockify Python/3.11.2 in September 2025, a browser terminal bridge of the kind these panels install, so the host was set up as a managed VPS well before the intrusion. The SSH banner is OpenSSH_10.0p2 Debian-7+deb13u4, a current Debian release, seen up to 8 September 2026.

Our crawler indexed the directory at 13:47 UTC on 7 September. Its index holds 141 entries, 112 files and 29 directories, matching the capture package. A second pass that evening, from 20:02 to 01:05, recorded the names of files it did not download and reached deeper into the Impacket environment than the capture does, including the site-packages versions.

Both queries below return that record, the first the host's HTTP history and the second the filenames our crawler indexed from the open directory.

SELECT * FROM ip.events.http.history WHERE ip = '213.163.205.35'

SELECT * FROM open_directory_filenames WHERE hostname LIKE 'http://213.163.205.35%'

                
Copy

Neither our malware tracking nor the C2 feed holds a record for this host, and no address in its /24 is flagged either. The staging server never probed our sensors.

The requesting addresses, by role

The staging host is one address in the log. The other five are the ones that reached in and pulled files.

Our bulk enrich feature helps view the six addresses and puts provider, country, VPN flags and the capture hit in one place. The roles below are read from the access log against the certificate and scanner evidence.

Figure 14Figure 14: The six addresses in one view: provider, country, VPN flag and the AttackCapture hit on the staging host.

The table below sets out what each address did in the log and how that activity is read.

AddressNetworkIn the access logAssessment
213.163.205[.]35UpCloud Ltd (AS202053), Singaporeserved the directorystaging and delivery host
121.58.231[.]55Converge ICT (AS17639), Mandaluyong, PHloader twice, both payloads, 21:38:42 to 22:54:44agency portal host, certificate match
121.58.231[.]35Converge ICT (AS17639), Mandaluyong, PHsource archive eleven attempts, 21:56:03 to 22:30:41agency portal host, certificate match
156.59.127[.]203Zenlayer (AS21859)source archive eleven times, second payloadSSL VPN appliance, no role established
172.105.82[.]111Linode, now Akamai (AS63949), Frankfurtwalked the tree over nine hours and took the toolingmass scanner
158.178.237[.]116Oracle (AS31898), Singaporeswept the directory in sixteen secondsCVE scanner

Both queries below back the table, the first returning the current enrichment for all six addresses at once and the second checking each against our honeypot records.

SELECT * FROM ip.current WHERE ip IN ('213.163.205.35','121.58.231.35','121.58.231.55','156.59.127.203','158.178.237.116','172.105.82.111')

SELECT * FROM ip.events.honeypot WHERE ip IN ('213.163.205.35','121.58.231.35','121.58.231.55','156.59.127.203','158.178.237.116','172.105.82.111')

                
Copy

The agency side of the request log

The address that took the loader and both payloads carries one domain in the platform's records, and it is the agency's: apps.dmw.gov[.]ph, answering 403 to the scanner. The address that pulled the source archive eleven times carries the agency's other portal name, legalassistance.dmw.gov[.]ph, sitting behind a FatPipe MPVPN login page. Neither host carries a risk flag on the platform.

Figure 15Figure 15: 121.58.231[.]55: Converge ICT (AS17639), Mandaluyong City, with no risk flag on the platform.

The domain record on that address is what the rest of this section turns on.

Figure 16Figure 16: The domain on 121.58.231[.]55: apps.dmw.gov[.]ph, answering 403 to the scanner.

The second address that downloaded from the directory sits with the same provider, in the same city.

Figure 17Figure 17: 121.58.231[.]35: the same provider and city, also without a risk flag.

Its own domain record names the agency's legal assistance portal, behind an appliance login.

Figure 18Figure 18: The single domain we record on 121.58.231[.]35: legalassistance.dmw.gov[.]ph, behind a FatPipe MPVPN login.

Both are ordinary Windows servers, answering as Microsoft-HTTPAPI/2.0 on ports 80 and 443 with SMB on 445 and WinRM on 5985 and 47001. The second address also presents a self-signed certificate named PORTAL.dmw.gov[.]ph on port 3389 and on port 8888, renewed on a six-month cycle.

The stronger evidence is the certificate itself. Both addresses present a valid GlobalSign wildcard for *.dmw.gov[.]ph issued to the Philippine Overseas Employment Administration, the agency the backup filenames describe. The pivot starts from the certificate hash.

We query our certificate inventory for those hashes, the three renewals of the agency wildcard, and return every address and port presenting them.

SELECT ip, port, certificate_hash, subject.common_name, timestamp FROM certificates.inventory
WHERE certificate_hash IN ('05E2DAF00FD6D1F91E5AC32B156BAE290BB43D4FA0C1521981D804582C6444D4','FA2FAC83EBC5DBDFEAFE8E6950275FE3BE0D4BE87DF37AF0CC66671C318287AC','59309CCA70A714CA7E6A2353D583D29B0EC02E408A413B86E85A621926C3B038')

                
Copy

The same search run from the common name returns eleven addresses presenting the wildcard, most of them in 121.58.231[.]0/24, among them .37, .41, .46, .60 and .61. That is a portal farm rather than one machine, and it is the reason a single address in the log should not be read as the whole of the agency's exposure.

Figure 19Figure 19: The certificate pivot across the platform: eleven addresses present the agency wildcard.

The history also shows the portal moving. The wildcard sat on 121.58.231[.]35 from June 2023 to July 2024, on 121.58.231[.]43 from July to September 2025, and on 121.58.231[.]55 from 15 September 2025 to the present.

Figure 20Figure 20: The pivots for 121.58.231[.]55: the certificate common name first, then fingerprints shared with hundreds of thousands of hosts.

The same two fingerprints appear on the archive address, from the years the portal ran there.

Figure 21Figure 21: The same certificate and fingerprint pivots for 121.58.231[.]35, with the wildcard at the top of the list.

The agency domain dmw.gov[.]ph itself resolves 145 subdomains, among them onlineservices, accreditation, agency, agencyportal, aims and ams, the same service families the transfer log names.

Figure 22Figure 22: The agency domain legalassistance.dmw.gov[.]ph resolves 145 subdomains, among them the service families the backup filenames describe.

This closes the question the request log left open. The certificate establishes what these addresses are, the agency's own portal hosts, not what they did with the files. The capture shows delivery to them and nothing about what ran on them afterwards.

The addresses with no assessed role

156.59.127[.]203 retrieved the source archive eleven times and checked the second payload within a minute of the rebuild. Our platform places it at Zenlayer (AS21859) and carries one warning on the address: a possible, unverified Mullvad VPN.

Figure 23Figure 23: 156.59.127[.]203: Zenlayer (AS21859) with one VPN warning, flagged as a possible unverified Mullvad exit.

The scan telemetry reads differently. The SSH banner is SSH-2.0-ArrayOS, the operating system of Array Networks SSL VPN appliances, with a second service on port 8008, and we last observed the host in 2022. An appliance of that kind is a plausible relay for someone else's traffic, which would fit a host that reads the same file eleven times. We record the discrepancy and do not resolve it.

Our code search over its own captures makes the log lines searchable, and the two archive retrievals sit next to each other in the index.

Figure 24Figure 24: The access log as we index it: 121.58.231[.]35 and 156.59.127[.]203 pulling the source archive minutes apart.

172.105.82[.]111 walked the directory for nine hours and took the toolkit, and it does that everywhere. Our honeypot network recorded 1,069 probes from it between January 2023 and September 2025, against paths such as /index.htm, /cgi and /apply.cgi, which are router and IoT exploitation patterns, with browser user agents in the requests. The tree walk is what it does to everything it finds.

158.178.237[.]116 is the same kind of host with a different purpose. It swept the directory in sixteen seconds, read the operator's logs and left.

Figure 25Figure 25: 158.178.237[.]116: Oracle Corporation (AS31898), Singapore.

The signal view for the same address shows what it does with that reach.

Figure 26Figure 26: The signal profile for 158.178.237[.]116: HTTP crawler, TLS client and the ZMap scanner.

Our sensors recorded 41 probes from it between 4 September and 12 October 2026, as an HTTP crawler, a TLS client and a ZMap mass-scan client, and one request for /config/secrets.json carrying the user agent WebSiphon/next-0.1. The same address appears in other captures' web-scan logs asking for /.env.development.

Figure 27Figure 27: The same address in a third-party web scan log, one row among many scanner hits.

It collects exposed secrets at scale. The sixteen-second sweep is its normal behaviour rather than interest in this operation.

That settles who touched the directory. The next question is whether this operator's tooling turns up anywhere else in our captures.

Where the toolkit does and does not appear

A loose search for the staged file names returns source archives under similar names on other hosts, including gp_src.tar on 154.89.151[.]143:443 and gp_src.tgz on 124.198.132[.]250:8000.

The query is below. Two of its terms are specific to this operator, but %gp_src% matches any GodPotato source archive, which is what pulls in the unrelated hosts above.

SELECT
  *
FROM
  open_directory_filenames
WHERE
  file_name LIKE '%Wrqsnx%'
  OR file_name LIKE '%portalload%'
  OR file_name LIKE '%gp_src%'

                
Copy

Output example:

Figure 28Figure 28: The loose search: source archives under similar names on other hosts, including gp_src.tar and gp_src.tgz.

The tighter search answers the question that matters. Run across the platform's whole capture index for the names this operator used, it returns twenty entries, and every one of them is on the staging host.

SELECT ip, hostname, file_name, timestamp FROM attackcapture.files
WHERE file_name LIKE '%Wrqsnx%' OR file_name LIKE '%portalload%'
   OR file_name LIKE '%rclone-chunk%' OR file_name LIKE '%rclone-drive%'
   OR file_name LIKE '%gp_src.tgz%' OR file_name LIKE '%gp_build%'
The query returns twenty entries, and the figure below is the whole of that result.

                
Copy
Figure 29Figure 29: The exact search: twenty entries across the whole capture index, all on the staging host.

GodPotato itself is a different matter. Ten other open directories across the platform expose GodPotato source or builds, on 130.94.11[.]60, 154.89.151[.]143, 177.3.42[.]39, 38.60.252[.]110, 45.32.9[.]123, 63.141.229[.]228, 63.141.229[.]229, 63.141.229[.]230, 124.198.132[.]250 and 149.88.73[.]163, between August and October 2026. Each packages it differently, as gp-src.zip, gp_src.cs, gp_src.tar or a plain GodPotato-main tree, and none carries the Wrqsnx rename or a loader. Leaving this tool in an open directory is a habit several operators share. This operator's copy is not on the shelf with them.

The tooling and the requesters account for the operator's side. Whose data they took is the other half.

Victims

The transfer log records 27 SQL Server backups whose filenames correspond to the case-management systems of a Philippine overseas-employment and migrant-worker administration. The names include POEA_EServices, POEA_HelpDesk, POEAHelpDeskDB, OFW and OfwDB, together with accreditation, repatriation, eContracts, Cashier and LandBank variants. The mapping is best read as a filename-based contextual assessment rather than as a confirmed organisational identification.

We have not examined any of the backups, and several of the mappings rest on shared naming rather than on documentation: BMonline, BMDB and BMContracts match the Balik-Manggagawa Online Processing System and OWMSDB matches the OFW Welfare Monitoring System, while the remaining entries such as RepatriationDB, AgencyDB and AdjudicationDB suggest their systems by name alone. No organisational identifier, victim hostname or credential is present in the capture, and the contents of the backups are not established.

The systems named in the backups belong to the agency that administers the Philippines' overseas-employment program. The Philippine Statistics Authority estimated 2.16 million overseas Filipino workers in 2023. That figure is the population those systems cover, not a count of the records in these backups, which we have not examined.

On the evening of 6 September an address in the requesting network retrieved the loader and both payloads across 76 minutes, and a second address in the same /24 retrieved the source archive repeatedly over the same window. The log establishes delivery and nothing further. It does not establish that either executed anything, and it does not establish those addresses as victim systems rather than as operators or other requesters.

Attribution

We do not attribute this activity to a tracked actor, and the details that could be mistaken for attribution signals are recorded here without supporting an inference. The AssemblyInfo.cs in the distributed source carries Chinese-language Visual Studio template comments, and the bundled SharpToken library carries Chinese-language source comments, the latter belonging to a third-party project rather than necessarily to this operator. The tar metadata names a Linux account, cicada.

The hypothesis considered and not supported is that these place the operator in a particular country, because a localised development environment indicates the language of the toolchain rather than the location or affiliation of the person using it, and the SharpToken comments may not be this operator's at all. The account handle requires corroboration we do not have, and the capture is not sufficient to confirm attribution or to identify a state nexus.

The technique does not require a vulnerability. A service account holding SeImpersonate sits one reachable handle from SYSTEM on a default Windows host, and the payload reads that condition rather than creating it, which is the part of this operation most likely to recur in others.

Indicators of compromise

Network

IndicatorRole in this case
213.163.205[.]35Staging host, unauthenticated directory on port 80, UpCloud Ltd (AS202053), Singapore. Also published in the Hunt.io AttackCapture report
172.105.82[.]111Walked the exposed tree over about nine hours and collected the tooling, including both payloads; role not established
156.59.127[.]203Retrieved the source archive eleven times and checked the second payload; role not established
121.58.231[.]xAn address in this /24 retrieved the loader and both payloads across 76 minutes; a second retrieved the source archive repeatedly; role not established, address masked
158.178.237[.]116Swept the directory in sixteen seconds, probing for secrets files, and collected the files present; role not established
80/tcpUnauthenticated Python HTTP server serving the staging directory
8888/tcpPython upload receiver, writes request bodies to /tmp/uploaded.dll

File hashes

SHA-256File
4188295ae1f7f8a99d15e90eb037eef3eb03f6acd4422bf877c6e3304e70fcb9Wrqsnx.dll, rebranded GodPotato payload, first build
0405d4f79a3cc97fa492f1957cde0d51bc569f5432792f1b8f72077aa3fb2434Wrqsnx_portal.dll, second build
fcbfc74ddffad4789120c618bdf166c6c8aaca286fb2d184f7fa0ed8b8f26c59portalload.ps1, stager
cde477ef57ef6f100dcb0242f055113690fdeade8204e0986a3ad257be1fb81eupload.py, upload receiver
9d3f2f6031ec3b487ae12dd6f9311dd89b4a6bd23af252212bcc1f5507784f39gp_src.tgz, incomplete source archive
ee15c2a54f1bb483f70bf7777ae08d39c8abbbf7f5b1f2139de0ff76ec3e241ehttp80.log, staging server access log
e7e6bfc3a2d6c3eb0ed6e1f4ade99ca761d517886412da99a2cf4a0626bce5e3rclone.log, transfer record

Host artifacts and strings

ArtifactNote
C:\Users\Public\ptcmd.txtBase64 command channel read by the payload; capability only, not observed on a host
C:\Users\Public\p_*.b64Base64 payload fragments reassembled by the stager
\.\pipe\Wrqsnx\pipe\epmapperNamed pipe created with Everyone Full Control; specific to this rename
[+] SHELL_DONEOperator's completion marker on the payload's stdout
POTATO_FIREDStager completion marker; specific to this toolkit
18f70770-8e64-11cf-9af1-0020af6e72f4ORCB interface GUID; inherited from public GodPotato and matches any build of the tool
ncacn_ip_tcp debugger trapInherited from public GodPotato; matches any build of the tool

MITRE ATT&CK Mapping

Status is carried on every row. Observed denotes activity present in the recovered logs, binaries or artifacts; inferred denotes activity supported by converging indicators and not directly established; capability only denotes a tool or function present in the recovered material whose execution is not demonstrated.

IDTechniqueTacticStatusEvidence
T1583.003Acquire Infrastructure: Virtual Private ServerResource DevelopmentInferredStaging host serving the working directory
T1588.005Obtain Capabilities: ExploitsResource DevelopmentObservedPublic GodPotato source present in the recovered tree
T1608.001Stage Capabilities: Upload MalwareResource DevelopmentObservedPayload and loader served from the operator's HTTP root
T1059.001PowerShellExecutionObservedportalload.ps1 is the delivered stager
T1059.003Windows Command ShellExecutionCapability onlycmd.exe /c invoked through the token utility
T1620Reflective Code LoadingExecutionCapability onlyIn-memory assembly load from base64 chunks
T1068Exploitation for Privilege EscalationPrivilege EscalationCapability onlyDCOM unmarshal trigger against the dispatch table
T1134.001Token ImpersonationPrivilege EscalationCapability onlyNamed-pipe impersonation, then SYSTEM token duplication
T1036MasqueradingDefense EvasionObservedGodPotato renamed end to end
T1027Obfuscated Files or InformationDefense EvasionCapability onlyPayload split into base64 chunks
T1140Deobfuscate/Decode Files or InformationDefense EvasionCapability onlyChunks concatenated and decoded before loading
T1213Data from Information RepositoriesCollectionObserved27 database backups staged and transferred
T1567Exfiltration Over Web ServiceExfiltrationUnknownTransfer completed; external destination and channel not established
T1003OS Credential DumpingCredential AccessCapability onlysecretsdump, dpapi and keylistattack present
T1087Account DiscoveryDiscoveryCapability onlyGetADUsers, GetADComputers and ldapdomaindump present, not observed in use
T1021Remote ServicesLateral MovementCapability onlyFive remote-execution methods present
-Initial AccessNot establishedUnknownNo vector in this capture
-Command and ControlNot establishedUnknownNeither payload beacons
-PersistenceNot establishedUnknownNo persistence mechanism in the recovered payload

Conclusion

What the recovered material establishes is a completed theft, a delivery server and tooling rebuilt in place. What it does not establish is how the operator entered the agency network, what command ran under SYSTEM, or where the 68.837 GiB was sent, and the operation ended because the working directory was public rather than because anyone detected it.

The exploit is public and unchanged, and the operator's work comprises the renaming, the stager and one rebuild. The payload is careful where correctness matters and careless where evidence accumulates: the impersonation-level checks are correct and defensive, the named-pipe error handling is correct, and the token selection resolves its object type at runtime rather than hardcoding an index, while a variable is declared and discarded and a system DLL page remains writable after the process exits.

The staging directory in this post was captured and indexed by AttackCapture before the operator took it down. If you want to see what's sitting in the open across your own exposed infrastructure, book a demo.

Disclosure note: Hunt.io notified the relevant national CERT prior to publication. No personal records or credentials from the affected systems appear in this report.


An operator copied 68.837 GiB of a Philippine government agency's database backups, logged the transfer for themselves, and then left that log open on the internet. We captured the directory while it was still serving.

The copy finished in under 24 minutes on 6 September 2026, 27 SQL Server backups whose names match the agency's overseas-employment and migrant-worker systems. Beside the log sat the operator's toolkit, a rebranded GodPotato build, a PowerShell stager, two payloads and a full Impacket environment.

The access log shows that tooling pulled the same evening, which establishes distribution from this server and nothing past it. How the operator got in, and whether any payload ran, are not in the capture.

Key Findings

We reverse-engineered the payload, traced the operator's logs, and pivoted the certificates to the agency itself. The key takeaways:

  • A staging host at UpCloud Ltd (AS202053) left the operator's working folder open through an unauthenticated HTTP directory on port 80, including the operator's own transfer and access logs

  • Completed 68.837 GiB copy of 27 SQL Server backups, transferred in 23m 46s at a tool-reported 20.238 MiB/s that does not reconcile with the volume and duration

  • Backup filenames matching the case-management systems of a Philippine overseas-employment and migrant-worker administration, including POEA and OFW variants

  • A rebranded GodPotato .NET build staged as Wrqsnx.dll and Wrqsnx_portal.dll, with the RPC pipe, namespace and assembly metadata renamed and internal identifiers left untouched

  • Two builds from two different compilers, the second compiled 6m 43s before it was retrieved

  • An eight-line PowerShell stager that rebuilds the payload in memory from base64 fragments, so no DLL touches disk

  • A full Impacket environment with no signs of modification, including LDAP and MSSQL relay checks and a tool targeting Windows Server 2025 domain controllers

  • No initial access vector, no command-and-control channel and no confirmed payload execution appear in the recovered data

The exposed staging server

Each point above traces back to a file the operator left in the open. We start with the server that served them.

The host 213.163.205[.]35:80 ran a Python HTTP server on port 80 with directory listing enabled, and it served the operator's working folder to anyone who asked. No defender found the exposure: the directory was captured while it was open. The access log records 543 requests from 76 distinct addresses across a 16-hour, 9-minute window on 6 and 7 September 2026.

Figure 01Figure 01: The capture in Hunt.io: the staging directory, served from 213.163.205[.]35:80 at UpCloud Ltd (AS202053), Singapore.

The operator's environment is identifiable from the recovered files, not from the host itself. The Impacket environment records its own path in its activation script: /tmp/imp. That places the toolkit in a temporary directory on the staging server, and it fits an operator working from a rented Linux host rather than a maintained workstation.

Most of the traffic against the directory was scanner noise with no link to the operation. The six addresses assessed below were selected for their retrieval of operational files; the remaining 70 requested only directory listings or common exploit paths. A WordPress and PHP RCE sweeper sent 49 requests and received 404 or 501 on every one.

A handful of addresses did more than scan, and they downloaded files. Their roles are assessed separately from their activity in the indicators section, because taking a file from an open directory establishes neither that the requester is the operator nor that it is a victim.

What the host exposed was the operator's working folder, not a finished deployment: more than a hundred files, including a payload builder and its source tree, two compiled payloads, a PowerShell stager, a complete Impacket environment, a small Python upload receiver, and the operator's own logs.

Figure 02Figure 02: The staging directory was captured: the payloads, the stager, the transfer logs and the Impacket environment, all in the open.

The upload receiver is a small Python service that binds port 8888 and writes request bodies to disk. Its companion log is zero bytes, but the handler contains no logging call, so the empty log is not evidence of disuse, and no received file was recovered. Whether the endpoint was ever used cannot be determined from this capture.

The logs are the most consequential files in the directory, and they are treated in their own section below.

Wrqsnx: a rebranded GodPotato

The payload is the most detailed piece in the directory, so we start there.

The payload is GodPotato, a publicly available .NET tool. It turns the rights of a service account into full SYSTEM control through DCOM and RPC, and it needs no Windows vulnerability to do it. The operator rebuilt it under the name Wrqsnx and renamed the namespace, the context classes, the pipe path and the assembly metadata, while leaving the source file names and some internal field names unchanged. That gap is a fingerprint: the tool is public, and the copy is lightly edited.

Microsoft's platform detects the payload as Trojan:MSIL/GodPotato.FF!MTB. That corroborates the lineage independently of our code reading. Everything below is read from the recovered files; none of it was observed running.

Rebuilding the payload in memory

The stager runs the payload without ever writing a DLL to disk. It is eight lines of PowerShell. It collects the base64 fragments named p_*.b64 from C:\Users\Public in filename order, joins them, strips whitespace, decodes the result in memory, loads it as a .NET assembly and calls its Main method.

The design has two weak points the operator accepted. The join depends on fixed-width fragment names, and the script never checks this. And the completion marker, POTATO_FIRED, only shows that the stager reached its last line: failures inside the payload are caught and swallowed, so the marker says nothing about SYSTEM.

Figure 03Figure 03: portalload.ps1 as served and no DLL touches disk.

Nothing in the stager validates the fragments, so whatever the files contain is what gets loaded.

Finding the target in memory

The payload takes over one decision inside Windows RPC. Hardcoding the location of that decision would work on a single Windows build, so the payload finds it at runtime instead. It copies the combase.dll module image into memory and searches for a short byte pattern: the size of the structure it wants followed by a known interface identifier.

From the first match, it follows the structure's own records to the dispatch table and learns how many arguments the routine it wants to replace takes, between four and fourteen. That count changes between Windows versions, and the payload reads it instead of assuming it.

Figure 04Figure 04: Finding combase.dll at runtime and building the 20-byte search pattern.

The second figure carries the walk on from the match to the pointer the payload replaces.

Figure 05Figure 05: Walking RPC_SERVER_INTERFACE and MIDL_SERVER_INFO to reach the dispatch table pointer.

The walk reads the layout Windows ships, so the same code reaches the routine on any build.

Taking over the RPC lookup

When Windows needs to reach an interface, one routine answers a single question: which transport does it use? The payload takes that routine over. It makes the dispatch table writable, replaces the first entry, the transport chooser, with a pointer to its own function, and stores the original pointer to put back later.

One thing is never put back. The memory page was made writable and stays writable after the process exits. No code is injected, and the change is four bytes wide, so it escapes tools that scan for injected code. It is the clearest trace the tool leaves on a host.

Figure 06Figure 06: HookRPC makes the page writable; Restore rewrites the pointer but not the page protection.

The two functions sit beside each other in the source, and the page permission is the only thing they disagree on.

Pulling in a SYSTEM connection

For the technique to work, a SYSTEM service has to connect to the payload. The payload creates the named pipe \.\pipe\Wrqsnx\pipe\epmapper with a descriptor that grants Everyone full control. That looks careless but is required, because a named pipe created normally would refuse the SYSTEM-context connection the technique depends on.

Figure 07Figure 07: The pipe is created with Everyone Full Control, a condition of the attack.

The payload then builds a genuine-looking COM object reference for a local object, rewrites its destination to point at the same machine with NTLM authentication, and hands it to CoUnmarshalInterface. combase asks the hooked lookup how to reach the interface, receives the pipe instead of a network address, and the DCOM resolver inside RPCSS, which runs as SYSTEM, opens the pipe. That is where the SYSTEM client comes from.

Figure 08Figure 08: The hooked routine answers combase with the pipe endpoint instead of a network address.

The answer the resolver receives is a pipe on the local machine, which is the connection the payload wants.

Stealing a SYSTEM token

With a SYSTEM client attached, the pipe thread impersonates the connected client, reads the system-wide handle table through NtQuerySystemInformation, and duplicates a token that matches three conditions: the local system SID S-1-5-18, an impersonation level of at least Impersonation, and System integrity or higher.

No memory corruption is involved at any point, and no vulnerability is exploited. Every call uses a permission the process already holds. The escalation works because a SYSTEM token is reachable in the table and the caller has the right to duplicate it.

Figure 09Figure 09: Reading the system handle table with NtQuerySystemInformation.

The search walks the table entry by entry, and the three conditions are the whole of the check.

Running the command

The payload runs one command as SYSTEM. It reads a base64 command from C:\Users\Public\ptcmd.txt, decodes it, runs it as cmd.exe /c under the stolen token, and pipes the output back to its own console. It prints the stolen identity with the result.

The child process is created without a window. That hides the console and nothing else: the creation event, the command line and the parent-child link are all recorded. The command file is not in the capture, so what ran as SYSTEM is not known.

Figure 10Figure 10: The stolen identity is printed, ptcmd.txt is read and decoded, the command runs as SYSTEM, and SHELL_DONE is written.

The output between the two markers belongs to the command, printed under the stolen identity.

Cleanup

The payload restores the original function pointer, connects to its own pipe and writes a single byte to release the waiting thread, then exits. Everything is reversed except the page protection from the third stage.

Two builds, one program

Two payloads were recovered. They are the same program from two different compilers, and the differences are the evidence. One build comes from Mono's mcs compiler and the other from Microsoft's Roslyn, based on three signals that agree: the compiler-generated class names, the image base, and the way field initialisers are placed.

The two builds differ in exactly one place, a stray dollar sign in an error message that never executes. The second build was compiled at 22:48:01 on 6 September and retrieved at 22:54:44, under seven minutes later. A fresh hash against hash-based blocking is the plausible reason, but no log states it.

The source tree and the served archive are byte-identical copies of the same eleven files, and the tree does not build. It calls a helper class named Sunday that ships in no file in the archive, and its project file declares an older .NET version than the binaries it produced. The tree matches the second build, not the first.

Figure 11Figure 11: The gp_build source tree: Program.cs, SharpToken.cs and the GodPotato project files.

The tree is the operator's build directory, and it is the last of the files left in the open.

The staged toolkit

The payload and its build tree were not the only tooling left in the open. The directory held a full Impacket environment, the standard toolkit for working with Windows networks from Linux. We swept all 69 Python scripts for hardcoded addresses, embedded data and added code, and found nothing. We did not diff them against upstream line by line, so a careful single-line edit could pass this check.

Two scripts check whether LDAP or MSSQL relay is viable against a target, and one filters domain controllers for Windows Server 2025. Those read as per-target checks rather than a spray.

The rest is the standard Active Directory attack surface, from secretsdump to five remote-execution methods. No tool in the set was observed in use, and the capture holds no command history, no tool output and no execution telemetry.

The exfiltration

The operator's own logs carry more weight than the payloads, because the operator wrote them for private use, not for an audience. The transfer log records a completed copy of 68.837 GiB across 27 files in 23 minutes 46 seconds.

2026/09/06 01:26:50 INFO  : POEA_EServices.bak: Multi-thread Copied (new)
Transferred:  68.837 GiB / 68.837 GiB, 100%, 20.238 MiB/s, ETA 0s
Transferred:  27 / 27, 100%
Elapsed time: 23m46.3s

                
Copy

Its counterpart records a failed attempt fourteen hours later against a source path of /data/chunk that no longer existed. That indicates the collection was assembled separately from the transfer and subsequently cleared.

The log does not name the source host or the destination remote. The volume and the displayed rate also do not reconcile: 68.837 GiB over 23 minutes 46 seconds averages approximately 49.4 MiB/s, while the summary line reads 20.238 MiB/s. Rclone's summary speed is a rolling average at completion, not total bytes divided by elapsed time, which accounts for the gap. We report both as logged.

The ordering of the transfer against the payload matters more than either figure. The transfer completed at 01:26:50 on 6 September and the first payload was fetched at 21:41:33 the same day, which the logs place approximately twenty hours later. So the payload was not the mechanism of the theft, and whatever access the operator held when the backups were copied was already sufficient.

That is as far as the operator's own files take us. The rest comes from what our platform already recorded about the host.

Infrastructure Analysis

The staging directory was served over port 80 from 213.163.205[.]35, a Linux host at UpCloud Ltd (AS202053) in Singapore. The Impacket virtual environment path, /tmp/imp, is recorded in the environment's own activation script. A separate Python service on the host binds port 8888 and accepts push uploads, though no received file was recovered and its use is not established. The transfer destination does not appear in the indicators, because the log does not name it. The staging address does appear: it is the same address published in the Hunt.io AttackCapture report covering this capture, so a defender who needs it for blocking has two sources for it.

Figure 12Figure 12: The staging host, flagged for the malicious open directory on 7 September 2026.

An automated capability check was run against the first payload as a cross-check and reported virtualisation and sandbox evasion, which we do not consider supported: the match derives from two token-enumeration names in a bundled third-party library, and no environment detection exists anywhere in the payload or that library. The same check reported no process injection and no event-triggered execution, which agrees with our own reading.

Our AttackCapture platform indexed the staging directory on 7 September 2026, and the same platform keeps the scan telemetry, the certificates and the directory listings behind it. We queried our tables for every address in the log, so each statement below rests on a record and can be reproduced with the query printed beside it.

The staging host

Our record for 213.163.205[.]35 gives the operator's platform: UpCloud Ltd (AS202053), Singapore, in the range 213.163.192[.]0/20, behind the PTR 213-163-205-35.sg-sin1.upcloud.host. The platform carries one warning on the address and nothing else: a potential malicious open directory, dated 7 September 2026.

Figure 13Figure 13: The staging host listening on port 80, running a SimpleHTTP/0.6 Python/3.13.5 under the title Directory listing for

The open ports confirm the capture's own story and add one detail. Port 80 answered with SimpleHTTP/0.6 Python/3.13.5 under the title Directory listing for /, which is Python's built-in server, started by hand. Port 887 carried a self-signed *.aapanel.com certificate valid to November 2035, and 887 is aaPanel's default port, so the VPS was run through that panel. The same port 80 had answered as WebSockify Python/3.11.2 in September 2025, a browser terminal bridge of the kind these panels install, so the host was set up as a managed VPS well before the intrusion. The SSH banner is OpenSSH_10.0p2 Debian-7+deb13u4, a current Debian release, seen up to 8 September 2026.

Our crawler indexed the directory at 13:47 UTC on 7 September. Its index holds 141 entries, 112 files and 29 directories, matching the capture package. A second pass that evening, from 20:02 to 01:05, recorded the names of files it did not download and reached deeper into the Impacket environment than the capture does, including the site-packages versions.

Both queries below return that record, the first the host's HTTP history and the second the filenames our crawler indexed from the open directory.

SELECT * FROM ip.events.http.history WHERE ip = '213.163.205.35'

SELECT * FROM open_directory_filenames WHERE hostname LIKE 'http://213.163.205.35%'

                
Copy

Neither our malware tracking nor the C2 feed holds a record for this host, and no address in its /24 is flagged either. The staging server never probed our sensors.

The requesting addresses, by role

The staging host is one address in the log. The other five are the ones that reached in and pulled files.

Our bulk enrich feature helps view the six addresses and puts provider, country, VPN flags and the capture hit in one place. The roles below are read from the access log against the certificate and scanner evidence.

Figure 14Figure 14: The six addresses in one view: provider, country, VPN flag and the AttackCapture hit on the staging host.

The table below sets out what each address did in the log and how that activity is read.

AddressNetworkIn the access logAssessment
213.163.205[.]35UpCloud Ltd (AS202053), Singaporeserved the directorystaging and delivery host
121.58.231[.]55Converge ICT (AS17639), Mandaluyong, PHloader twice, both payloads, 21:38:42 to 22:54:44agency portal host, certificate match
121.58.231[.]35Converge ICT (AS17639), Mandaluyong, PHsource archive eleven attempts, 21:56:03 to 22:30:41agency portal host, certificate match
156.59.127[.]203Zenlayer (AS21859)source archive eleven times, second payloadSSL VPN appliance, no role established
172.105.82[.]111Linode, now Akamai (AS63949), Frankfurtwalked the tree over nine hours and took the toolingmass scanner
158.178.237[.]116Oracle (AS31898), Singaporeswept the directory in sixteen secondsCVE scanner

Both queries below back the table, the first returning the current enrichment for all six addresses at once and the second checking each against our honeypot records.

SELECT * FROM ip.current WHERE ip IN ('213.163.205.35','121.58.231.35','121.58.231.55','156.59.127.203','158.178.237.116','172.105.82.111')

SELECT * FROM ip.events.honeypot WHERE ip IN ('213.163.205.35','121.58.231.35','121.58.231.55','156.59.127.203','158.178.237.116','172.105.82.111')

                
Copy

The agency side of the request log

The address that took the loader and both payloads carries one domain in the platform's records, and it is the agency's: apps.dmw.gov[.]ph, answering 403 to the scanner. The address that pulled the source archive eleven times carries the agency's other portal name, legalassistance.dmw.gov[.]ph, sitting behind a FatPipe MPVPN login page. Neither host carries a risk flag on the platform.

Figure 15Figure 15: 121.58.231[.]55: Converge ICT (AS17639), Mandaluyong City, with no risk flag on the platform.

The domain record on that address is what the rest of this section turns on.

Figure 16Figure 16: The domain on 121.58.231[.]55: apps.dmw.gov[.]ph, answering 403 to the scanner.

The second address that downloaded from the directory sits with the same provider, in the same city.

Figure 17Figure 17: 121.58.231[.]35: the same provider and city, also without a risk flag.

Its own domain record names the agency's legal assistance portal, behind an appliance login.

Figure 18Figure 18: The single domain we record on 121.58.231[.]35: legalassistance.dmw.gov[.]ph, behind a FatPipe MPVPN login.

Both are ordinary Windows servers, answering as Microsoft-HTTPAPI/2.0 on ports 80 and 443 with SMB on 445 and WinRM on 5985 and 47001. The second address also presents a self-signed certificate named PORTAL.dmw.gov[.]ph on port 3389 and on port 8888, renewed on a six-month cycle.

The stronger evidence is the certificate itself. Both addresses present a valid GlobalSign wildcard for *.dmw.gov[.]ph issued to the Philippine Overseas Employment Administration, the agency the backup filenames describe. The pivot starts from the certificate hash.

We query our certificate inventory for those hashes, the three renewals of the agency wildcard, and return every address and port presenting them.

SELECT ip, port, certificate_hash, subject.common_name, timestamp FROM certificates.inventory
WHERE certificate_hash IN ('05E2DAF00FD6D1F91E5AC32B156BAE290BB43D4FA0C1521981D804582C6444D4','FA2FAC83EBC5DBDFEAFE8E6950275FE3BE0D4BE87DF37AF0CC66671C318287AC','59309CCA70A714CA7E6A2353D583D29B0EC02E408A413B86E85A621926C3B038')

                
Copy

The same search run from the common name returns eleven addresses presenting the wildcard, most of them in 121.58.231[.]0/24, among them .37, .41, .46, .60 and .61. That is a portal farm rather than one machine, and it is the reason a single address in the log should not be read as the whole of the agency's exposure.

Figure 19Figure 19: The certificate pivot across the platform: eleven addresses present the agency wildcard.

The history also shows the portal moving. The wildcard sat on 121.58.231[.]35 from June 2023 to July 2024, on 121.58.231[.]43 from July to September 2025, and on 121.58.231[.]55 from 15 September 2025 to the present.

Figure 20Figure 20: The pivots for 121.58.231[.]55: the certificate common name first, then fingerprints shared with hundreds of thousands of hosts.

The same two fingerprints appear on the archive address, from the years the portal ran there.

Figure 21Figure 21: The same certificate and fingerprint pivots for 121.58.231[.]35, with the wildcard at the top of the list.

The agency domain dmw.gov[.]ph itself resolves 145 subdomains, among them onlineservices, accreditation, agency, agencyportal, aims and ams, the same service families the transfer log names.

Figure 22Figure 22: The agency domain legalassistance.dmw.gov[.]ph resolves 145 subdomains, among them the service families the backup filenames describe.

This closes the question the request log left open. The certificate establishes what these addresses are, the agency's own portal hosts, not what they did with the files. The capture shows delivery to them and nothing about what ran on them afterwards.

The addresses with no assessed role

156.59.127[.]203 retrieved the source archive eleven times and checked the second payload within a minute of the rebuild. Our platform places it at Zenlayer (AS21859) and carries one warning on the address: a possible, unverified Mullvad VPN.

Figure 23Figure 23: 156.59.127[.]203: Zenlayer (AS21859) with one VPN warning, flagged as a possible unverified Mullvad exit.

The scan telemetry reads differently. The SSH banner is SSH-2.0-ArrayOS, the operating system of Array Networks SSL VPN appliances, with a second service on port 8008, and we last observed the host in 2022. An appliance of that kind is a plausible relay for someone else's traffic, which would fit a host that reads the same file eleven times. We record the discrepancy and do not resolve it.

Our code search over its own captures makes the log lines searchable, and the two archive retrievals sit next to each other in the index.

Figure 24Figure 24: The access log as we index it: 121.58.231[.]35 and 156.59.127[.]203 pulling the source archive minutes apart.

172.105.82[.]111 walked the directory for nine hours and took the toolkit, and it does that everywhere. Our honeypot network recorded 1,069 probes from it between January 2023 and September 2025, against paths such as /index.htm, /cgi and /apply.cgi, which are router and IoT exploitation patterns, with browser user agents in the requests. The tree walk is what it does to everything it finds.

158.178.237[.]116 is the same kind of host with a different purpose. It swept the directory in sixteen seconds, read the operator's logs and left.

Figure 25Figure 25: 158.178.237[.]116: Oracle Corporation (AS31898), Singapore.

The signal view for the same address shows what it does with that reach.

Figure 26Figure 26: The signal profile for 158.178.237[.]116: HTTP crawler, TLS client and the ZMap scanner.

Our sensors recorded 41 probes from it between 4 September and 12 October 2026, as an HTTP crawler, a TLS client and a ZMap mass-scan client, and one request for /config/secrets.json carrying the user agent WebSiphon/next-0.1. The same address appears in other captures' web-scan logs asking for /.env.development.

Figure 27Figure 27: The same address in a third-party web scan log, one row among many scanner hits.

It collects exposed secrets at scale. The sixteen-second sweep is its normal behaviour rather than interest in this operation.

That settles who touched the directory. The next question is whether this operator's tooling turns up anywhere else in our captures.

Where the toolkit does and does not appear

A loose search for the staged file names returns source archives under similar names on other hosts, including gp_src.tar on 154.89.151[.]143:443 and gp_src.tgz on 124.198.132[.]250:8000.

The query is below. Two of its terms are specific to this operator, but %gp_src% matches any GodPotato source archive, which is what pulls in the unrelated hosts above.

SELECT
  *
FROM
  open_directory_filenames
WHERE
  file_name LIKE '%Wrqsnx%'
  OR file_name LIKE '%portalload%'
  OR file_name LIKE '%gp_src%'

                
Copy

Output example:

Figure 28Figure 28: The loose search: source archives under similar names on other hosts, including gp_src.tar and gp_src.tgz.

The tighter search answers the question that matters. Run across the platform's whole capture index for the names this operator used, it returns twenty entries, and every one of them is on the staging host.

SELECT ip, hostname, file_name, timestamp FROM attackcapture.files
WHERE file_name LIKE '%Wrqsnx%' OR file_name LIKE '%portalload%'
   OR file_name LIKE '%rclone-chunk%' OR file_name LIKE '%rclone-drive%'
   OR file_name LIKE '%gp_src.tgz%' OR file_name LIKE '%gp_build%'
The query returns twenty entries, and the figure below is the whole of that result.

                
Copy
Figure 29Figure 29: The exact search: twenty entries across the whole capture index, all on the staging host.

GodPotato itself is a different matter. Ten other open directories across the platform expose GodPotato source or builds, on 130.94.11[.]60, 154.89.151[.]143, 177.3.42[.]39, 38.60.252[.]110, 45.32.9[.]123, 63.141.229[.]228, 63.141.229[.]229, 63.141.229[.]230, 124.198.132[.]250 and 149.88.73[.]163, between August and October 2026. Each packages it differently, as gp-src.zip, gp_src.cs, gp_src.tar or a plain GodPotato-main tree, and none carries the Wrqsnx rename or a loader. Leaving this tool in an open directory is a habit several operators share. This operator's copy is not on the shelf with them.

The tooling and the requesters account for the operator's side. Whose data they took is the other half.

Victims

The transfer log records 27 SQL Server backups whose filenames correspond to the case-management systems of a Philippine overseas-employment and migrant-worker administration. The names include POEA_EServices, POEA_HelpDesk, POEAHelpDeskDB, OFW and OfwDB, together with accreditation, repatriation, eContracts, Cashier and LandBank variants. The mapping is best read as a filename-based contextual assessment rather than as a confirmed organisational identification.

We have not examined any of the backups, and several of the mappings rest on shared naming rather than on documentation: BMonline, BMDB and BMContracts match the Balik-Manggagawa Online Processing System and OWMSDB matches the OFW Welfare Monitoring System, while the remaining entries such as RepatriationDB, AgencyDB and AdjudicationDB suggest their systems by name alone. No organisational identifier, victim hostname or credential is present in the capture, and the contents of the backups are not established.

The systems named in the backups belong to the agency that administers the Philippines' overseas-employment program. The Philippine Statistics Authority estimated 2.16 million overseas Filipino workers in 2023. That figure is the population those systems cover, not a count of the records in these backups, which we have not examined.

On the evening of 6 September an address in the requesting network retrieved the loader and both payloads across 76 minutes, and a second address in the same /24 retrieved the source archive repeatedly over the same window. The log establishes delivery and nothing further. It does not establish that either executed anything, and it does not establish those addresses as victim systems rather than as operators or other requesters.

Attribution

We do not attribute this activity to a tracked actor, and the details that could be mistaken for attribution signals are recorded here without supporting an inference. The AssemblyInfo.cs in the distributed source carries Chinese-language Visual Studio template comments, and the bundled SharpToken library carries Chinese-language source comments, the latter belonging to a third-party project rather than necessarily to this operator. The tar metadata names a Linux account, cicada.

The hypothesis considered and not supported is that these place the operator in a particular country, because a localised development environment indicates the language of the toolchain rather than the location or affiliation of the person using it, and the SharpToken comments may not be this operator's at all. The account handle requires corroboration we do not have, and the capture is not sufficient to confirm attribution or to identify a state nexus.

The technique does not require a vulnerability. A service account holding SeImpersonate sits one reachable handle from SYSTEM on a default Windows host, and the payload reads that condition rather than creating it, which is the part of this operation most likely to recur in others.

Indicators of compromise

Network

IndicatorRole in this case
213.163.205[.]35Staging host, unauthenticated directory on port 80, UpCloud Ltd (AS202053), Singapore. Also published in the Hunt.io AttackCapture report
172.105.82[.]111Walked the exposed tree over about nine hours and collected the tooling, including both payloads; role not established
156.59.127[.]203Retrieved the source archive eleven times and checked the second payload; role not established
121.58.231[.]xAn address in this /24 retrieved the loader and both payloads across 76 minutes; a second retrieved the source archive repeatedly; role not established, address masked
158.178.237[.]116Swept the directory in sixteen seconds, probing for secrets files, and collected the files present; role not established
80/tcpUnauthenticated Python HTTP server serving the staging directory
8888/tcpPython upload receiver, writes request bodies to /tmp/uploaded.dll

File hashes

SHA-256File
4188295ae1f7f8a99d15e90eb037eef3eb03f6acd4422bf877c6e3304e70fcb9Wrqsnx.dll, rebranded GodPotato payload, first build
0405d4f79a3cc97fa492f1957cde0d51bc569f5432792f1b8f72077aa3fb2434Wrqsnx_portal.dll, second build
fcbfc74ddffad4789120c618bdf166c6c8aaca286fb2d184f7fa0ed8b8f26c59portalload.ps1, stager
cde477ef57ef6f100dcb0242f055113690fdeade8204e0986a3ad257be1fb81eupload.py, upload receiver
9d3f2f6031ec3b487ae12dd6f9311dd89b4a6bd23af252212bcc1f5507784f39gp_src.tgz, incomplete source archive
ee15c2a54f1bb483f70bf7777ae08d39c8abbbf7f5b1f2139de0ff76ec3e241ehttp80.log, staging server access log
e7e6bfc3a2d6c3eb0ed6e1f4ade99ca761d517886412da99a2cf4a0626bce5e3rclone.log, transfer record

Host artifacts and strings

ArtifactNote
C:\Users\Public\ptcmd.txtBase64 command channel read by the payload; capability only, not observed on a host
C:\Users\Public\p_*.b64Base64 payload fragments reassembled by the stager
\.\pipe\Wrqsnx\pipe\epmapperNamed pipe created with Everyone Full Control; specific to this rename
[+] SHELL_DONEOperator's completion marker on the payload's stdout
POTATO_FIREDStager completion marker; specific to this toolkit
18f70770-8e64-11cf-9af1-0020af6e72f4ORCB interface GUID; inherited from public GodPotato and matches any build of the tool
ncacn_ip_tcp debugger trapInherited from public GodPotato; matches any build of the tool

MITRE ATT&CK Mapping

Status is carried on every row. Observed denotes activity present in the recovered logs, binaries or artifacts; inferred denotes activity supported by converging indicators and not directly established; capability only denotes a tool or function present in the recovered material whose execution is not demonstrated.

IDTechniqueTacticStatusEvidence
T1583.003Acquire Infrastructure: Virtual Private ServerResource DevelopmentInferredStaging host serving the working directory
T1588.005Obtain Capabilities: ExploitsResource DevelopmentObservedPublic GodPotato source present in the recovered tree
T1608.001Stage Capabilities: Upload MalwareResource DevelopmentObservedPayload and loader served from the operator's HTTP root
T1059.001PowerShellExecutionObservedportalload.ps1 is the delivered stager
T1059.003Windows Command ShellExecutionCapability onlycmd.exe /c invoked through the token utility
T1620Reflective Code LoadingExecutionCapability onlyIn-memory assembly load from base64 chunks
T1068Exploitation for Privilege EscalationPrivilege EscalationCapability onlyDCOM unmarshal trigger against the dispatch table
T1134.001Token ImpersonationPrivilege EscalationCapability onlyNamed-pipe impersonation, then SYSTEM token duplication
T1036MasqueradingDefense EvasionObservedGodPotato renamed end to end
T1027Obfuscated Files or InformationDefense EvasionCapability onlyPayload split into base64 chunks
T1140Deobfuscate/Decode Files or InformationDefense EvasionCapability onlyChunks concatenated and decoded before loading
T1213Data from Information RepositoriesCollectionObserved27 database backups staged and transferred
T1567Exfiltration Over Web ServiceExfiltrationUnknownTransfer completed; external destination and channel not established
T1003OS Credential DumpingCredential AccessCapability onlysecretsdump, dpapi and keylistattack present
T1087Account DiscoveryDiscoveryCapability onlyGetADUsers, GetADComputers and ldapdomaindump present, not observed in use
T1021Remote ServicesLateral MovementCapability onlyFive remote-execution methods present
-Initial AccessNot establishedUnknownNo vector in this capture
-Command and ControlNot establishedUnknownNeither payload beacons
-PersistenceNot establishedUnknownNo persistence mechanism in the recovered payload

Conclusion

What the recovered material establishes is a completed theft, a delivery server and tooling rebuilt in place. What it does not establish is how the operator entered the agency network, what command ran under SYSTEM, or where the 68.837 GiB was sent, and the operation ended because the working directory was public rather than because anyone detected it.

The exploit is public and unchanged, and the operator's work comprises the renaming, the stager and one rebuild. The payload is careful where correctness matters and careless where evidence accumulates: the impersonation-level checks are correct and defensive, the named-pipe error handling is correct, and the token selection resolves its object type at runtime rather than hardcoding an index, while a variable is declared and discarded and a system DLL page remains writable after the process exits.

The staging directory in this post was captured and indexed by AttackCapture before the operator took it down. If you want to see what's sitting in the open across your own exposed infrastructure, book a demo.