ContractFuzzer
2022-12-16 17:23:00 6 举报
AI智能生成
ContractFuzzer分析
作者其他创作
大纲/内容
base
Dockerfile
example
示例合约
tools
python封装工具
download_verified_contract_from_etherscan.py
从以太坊浏览器下载合约的abi和bin
excelUtil.py
Excel文件的读写
get_function_signature_from_abi.py
从abi文件中提取对应的函数签名
0x06fdde03:name()
0x07546172:minter()
0x0758a980:specialBonus(address)
get_function_signature_pair_from_bin.py
从bin文件中提取对应的函数签名对(合约函数签名:函数内部调用签名)
0xdd9e7b1b: 0x70a08231 0xa9059cbb
0xfcfdbc23: 0x70a08231 0xa9059cbb
0xea083b86: 0x70a08231 0xa9059cbb
Ethereum
私有链配置文件
启动命令
geth --fast --identity "TestNode2" --rpc -rpcaddr "0.0.0.0" --rpcport "8545" --rpccorsdomain "*" --port "30303" --nodiscover --rpcapi "db,eth,net,web3,miner,net,personal,net,txpool,admin" --networkid 1900 --datadir /ContractFuzzer/Ethereum --nat "any" --targetgaslimit "9000000000000" --unlock 0 --password "/ContractFuzzer/Ethereum/pwd.txt" --mine
私有链的配置信息
keystore
五个测试账户数据
transactions.rlp
交易日志
pwd.txt
解锁账户密码: 123456
networkid
链id:1900
go-ethereum-cf
hook EVM执行操作码流程,生成新的geth
hacker_contractcall.go
结构体
HackerContractCall
封装函数体
caller
调用合约地址
callee
被调用合约函数
value
函数传入以太坊
gas
函数调用gas费
finalgas
最终消耗gas费
input
传入参数
nextcalls
后续调用函数
OperationStack
函数操作码栈
StateStack
状态栈
throwException
是否抛出异常
errOutGas
是否gas费不足
errOutBalance
是否余额不足
newHackerContractCall()
初始化操作码栈,第一项为传入的operartion
初始化状态栈为空
初始化nextcalls为空
初始化input参数
操作码函数
OnOpcode()
call.OperationStack.push(opCodeToString[OPCODE])
call.StateStack.push(newHackerState(call.caller, call.callee))
OnCall()
OnDelegateCall()
OnCallCode()
OnCloseCall()
call.finalgas = finalgas
确定最终gas费
生命周期函数
hacker_init()
在 evm.Call()函数中调用
EVM接收前端参数并进行合约函数调用时执行
初始化函数列表、函数哈希列表、函数调用栈
将此次EVM的直接调用压入函数调用栈第一个位置
hacker_close()
在 evm.Call()函数最后调用
本次EVM执行流程结束执行
函数调用栈清空
创建所有测试机
InitOracle(hacker_call_hashs, hacker_calls)
初始化函数列表与函数哈希列表
TestOracle()
测试漏洞
将测试结果发送给fuzzServer: http://localhost:8888/hack
values := url.Values{"oracles": {string(features_str)}, "profile": {GetReportor().Profile(hacker_call_hashs, hacker_calls)}}
url := "http://localhost:8888/hack?" + values.Encode()
url := "http://localhost:8888/hack?" + values.Encode()
oracles
漏洞种类
profile
具体细节
hacker_instruction.go
Hacker_record()
hook EVM操作码
传入 call.onOpCode()函数
压入函数操作码栈
调用 intructions.OpCode()函数
EVM原生函数
hacker_operation.go
HackerOperationStack
操作码栈
hacker_oracle.go
漏洞测试机
接口
Oracle
InitOracle()
TestOracle()
判断是否存在漏洞
Write()
String()
实现
HackerRootCallFailed
hacker_call_hashs
函数哈希列表
hacker_calls
函数列表
HackerReentrancy
hacker_call_hashs
hacker_calls
repeatedPairs
重复函数对
feauture
描述
HackerRepeatedCall
hacker_call_hashs
hacker_calls
repeatedPairs
HackerEtherTransfer
hacker_call_hashs
hacker_calls
hacker_exception_calls
发送以太的函数
HackerEtherTransferFailed
hacker_call_hashs
hacker_calls
hacker_exception_calls
HackerCallEtherTransferFailed
hacker_call_hashs
hacker_calls
hacker_exception_calls
HackerGaslessSend
hacker_call_hashs
hacker_calls
hacker_exception_calls
HackerDelegateCallInfo
hacker_call_hashs
hacker_calls
hacker_delegate_calls
调用了delegatecall的函数
feauture
HackerExceptionDisorder
hacker_call_hashs
hacker_calls
hacker_exception_calls
抛出异常但跟函数未抛出异常的函数
HackerSendOpInfo
hacker_call_hashs
hacker_calls
hacker_exception_calls
通过send调用的函数
HackerCallExecption
hacker_call_hashs
hacker_calls
hacker_exception_calls
通过call调用的函数抛出异常
HackerUnknownCall
hacker_call_hashs
hacker_calls
hacker_exception_calls
通过消息调用者或input传入的函数
HackerStorageChanged
hacker_call_hashs
hacker_calls
hacker_exception_calls
修改账户状态的函数
HackerTimestampOp
hacker_call_hashs
hacker_calls
hacker_exception_calls
调用了TIMESTAMP的函数
HackerNumberOp
hacker_call_hashs
hacker_calls
hacker_exception_calls
调用了NUMBER的函数
HackerBlockHashOp
hacker_call_hashs
hacker_calls
hacker_exception_calls
调用了BLOCKHASH的函数
HackerBalanceGtZero
hacker_call_hashs
hacker_calls
生成报告
HackerCallInfoReportor
Profile()
漏洞细节
根调用签名
对总函数列表、函数列表哈希、后续调用进行合并哈希
操作码长度
操作栈
hacker_state.go
封装地址状态结构体与方法
Hacker_ContractState
addr
storage
balance
HackerState
contracts []*Hacker_ContractState
HackerStateStack
data []*HackerState
hacker_utils.go
封装一些常用函数
ShowDiffState()
判断两个地址状态是否一致
showDiffStorage
判断storage是否一致
ShowDiffBalance
判断余额是否一致
Hash()
对一次函数调用进行哈希
Hash(caller)+Hash(callee)+Hash(input)
hacker_hub.go
isRelOracle()
判断合约是否为启动时注册的release oracle服务
contract_fuzzer
根据abi fuzz测试合约输入序列
contractfuzzer
main()
fuzz.Start(*abi_dir,*out_dir)
对 abi_dir 下的合约进行fuzz
server.Start(*addr_map,*reporter)
启动监听服务
fuzz
fuzz测试合约的输入序列
abi.fuzz()
g_func_Robin.Random_select(funcs)
随机选取函数
f.Inputs.fuzz()
随机生成输入参数
fuzz(type)
Cfundemental: 基本类型
不同case分为byte、uint、address、string等进行fuz
CfixedArray: 固定数组
遍历每个元素
进入基本类型逻辑
CdynamicArray: 动态数组
生成随机长度固定数组
进入固定数组逻辑
将输入序列发送给fuzzMonitor: http://127.0.0.1:8088/runnerMonitor
sendMsg2RunnerMonitor(current_contract_address,msgs)
current_contract_address
调用合约地址
msgs
输入序列
server
监听fuzz测试结果
监听端口: 8888
监听路径: /hack
保存测试文件
config
fuzz的种子文件
abi
封装abi函数
contract_tester
中转fuzz客户端与私链通信,添加代理
启动命令
bnode ./utils/runFuzzMonitor --ip http://127.0.0.1:8545 --account 0 --value 0
启动fuzzMonitor
RunnerMonitor()
监听端口: 8088
接收参数
address
调用合约地址
msg
输入序列
getAgent()
部署代理合约
Agen.sol
AgentCallWithValue(address contract_addr,bytes msg_data)
传入调用测试合约的地址与input输入,保存为合约变量
供后续调用
function()
根据已定义的合约地址与输入参数重新调用函数
fallback函数,供重入测试
go(address,msg_group)
MyCallWithValueBatch(argsAgent)
调用代理合约的AgentCallWithValue函数
将测试合约地址与传入参数保存进合约
sendBatchTransaction(args)
发送测试交易
调用测试合约地址与传入参数
进入EVM流程
contract_deployer
部署测试合约
使用命令
bnode ./utilsScripts/deployContract.js --contractdir $CONTRACTS -bindir $BINS --abidir $ABIS
根据合约的abi与bin部署到测试链上
收藏
0 条评论
下一页
为你推荐
查看更多
抱歉,暂无相关内容