大神论坛

找回密码
快速注册
查看: 113 | 回复: 0

[源码] [Go] golang 一个简单的支持模糊搜索patch的代码

ind

主题

帖子

11

积分

初入江湖

UID
212
积分
11
精华
威望
22 点
违规
大神币
68 枚
注册时间
2021-09-21 08:24
发表于 2023-09-03 09:16
本帖最后由 ind 于 2023-09-03 09:16 编辑

用go的优势就是支持全平台,一套代码我们可以给mac、linux、windows的程序做patch。
代码核心函数为patch(filename string, originBytes []string, newBytes []string, patchOnce bool),4个参数分别意义为:
1.filename 为需要patch的文件路径
2.originBytes 为需要搜索的二进制字符串数组,支持??
3.newBytes 为对应替换的二进制字符串数据,支持??
4.patchOnce 为true时表示搜索替换所有结果,为false时只搜索到的第一个结果

代码比较丑,希望各位大佬们可以优化分享。

package main

import (
"encoding/hex"
"fmt"
"os"
"strings"
)

func main() {
exe := "test.exe"
exeOriginBytes := []string{"8B 7B 08 8B 73 10 8B C7 83 E8 01"}
exeNewbytes := []string{"FF 43 08 FF 43 10 B0 01 33 C0 90"}
dll := "test.dll"
dllOriginBytes := []string{"7F ?? 7C ?? 39 75 F4 77 ?? 39 45 FC 7F ?? 7C ?? 3B F1 77 ?? 80 7D 08 00 75 ?? 8B 37"}
dllNewBytes := []string{"7F 00 7C 00 39 75 F4 77 00 39 45 FC 7F 00 7C 00 3B F1 77 00 80 7D 08 00 EB ?? 8B 37"}
patch(exe, exeOriginBytes, exeNewbytes, false)
patch(dll, dllOriginBytes, dllNewBytes, false)

}

func patch(filename string, originBytes []string, newBytes []string, patchOnce bool) {
origin, err := os.ReadFile(filename)

if err != nil {
fmt.Println("patch失败,未找到指定文件: " + filename)
return
}
patchlist := make(map[int][]byte)
for i := range originBytes {
oldstr, keys := str2bytes(originBytes[i])
patchstr, patchkeys := str2bytes(newBytes[i])
patchlens := len(patchstr)
locs := fuzzsearch(origin, oldstr, keys, patchOnce)
if len(locs) > 0 {
for i, v := range locs {
fmt.Printf("找到patch点: %d\n", i+1)
tmpstr := origin[v : v+patchlens]
tmpdata := fuzzreplace(tmpstr, patchstr, patchkeys)
patchlist[v] = tmpdata
}
} else {
fmt.Printf("未找到patch点: %d\n", i+1)
return
}
}
newFile := replace(origin, patchlist)
err = os.WriteFile(filename, newFile, os.ModePerm)
if err == nil {
fmt.Println(filename + " Patch成功")
} else {
fmt.Println(filename + " Patch失败")
}
}

func fuzzsearch(src []byte, hexsub []byte, fuzzkeys []int, patchonce bool) []int {
offsets := []int{}
dwsublen := len(hexsub)
dwsrclen := len(src)

p := make([]int, 256)

for i := 0; i < 256; i++ {
p[i] = -1
}

wildaddr := 0
if len(fuzzkeys) > 0 {
wildaddr = fuzzkeys[len(fuzzkeys)-1]
}
for i := wildaddr + 1; i < dwsublen; i++ {
p[hexsub[i]] = dwsublen - i
}

for i := 0; i < 256; i++ {
if p[i] == -1 {
p[i] = dwsublen - wildaddr
}
}
j, k := 0, 0
j = dwsublen - 1
found := true
for {
found = true
for k = 0; k < dwsublen; k++ {
if !isfound(fuzzkeys, dwsublen-k-1) && src[j-k] != hexsub[dwsublen-k-1] {
found = false
break
}
}
if found {
if j < dwsrclen {
offsets = append(offsets, j-dwsublen+1)
if patchonce {
break
}
}
}
if j < dwsrclen-dwsublen-1 {
j += p[src[j+1]]
} else {
j++
}
if j > dwsrclen-dwsublen {
break
}
}
return offsets
}

func isfound(source []int, ptr int) bool {
for _, i := range source {
if i == ptr {
return true
}
}
return false
}

func fuzzreplace(oldstr []byte, patchstr []byte, patchkeys []int) []byte {
tmplist := make([]byte, len(patchstr))
copy(tmplist, patchstr)
for i := range tmplist {
if isfound(patchkeys, i) {
tmplist[i] = oldstr[i]
}
}
return tmplist
}

func replace(origin []byte, patchlist map[int][]byte) []byte {
tmpdata := origin
for index, new := range patchlist {
copy(tmpdata[index:index+len(new)], new)
}
return tmpdata
}
func str2bytes(binstr string) ([]byte, []int) {
var fuzzkeys []int
tmpstr := strings.Replace(binstr, " ", "", -1)
hexlens := len(tmpstr) / 2
for i := 0; i < hexlens; i++ {
tmphex := tmpstr[i*2 : i*2+2]
if tmphex == "??" {
fuzzkeys = append(fuzzkeys, i)
}
}
tmpstr = strings.Replace(tmpstr, "??", "00", -1)
binlist, _ := hex.DecodeString(tmpstr)
return binlist, fuzzkeys
}


大神论坛  脱壳破解

返回顶部