Tối thứ Ba, một dự án AI Agent mới gọi là 'NeuroMesh' vừa announce raise 15 triệu USD từ một quỹ lớn. Token chưa TGE, nhưng hype đã ngập Twitter. Bỗng nhiên, một dòng code trong hợp đồng thông minh của họ bị phát hiện – không phải lỗi ‘by design’, mà là một backdoor cho phép admin rút toàn bộ liquidity pool bất kỳ lúc nào. Chỉ trong 48 giờ sau khi bài phân tích của tôi lên sóng, đội ngũ dự án đã vội vã deploy bản vá, nhưng câu hỏi đặt ra: đây là sai sót kỹ thuật hay kế hoạch có chủ đích?

Tôi nhận được tin nhắn từ một bot theo dõi mempool lúc 2 giờ sáng: một giao dịch lạ gửi 1.2 ETH đến một địa chỉ mới, deploy một hợp đồng với tên biến đáng ngờ: ‘emergencyWithdraw’. Ngay lập tức, tôi kích hoạt script reverse-engineering – thói quen có từ năm 2020, khi tôi live-stream vụ tấn công bZx. Bạn có biết, sau gần 6 năm làm aggregator, tôi đã xây dựng một thư viện signature mẫu cho từng loại backdoor phổ biến? Cái này trông giống hệt pattern của vụ ‘rug pull’ trên Arbitrum năm ngoái, chỉ khác ở chỗ họ giấu nó dưới một hàm ‘renounceOwnership’ giả.
Câu chuyện bắt đầu từ một tweet của một KOL có 200k followers: ‘NeuroMesh – AI Agent đầu tiên trên Base có khả năng tự học on-chain. Team do 3 cựu Google Brain dẫn dắt. Token sắp IDO.’ Trong vòng 30 phút, bài đăng có 2.000 like. Cộng đồng FOMO đổ xô vào Discord, farming testnet. Nhưng với tôi, một Tiến sĩ Mật mã học đã từng đọc hợp đồng ICO EOS suốt 2 tuần để phát hiện lỗ hổng 2.5 triệu USD, điều này ngửi thấy mùi ‘narrative quá đẹp’. Tôi mở Etherscan, tra địa chỉ deployer. Lịch sử giao dịch của nó chỉ có 3 tháng – một dấu hiệu của ‘tài khoản rác’. Họ thuê một auditor bên thứ ba? Có, nhưng báo cáo audit chỉ cover 70% code – phần còn lại được gắn mác ‘upgradable proxy’ – nơi thường giấu backdoor nhất.
Tôi bắt đầu đào sâu.
Hợp đồng chính là một proxy ERC-1967, với implementation được deploy sau 2 block. Tôi dùng công cụ phổ biến – nhưng với tham số tùy chỉnh: scan toàn bộ storage layout. Kết quả: có một biến address private owner không được khởi tạo trong constructor, thay vào đó được set qua một hàm initialize chỉ gọi một lần. Nhưng tôi nhận ra rằng hàm initialize đó có modifier onlyInitializing thay vì initializer – một lỗi kinh điển cho phép bất kỳ ai gọi lại nó nếu hợp đồng implementation được nâng cấp. Và team đã set _initializing = false trong proxy, nghĩa là kẻ tấn công có thể gọi initialize trực tiếp trên implementation, set owner về địa chỉ của mình.
Chưa dừng lại, tôi kiểm tra hàm emergencyWithdraw. Nó chỉ đơn giản transfer toàn bộ balance của contract đến owner. Và owner thì có thể bị chiếm quyền qua lỗi initialize. Một chuỗi tấn công hoàn hảo: 1. Gọi initialize trên implementation -> set owner thành address attacker. 2. Gọi emergencyWithdraw -> rút hết token. Tổng cộng chỉ cần 2 giao dịch, tốn chưa tới 0.01 ETH gas. Nếu tôi không phát hiện sớm, khi dự án raise xong và liquidity pool được tạo, kẻ tấn công (có thể chính là team) sẽ rút sạch 15 triệu USD trong nháy mắt.
Cảm giác giống như năm 2021 khi tôi reverse-engineer hợp đồng CryptoPunks, phát hiện ra thuật toán rarity trait không được công bố. Khi đó, tôi viết bộ 3 bài phân tích kèm code mẫu Solidity, chứng minh các công cụ đánh giá NFT thời đó sai lệch 30%. NeuroMesh cũng vậy – họ dựa vào sự mù mờ về kỹ thuật của đám đông để che giấu một backdoor. Nhưng có điểm khác: thay vì lỗi vô tình, đây có vẻ là có chủ đích. Tôi kiểm tra lịch sử commit trên GitHub của họ: 2 ngày trước khi announce, repository private bỗng public, và commit cuối cùng chính là thêm hàm emergencyWithdraw – kèm comment ‘fix’. Một cái fix có chủ đích? Không, đó là backdoor được ngụy trang.
Tôi viết bài phân tích và đăng lên aggregator của mình lúc 6 giờ sáng. Dùng Twitter thread, tweet đầu tiên: ‘NeuroMesh vừa raise 15M. Hợp đồng của họ có một lỗ hổng cho phép rút toàn bộ quỹ. Đây là code và cách khai thác.’ Kèm theo ảnh chụp màn hình và dòng code Solidity. Chỉ sau 3 giờ, bài viết có 25.000 lượt xem. Cộng đồng Discord của họ bắt đầu hoảng loạn. Team phản hồi trong vòng 12 giờ, nói rằng ‘đây là lỗi không cố ý, chúng tôi sẽ fix ngay’. Họ deploy bản vá, thay emergencyWithdraw bằng một hàm chỉ cho phép rút khi có multi-sig. Nhưng tôi kiểm tra bản vá: họ vẫn giữ lại proxy implementation cũ, và chỉ disable hàm cũ bằng cách set owner = address(0). Điều đó có nghĩa là nếu ai đó gọi initialize trước khi họ vá, thì owner đã bị set lại. May mắn là chưa ai làm điều đó.
Nhưng câu hỏi thực sự: đây là sơ suất hay kế hoạch?
Dựa trên kinh nghiệm audit của tôi, các lỗi kiểu initialize thiếu initializer thường chỉ xuất hiện ở những dự án mới code vội. Nhưng trong trường hợp này, team có đến 3 kỹ sư từ Google Brain, có tiền đầu tư từ quỹ lớn, và hợp đồng được audit (dù chỉ 70%). Khả năng họ ‘vô tình’ quên một lỗi cơ bản đến vậy là rất thấp. Tôi nghi ngờ rằng đây là một ‘stress test’ ngược: họ cố tình tạo lỗ hổng để xem cộng đồng có phát hiện không, rồi vá lại để tạo uy tín. Hoặc tệ hơn, họ đã lên kế hoạch rug pull, nhưng bị lộ trước khi kịp hành động. Tôi chọn tin vào kịch bản thứ hai – vì nếu muốn test, họ đã công bố bug bounty. Thay vào đó, họ im lặng cho đến khi bài phân tích của tôi viral.
Góc nhìn nghịch chiều:
Đám đông đang reo hò vì ‘team đã fix lỗi nhanh chóng, minh bạch’. Nhưng hãy nhìn vào bức tranh lớn: dự án raise 15 triệu USD, có audit, có KOL, nhưng vẫn có một backdoor nguy hiểm đến vậy. Điều này cho thấy hệ thống bảo vệ hiện tại thất bại thảm hại. Audit chỉ check 70% code, phần proxy – nơi ẩn chứa lỗi – lại nằm ngoài phạm vi. Cộng đồng dựa vào KOL và tên tuổi team, thay vì tự kiểm tra hợp đồng. Nếu không có những ‘kẻ săn tin’ như tôi, 15 triệu USD đã bay hơi. Và còn bao nhiêu dự án khác đang tồn tại với những lỗ hổng tương tự?
Tôi nhớ lại cuộc tranh luận với cộng đồng Solana năm 2022, khi tôi chỉ ra 80% số khối do 5 validator tạo ra. Lúc đó, mọi người bảo tôi ‘FUD’, nhưng sau đó Solana đã ngừng mạng 6 lần. Bây giờ, NeuroMesh cũng vậy – họ bảo ‘lỗi đã được vá, không sao’. Nhưng tin tôi đi, một team sẵn sàng deploy backdoor sẽ sẵn sàng tạo lỗ hổng khác. Tôi đã theo dõi địa chỉ implementation của họ: 3 ngày sau, họ deploy bản nâng cấp mới, thêm một hàm mint với số lượng không giới hạn, nhưng lại quên set cap. Lỗi lại tái diễn.
Takeaway:
Đừng bao giờ tin vào audit 70%, đừng bao giờ tin vào team ‘có tên tuổi’ mà không tự xem code. Thị trường tăng đang che giấu vô số quả bom kỹ thuật. Tôi đã dành 18 năm để săn tin, và tôi biết rằng: mỗi khi bạn FOMO, một kẻ nào đó đang cười. Hãy hỏi tôi làm thế nào để check hợp đồng của dự án bạn đang hold – tôi sẵn sàng giúp, miễn là bạn có thể chịu được sự thật.