使用Golang修改EXE属性:如何将Anomalies值写入原文件?
可行解决方案说明
首先明确:pe.Anomalies是saferwall/pe库在内存中生成的分析字段,不属于PE文件格式的原生结构,因此无法直接通过库的默认方法将其写回原EXE。要实现“下次读取能获取到设置的Anomalies值”,需要把这个字段的内容存储到PE文件的某个可自定义的区域,下次读取时再从该区域取出并赋值给Anomalies。
以下是两种具体实现方案:
方案一:利用PE自定义资源段存储
PE格式允许添加自定义资源,我们可以将Anomalies序列化为JSON字符串,存入自定义资源中,下次读取时再解析出来。
写入代码示例
package main import ( "encoding/json" "os" "github.com/saferwall/pe" ) // 自定义资源类型和名称,用于标识我们存储的Anomalies数据 const ( customResType = 1000 // 自定义资源类型ID(需大于16,避免和系统类型冲突) customResName = "PE_ANOMALIES" ) func main() { exePath, err := os.Executable() if err != nil { panic(err) } // 读取并解析PE文件 peFile, err := pe.New(exePath, &pe.Options{}) if err != nil { panic(err) } defer peFile.Close() if err := peFile.Parse(); err != nil { panic(err) } // 设置自定义Anomalies peFile.Anomalies = []string{"some sample anomalies", "other sample anomalies"} // 序列化为JSON anomaliesData, err := json.Marshal(peFile.Anomalies) if err != nil { panic(err) } // 添加自定义资源到PE文件 err = peFile.AddResource(customResType, customResName, anomaliesData) if err != nil { panic(err) } // 将修改后的PE数据写回原文件(注意:建议先备份原文件) outputFile, err := os.Create(exePath) if err != nil { panic(err) } defer outputFile.Close() _, err = peFile.Write(outputFile) if err != nil { panic(err) } }
读取代码示例
package main import ( "encoding/json" "fmt" "os" "github.com/saferwall/pe" ) const ( customResType = 1000 customResName = "PE_ANOMALIES" ) func main() { exePath, err := os.Executable() if err != nil { panic(err) } peFile, err := pe.New(exePath, &pe.Options{}) if err != nil { panic(err) } defer peFile.Close() if err := peFile.Parse(); err != nil { panic(err) } // 读取自定义资源中的Anomalies数据 resData, err := peFile.GetResource(customResType, customResName) if err == nil && len(resData) > 0 { var anomalies []string if err := json.Unmarshal(resData, &anomalies); err == nil { peFile.Anomalies = anomalies } } // 验证结果 fmt.Println("Anomalies:", peFile.Anomalies) }
方案二:添加自定义节存储数据
如果资源段无法满足需求,可以在PE文件中添加一个新的节,将序列化后的Anomalies数据写入该节。
核心代码片段(写入部分)
// 序列化Anomalies anomaliesData, err := json.Marshal(peFile.Anomalies) if err != nil { panic(err) } // 添加自定义节,节名建议用8个字符以内(PE节名限制) err = peFile.AddSection(".anomalies", anomaliesData, pe.SCN_CNT_INITIALIZED_DATA|pe.SCN_MEM_READ) if err != nil { panic(err) } // 写回文件 outputFile, err := os.Create(exePath) if err != nil { panic(err) } defer outputFile.Close() _, err = peFile.Write(outputFile) if err != nil { panic(err) }
核心代码片段(读取部分)
// 遍历节找到自定义节 for _, sec := range peFile.Sections { if sec.Name == ".anomalies" { var anomalies []string if err := json.Unmarshal(sec.Data, &anomalies); err == nil { peFile.Anomalies = anomalies break } } }
注意事项
- 操作EXE文件前务必备份原文件,避免破坏可执行性
- 自定义资源类型ID需大于16,避免与系统预定义资源类型冲突
- 添加自定义节时,要注意节的内存属性设置(如
SCN_MEM_READ表示只读,避免权限问题) - 序列化方式除了JSON,也可以用Gob等二进制格式,效率更高但可读性差
内容的提问来源于stack exchange,提问作者Ethan Leonard
相关产品推荐
相关产品推荐

