BTC
ETH
HTX
SOL
BNB
Xem thị trường
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt

Dạy bạn chat với ETH

Bài viết này có khoảng 4218 từ, đọc toàn bộ bài viết mất khoảng 7 phút
Dữ liệu đầu vào mà chúng ta thường thấy trong các trình duyệt blockchain chính xác là gì?
Tóm tắt AI
Dữ liệu đầu vào mà chúng ta thường thấy trong các trình duyệt blockchain chính xác là gì?

lời tựa

tiêu đề phụ

lời tựaCách đây ít lâu có vụ đánh cắp Poly Network, một địa chỉ chuyển tiền đến địa chỉ của hacker và thông báo USDT trong dữ liệu đầu vào đã bị đóng băng, không sử dụng USDT, sau khi hacker biết chuyện, anh ta đã chuyển 13,37 ETH đến địa chỉ.Biết Phòng thí nghiệm bảo mật chuỗi khối Chuangyu

Input data

Trả lời cho bạn.

tiêu đề phụ

Trong giao thức Ethereum, khi giao dịch (transaction) là tạo hợp đồng, dữ liệu đầu vào là mã EVM của chương trình khởi tạo tài khoản;

Và khi giao dịch là một cuộc gọi tin nhắn, dữ liệu đầu vào là dữ liệu cuộc gọi chức năng hợp đồng.

Trong các trường hợp bình thường, một cuộc gọi tin nhắn đơn giản, chẳng hạn như gọi chức năng chuyển tiền, cần điền địa chỉ _nơi bạn muốn chuyển và số tiền _số tiền bạn muốn chuyển.Những thông tin cơ bản này được bao gồm trong dữ liệu đầu vào.

Hãy cùng tìm hiểu cấu trúc của dữ liệu đầu vào khi một thông báo được gọi thông qua phân tích cụ thể về giao dịch chuyển tiền gọi là hợp đồng.

Hình thức phân tích:

  • Mẫu ban đầu:

  • Chúng tôi chia dữ liệu đầu vào ban đầu thành ba phần để phân tích:

  • 0xa9059cbb: định danh chức năng

000000000000000000000000345d8e3a1f62ee6b1d483890976fd66168e390f2: Tham số đầu tiên là địa chỉ, là địa chỉ bạn muốn chuyển và nó sẽ được điền vào 32 byte, tức là 64 ký tự thập lục phân

00000000000000000000000000000000000000000000054b7d8ed70650b290000: Tham số thứ hai là giá trị, là số tiền bạn muốn chuyển và nó sẽ được điền vào 32 byte, tức là 64 ký tự thập lục phân

Qua phân tích so sánh, chúng ta có thể thấy cấu trúc cơ bản của dữ liệu đầu vào là định danh hàm + tham số.

định danh chức năng"transfer(adddress,uint256)"Mã định danh hàm ở đây là bộ chọn hàm.Theo tài liệu chính thức, bộ chọn hàm là 4 byte đầu tiên của hàm băm Keccak (SHA-3) của chữ ký hàm (big endian với bit cao ở bên trái).

Chúng ta có thể chuyển mã bytess4(keccake256(

)) hoặc các công cụ trực tuyến để lấy chữ ký chức năng này.

Hình bên dưới cho thấy bốn byte đầu tiên của kết quả mã hóa (a9059cbb) nhất quán với mã định danh chức năng trong dữ liệu đầu vào.

Lý do tại sao chữ ký chức năng bị cắt bớt bốn byte là để xem xét chi phí Gas.

Trong một giao dịch, 0 byte cần trả 4 gas, trong khi các byte khác 0 cần 68 gas, gấp 17 lần 0 byte.

Chuỗi ngẫu nhiên 32 byte được tạo trong mã hóa SHA-3 có xu hướng có nhiều byte khác không hơn, do đó, chi phí gần đúng là 32x68=2176 gas và chi phí cắt ngắn là khoảng 4x68=272 gas, điều này cho thấy rằng nó bị cắt bớt thành bốn byte Nó có thể tiết kiệm khoảng 8 lần phí gas.

Chức năng của mã định danh chức năng là chỉ định chức năng nào sẽ gọi, trong cùng một hợp đồng, xác suất 4 byte đầu tiên của chữ ký SHA-3 của hai chức năng khác nhau giống nhau là rất nhỏ, do đó, việc cắt bớt 4 byte sẽ không thành công. thực sự Ảnh hưởng đến các cuộc gọi chức năng.

tham số

Tổng hợp các kiểu mảng tĩnh thông dụng: uint, bool, Address, bytes[0-32], các kiểu mảng động: bytes, string, address[], bytes32[].....

loại tĩnh

Chúng tôi sử dụng chức năng mã hóa ABI của pyethereum để nghiên cứu cách mã hóa các loại dữ liệu khác nhau.

import rlp  
from ethereum.abi import encode_abi

loại tĩnh

> encode_abi(["address", "uint256"],

[345d8e3a1f62ee6b1d483890976fd66168e390f2,1]).hex()

000000000000000000000000345d8e3a1f62ee6b1d483890976fd66168e390f2

0000000000000000000000000000000000000000000000000000000000000001

Đầu tiên nhập hàm encode_abi

> encode_abi(["int8[3]"],[[1, 2, 3]).hex()

Hãy lấy hàm transfer(address,uint 256) làm ví dụ

0000000000000000000000000000000000000000000000000000000000000001

0000000000000000000000000000000000000000000000000000000000000002

0000000000000000000000000000000000000000000000000000000000000003

Các mảng có độ dài cố định nhỏ hơn 32 byte sẽ tự động được điền vào 32 byte:

// tự động điền 0

> encode_abi(
    ["uint256[]", "uint256[]", "uint256[]"],

    [[0xa1, 0xa2, 0xa3], [0xb1, 0xb2, 0xb3], [0xc1, 0xc2, 0xc3]]

).hex()

kiểu động

Mã hóa kiểu động phức tạp hơn một chút và độ lệch cần được tính toán trước để xử lý trình giữ chỗ. Hãy sử dụng một ví dụ đơn giản để minh họa.

// Độ lệch của tham số 1: 32*3=96 Hệ thập lục phân 0x60000000000000000000000000000000000000000000000000000000000000060

// Độ lệch của tham số 2 = độ lệch của tham số 1 + độ dài phần dữ liệu của tham số 1 = 96+32*4=224 hệ thập lục phân 0xE000000000000000000000000000000000000000000000000000000000000000000000

// Độ lệch của tham số 3 = độ lệch của tham số 2 + độ dài phần dữ liệu của tham số 2 = 224+32*4=352 thập lục phân 0x160000000000000000000000000000000000000000000000000000000000000160

// Dữ liệu của tham số 1 bắt đầu được truyền vào tại offset 0x60

000000000000000000000000000000000000000000000000000000000000000000003//phần tử

0000000000000000000000000000000000000000000000000000000000000000a1//Phần tử mảng đầu tiên

0000000000000000000000000000000000000000000000000000000000000000a2//Phần tử mảng thứ hai

0000000000000000000000000000000000000000000000000000000000000003

00000000000000000000000000000000000000000000000000000000000000b1

00000000000000000000000000000000000000000000000000000000000000b2

00000000000000000000000000000000000000000000000000000000000000b3

0000000000000000000000000000000000000000000000000000000000000000a3//Phần tử mảng thứ ba

0000000000000000000000000000000000000000000000000000000000000003

00000000000000000000000000000000000000000000000000000000000000c1

00000000000000000000000000000000000000000000000000000000000000c2

00000000000000000000000000000000000000000000000000000000000000c3

// vị trí 0xe0. Dữ liệu cho tham số 2

// vị trí 0x160. Dữ liệu cho tham số 3

tấn công địa chỉ ngắn

Sau khi phân tích trước đó, khi độ dài của loại tĩnh như địa chỉ nhỏ hơn 32 byte, EVM sẽ điền độ dài thành 32 byte theo quy tắc. Nếu địa chỉ truyền kết thúc bằng 00, chẳng hạn như 0x641988625108585185752230bde001b3ebd0fc00, hãy xóa hai số 0 sau địa chỉ khi truyền, EVM sẽ vẫn nghĩ rằng address_to là 32 bit, do đó, nó sẽ lấy 0 từ bit cao của _value để bổ sung và số lượng bit trong số lượng sẽ nhiều hơn hai bit, nghĩa là nó sẽ được nhân với 256.

Quá trình tấn công như sau:

Xóa số 0 trong byte cuối cùng của địa chỉ truyền độc hại

000000000000000000000000641988625108585185752230bde001b3ebd0fc

Định danh chức năng: a9059cbb

00000000000000000000000000000000000000000000000000000000000000001

Địa chỉ chuyển khoản:

Số tiền chuyển khoản:

Do quy tắc điền của EVM, kết quả phân tích cú pháp là: 0xa9059cbb00000000000000000000000641988625108585185752230bde001b3ebd0fc000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000100

Sau khi phân tách, chúng tôi thấy rằng số tiền chuyển đã được tăng lên hai chữ số, tức là một byte, gấp 256 lần số tiền chuyển ban đầu.

000000000000000000000000641988625108585185752230bde001b3ebd0fc00

Địa chỉ chuyển khoản:

00000000000000000000000000000000000000000000000000000000000000100

Số tiền chuyển khoản:

tiêu đề phụ

Cách đính kèm thông tin vào dữ liệu đầu vào

Trường dữ liệu đầu vào cho các giao dịch chuyển tiền trực tiếp trong Ethereum mặc định không có nội dung, nhưng chúng ta có thể thực hiện "chức năng trò chuyện" ở đầu bài viết bằng cách thiết lập ví.

Chúng tôi lấy ví MetaMask làm ví dụ để chỉ ra cách đính kèm một số thông tin bổ sung vào trường dữ liệu đầu vào thông qua chuyển khoản.

3. Sau khi chuyển thành công, bạn có thể xem thông tin đính kèm trong etherscan

tóm tắt

tiêu đề phụ

ETH
Chào mừng tham gia cộng đồng chính thức của Odaily
Nhóm đăng ký:
https://t.me/Odaily_News
Nhóm trò chuyện:
https://t.me/Odaily_GoldenApe
Tài khoản chính thức:
https://twitter.com/OdailyChina