Skip to main content
Sandfish

· Updated

Weathered Raven: the contracts behind fake USDT transfers

A fake 1-USDT transfer form requested unlimited spending permission. Contract history links three actor clusters and explains a later 7,999.99-USDT transfer.

At 12:37:47 UTC on 26th September 2026, a wallet received 7,999.99 USDT. Twelve seconds later, a spending contract moved the full amount to another wallet, leaving the source wallet with zero USDT. The contract used spending permission already recorded on BNB Smart Chain.

I found this transfer while investigating fake wallet-transfer pages associated with Weathered Raven. One page displayed a 1-USDT transfer, but its code requested unlimited permission to spend the connected wallet's USDT. The permission went to a contract, and the wallet allowed to control that contract could change after approval. A later controller could therefore use that permission without asking the token holder to approve it again.

Following the contracts also connected this investigation to Azure Iguana and Steady Iguana. Sandfish uses these actor-cluster names to group related evidence. The contracts shared a controller, but that does not tell us whether the sites had the same operator.

The 7,999.99-USDT transfer shows how that changing authority could affect a newly funded wallet. It involved another contract found through the investigation; the page that obtained its approval remains unknown.

The 1-USDT form requested unlimited approval

The Trustwallet-neon capture opened a page headed Send USDT on 14th September 2026. The page had already filled in an address and an amount of 1 USDT, with Next enabled before any interaction.

Captured Send USDT page with a masked page-set address, amount 1, an approximate value of $1.00, Max, and an enabled Next button.

The captured site before interaction, on 14th September 2026 at 21:17:08 UTC. The address supplied by the page is masked. This screenshot shows the site interface; the capture did not reach a wallet signing prompt.

The archived code behind Next prepared an approval for a fixed spending contract on BNB Smart Chain:

approve(spending contract, maximum uint256)

An approval gives another address permission to spend tokens from the approving wallet. The amount of that permission is called an allowance. This request used the largest allowance the token contract accepts, commonly described as unlimited. It could cover future deposits as well as the wallet's current balance, although the approval itself would transfer no USDT.

I tested the fields with the archived code and a simulated wallet, with all browser network access blocked. Changing the amount from 1 to 875.25 USDT changed the displayed dollar value but produced exactly the same approval request. Changing the recipient also left the request unchanged. The fields only had to contain text to enable Next; neither controlled the spending permission.

Offline tests with amounts of 1 and 875.25 USDT, and with different recipients, all produced the same unlimited approval for contract 0xecfa…ab94.

A diagram of the archived-code comparison. Each changed field led to the same approval request. The test used a simulated wallet and sent no transaction.

The real capture stopped at a missing-wallet message, so it cannot show what a wallet would display before signing. The offline test establishes what the page asked the wallet to do.

The code was also set to send Telegram reports once the wallet returned a transaction hash. The report templates included the connected wallet and the hash; neither transfer field appeared in them. Matching notification settings helped me find related pages, and stored report references let me check whether the requested approvals had actually succeeded.

Fifteen approvals succeeded on-chain

All fifteen transactions named in the primary bot's stored reports were successful unlimited USDT approvals. They authorized five spending contracts, including the contract configured in Trustwallet-neon.

The bot was recorded as imvao_bot. Its reports came from an authorized review of private archived Telegram records; the public capture links show the page code, not those records. I checked each reported transaction against its on-chain input and the token's Approval event. Fourteen reported wallet addresses matched the transaction sender. The remaining report had no recoverable wallet field.

That check was necessary because the page treated a returned transaction hash as success without waiting for confirmation. One report preceded its transaction's mined block by four seconds. The chain receipts supplied the confirmation the page had skipped.

The approved contracts had also used the permission. Five later transfers, totaling 2.75 USDT, matched both the wallet and the approved contract in those reports. For example, the Trustwallet-neon contract moved 0.05 USDT on 3rd September, with matching transaction input and token events.

These transactions show that the permissions were granted and used. The records do not tell us whether the wallets belonged to visitors or testers. To understand who could spend from them, I had to check the contracts' control history.

The approved contract could change controllers

The wallet authorized to use an approval could change while the approved contract address stayed the same. A page could therefore name the correct spending contract while its COMPANY_WALLET_ADDRESS setting still gave an old controller address.

The contract stored its own company-wallet address and checked that address before allowing a spending call. I use controller for the wallet that passed this check; “company” is a field name, not an identified business. The controller chose which wallet to spend from and where to send the tokens. It also supplied the amount, which the contract passed to USDT's transferFrom method to use an existing allowance.

At the review block on 20th October 2026, several contracts returned 0xfbd4…d2788 from companyWallet(), differing from their page settings. This was the shared controller that connected the next parts of the investigation.

For Trustwallet-neon, historical state showed exactly when control changed. On 12th September, a successful call to setCompanyWallet replaced 0xe9d8…48e7 with the shared controller. The execution trace showed the call coming from the old controller's account.

The token holder's approval still named the same contract. That contract now accepted spending instructions from a different wallet.

A later controller spent the new deposit

The shared controller's transactions led to 0x678a…90c5, the contract that moved the 7,999.99 USDT. It was separate from the five contracts in the bot reports. Its executable code matched the Trustwallet-neon contract after removing compiler metadata, and the same shared controller used it to make the large transfer.

The code match and the shared controller connected this contract to the earlier pages. Its history showed when the controller acquired authority to spend.

Four dated transactions: an unlimited USDT approval on 3rd February, a controller change on 16th May, and a 7,999.99-USDT deposit followed twelve seconds later by a full-balance transfer on 26th September 2026.

Four public BNB Smart Chain transactions, all in 2026 UTC. This diagram shows recorded events; the intervening allowance history was not fully checked. Each transaction is linked in the text.

The source wallet approved an unlimited USDT allowance on 3rd February, 235 days before the deposit. I did not check every intervening approval event, so I cannot say the allowance stayed unchanged throughout those months.

On 16th May, the earlier controller, 0xea10…f0c8, changed the contract's company wallet to 0xfbd4…d2788. Reads from the blocks immediately before and after that transaction confirmed the change.

By 26th September, the source wallet held zero USDT immediately before the deposit block. The incoming 7,999.99 USDT became its full balance. Twelve seconds later, the shared controller called the spending contract and received all of it. The execution trace showed the contract calling USDT, and the token event confirmed the transfer.

Etherscan labels the deposit sender's address Binance: Hot Wallet 11. That label comes from Ethereum's explorer; it does not identify who requested this BNB Smart Chain payment.

Immediately before the spending transaction, the allowance was at its maximum value. The contract could use that existing permission, so the transaction needed no new approval from the source wallet.

The twelve-second interval does not tell us how the transfer was triggered. The deposit trace ended inside USDT without calling the spending contract. The later transfer required a separate signed operation, and the verified contract source required the controller to supply the spending instructions. It did not monitor deposits or calculate the wallet's full balance.

A different controller from the one present in February had spent the newly deposited balance. We can verify that transfer, but we cannot identify its approval page or establish whether the wallet owner consented to the later spending.

The same controller connects contracts used by Weathered Raven, Azure Iguana, and Steady Iguana. Five captures across four hosting tenants in the latter two clusters exposed two more spending contracts. Both the Azure approval code and the Steady approval code requested unlimited allowances.

At the review block, both contracts returned 0xfbd4…d2788 as owner and company wallet. Their source identified them as SecureVault, a contract type with a fixed payout address. Unlike the earlier contracts, these could only send tokens to a recipient embedded in their code. Each recipient matched its page settings and differed from the shared controller.

Three page-linked contracts returned the same company wallet on 20th October 2026. Their control changes occurred on different dates, and both SecureVault contracts were paused.

The lines connect contracts to their shared company-wallet value at the review block. Dates come from public control-change transactions. They describe contract authority, not ownership of the sites or a flow of funds.

The control-change dates explain the limits of this connection. The Steady Iguana contract was paused before ownership transferred on 22nd August. Its September page captures came later. For Azure Iguana, the order was reversed: the captures preceded the 27th September transaction that changed the controller, paused spending, and transferred ownership.

Both contracts were also paused at the October review block, when read-only calls confirmed that their spending methods rejected execution. The verified source lets the owner reverse that pause. Pausing stopped spending through the contracts, while leaving token approvals in place. A page could still request new approvals for a paused contract.

These transactions used the old accounts' authority, but the records cannot identify who held their keys or why control changed. The new controller could have acquired existing contracts through a later intervention. The pause records support that possibility without establishing whether the intervention was protective or hostile.

We found a dated contract-control relationship across three actor clusters. That relationship alone cannot assign their earlier pages to one operator, or extend to every contract in each cluster. Another reviewed Azure Iguana contract, 0x5532…c624, returned a different company wallet.

Deployment funding connects more of the contracts

Funding records connect parts of the Weathered Raven-linked contract set before the later changes in control. I checked which wallets created the contracts and who supplied their first BNB, the currency used to pay transaction fees on this chain.

On 7th September, the earlier Trustwallet-neon controller, 0xe9d8…48e7, funded 0xab76…465c before that wallet's first outgoing transaction. The recipient created five reviewed contracts, including four in the original approval reports. Both wallets also acted as historical controllers and directed USDT to the same recipient, 0x9eed…7ef6. Their connection included both deployment funding and actual payouts.

Another wallet, 0xb93e…0f82, funded the creators of contracts used by two other pages:

The creation receipts confirmed that the funded wallets deployed those contracts. This connection comes from their setup funding; it does not depend on them later having the same controller. The Send-USDT-puce contract, for example, had a different recorded controller.

The shared funder also appeared among the wallets whose USDT the contracts spent. In one transaction, a contract transferred 1 USDT from that wallet back to the same wallet. Another did the same with 0.12 USDT. These events used an allowance but moved no tokens between wallets. The 1.12 USDT still appeared in the transfer-event total.

The transfer total includes returned funds

The completed search found 27 contract-driven transfer events totaling 8,239.04 USDT, rounded to two decimals. That is a gross event total. It includes funds sent back to their source and cannot serve as a loss estimate.

The search covered ten contracts from 3rd September to the review block on 20th October. It includes the five transfers matched to the original reports and the 7,999.99-USDT case. It excludes the SecureVault pair and two further contracts deployed by the earlier 0xe9d8…48e7 and 0xab76…465c controllers.

Alongside the 1.12 USDT of self-transfers, the search found 84 USDT returning to the controller that supplied it. On 8th September, that controller sent 30 USDT and then 10 USDT to another wallet. Five seconds after the second payment, a contract transferred 40 USDT back. The controller then sent 44 USDT and recovered it six seconds later.

Those short intervals resemble the timing of the large transfer, yet here the source of the deposits was the controller itself. Speed alone cannot identify theft. Subtracting these known returns and self-transfers would not resolve the remaining transactions either, because their records may include testing or spending with consent.

The controller's 23,752.72-USDT balance at the review block answers a different question: how much it held at that moment. It already had more than 13,156 USDT at the search's starting block. Assigning the whole balance to these pages would include funds that predated the reviewed activity.

What the approvals allowed

The fake transfer form requested permission far beyond its displayed 1 USDT. Changing the amount or recipient did not change the request. Chain receipts confirmed that wallets had granted these unlimited allowances and that the contracts had used them.

The contracts add the part the page settings could not explain. Their controllers could change while the approved addresses stayed fixed. In the 7,999.99-USDT case, a controller different from the one present at the February approval used existing permission to spend a newly deposited balance.

The same control history connected contracts in Weathered Raven with Azure Iguana and Steady Iguana. Funding records supplied separate connections during deployment, before some of those control changes. The people behind the wallets remain unidentified.

The unresolved questions concern who obtained the approvals and why control later changed. Identifying the large transfer's approval page would connect it to a specific lure. To assess losses, we would need to know whether the wallet owner authorized the spending and what the payment was for. The chain records show the contract accepting the new controller's instructions and using an allowance already recorded by USDT.

Indicators and method

These addresses have different roles. The USDT token contract itself is shared infrastructure and is not an actor indicator.

RoleAddress
Shared controller and recipient of the 7,999.99-USDT transfer0xfbd4e0a2fb719f65141ec810a43f6ba6d20d2788
Spending contract in that transfer0x678a4efd236b49e95ff147294a03b2e7eed490c5
Spender configured in Trustwallet-neon0xecfaae6d5bd584b6ea41dd9dd26ebe740c63ab94
Shared funder of the Zara and Send-USDT-puce creators0xb93e4d0710a5befe8572742f8bef14859bb10f82

The research started with stored browser captures and an authorized review of private Telegram records. Read-only BNB Smart Chain calls supplied the transaction and contract history. The interface comparison used archived code with simulated wallet responses and all browser network access blocked; it sent no real transaction. Receipt checks matched transaction input to token events. Historical state and selected execution traces confirmed control changes and the calls behind transfers.

The ten-contract accounting window covers blocks 119729435–128741923, ending on 20th October 2026 at 11:56:28 UTC. Earlier approvals, deployments, and ownership changes came from targeted historical checks. The broader deployment review verified thirteen contract creations by eight wallets; that is a different scope from the transfer search.

Repeated report references were counted once per transaction hash. For example, 28 stored records associated with Steady Iguana identified seven distinct successful August approvals. The report count measures neither transactions nor victims.

BscScan links identify public transactions. Verification used direct chain queries through RPC because explorer page access was limited. The Telegram findings depend on private source records. Amounts in the narrative are rounded where stated; the investigation ledgers retain integer token units.