BTC
ETH
HTX
SOL
BNB
시장 동향 보기
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt

심층 EVM - 계약 분류의 사소한 문제 뒤에 숨겨진 위험

十四君
特邀专栏作者
이 기사는 약 3491자로, 전체를 읽는 데 약 5분이 소요됩니다
계약을 분류해야 하는 이유부터 시작하여 각 시나리오가 직면할 수 있는 악의적인 공격의 종류와 결합하여 비교적 안전한 계약 분류 분석 알고리즘 세트가 최종적으로 제공됩니다.
AI 요약
계약을 분류해야 하는 이유부터 시작하여 각 시나리오가 직면할 수 있는 악의적인 공격의 종류와 결합하여 비교적 안전한 계약 분류 분석 알고리즘 세트가 최종적으로 제공됩니다.

스마트 계약 분야에서는"이더리움 가상 머신 EVM"그리고 알고리즘과 데이터 구조가 첫 번째 원칙입니다.

이 기사는 계약을 분류해야 하는 이유에서 시작하여 각 시나리오가 직면할 수 있는 악의적인 공격의 종류를 결합하고 마지막으로 비교적 안전한 계약 분류 분석 알고리즘 세트를 제공합니다.

기술적인 내용은 높지만 잡담의 독서자료로도 활용이 가능하다.첫 번째 레벨 제목

1. 계약을 분류해야 하는 이유는 무엇입니까?

그만큼 중요하기 때문에 거래소, 지갑, 블록체인 브라우저, 데이터 분석 플랫폼 등 Dapps의 초석이라고 할 수 있습니다!

거래가 ERC 20 전송인 이유는 그의 행동이 적어도 다음과 같은 ERC 20 표준을 준수하기 때문입니다.

  1. 거래 상태는 SUCCESS입니다.

  2. 받는 사람 주소는 ERC 20 표준을 준수하는 계약입니다.

  3. 트랜잭션 CallData의 처음 4자리가 0x a 9059 cbb라는 사실을 특징으로 하는 전송 기능이라고 합니다.

  4. 실행 후 To 주소로 전송 이벤트가 전송됩니다.

분류가 잘못되면 거래 행동이 잘못 판단됩니다.

트랜잭션 행위를 초석으로 To 주소를 정확하게 분류할 수 있는지 여부는 CallData의 판단에서 완전히 다른 결론으로 ​​이어집니다. Dapp의 경우 체인 안팎의 정보 통신은 트랜잭션 이벤트 모니터링에 크게 의존하며 동일한 이벤트 코드는 표준을 충족하는 계약으로 전송된 경우에만 신뢰할 수 있습니다.

분류가 잘못되면 실수로 트랜잭션이 블랙홀로 이동합니다.

사용자가 특정 컨트랙트로 토큰을 전송하는 경우 컨트랙트에 토큰 전송을 위한 사전 설정된 기능 방법이 없으면 소각과 마찬가지로 자금이 잠기며 통제할 수 없습니다.

그리고 많은 프로젝트들이 내장형 지갑 지원을 추가하기 시작한 지금, 사용자들을 위한 지갑 관리는 불가피합니다. 자산 기준.

추가 읽기 단락 1:[계약해석] CryptoPunk는 세계 최초의 탈중앙화 NFT 거래 시장입니다.

2. 분류의 위험은 무엇입니까?

체인은 아이덴티티도 없고 법치도 없는 곳으로 악의적일지라도 정상적인 거래를 막을 수는 없습니다.

그는 할머니인 척하는 늑대가 될 수 있으며, 할머니가 할 것으로 기대하는 대부분의 행동을 하지만 집에 침입하여 도둑질할 목적을 가지고 있습니다.

표준을 선언하지만 실질적으로 충족하지 못할 수 있음

일반적인 분류 방법은 EIP-165 표준을 직접 채택하고 주소가 ERC 20을 지원하는지 여부 등을 읽는 것입니다. 물론 이것은 효율적인 방법이지만 결국 계약은 상대방에 의해 제어되므로 진술 결국 위조 할 수 있습니다.

165 표준 쿼리는 체인의 제한된 작업 코드에서 가장 낮은 비용으로 자금이 블랙홀로 이동하는 것을 방지하는 방법일 뿐입니다.

이것이 이전에 NFT를 분석할 때 표준에 SafeTransferFrom 메서드가 있을 것이라고 구체적으로 언급한 이유입니다. 여기서 Safe는 상대방이 NFT를 전송할 수 있는 능력이 있는지 확인하기 위해 165 표준을 사용하는 것을 말합니다.

추가 읽기 단락 2.2:[소스코드 해석] 당신이 구매한 NFT는 정확히 무엇인가요?

계약 바이트 코드에서 시작하여 소스 코드 수준에서 정적 분석을 수행하고 계약의 예상 동작에서 시작해야만 더 정확할 수 있습니다.

3. 계약 분류 체계 설계

다음으로 전반적인 계획을 체계적으로 분석하고 우리의목표는 "정확성"과 "효율성"의 두 가지 핵심 지표입니다.

방향이 맞더라도 바다 건너편에 도달하는 방법은 명확하지 않다는 것을 알아야 합니다.바이트코드 분석을 수행하는 첫 번째 중지는 코드를 얻는 것입니다.

3.1 코드는 어떻게 얻나요?

체인의 관점에서 볼 때 RPC 방식인 getCode가 있는데 체인에 지정된 주소에서 바이트코드를 얻을 수 있고 codeHash가 EVM의 계정 구조에 있기 때문에 읽는 속도가 매우 빠릅니다. . 맨 위에.

그러나이 방법은 특정 주소를 얻는 것과 같습니다.정확성과 효율성을 더 높이고 싶습니까?

계약 배포 트랜잭션인 경우 배포된 코드가 실행된 직후 또는 아직 메모리 풀에 있는 경우에도 배포된 코드를 가져오는 방법은 무엇입니까?

트랜잭션이 계약 팩토리 모드인 경우 트랜잭션의 Calldata에 소스 코드가 있습니까?

결국 내 방식은 체와 같은 모드로 분류하는 것입니다.

  1. 비계약 배포 트랜잭션의 경우 getCode를 직접 사용하여 분류를 위한 관련 주소를 얻습니다.

  2. 최신 mempool 트랜잭션의 경우 대상 주소가 비어 있고 CallData가 생성자가 있는 소스 코드인 트랜잭션을 필터링합니다.

  3. 컨트랙트 팩토리 모드 트랜잭션의 경우 컨트랙트에 의해 배포된 컨트랙트를 재활용하여 다른 컨트랙트를 호출하여 배포를 실행할 수 있으므로 트랜잭션의 하위 트랜잭션을 재귀적으로 분석하고 유형이 CREATE 또는 CREATE 2인 각 호출을 기록합니다. .

데모 구현을 했을 때 다행스럽게도 현재 rpc 버전이 상대적으로 높다는 것을 알았습니다. 왜냐하면 전체 프로세스 중 가장 어려운 부분이 3을 실행할 때 지정된 유형의 호출을 재귀적으로 찾는 방법이기 때문입니다. 최하위 방법은 opcode를 통해 컨텍스트를 복원합니다.

다행스럽게도 현재 geth 버전에는 debug_traceTransaction 메서드가 있어 opcode 작업 코드를 통해 각 호출의 컨텍스트 정보를 정렬하고 핵심 필드를 정렬하는 데 도움이 될 수 있습니다.

결국 다양한 배포 모드(직접 배포, 공장 모드의 단일 배포, 공장 모드의 일괄 배포)의 원본 바이트 코드를 얻을 수 있습니다.

3.2 코드에서 분류하는 방법은 무엇입니까?

가장 쉽지만 안전하지 않은 방법은 코드를 문자열과 직접 일치시키는 것입니다. ERC 20을 예로 들면 표준 호환 기능은 다음과 같습니다.

함수 이름 다음에는 함수의 함수 서명입니다.이전 분석에서 언급했듯이 트랜잭션은 대상 함수를 찾기 위해 callData의 처음 4자리 일치에 따라 달라집니다.추가 읽기:

따라서 이 6가지 기능의 서명을 계약 바이트코드에 저장해야 합니다.

보조 제목

3.3 정확도 향상 1- 디컴파일

더 정확한 방법은 Opcode를 디컴파일하는 것입니다! 디컴파일은 얻은 바이트코드를 opcode로 변환하는 과정이고, 고급 디컴파일은 의사코드로 변환하여 사람이 읽기에 더 도움이 됩니다. 기사의 끝.

solidity(고급 언어) -> bytecode(bytecode) -> opcode(연산 코드)

우리는 기능을 명확하게 찾을 수 있으며 기능 서명은 opcode PUSH 4에 의해 실행되므로 추가 방법은 전체 텍스트에서 PUSH 4 이후의 내용을 추출하고 기능 표준과 일치시키는 것입니다.

간단한 성능 실험도 해봤는데 Go 언어가 매우 효율적이고 1W 번 디컴파일하는 데 220ms 밖에 걸리지 않는다고 말해야 합니다.

다음은 어려울 것입니다.

3.4 정확도 향상 2-코드 블록 찾기

위의 정확도는 향상되었지만 PUSH 4 명령을 트리거하는 바이트 4 유형의 변수를 여전히 생성할 수 있기 때문에 전체 텍스트 검색 PUSH 4이기 때문에 충분하지 않습니다.

고민하다가 오픈소스 프로젝트 구현을 생각했는데 ETL은 분석을 위해 체인에서 데이터를 읽어오는 도구입니다. 계약을 분류합니다.

분석 후 코드 블록의 분류를 기반으로 하며 첫 번째 basic_blocks[ 0 ]에서 푸시 4 명령어만 처리함을 알 수 있습니다.

그러면 문제는 코드 블록을 정확하게 판단하는 방법입니다.

code block의 개념은 REVERT + JUMPDEST의 연속된 opcode 2개에서 나오며, 전체 function selector의 opcode 간격에서 함수가 너무 많으면 페이지를 넘기는 로직이 나타나기 때문에 여기에서 두 개의 연속적인 opcode가 필요하다. 그러면 JUMPDEST 명령도 나타납니다.

3.5 정확도 향상 3-기능 선택기 찾기

기능 선택기의 기능은 트랜잭션의 Calldata의 처음 4바이트를 읽고 코드에 미리 설정된 계약 기능 서명과 일치시키고 명령이 기능 방법에 의해 지정된 메모리 위치로 점프하도록 돕는 것입니다.

최소한의 모의 실행을 시도해 봅시다

이 부분은 두 함수의 selector store(uint 256)와 retrieve()이며 서명은 2 e 64 cec 1, 6057361 d로 계산할 수 있습니다.

디컴파일 후 두 부분으로 나눌 수 있는 다음 opcode 문자열을 얻게 됩니다.

첫 번째 부분:

컴파일러에서 계약의 함수 선택기 부분만 callData의 내용을 가져옵니다. 즉, 아래 그림과 같이 해당 CallData의 함수 호출 서명을 가져옵니다.

EVM의 메모리 풀 변경을 시뮬레이션하여 효과를 볼 수 있습니다.

두 번째 부분:

선택자의 값과 일치하는지 판단하는 과정

1. retrieve()의 4바이트 함수 서명(0x 2 e 64 cec 1)을 스택에 전달합니다.

2. EQ opcode는 스택 영역에서 2개의 변수, 즉 0x 2 e 64 cec 1 및 0x 6057361 d를 팝하고 이들이 동일한지 확인합니다.

3. PUSH 2는 2바이트의 데이터(여기서는 0x 003 b, 십진수는 59)를 스택으로 전송하고 스택 영역에는 바이트코드에서 다음 실행 명령의 위치를 ​​지정하는 프로그램 카운터가 있습니다. 여기서는 retrieve() 바이트코드가 시작되는 59를 설정합니다.

4. 점프피 대표"만약..., 다음으로 이동..."스택에서 2개의 값을 입력으로 팝하고 조건이 참이면 프로그램 카운터가 59로 업데이트됩니다.

이것이 EVM이 계약의 함수 호출을 기반으로 실행해야 하는 함수 바이트코드의 위치를 ​​결정하는 방법입니다.

실제로는 계약의 모든 기능과 점프 위치에 대한 "if 문"의 단순한 집합일 뿐입니다.

4. 계획 요약

전체적인 개요는 다음과 같다

  1. 각 계약 주소는 GO의 VM 및 ASM 라이브러리를 사용하여 rpc getcode 또는 debug_traceTransaction을 통해 배포된 바이트코드를 얻을 수 있으며 디컴파일 후 opcode를 얻을 수 있습니다.

  2. EVM 운용 원칙상 계약은 다음과 같은 특징을 갖게 됩니다.

    • 두 개의 연속 opcode REVERT+JUMPDEST를 코드 블록 구분으로 사용

    • 계약에는 기능 선택기의 기능이 있어야 하며 이 기능도 첫 번째 코드 블록에 있어야 합니다.

    • 기능 선택기에서 해당 기능 메서드는 모두 PUSH 4를 opcode로 사용합니다.

    • 이 셀렉터에 포함된 opcode에는 연속적인 PUSH 1 00, CALLDATALOAD, PUSH 1 e 0, SHR, DUP 1이 있으며 핵심 기능은 callDate 데이터를 로드하고 변위 작업을 수행하는 것이며 다른 구문은 생성되지 않습니다.

3. 해당 기능 서명은 eip에 정의되어 있으며 필수 및 선택적 지우기 명령이 있습니다.

4.1 고유성 증명

이 시점에서 우리는 기본적으로 고효율 및 고정확도의 계약 분석 방법을 달성했다고 말할 수 있습니다. REVER+JUMPDEST를 사용하여 코드 블록을 구별하고 불가피한 CallDate 로딩과 변위를 결합하여 고유한 판단을 내립니다.솔리디티 계약을 사용하여 유사한 opcode 시퀀스를 구현할 수 있습니까?

비교 실험을 해보았는데요, msg.sig와 같은 CallData를 solidity 문법 레벨에서 얻는 방법이 있긴 하지만, 컴파일 후 opcode의 구현 방법이 다릅니다.

5. 요약

그렇게 유창한 분석 끝에 3일이 흘렀다.

매우 꼼꼼하긴 하지만, byte 4를 사용하여 일상 생활에서 기준을 충족하는지 악의적으로 혼동하는 컨트랙트의 경우 양동이에 떨어질 수 있습니다.

따라서 실제로 이 3일 동안 분석에 투자한 ROI는 매우 낮습니다. 하지만 끝없이 흐르는 시간의 강에서는 아주 작은 확률이라도 언젠가는 일어나게 마련이다.

불신의 원칙이 있어야만 우리는 web3 세계에서 더 멀리 갈 수 있습니다.

오늘 친구가 나에게 매우 사려 깊은 주제를 물었습니다.업계 KOL이 되는 최종 목표는 무엇입니까? 당신의 비즈니스 모델은 무엇입니까?

기술 문서의 트래픽이 항상 암울하다는 것을 알고 있지만 트래픽이 목적은 아닙니다.항상 원래 비전에 있기를 바랍니다.

텍스트

텍스트

opcode 샘플 및 Go 디컴파일 샘플 코드가 필요하신 경우 공식 계정 백그라운드에서 "계약 분류"에 회신하시면 받으실 수 있습니다.

종속 라이브러리:

https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.11.6/core/asm#Compiler.Feed

https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.11.6/core/vm

원리 분석:

https://whileydave.com/2023/01/04/disassembling-evm-bytecode-the-basics/

https://yanniss.github.io/elipmoc-oopsla 22.pdf

https://yanniss.github.io/gigahorse-icse 19.pdf

https://www.evm.codes/? fork=shanghai

https://learnblockchain.cn/article/4800 

https://learnblockchain.cn/article/3647 

오픈 소스 프로젝트 소스 코드 참조:

https://github.com/blockchain-etl/ethereum-etl/blob/2d a 9 d 050 f 4 ae 4 fa 4 e 818 bbfb 22 d5 cfb 5234 b 2 e 29/ethereumetl/service/eth_contract_service.py#L2 9-L 43 

https://github.com/ethereum/evmdasmhttps://github.com/tintinweb/ethereum-dasm/blob/master/ethereum_dasm/evmdasm.py#L3 42 

    14 좋아요 및 팔로우, 기술적 관점에서 가치 제공

    Web3.0
    NFT
    기술
    스마트 계약
    Odaily 공식 커뮤니티에 가입하세요