Background on the Bybit Hack


TX ID for the Transaction that Created the Legitimate Bybit Proxy Address: 0x11dddabcbe93e6d89b664cf149b503044b317a7215dd15614386afb78572cf58
Main Bybit Hot Wallet: 0xf89d7b9c864f589bbF53a82105107622B35EaA40 (recipient of tens of thousands of Ethereum before the hack took place)
Hack TX ID: 0xb61413c495fdad6114a7aa863a00b2e3c28945979a10885b12b30316ea9f072c
Attacker Address (first one; initiated the transaction itself): 0x0fa09C3A328792253f8dee7116848723b72a6d2e
Exchange Hot Wallet Address (for some reason the powers that be at Etherscan decided to change the title of this wallet to 'cold wallet' after the hack took place): 0x1Db92e2EeBC8E0c075a02BeA49a2935BcD2dFCF4
Bybit 'Exploiter' Address: 0x47666fab8bd0ac7003bce3f5c3585383f09486e2 (initial recipient of the illicit funds)
Unknown Contract Address #1: 0xbdd077f651ebe7f7b3ce16fe5f2b025be2969516
Real Implementation Address: 0x34cfac646f301356faa8b21e94227e3583fe3f5f
Suspicious Activity Prior to the Hack
There were four major ETH withdrawals that took place in the week leading up to the hack itself that are worth scrutinizing (not accusing the team of foul play here, but there could be a forensic connection between these transactions and the ultimate compromise that befell Bybit).
12 hours before the hack (-20,000 Ethereum): 0xf08ad5e60962f1cf6974361e8aa3f5c95de1d51c8fb43c840117bddb301562d3 (February 21st, 2025; 3:21 a.m.)
3 days before the hack (-25,000 Ethereum): 0xf40cd51100d9c294c8a1da828619d2d2b18e6db99cc1fbb7d9e0d6a7f9bde370 (February 18th, 2025; 2:03 a.m.)
4 days before the hack (-25,000 Ethereum): 0x2af628dabcc8e45232bd8c97ed83fe1954bae767412f43fed03253b4872dda2c (February 17th, 2025; 7:09 a.m.)
7 days before the hack (-20,000 Ethereum): 0xc15ea48b6575cee2a707834534221b5e98aa071e85379e6ea5e65b66d8c445d9 (February 14th, 2025; 7:55 a.m.)
In total, these 4 separate withdrawals account for 85k Ethereum. The dollar notional value of all of those Ethereum (at the time of their transfers) accounts for roughly ~$241 million. The status of these funds is currently unknown.
The Bybit Smart Contract Setup
This is a proxy contract orchestration adopted from the Gnosis Safe Proxy Contract (multi-sig) construction. Purpose of this setup is to protect funds, and users of this contract model do not actually deploy any of their own contract code. They simply create their child contract from the boilerplate provided already by Gnosis and then the fallback (logic/implementation) that gets called whenever there is a call on the main proxy is deployed and controlled by Gnosis / Safe team themselves (not the exchange/entity deploying the proxy routing contract).
The purpose of this setup is to take as much 'out of the hands' of the implementer as possible. All they have to do is launch a child smart contract using the parent (ancestor) as the provider of the immutable code here. That contract is already programmed (when it gets initialized/constructors called), to call on a pre-defined hardset logic implementation contract. That contract, as the name implies, holds all of the logic for the whole orchestration. Thus, the main proxy is designed to be basic on purpose.
Here is the actual code (all of it, line by line), for the Bybit smart contract orchestration:
/**
*Submitted for verification at Etherscan.io on 2020-01-13
*/
pragma solidity ^0.5.3;
/// @title Proxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.
/// @author Stefan George - <stefan@gnosis.io>
/// @author Richard Meissner - <richard@gnosis.io>
contract Proxy {
// masterCopy always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated.
// To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt`
address internal masterCopy;
/// @dev Constructor function sets address of master copy contract.
/// @param _masterCopy Master copy address.
constructor(address _masterCopy)
public
{
require(_masterCopy != address(0), "Invalid master copy address provided");
masterCopy = _masterCopy;
}
/// @dev Fallback function forwards all transactions and returns all received return data.
function ()
external
payable
{
// solium-disable-next-line security/no-inline-assembly
assembly {
let masterCopy := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)
// 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0s
if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) {
mstore(0, masterCopy)
return(0, 0x20)
}
calldatacopy(0, 0, calldatasize())
let success := delegatecall(gas, masterCopy, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
if eq(success, 0) { revert(0, returndatasize()) }
return(0, returndatasize())
}
}
}
Initial Notes on the Smart Contract
Uses an old pragma version at the top (i.e.,
^0.5.3
). This is even older than what we saw with the Gnosis Safe Proxy 1.3.0 orchestration that WazirX implemented (that was also compromised a few months ago back in July 2024). My guess is that (based on the time the smart contract was deployed; year 2020), that they had the 1.2.0 version of the contracts in deployment (nearly half a decade of iterative improvements and security patches they're missing out).These older contracts also typically point to older logic implementation contracts as well. The whole point of a delegated proxy orchestration is that its supposed to serve as a 'workaround' to the whole "immutable code" issue that smart contracts run into. In essence, one of the most touted features of blockchain (i.e., 'finality' + 'immutability'), turn out to be quasi-issues in the world of smart contracts where programmers/developers are infallible beings that may push a contract 'live' on the mainnet that contains errors, flaws, glitches or other issues that must be later amended and/or upgraded. Since the code of deployed contracts have been and will always be considered immutable, the workaround was to use proxy delegates.
Looking at the hacked contract, we can see the bytecode was not verified (no surprise here). Upon decompilation (by Dedaub), we can see that the same function that was called by the attacker in the initial transaction existed within the 'evil' implementation contract (likely ended up replacing the 'good' one as the predominant implementation; that's just a premature guess though until I can do some more research and figure out what the fuck actually happened throughout the course of this hack).
Ownership Information for the Main Bybit Proxy
The original owners of the multi-signature that Bybit deployed can be found in the contract's creation TX ID: 0x11dddabcbe93e6d89b664cf149b503044b317a7215dd15614386afb78572cf58
Proxy Contract Address: 0x1db92e2eebc8e0c075a02bea49a2935bcd2dfcf4
Here are the owners (verified signers) that were instantiated via that TX:
0x2cdd560058d5ac32dc416aaa09eaf93230c0b7b3
0xd367f8322b64f29faf71ddb5c1877dc9ed6ec644
0xe3df2cceac61b1afa311372ecc5b40a3a6585a9e
0xbe72691aca605050d1e693a2c2c6a9f3f41dc939
Fallback Handler (contract): 0xd5d82b6addc9027b22dca772aa68d5d74cdbdf44 Implementation/Logic Address: 0x34cfac646f301356faa8b21e94227e3583fe3f5f Parent (Factory): 0x76e2cfc1f5fa8f6a5b3fc4c8f4788f0116861f9b Calling Address (belongs to Bybit): 0xc7a2e64543d55f0dc139974f8c098fd7ff3b4d8f
Ownership Changes
Keep in mind that the total # of owners on this smart contract is stored at a specific storage offset; that storage offset is:
0x0000000000000000000000000000000000000000000000000000000000000003
(this is going to be something we double back to refer to in the not so distant future)
Let's start by listing the transaction IDs and times (dates/block heights) where there was an ownership change that added an owner/authorized signer to the Bybit proxy:
0x1425b4dad07b6812d356a00919f6fca35c7f67dda1476581fabe06820101c888 (July 4th, 2024):
addOwnerWithThreshold
[0x3dd4b4dbe6aee6f49a65f0c1ac508deff761c195]0xddd7bf90d134932bcb27eabc6d414a7190fe776336f9a608e19ad22693f4752b (August 21st, 2023):
swapOwner
andRemovedOwner
[0x913b41a348dfb9300a00f01459ac1b43ea23d998]0xb4e20008eff6a4ddb79521fabf7df9bfdb5b4018a60d88624fc1887b65a76433 (January 28th, 2023):
addOwnerWithThreshold
[0x828424517f9f04015db02169f4026d57b2b072290xcd45e217049cf9ce1a3fd87aae3e4fecf63c8f3c31396a9ddd3e641ceef159f0 (October 29th, 2021):
addOwnerWithThreshold
[0x2cdd560058d5ac32dc416aaa09eaf93230c0b7b3]
There were also two transactions made that removed an owner (explicitly) from the smart contract:
0x62e69929856083fb847caa54f647ebc7095a0f0dbdbfaea0530b55f47ba4fc37 (July 5th, 2024) [0x828424517f9f04015db02169f4026d57b2b07229]
0xddd7bf90d134932bcb27eabc6d414a7190fe776336f9a608e19ad22693f4752b (August 21st, 2023): this was already noted above among the transactions where an owner was added [0x913b41a348dfb9300a00f01459ac1b43ea23d998]
Quick Note: The only transaction among the ones above where there was no owner that was added, swapped or replaced was the one made on July 5th, 2024 (
0x62e69929856083fb847caa54f647ebc7095a0f0dbdbfaea0530b55f47ba4fc37
).Calling Addresses are in Brackets Above
The final list of owners at the time of the hack was:
0x2cdd560058d5ac32dc416aaa09eaf93230c0b7b3
0xd367f8322b64f29faf71ddb5c1877dc9ed6ec644
0xe3df2cceac61b1afa311372ecc5b40a3a6585a9e
0x828424517f9f04015db02169f4026d57b2b07229
0x3cc3a225769900e003e264dd4cb43e90896bc21a
1f4eb0a903619ac168b19a82f1a6e2e426522211
Some Additional Information
Several other proxies were created by the owners of the Bybit proxy that was compromised:
0x72ede922683dc98497317744cd9ee62345462561
(December 12th, 2021)0x705199fe234a7a2f1bc8b95dd7d08284c8f467f1
(November 3rd, 2022)0x2ebf891f4718eb8367013d8d975a1e5afcae277f
(November 17th, 2022)0xd2f0c70ac768cba8c10ee64fc2657ee8c1ca862f
(January 10th, 2023)0x6f4565c9d673dbdd379aba0b13f8088d1af3bb0c
(April 3rd, 2023)0x0729ff91c188ebc6f290ba4e228cff72ef940044
(August 7th, 2023)0x086a8d541febd35bed66a799e08a1799af5f4481
(August 14th, 2023)0x089423ad2f9f195a72b28d37c902a1d060586d39
(November 27th, 2023)0x75ae0e74b18290646b5c56c2ff6e58f9e41a9c33
(February 2nd, 2024)0xc3350595ed42ebe94556277bc77d257c76065291
(February 2nd, 2024)
Suspicious Pre-Hack Activity by Hackers
Noticed something interesting on the blockchain. Out of curiosity, I found myself visiting one of Bybit's (unmarked) addresses located here: 0xa7a93fd0a276fc1c0197a5b5623ed117786eed06
Looking closer at those failed transactions, I could see that the sender was: 0xf07a76ae06c8d5996874cc6994e38d3b33e78076 (albeit, its worth noting that these transactions came well after the actual hack took place; keep that in mind moving forward).
What's notable, however, is that this address had been making failed calls to several other smart contracts around the Ethereum ecosystem just a week or so before the actual attack took place.
The contract in question that received this failed call is 0xCe6E7Dd39487AB304937CaB29B3EbDE1c96740dA and it, too, is a Gnosis Safe proxy with the same versioning as the Bybit proxy that was compromised a week later on February 21st, 2025.
While it cannot be confirmed that this address is definitively tied with the hackers in question, it does raise the question of whether the hackers were merely canvassing the entire Ethereum ecosystem in an attempt to find any and all contracts that were deployed with the Gnosis Safe Proxy 1.1.1 implementation in an effort to see which ones would be vulnerable to compromise in some capacity.
A closer look at the blockchain shows that the attackers had attempted to compromise the Zen Exchange about a week prior to targeting Bybit. The only difference between the two (and why the former remained safe), is because the Zen implementation is substantially more secure than what Bybit had deployed.
Subscribe to my newsletter
Read articles from Cryptomedication directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Cryptomedication
Cryptomedication
#Blockchain #BlockSec #OSINT #CyberSec #Darkweb | Isaiah 54:17 Fingerpint: 54EADD6FCBCF520E37A003E04D3ECE027AEFA381