如何在编译后的二进制文件中隐藏一个值

huangapple go评论81阅读模式
英文:

How to hide a value in a compiled binary

问题

我想隐藏代码中的一个字符串常量。例如,在以下代码中,变量a的值可以是一个秘密:

package main

import "fmt"

func main() {
  a := "someStringXYZ"
  fmt.Println(a)
}

这是如何编译这个go文件的:

$ go build -ldflags='-extldflags=-static' abc.go

同样也可以正常工作:

$ ./abc 
someStringXYZ

如果我在这个二进制文件上使用strings命令,我可以获取变量a的值。

$ strings abc | grep XYZ
eq=runtime: val=someStringXYZsrmount errortimer expiredtraceStackTabtriggerRatio=value method xadd64 failedxchg64 failed}

有没有办法可以保持这个值的隐藏?

我不希望使用AppTokens从秘密存储中获取值的解决方案,因为这样AppTokens就会变得可见。

英文:

I want to hide a string constant present in the code. For example, in the following code - the variable a's value can be a secret:

package main

import "fmt"

func main() {
  a := "someStringXYZ"
  fmt.Println(a)
}

This is how compiled this go file:

$ go build -ldflags='-extldflags=-static' abc.go

Works fine as well:

$ ./abc 
someStringXYZ

If I use the strings command on this binary then I can get the value of the variable a.

$ strings abc | grep XYZ
eq=runtime: val=someStringXYZsrmount errortimer expiredtraceStackTabtriggerRatio=value method xadd64 failedxchg64 failed}

Is there a way I can keep this value hidden?

I'm not looking for a solution in which the app will use the AppTokens to get the value from secret storage because then the AppTokens becomes visible.

答案1

得分: 4

正如评论中所指出的,你无法完全隐藏它。为了至少从strings中隐藏它(如果这是你想要的),你可以将它保存为[]byte而不是string,像这样:

package main

import "fmt"

func main() {
    a := []byte("someStringXYZ")
    fmt.Println(string(a))
}

现在,当我编译并在其上运行strings时,它不再找到"someStringXYZ"。显然,如果你尝试,你仍然可以轻松提取它,并且它显然会在运行时的某个时刻显示在内存中,但这可能不是你目前关注的问题(我不确定你的应用程序是什么)。

请注意,这仅在字面量仅出现在转换中的情况下有效,而不是在其他任何地方。

无论如何,如果你有一个硬编码的令牌,并且需要隐藏它,那么在设计阶段你可能做错了一些事情。你应该重新考虑设计。

编辑:解释为什么这种方法有效;我不确定,但我认为这是因为[]byte不会存储终止的空字节,或者类似的情况。strings只会找到以某个不可打印字符结尾的长度为4或更长的可打印字符,所以实际上,我们可能只是侥幸而已。正如我之前所说,换个说法;混淆并不等于安全。如果someStringXYZ很重要,那么这种方法并不安全。

英文:

As the comments noted, you can't really make it fully hidden. What you can do, in order to at least hide it from strings (if that's all you want), is save it as a []byte, not a string, like so:

package main

import "fmt"

func main() {
    a := []byte("someStringXYZ")
    fmt.Println(string(a))
}

Now, when I compile and run strings on it, it doesn't find "someStringXYZ" anymore. You can still obviously extract it easily, if you tried, and it will obviously show up in memory at some point when it runs, but that might not be your immediate concern (I'm not sure what your application is).

Note that this only works if the literal only appears there in the cast, not anywhere else.

Either way - if you have a token hardcoded, and you need to hide it, you're probably doing something wrong at the design-stage. You should reconsider that design.

Edit: To explain why this method works; I'm not sure, but I think it's because []byte are not stored with a terminating null-byte, or something along those lines. strings only finds printable characters of length 4 or longer that end with some unprintable character - so really, we might just be getting lucky. As I said before, but to phrase it differently; Obfuscation is not security. This isn't safe if someStringXYZ is important.

huangapple
  • 本文由 发表于 2021年7月6日 16:26:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/68267047.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定