Fix reflection detection for linknamed methods (#883)

pull/876/head
NHAS 5 months ago committed by GitHub
parent 48dd2263a9
commit 69d7b84f35
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -9,6 +9,7 @@
Andrew LeFevre <jalefevre@liberty.edu>
Daniel Martí <mvdan@mvdan.cc>
Emmanuel Chee-zaram Okeke <ecokeke21@gmail.com>
NHAS <jordanatararimu@gmail.com>
Nicholas Jones <me@nicholasjon.es>
Zachary Wasserman <zachwass2000@gmail.com>
lu4p <lu4p@pm.me>

@ -223,7 +223,15 @@ func entryOffKey() uint32 {
return runtimeHashWithCustomSalt([]byte("entryOffKey"))
}
func hashWithPackage(pkg *listedPackage, name string) string {
func hashWithPackage(tf *transformer, pkg *listedPackage, name string) string {
// In some places it is not appropriate to access the transformer
if tf != nil {
// If the package is marked as "in-use" by reflection, the private structures are not obfuscated, so dont return them as a hash. Fixes #882
if _, ok := tf.curPkgCache.ReflectObjects[pkg.ImportPath+"."+name]; ok {
return name
}
}
// If the user provided us with an obfuscation seed,
// we use that with the package import path directly..
// Otherwise, we use GarbleActionID as a fallback salt.

@ -664,7 +664,7 @@ func (tf *transformer) transformAsm(args []string) ([]string, error) {
newPaths := make([]string, 0, len(paths))
if !slices.Contains(args, "-gensymabis") {
for _, path := range paths {
name := hashWithPackage(tf.curPkg, filepath.Base(path)) + ".s"
name := hashWithPackage(tf, tf.curPkg, filepath.Base(path)) + ".s"
pkgDir := filepath.Join(sharedTempDir, tf.curPkg.obfuscatedImportPath())
newPath := filepath.Join(pkgDir, name)
newPaths = append(newPaths, newPath)
@ -754,7 +754,7 @@ func (tf *transformer) transformAsm(args []string) ([]string, error) {
// directory, as assembly files do not support `/*line` directives.
// TODO(mvdan): per cmd/asm/internal/lex, they do support `#line`.
basename := filepath.Base(path)
newName := hashWithPackage(tf.curPkg, basename) + ".s"
newName := hashWithPackage(tf, tf.curPkg, basename) + ".s"
if path, err := tf.writeSourceFile(basename, newName, buf.Bytes()); err != nil {
return nil, err
} else {
@ -870,7 +870,7 @@ func (tf *transformer) replaceAsmNames(buf *bytes.Buffer, remaining []byte) {
remaining = remaining[nameEnd:]
if lpkg.ToObfuscate && !compilerIntrinsics[lpkg.ImportPath][name] {
newName := hashWithPackage(lpkg, name)
newName := hashWithPackage(tf, lpkg, name)
if flagDebug { // TODO(mvdan): remove once https://go.dev/issue/53465 if fixed
log.Printf("asm name %q hashed with %x to %q", name, tf.curPkg.GarbleActionID, newName)
}
@ -1108,7 +1108,7 @@ func (tf *transformer) transformDirectives(comments []*ast.CommentGroup) {
func (tf *transformer) transformLinkname(localName, newName string) (string, string) {
// obfuscate the local name, if the current package is obfuscated
if tf.curPkg.ToObfuscate && !compilerIntrinsics[tf.curPkg.ImportPath][localName] {
localName = hashWithPackage(tf.curPkg, localName)
localName = hashWithPackage(tf, tf.curPkg, localName)
}
if newName == "" {
return localName, ""
@ -1130,8 +1130,8 @@ func (tf *transformer) transformLinkname(localName, newName string) (string, str
}
pkgSplit := 0
var lpkg *listedPackage
var foreignName string
var lpkg *listedPackage
for {
i := strings.Index(newName[pkgSplit:], ".")
if i < 0 {
@ -1183,22 +1183,22 @@ func (tf *transformer) transformLinkname(localName, newName string) (string, str
// pkg/path.(*Receiver).method
receiver = strings.TrimPrefix(receiver, "(*")
receiver = strings.TrimSuffix(receiver, ")")
receiver = "(*" + hashWithPackage(lpkg, receiver) + ")"
receiver = "(*" + hashWithPackage(tf, lpkg, receiver) + ")"
} else {
// pkg/path.Receiver.method
receiver = hashWithPackage(lpkg, receiver)
receiver = hashWithPackage(tf, lpkg, receiver)
}
// Exported methods are never obfuscated.
//
// TODO(mvdan): We're duplicating the logic behind these decisions.
// Reuse the logic with transformCompile.
if !token.IsExported(name) {
name = hashWithPackage(lpkg, name)
name = hashWithPackage(tf, lpkg, name)
}
newForeignName = receiver + "." + name
} else {
// pkg/path.function
newForeignName = hashWithPackage(lpkg, foreignName)
newForeignName = hashWithPackage(tf, lpkg, foreignName)
}
newPkgPath := lpkg.ImportPath
@ -1276,7 +1276,7 @@ func (tf *transformer) processImportCfg(flags []string, requiredPkgs []string) (
// For beforePath="vendor/foo", afterPath and
// lpkg.ImportPath can be just "foo".
// Don't use obfuscatedImportPath here.
beforePath = hashWithPackage(lpkg, beforePath)
beforePath = hashWithPackage(tf, lpkg, beforePath)
afterPath = lpkg.obfuscatedImportPath()
}
@ -2037,7 +2037,7 @@ func (tf *transformer) transformGoFile(file *ast.File) *ast.File {
return true // we only want to rename the above
}
node.Name = hashWithPackage(lpkg, name)
node.Name = hashWithPackage(tf, lpkg, name)
// TODO: probably move the debugf lines inside the hash funcs
if flagDebug { // TODO(mvdan): remove once https://go.dev/issue/53465 if fixed
log.Printf("%s %q hashed with %x… to %q", debugName, name, hashToUse[:4], node.Name)
@ -2156,7 +2156,7 @@ func (tf *transformer) transformLink(args []string) ([]string, error) {
if path != "main" {
newPath = lpkg.obfuscatedImportPath()
}
newName := hashWithPackage(lpkg, name)
newName := hashWithPackage(tf, lpkg, name)
flags = append(flags, fmt.Sprintf("-X=%s.%s=%s", newPath, newName, stringValue))
})

@ -127,7 +127,7 @@ func printFile(lpkg *listedPackage, file *ast.File) ([]byte, error) {
newName := ""
if !flagTiny {
origPos := fmt.Sprintf("%s:%d", filename, origOffset)
newName = hashWithPackage(lpkg, origPos) + ".go"
newName = hashWithPackage(nil, lpkg, origPos) + ".go"
// log.Printf("%q hashed with %x to %q", origPos, curPkg.GarbleActionID, newName)
}

@ -69,7 +69,7 @@ One can reverse a captured panic stack trace as follows:
continue
}
addHashedWithPackage := func(str string) {
replaces = append(replaces, hashWithPackage(lpkg, str), str)
replaces = append(replaces, hashWithPackage(nil, lpkg, str), str)
}
// Package paths are obfuscated, too.
@ -113,7 +113,7 @@ One can reverse a captured panic stack trace as follows:
// Reverse position information of call sites.
pos := fset.Position(node.Pos())
origPos := fmt.Sprintf("%s:%d", goFile, pos.Offset)
newFilename := hashWithPackage(lpkg, origPos) + ".go"
newFilename := hashWithPackage(nil, lpkg, origPos) + ".go"
// Do "obfuscated.go:1", corresponding to the call site's line.
// Most common in stack traces.

@ -199,7 +199,7 @@ func (p *listedPackage) obfuscatedImportPath() string {
if !p.ToObfuscate {
return p.ImportPath
}
newPath := hashWithPackage(p, p.ImportPath)
newPath := hashWithPackage(nil, p, p.ImportPath)
log.Printf("import path %q hashed with %x to %q", p.ImportPath, p.GarbleActionID, newPath)
return newPath
}

@ -17,7 +17,6 @@ module test/main
go 1.22
replace big.chungus/meme => ./big.chungus/meme
require big.chungus/meme v0.0.0
-- a.go --
package main
@ -76,6 +75,10 @@ func renamedFunc() string
//go:linkname tagline big.chungus/meme.chungify
func tagline() string
// A linkname to an external non-obfuscated func with receiver which is also non-obfuscated
//go:linkname changeThing test/main/imported.(*channel).changeThing
func changeThing(c unsafe.Pointer, to string)
func main() {
println(obfuscatedFunc())
@ -97,6 +100,13 @@ func main() {
println(tagline())
println(imported.ByteIndex("01234", '3'))
linknameCalledInPkg()
a := imported.Return("initial_text")
val := reflect.ValueOf(a)
changeThing(val.UnsafePointer(), "to this")
println(a.DoThing())
}
-- imported/imported.go --
package imported
@ -104,8 +114,32 @@ package imported
import (
_ "strings"
_ "unsafe"
"reflect"
)
type Test interface {
DoThing() string
}
func Return(c string) Test {
return &channel{dummy: c}
}
type channel struct {
dummy string
}
var _ = reflect.TypeOf(channel{})
func (c *channel) DoThing() string {
return c.dummy
}
func (c *channel) changeThing(to string) {
c.dummy = to
}
func ObfuscatedFuncImpl() string {
return "obfuscated func"
}
@ -156,3 +190,4 @@ renamed func
featuring Dante from the Devil May Cry series
3
obfuscated func
to this
Loading…
Cancel
Save