package tools import ( "encoding/binary" "encoding/hex" "regexp" ) func PatchBinary(input []byte) []byte { if input == nil { return nil } stringCode := hex.EncodeToString(input) stringCode = Patch(stringCode) result, _ := hex.DecodeString(stringCode) return result } func patchPattern1(input string) string { // Case 1 // PUSH1 v1 DUP1 PUSH1 v2 PUSH1 v3 CODECOPY // we have to set v1 = v1 + 1 r, _ := regexp.Compile("60..8060..60..39") loc := r.FindStringIndex(input) if len(loc) > 0 { valLoc := loc[0]/2 + 1 bString, _ := hex.DecodeString(input) bString[valLoc]++ input = hex.EncodeToString(bString) } return input } func patchPattern2(input string) string { // Case 2 // PUSH2 v1 v2 DUP1 PUSH2 v3 PUSH1 v4 CODECOPY // we have to set BigEndian(v1,v2)++ r, _ := regexp.Compile("61....8061....60..39") loc := r.FindStringIndex(input) if len(loc) > 0 { valLoc := loc[0]/2 + 1 bString, _ := hex.DecodeString(input) val := binary.BigEndian.Uint16(bString[valLoc : valLoc+2]) val++ binary.BigEndian.PutUint16(bString[valLoc:], val) input = hex.EncodeToString(bString) } return input } func patchPattern3(input string) string { // Case 3 // PUSH1 v1 DUP1 PUSH3 v2 v3 v4 DUP4 CODECOPY // we have to set BigEndian(v2,v3,v4)++ r, _ := regexp.Compile("60..8062......8339") loc := r.FindStringIndex(input) if len(loc) > 0 { valLoc := loc[0]/2 + 4 bString, _ := hex.DecodeString(input) toConvert := append([]byte{0}, bString[valLoc:valLoc+3]...) tmpBinary := make([]byte, 4) val := binary.BigEndian.Uint32(toConvert) val-- binary.BigEndian.PutUint32(tmpBinary, val) bString[valLoc] = tmpBinary[1] bString[valLoc+1] = tmpBinary[2] bString[valLoc+2] = tmpBinary[3] input = hex.EncodeToString(bString) } return input } func patchPattern4(input string) string { // Case 4 // PUSH2 v1 v2 DUP1 PUSH2 v3 DUP4 CODECOPY // we have to set BigEndian(v1,v2)+2 r, _ := regexp.Compile("61....8061....8339") loc := r.FindStringIndex(input) if len(loc) > 0 { valLoc := loc[0]/2 + 1 bString, _ := hex.DecodeString(input) val := binary.BigEndian.Uint16(bString[valLoc : valLoc+2]) val = val + 2 binary.BigEndian.PutUint16(bString[valLoc:], val) input = hex.EncodeToString(bString) } return input } func patchPattern5(input string) string { // Case 5 // PUSH1 v1 DUP1 PUSH2 v2 v3 DUP4 CODECOPY // we have to set BigEndian(v2,v3)++ r, _ := regexp.Compile("60..8061....8339") loc := r.FindStringIndex(input) if len(loc) > 0 { valLoc := loc[0]/2 + 4 bString, _ := hex.DecodeString(input) val := binary.BigEndian.Uint16(bString[valLoc : valLoc+2]) val = val + 1 binary.BigEndian.PutUint16(bString[valLoc:], val) input = hex.EncodeToString(bString) } return input } func patchPattern6(input string) string { // Case 6 // SUB DUP1 PUSH2 v2 v3 DUP4 CODECOPY // we have to set BigEndian(v2,v3)++ r, _ := regexp.Compile("038061....8339") loc := r.FindStringIndex(input) if len(loc) > 0 { valLoc := loc[0]/2 + 3 bString, _ := hex.DecodeString(input) val := binary.BigEndian.Uint16(bString[valLoc : valLoc+2]) val = val + 1 binary.BigEndian.PutUint16(bString[valLoc:], val) input = hex.EncodeToString(bString) } return input } func addPrefix(input string) string { r, _ := regexp.Compile("6060604052") loc := r.FindAllStringIndex(input, -1) if len(loc) > 0 { for i, offset := range loc { insertLoc := offset[0] + i*2 if !isDelegateCall(input, insertLoc) { input = input[:insertLoc] + "00" + input[insertLoc:] } } if input[0:2] != "00" { input = "00" + input } } return input } func isDelegateCall(input string, codeStartAt int) bool { delegateCallPrefix := "6504032353da7150" prefixLen := len(delegateCallPrefix) newStartAt := codeStartAt - prefixLen if newStartAt >= 0 { if input[newStartAt:newStartAt+prefixLen] == delegateCallPrefix { return true } } return false } // Patch patch lagacy bytecode(hex string) to new vm interface compatible bytecode func Patch(input string) string { if len(input) == 0 { return input } input = patchPattern1(input) input = patchPattern2(input) input = patchPattern3(input) input = patchPattern4(input) input = patchPattern5(input) input = patchPattern6(input) result := addPrefix(input) return result }