ContractFuzzer
2022-12-16 17:23:00 6 举报
AI智能生成
ContractFuzzer分析
作者其他创作
大纲/内容
base
Dockerfile
example
示例合约<br>
tools
python封装工具
download_verified_contract_from_etherscan.py
从以太坊浏览器下载合约的abi和bin
excelUtil.py
Excel文件的读写
get_function_signature_from_abi.py
从abi文件中提取对应的函数签名
0x06fdde03:name()
0x07546172:minter()<br>
0x0758a980:specialBonus(address)<br>
get_function_signature_pair_from_bin.py
从bin文件中提取对应的函数签名对(合约函数签名:函数内部调用签名)
0xdd9e7b1b: 0x70a08231 0xa9059cbb
0xfcfdbc23: 0x70a08231 0xa9059cbb
0xea083b86: 0x70a08231 0xa9059cbb
Ethereum
私有链配置文件
启动命令<br>
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 <br>
私有链的配置信息
keystore
五个测试账户数据
transactions.rlp
交易日志
pwd.txt
解锁账户密码: 123456<br>
networkid
链id:1900
go-ethereum-cf
hook EVM执行操作码流程,生成新的geth
hacker_contractcall.go
结构体
HackerContractCall
封装函数体
caller
调用合约地址
callee
被调用合约函数
value<br>
函数传入以太坊<br>
gas
函数调用gas费
finalgas
最终消耗gas费<br>
input
传入参数
nextcalls<br>
后续调用函数
OperationStack
函数操作码栈<br>
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()函数中调用<br>
EVM接收前端参数并进行合约函数调用时执行
初始化函数列表、函数哈希列表、函数调用栈<br>
将此次EVM的直接调用压入函数调用栈第一个位置<br>
hacker_close()
在 evm.Call()函数最后调用<br>
本次EVM执行流程结束执行
函数调用栈清空
创建所有测试机
InitOracle(hacker_call_hashs, hacker_calls)<br>
初始化函数列表与函数哈希列表
TestOracle()
测试漏洞
将测试结果发送给fuzzServer: http://localhost:8888/hack
values := url.Values{"oracles": {string(features_str)}, "profile": {GetReportor().Profile(hacker_call_hashs, hacker_calls)}}<br>url := "http://localhost:8888/hack?" + values.Encode()
oracles
漏洞种类
profile
具体细节
hacker_instruction.go
Hacker_record()<br>
hook EVM操作码<br>
传入 call.onOpCode()函数<br>
压入函数操作码栈
调用 intructions.OpCode()函数<br>
EVM原生函数<br>
hacker_operation.go
HackerOperationStack
操作码栈<br>
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
抛出异常但跟函数未抛出异常的函数<br>
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
生成报告<br>
HackerCallInfoReportor
Profile()
漏洞细节<br>
根调用签名
对总函数列表、函数列表哈希、后续调用进行合并哈希
操作码长度
操作栈
hacker_state.go
封装地址状态结构体与方法<br>
Hacker_ContractState
addr
storage
balance<br>
HackerState
contracts []*Hacker_ContractState<br>
HackerStateStack
data []*HackerState
hacker_utils.go
封装一些常用函数
ShowDiffState()
判断两个地址状态是否一致
showDiffStorage
判断storage是否一致
ShowDiffBalance
判断余额是否一致
Hash()
对一次函数调用进行哈希
Hash(caller)+Hash(callee)+Hash(input)
hacker_hub.go
isRelOracle()
判断合约是否为启动时注册的release oracle服务<br>
contract_fuzzer
根据abi fuzz测试合约输入序列
contractfuzzer
main()
fuzz.Start(*abi_dir,*out_dir)
对 abi_dir 下的合约进行fuzz<br>
server.Start(*addr_map,*reporter)
启动监听服务
fuzz
fuzz测试合约的输入序列<br>
abi.fuzz()
g_func_Robin.Random_select(funcs)
随机选取函数
f.Inputs.fuzz()
随机生成输入参数
fuzz(type)
Cfundemental: 基本类型<br>
不同case分为byte、uint、address、string等进行fuz
CfixedArray: 固定数组<br>
遍历每个元素<br>
进入基本类型逻辑
CdynamicArray: 动态数组<br>
生成随机长度固定数组<br>
进入固定数组逻辑
将输入序列发送给fuzzMonitor: http://127.0.0.1:8088/runnerMonitor
sendMsg2RunnerMonitor(current_contract_address,msgs)
current_contract_address
调用合约地址
msgs
输入序列<br>
server
监听fuzz测试结果<br>
监听端口: 8888<br>
监听路径: /hack<br>
保存测试文件<br>
config
fuzz的种子文件
abi
封装abi函数
contract_tester
中转fuzz客户端与私链通信,添加代理
启动命令
bnode ./utils/runFuzzMonitor --ip http://127.0.0.1:8545 --account 0 --value 0
启动fuzzMonitor
RunnerMonitor()
监听端口: 8088<br>
接收参数
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
部署测试合约
使用命令<br>
bnode ./utilsScripts/deployContract.js --contractdir $CONTRACTS -bindir $BINS --abidir $ABIS
根据合约的abi与bin部署到测试链上
收藏
0 条评论
下一页
为你推荐
查看更多