BTC
ETH
HTX
SOL
BNB
View Market
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt

Teach you to chat with ETH

This article is about 4218 words, reading the full article takes about 7 minutes
What exactly is the input Data that we often see in blockchain browsers?
AI Summary
Expand
What exactly is the input Data that we often see in blockchain browsers?

foreword

secondary title

forewordSome time ago, there was an episode of the theft of Poly Network. An address transferred money to the hacker’s address and informed the USDT in the input data that it had been frozen. Do not use USDT. After the hacker knew about it, he transferred 13.37 ETH to the address.Know Chuangyu Blockchain Security Lab

Input data

Answer for you.

secondary title

In the Ethereum protocol, when the transaction (transaction) is a contract creation, the input data is the EVM code of the account initialization program;

And when the transaction is a message call, the input data is the contract function call data.

Under normal circumstances, a simple message call, such as calling a transfer function, needs to fill in the address _to you want to transfer and the amount _amount you want to transfer. These basic information are included in the input data.

Let's understand the structure of input data when a message is called through a specific analysis of a transfer transaction that calls a contract.

Analytical form:

  • Original form:

  • We divide the original input data into three parts for analysis:

  • 0xa9059cbb: function identifier

00000000000000000000000345d8e3a1f62ee6b1d483890976fd66168e390f2: The first parameter is address, which is the address you want to transfer, and it will be filled to 32 bytes, that is, 64 hexadecimal characters

00000000000000000000000000000000000000000054b7d8ed70650b290000: The second parameter is value, which is the amount you want to transfer, and it will be filled to 32 bytes, that is, 64 hexadecimal characters

Through comparative analysis, we can find that the basic structure of input data is function identifier + parameter.

function identifier"transfer(adddress,uint256)"The function identifier here is the function selector. According to the official document, the function selector is the first 4 bytes of the Keccak (SHA-3) hash of a function signature (big endian with the high bit on the left).

We can pass the code bytess4(keccake256(

)) or online tools to get this function signature.

The figure below shows that the first four bytes of the encryption result (a9059cbb) are consistent with the function identifier in the input data.

The reason why the function signature is truncated to four bytes is to consider the Gas cost.

The 32-byte random string generated in SHA-3 encryption tends to have more non-zero bytes, so the approximate cost is 32x68=2176 gas, and the truncation cost is about 4x68=272 gas, which shows that it is truncated to four bytes It can save about 8 times the gas fee.

parameter

The function of the function identifier is to specify which function to call. In the same contract, the probability of the first 4 bytes of the SHA-3 signature of two different functions being the same is very small, so truncating to four bytes will not actually Affects function calls.

parameter

Summarize common static types: uint, bool, Address, bytes[0-32], dynamic array types: bytes, string, address[], bytes32[].....

static type

We use pyethereum's ABI encoding function to study how different data types are encoded.

import rlp  
from ethereum.abi import encode_abi

static type

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

[345d8e3a1f62ee6b1d483890976fd66168e390f2,1]).hex()

000000000000000000000000345d8e3a1f62ee6b1d483890976fd66168e390f2

0000000000000000000000000000000000000000000000000000000000000001

First import the encode_abi function

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

Let's take the function transfer(address,uint 256) as an example

0000000000000000000000000000000000000000000000000000000000000001

0000000000000000000000000000000000000000000000000000000000000002

0000000000000000000000000000000000000000000000000000000000000003

Fixed-length arrays smaller than 32 bytes will be automatically filled to 32 bytes:

// autofill 0

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

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

).hex()

dynamic type

Dynamic type encoding is a little more complicated, and the offset needs to be calculated first for placeholder processing. Let's use a simple example to illustrate it.

// Offset of parameter 1: 32*3=96 Hexadecimal 0x60000000000000000000000000000000000000000000000000000000000000060

// Offset of parameter 2 = offset of parameter 1 + data part length of parameter 1 = 96+32*4=224 hexadecimal 0xE0000000000000000000000000000000000000000000000000000000000000000000000000

// Offset of parameter 3 = offset of parameter 2 + data part length of parameter 2 = 224+32*4=352 hexadecimal 0x16000000000000000000000000000000000000000000000000000000000000160

// The data of parameter 1 starts to be passed in at offset 0x60

00000000000000000000000000000000000000000000000000000000000000003//elements

0000000000000000000000000000000000000000000000000000000000000a1//The first array element

0000000000000000000000000000000000000000000000000000000000000a2//The second array element

0000000000000000000000000000000000000000000000000000000000000003

00000000000000000000000000000000000000000000000000000000000000b1

00000000000000000000000000000000000000000000000000000000000000b2

00000000000000000000000000000000000000000000000000000000000000b3

0000000000000000000000000000000000000000000000000000000000000a3//The third array element

0000000000000000000000000000000000000000000000000000000000000003

00000000000000000000000000000000000000000000000000000000000000c1

00000000000000000000000000000000000000000000000000000000000000c2

00000000000000000000000000000000000000000000000000000000000000c3

// 0xe0 position. Data for parameter 2

//0x160 position. Data for parameter 3

short address attack

After the previous analysis, when the length of the static type such as address is less than 32 bytes, EVM will fill the length to 32 bytes according to the rules. If the address of the transfer ends with 00, such as 0x641988625108585185752230bde001b3ebd0fc00, remove the two zeros after the address when transferring , EVM will still think that address_to is 32 bits, so it will take 0 from the high bit of _value to supplement, and the number of bits in amount will be two more bits, that is, it will be multiplied by 256.

The attack process is as follows:

Remove the 0 in the last byte of the malicious transfer address

000000000000000000000000641988625108585185752230bde001b3ebd0fc

Function identifier: a9059cbb

00000000000000000000000000000000000000000000000000000000000000001

Transfer address:

transfer amount:

Due to the filling rules of EVM, the parsing result is: 0xa9059cbb00000000000000000000000641988625108585185752230bde001b3ebd0fc000000000000000000000000000000000000000 0000000000000000000000000100

After decomposing, we found that the transfer amount has been increased by two digits, that is, by one byte, which is 256 times the original transfer amount.

000000000000000000000000641988625108585185752230bde001b3ebd0fc00

Transfer address:

00000000000000000000000000000000000000000000000000000000000000100

transfer amount:

secondary title

How to attach information to input data

The input data field for direct transfer transactions in Ethereum has no content by default, but we can implement the "chat function" at the beginning of the article by setting up the wallet.

We take the MetaMask wallet as an example to show how to attach some additional information to the input data field through transfer.

3. After the transfer is successful, you can see the attached information in etherscan

Summarize

secondary title

ETH
Welcome to Join Odaily Official Community