一个简单的支持模糊搜索patch的代码
用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[]byte)
for i := range originBytes {
oldstr, keys := str2bytes(originBytes)
patchstr, patchkeys := str2bytes(newBytes)
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
tmpdata := fuzzreplace(tmpstr, patchstr, patchkeys)
patchlist = 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 = -1
}
wildaddr := 0
if len(fuzzkeys) > 0 {
wildaddr = fuzzkeys
}
for i := wildaddr + 1; i < dwsublen; i++ {
p] = dwsublen - i
}
for i := 0; i < 256; i++ {
if p == -1 {
p = 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 != hexsub {
found = false
break
}
}
if found {
if j < dwsrclen {
offsets = append(offsets, j-dwsublen+1)
if patchonce {
break
}
}
}
if j < dwsrclen-dwsublen-1 {
j += p]
} 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 = oldstr
}
}
return tmplist
}
func replace(origin []byte, patchlist map[]byte) []byte {
tmpdata := origin
for index, new := range patchlist {
copy(tmpdata, 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
if tmphex == "??" {
fuzzkeys = append(fuzzkeys, i)
}
}
tmpstr = strings.Replace(tmpstr, "??", "00", -1)
binlist, _ := hex.DecodeString(tmpstr)
return binlist, fuzzkeys
}
加个GUI就完美了 大佬,求个C#版本。。 @iamok
但是代码看着很精干,不算很复杂。 谢谢分享 Go一统江湖浓浓的GPT味啊{:lol:} 飘云 发表于 2023-9-1 00:20
Go一统江湖浓浓的GPT味啊😀
哈哈,飘总一眼就看出我这个代码的业余
不过这个还真不是gpt写的,
大概21年初的时候当时网上还是看了很多别人的代码,kmp和sunday这些都看了下
抄了匹配算法部分,支持??是按自己想法改写的,所以实现方式估计很丑很业余,也不清楚现有的类似工具是用什么形式处理的。
iamok 发表于 2023-9-1 09:09
哈哈,飘总一眼就看出我这个代码的业余
不过这个还真不是gpt写的,
反正比我写得好~ 感谢分享~{:hug:}
本帖最后由 small-q 于 2023-9-1 16:52 编辑
谢谢大佬分享,收藏学习 感谢分享好东西。
页:
[1]