Nền
Bài viết trước của CertiK "Chơi một trò chơi mới trên chuỗi " Tiết lộ kỹ thuật RugPull quy mô lớn" tiết lộ một địa chỉ máy thu hoạch tự động lừa đảo thoát quy mô lớn 0xdf1a nhắm mục tiêu vào các bot mới. Địa chỉ này đã hoàn thành hơn 200 lần thoát chỉ trong khoảng hai tháng. Lừa đảo (sau đây gọi chung là RugPull ), nhưng băng đảng này không chỉ có một phương pháp RugPull.
Bài viết trước đã sử dụng mã thông báo MUMI làm ví dụ để mô tả phương pháp RugPull của nhóm đằng sau địa chỉ:Sửa đổi trực tiếp mã thông báo của địa chỉ thuế thông qua số dư cửa sau mã, nhưng không sửa đổi tổng nguồn cung cấp mã thông báo cũng như không gửi sự kiện Chuyển khoản, vì vậy người dùng đã xem etherscan không thể phát hiện ra hành vi bí mật đúc mã thông báo của dự án.
Bài viết hôm nay sử dụng token "ZhongHua" làm ví dụ để phân tích một phương pháp RugPull khác của nhóm: sử dụng logic hàm thuế phức tạp để che đậy hàm truyền của RugPull. Tiếp theo, chúng tôi phân tích chi tiết về một phương thức RugPull khác tại địa chỉ 0xdf1a thông qua trường hợp mã thông báo "ZhongHua".
Lừa đảo chuyên sâu
Trong trường hợp này, bên dự án Tổng cộng 999 tỷ ZhongHua đã được đổi lấy khoảng 5,884 WETH, làm cạn kiệt tính thanh khoản của nhóm. Để hiểu sâu hơn về toàn bộ trò lừa đảo RugPull, hãy cùng phân loại các sự kiện ngay từ đầu.
Triển khai mã thông báo
Ngày 1 tháng 1 :40 sáng ngày 18 (giờ UTC, giống như bên dưới), địa chỉ của kẻ tấn công (?0x74fc) đã triển khai mã thông báo ERC20 có tên ZhongHua (?0x71d7) và khai thác trước 1 tỷ mã thông báo và gửi chúng đến địa chỉ của kẻ tấn công (?0x74fcfc ).
Số lượng mã thông báo được khai thác trước phù hợp với số lượng được xác định trong mã nguồn hợp đồng.
Thêm thanh khoản
1:50 (10 phút sau khi tạo mã thông báo), địa chỉ kẻ tấn công (?0x74fc) Cấp quyền phê duyệt mã thông báo ZhongHua cho Bộ định tuyến Uniswap V2 để chuẩn bị bổ sung tính thanh khoản.
1 phút sau, địa chỉ của kẻ tấn công (?0x74fc) gọi hàm addLiquidityETH trong Bộ định tuyến để thêm thanh khoản nhằm tạo nhóm thanh khoản ZhongHua-WETH (?0x5c8b), thêm tất cả các mã thông báo được khai thác trước và 1,5 ETH vào nhóm thanh khoản, và cuối cùng đã thu được khoảng 1.225 mã thông báo LP.
Từ hồ sơ chuyển mã thông báo ở trên, chúng ta có thể thấy rằng trong một lần chuyển tiền, kẻ tấn công (?0x74fc) đã gửi 0 mã thông báo đến chính hợp đồng mã thông báo ZhongHua.
Việc chuyển tiền này không phải là một lần chuyển tiền thông thường để tăng tính thanh khoản. Bằng cách xem mã nguồn của hợp đồng mã thông báo, chúng tôi nhận thấy rằng chức năng _getAmount được triển khai. chịu trách nhiệm chuyển tiền từ địa chỉ The from khấu trừ tiền và tính phí xử lý sẽ phải trả, sau đó gửi phí xử lý đến địa chỉ mã thông báo, sau đó kích hoạt sự kiện Chuyển cho biết rằng địa chỉ mã thông báo nhận được phí xử lý.
Hàm _getAmount sẽ xác định xem người gửi chuyển khoản có phải là _owner hay không. Nếu là _owner, phí xử lý sẽ được đặt thành 0. _owner được chỉ định bởi tham số đầu vào của hàm tạo khi hợp đồng có thể sở hữu được triển khai.
Hợp đồng mã thông báo ZhongHua kế thừa hợp đồng Có thể sở hữu và sử dụng thông điệp của người triển khai làm tham số đầu vào của hàm tạo có thể sở hữu trong quá trình triển khai.
Vậy địa chỉ của kẻ tấn công (?0x74fc) là _chủ sở hữu của hợp đồng mã thông báo. Việc chuyển mã thông báo bằng 0 để tăng thêm tính thanh khoản được gửi thông qua hàm _getAmount, bởi vì _getAmount sẽ được gọi trong các hàm chuyển và transferFrom.
Khóa thanh khoản vĩnh viễn
1 Tại 51:00 (trong vòng 1 phút kể từ khi tạo nhóm thanh khoản), địa chỉ kẻ tấn công (?0x74fc) sẽ gửi tất cả 1.225 mã thông báo LP thu được bằng cách thêm thanh khoản trực tiếp vào địa chỉ 0xdead để hoàn tất việc khóa vĩnh viễn mã thông báo LP.
Tương tự như trường hợp mã thông báo MUMI, khi LP bị khóa, về mặt lý thuyết, địa chỉ của kẻ tấn công (?0x74fc) không còn khả năng thực hiện RugPull bằng cách loại bỏ thanh khoản. Trong vụ lừa đảo RugPull do địa chỉ 0xdf1a dẫn đầu, nhắm vào các robot mới, bước này chủ yếu được sử dụng để đánh lừa tập lệnh chống lừa đảo của các robot mới.
Tại thời điểm này, từ quan điểm của người dùng, tất cả các Token được khai thác trước đã được sử dụng để thêm vào nhóm thanh khoản và không có điều bất thường nào xảy ra.
RugPull
2:10 sáng Vài phút (khoảng 30 phút sau khi mã thông báo ZhongHua được tạo), kẻ tấn công địa chỉ 2 (?0x5100) đã triển khai một hợp đồng tấn công (?0xc403) dành riêng cho RugPull.
Tương tự như trường hợp mã thông báo MUMI, phía dự án không sử dụng địa chỉ tấn công để triển khai hợp đồng mã thông báo ZhongHua và hợp đồng tấn công được sử dụng cho RugPull không phải là nguồn mở. Mục đích là để gây khó khăn hơn để các kỹ thuật viên truy tìm nguồn gốc. Một số trò lừa đảo RugPull có đặc điểm này.
Vào lúc 7:46 sáng (khoảng 6 giờ sau khi hợp đồng mã thông báo được tạo), địa chỉ kẻ tấn công 2 (?0x5100) đã thực hiện RugPull.
Bằng cách gọi phương thức "swapExactETHForTokens" của hợp đồng tấn công (?0xc403), anh ta đã chuyển 999 tỷ mã thông báo ZhongHua từ hợp đồng tấn công và trao đổi khoảng 5,884 ETH, và đã rút cạn phần lớn thanh khoản trong nhóm.
Vì hợp đồng tấn công (?0xc403) không phải là nguồn mở nên chúng tôi đã dịch ngược mã byte của nó và kết quả như sau:
https://app.dedaub.com/ethereum/address/0xc40343c5d0e9744a7dfd8eb7cd311e9cec49bd2e/decompiled
Hợp đồng tấn công (?0xc403 ) Chức năng chính của chức năng "swapExactETHForTokens" là trước tiên sử dụng phê duyệt để cấp cho Bộ định tuyến UniswapV2 số quyền chuyển mã thông báo ZhongHua tối đa, sau đó sử dụng Bộ định tuyến để chỉ định số lượng mã thông báo ZhongHua "xt" mà người gọi sở hữu (hợp đồng tấn công (?0xc403) ) được chuyển đổi thành ETH và gửi đến địa chỉ "_rescue" được khai báo trong hợp đồng tấn công (?0xc403).
Bạn có thể thấy rằng địa chỉ tương ứng với "_rescue" chính xác là người triển khai hợp đồng tấn công (?0xc403): địa chỉ kẻ tấn công 2 (?0x5100).
Tham số đầu vào xt của giao dịch RugPull này là 999.000.000.000.000.000.000, tương ứng với 999 tỷ ZhongHua token (số thập phân của ZhongHua là 9).
Cuối cùng, dự án đã sử dụng 999 tỷ ZhongHua để rút WETH trong nhóm thanh khoản và hoàn thành RugPull.
Tương tự như trường hợp MUMI ở bài viết trước, trước tiên chúng ta cần xác nhận nguồn gốc của token ZhongHua trong hợp đồng tấn công (?0xc403)< /mạnh>. Chúng tôi đã biết từ bài viết trước rằng tổng nguồn cung cấp mã thông báo ZhongHua là 1 tỷ và sau khi RugPull kết thúc, tổng nguồn cung cấp mã thông báo ZhongHua mà chúng tôi đã truy vấn trong trình khám phá khối vẫn là 1 tỷ. số lượng mã thông báo được bán theo hợp đồng tấn công (?0xc403) là 999 tỷ, gấp 999 lần tổng nguồn cung được ghi nhận trong hợp đồng Con số này vượt xa con số. tổng nguồn cung cấp số lượng token đến từ đâu?
Chúng tôi đã kiểm tra lịch sử sự kiện chuyển ERC20 của hợp đồng và nhận thấy rằng, giống như trường hợp RugPull của mã thông báo MUMI, hợp đồng tấn công (?0xc403) trong trường hợp mã thông báo ZhongHua cũng không có sự kiện chuyển mã thông báo ERC20.
Trong trường hợp MUMI, mã thông báo của hợp đồng thuế đến từ việc sửa đổi trực tiếp số dư trong hợp đồng mã thông báo, khiến hợp đồng thuế sở hữu trực tiếp mã thông báo vượt xa tổng nguồn cung. Vì hợp đồng mã thông báo MUMI không sửa đổi Tổng nguồn cung của mã thông báo khi sửa đổi số dư, cũng như không kích hoạt sự kiện Chuyển khoản, nên chúng tôi không thể xem bản ghi chuyển mã thông báo của hợp đồng thuế trong trường hợp MUMI, như thể hợp đồng thuế được sử dụng đối với mã thông báo RugPull như thể nó giống như xuất hiện từ không khí vậy.
Quay lại trường hợp ZhongHua, các token ZhongHua trong hợp đồng tấn công (?0xc403) dường như cũng xuất hiện đột ngột nên chúng ta cũng đi đến ZhongHua hợp đồng mã thông báo Tìm kiếm từ khóa "cân bằng" trong .
Kết quả cho thấy chỉ có ba sửa đổi đối với biến số dư trong toàn bộ hợp đồng mã thông báo, đó là "_getAmount", " _transferFrom" và Trong hàm "_transferBasic".
"_getAmount" được sử dụng để xử lý logic thu phí chuyển khoản, "_transferFrom" và "_transferBasic" được sử dụng để xử lý logic chuyển khoản và hình sau không xuất hiện mã thông báo MUMI thường trực tiếp sửa đổi báo cáo số dư một cách rõ ràng.
Quan trọng hơn, hợp đồng mã thông báo MUMI không kích hoạt sự kiện Chuyển khoản khi nó trực tiếp sửa đổi số dư của hợp đồng thuế. Đây là lý do tại sao chúng tôi không thể truy vấn sự kiện chuyển mã thông báo của hợp đồng thuế trong trình duyệt khối, nhưng hợp đồng thuế có thể. Lý do để sở hữu một số lượng lớn tiền xu.
Tuy nhiên, trong hợp đồng token ZhongHua, cho dù đó là chức năng "_getAmount", "_transferFrom" hay "_transferBasic", sau khi sửa đổi số dư, họ đều có The Sự kiện chuyển được kích hoạt chính xác Điều này mâu thuẫn với trường hợp chúng tôi không thể tìm thấy sự kiện Chuyển trong đó mã thông báo đã được chuyển khi chúng tôi truy vấn sự kiện Chuyển liên quan đến hợp đồng tấn công (?0xc403) .
Có lẽ nào không giống như trường hợp MUMI, các mã thông báo trong hợp đồng tấn công (?0xc403) thực sự xuất hiện một cách bất ngờ?
Các kỹ thuật bí mật
< strong> Các token tấn công hợp đồng đến từ đâu?
Trong quá trình phân tích vụ việc, khi chúng tôi phát hiện ra rằng mọi sửa đổi đều trong hợp đồng ZhongHua Khi số dư kích hoạt chính xác sự kiện Chuyển nhưng vẫn không thể tìm thấy bản ghi chuyển mã thông báo hoặc sự kiện Chuyển liên quan đến hợp đồng tấn công (?0xc403), bạn cần tìm ý tưởng phân tích mới.
Chúng tôi đã truy vấn một số lượng lớn hồ sơ chuyển khoản và từng sử dụng chức năng "performZhongSwap" trong hợp đồng như một bước đột phá. hợp đồng mã thông báo Để bán, trong các sự cố RugPull khác mà chúng tôi đã phân tích, có nhiều trường hợp loại chức năng này được sử dụng làm cửa hậu RugPull.
Mặc dù đã kiểm tra các chức năng khác nhưng không tìm thấy gì. Vì vậy, chúng tôi bắt đầu tập trung vào chính chức năng "chuyển giao". Bất kể kẻ tấn công thực hiện RugPull như thế nào, logic triển khai của chức năng "chuyển giao" phải chứa thông tin quan trọng nhất.
Chuyển khoản nghiêm trọng
Hàm "chuyển" trong hợp đồng mã thông báo gọi trực tiếp hàm "_transferFrom".
Có vẻ như chức năng "chuyển" thực hiện thao tác chuyển mã thông báo và sự kiện Chuyển sẽ được kích hoạt sau khi quá trình chuyển hoàn tất.
Nhưngtrước khi chuyển mã thông báo, chức năng "chuyển khoản" trước tiên sẽ sử dụng chức năng "_isNotTax" để xác định xem người gửi chuyển khoản có phải là người nộp thuế- địa chỉ miễn phí: nếu không thì hãy sử dụng chức năng "_getAmount" để thu thuế; nếu vậy, sẽ không thu thuế và mã thông báo sẽ được gửi trực tiếp đến người nhận. Và đó chính xác là vấn đề nằm ở đâu.
Như đã đề cập ở trên, Khi triển khai "_getAmount", hợp đồng mã thông báo sẽ xác minh số dư của người gửi và kiểm tra số dư của người gửi. được thực hiện và phí được gửi đến hợp đồng mã thông báo.
Vấn đề là "_getAmount" chỉ được sử dụng khi người gửi không được Khi gọi đến địa chỉ miễn thuế. Khi người gửi là địa chỉ miễn thuế, số tiền này sẽ được cộng trực tiếp vào số dư của người nhận.
Vấn đề trở nên rất rõ ràng vào thời điểm này:Khi địa chỉ miễn thuế được sử dụng làm người gửi để chuyển, hợp đồng mã thông báo không xác minh liệu số dư của người gửi là đủ. Thậm chí không có thao tác trừ số tiền từ số dư của người gửi. Điều này có nghĩa là bất kỳ số lượng token nào cũng có thể được gửi đến bất kỳ địa chỉ nào miễn là đó là địa chỉ miễn thuế được xác định bởi hợp đồng token. Đây là lý do tại sao hợp đồng tấn công (?0xc403) có thể chuyển trực tiếp gấp 999 lần tổng nguồn cung cấp mã thông báo.
Sau khi kiểm tra, người ta thấy rằng hợp đồng mã thông báo chỉ đặt _taxReceipt làm địa chỉ miễn thuế trong hàm tạo và địa chỉ tương ứng với _taxReceipt là hợp đồng tấn công (? 0xc403).
Phương thức RugPull của mã thông báo ZhongHua đã được xác định:Kẻ tấn công đã sử dụng logic cụ thể để phá vỡ các đặc quyền. xác minh số dư của địa chỉ cho phép địa chỉ đặc quyền chuyển mã thông báo ra khỏi không khí, từ đó hoàn thành RugPull.
Cách kiếm lợi nhuận
Lợi dụng lỗ hổng trên, kẻ tấn công có địa chỉ 2 (?0x5100) trực tiếp gọi tới sở hữu "swapExactETHForTokens" của hợp đồng tấn công đặc quyền (?0xc403) hoàn thành RugPull. Trong chức năng "swapExactETHForTokens", hợp đồng tấn công (?0xc403) đã cấp quyền chuyển mã thông báo cho Bộ định tuyến Uniswap V2, sau đó gọi trực tiếp chức năng trao đổi mã thông báo của Bộ định tuyến để trao đổi 999 tỷ mã thông báo ZhongHua lấy 5,88 ETH trong nhóm.
Trên thực tế, ngoài giao dịch RugPull nêu trên, bên dự án cũng đã bán nó 11 lần thông qua hợp đồng tấn công (?0xc403 ). strong>Mã thông báo, đã thu được tổng cộng 9,64 ETH; bao gồm cả giao dịch RugPull cuối cùng, đã thu được tổng cộng 15,52 ETH. Chi phí chỉ là 1,5 ETH để thêm tính thanh khoản, một khoản phí nhỏ để triển khai hợp đồng và một lượng nhỏ ETH để thu hút các robot mới tích cực trao đổi.
Ngay cả nhóm dự án cũng đã sử dụng các địa chỉ EOA khác nhau để gọi hợp đồng tấn công (?0xc403) để bán mã thông báo. Có vẻ như những người gửi khác nhau đang bán mã thông báo để ngụy trang. ý định thực sự của nó là liên tục rút tiền.
Tóm tắt
Bây giờ nhìn lại và suy nghĩ về toàn bộ trường hợp RugPull token ZhongHua, tôi thấy rằng bản thân phương pháp này rất đơn giản , nhưng chỉ cần hủy xác minh số dư mã thông báo của địa chỉ đặc quyền. Nhưng tại sao lại không suôn sẻ khi phân tích vụ án này? Có thể có hai lý do chính:
1. Bảo vệ an ninh và tấn công có tầm nhìn khác nhau. Đối với những người hành nghề bảo mật, xác minh số dư trong mã là đảm bảo bảo mật cơ bản nhất cần được hoàn thành. Do đó, hầu hết những người hành nghề bảo mật sẽ tin rằng chức năng "chuyển khoản" sẽ hoàn thành việc xác minh số dư của người dùng như một điều tất nhiên. Hãy cảnh giác với những lỗ hổng như vậy (hoặc cho rằng những lỗ hổng đó quá cơ bản và những kẻ tấn công sẽ không sử dụng chúng).
Tuy nhiên, từ góc độ kẻ tấn công, phương thức tấn công hiệu quả nhất thường đơn giản nhất: không xác minh số dư vừa hiệu quả vừa dễ bị lợi dụng. Bỏ qua kỹ thuật RugPull, không có lý do gì để không sử dụng. Đây thực sự là trường hợp ít nhất từ góc độ mô tả trường hợp, phương pháp RugPull trong trường hợp mã thông báo ZhongHua để lại ít dấu vết nhất. Cuối cùng, nó vẫn cần thiết. kiểm tra mã theo cách thủ công để xác định vị trí cửa hậu mã.
2. Phía dự án đang cố tình che giấu mã cửa sau không yêu cầu xác minh số dư cho các địa chỉ đặc quyền. Nhóm dự án thậm chí còn triển khai độc lập một bộ logic tính toán chuyển thuế hoàn chỉnh cũng như logic rút địa chỉ mã thông báo và tái đầu tư cho các địa chỉ không có đặc quyền, khiến việc triển khai logic chuyển phức tạp cho mã thông báo có vẻ hợp lý. Khi chuyển tiền đến các địa chỉ thông thường khác, hành vi này không khác gì hành vi bình thường. Nếu không xem kỹ mã, sẽ không tìm thấy manh mối nào cả.
So sánh các trường hợp RugPull của nhóm này đối với mã thông báo MUMI và mã thông báo ZhongHua, cả hai đều sử dụng các phương pháp tương đối bí mật để kiểm soát quyền đối với số lượng lớn mã thông báo. .
Trong trường hợp MUMI token RugPull, bên dự án đã trực tiếp sửa đổi số dư mà không sửa đổi TotalSupply hoặc kích hoạt sự kiện Chuyển khoản, khiến người dùng không thể nhận thức được các đặc quyền Địa chỉ đã nắm giữ một lượng lớn mã thông báo.
Trường hợp mã thông báo ZhongHua kỹ lưỡng hơn bằng cách không trực tiếp xác minh số dư của địa chỉ đặc quyền, ngoài việc xem mã nguồn. , Bằng mọi cách, không thể phát hiện ra rằng địa chỉ đặc quyền đã sở hữu mã thông báo không giới hạn (sử dụng BalanceOf để truy vấn số dư của địa chỉ đặc quyền sẽ hiển thị 0, nhưng mã thông báo không giới hạn có thể được chuyển).
Trường hợp RugPull của mã thông báo ZhongHua phản ánh các vấn đề bảo mật tiềm ẩn của tiêu chuẩn mã thông báo ERC20 chỉ có thể được sử dụng để hạn chế bảo mật A. quân tử không thể đề phòng kẻ ác. Những kẻ tấn công thường ẩn các cửa hậu khó phát hiện trên cơ sở triển khai logic nghiệp vụ tiêu chuẩn. Bằng cách tiêu chuẩn hóa hành vi của mã thông báo, mặc dù tính linh hoạt của các chức năng bị giảm nhưng khả năng xảy ra các cửa sau ẩn sẽ tránh được và cung cấp nhiều bảo mật hơn.