Commit Graph

659 Commits (master)
 

Author SHA1 Message Date
Daniel Martí c41f026cd6 README: clarify that we have no plans to exclude files or packages
This is a common question in the issue tracker: #631, #777, #802, #844.
While here, tweak the wording and formatting in the section as well.
5 days ago
Daniel Martí 9f82b2bbfe make pointer regular expressions more flexible
We just got a failure on Mac on CI with pointers past eight digits:

    (0x10432dec0,0x10433c690)

Use `[[:xdigit:]]+` consistently.
5 days ago
Daniel Martí 20a92460d5 all: use cmd.Environ rather than os.Environ
Added in Go 1.19, this keeps os/exec's default environment logic,
such as ensuring that $PWD is always set.
2 months ago
Daniel Martí 52d436d38a remove err conditional that was never met
gopls correctly pointed out that the err==nil check was never met,
as err was assigned and we returned early when err!=nil.

This was an oversight when I wrote this; when Encode fails,
we shouldn't return, because we still want to close the file.
We don't defer because we want to check the error; explain that.
2 months ago
Daniel Martí d2beda1f00 switch frankban/quicktest for go-quicktest/qt
The latter is newer and uses generics.
2 months ago
Daniel Martí f09db67c89 use types.Info.PkgNameOf
It accomplishes the same Implicits/Defs logic we were doing here.
2 months ago
Daniel Martí f08edd026d README: document the package initialization order caveat
Keeping the original lexical sorting of Go packages would be very hard,
as a Go program may import an unknown number of Go packages,
and we load and obfuscate one package at a time by design.

One option would be to load all packages upfront when obfuscating
main packages, but that would break the per-package caching of
ofbuscated Go packages, causing a huge slow-down in builds.

Another option would be to not obfuscate import paths,
which would clearly cause a worsening of the obfuscation quality.

The third option is to not attempt to keep the original order,
and document that as a caveat in the README.
I suspect the vast majority of Go projects won't be affected by this,
and those few that might be can always use imports to enforce the order.

Closes #693, per the decision above to not change what we do.
2 months ago
Daniel Martí 9a2ef369b2 fail early if we know we lack Go linker patches
Right now, we only have linker patches for Go 1.22.x.
We only ever maintain those for one or two major Go versions at a time.

If a user tries to use the Go toolchain from 1.21, we already fail
with "Go version too old" messages early on, but we don't for 1.23,
causing a relatively confusing error later on when we link a binary:

    cannot get modified linker: cannot retrieve linker patches: open patches/go1.23: file does not exist

Instead, fail early and with a good error message.
2 months ago
Daniel Martí d138afaf32 don't panic when we can error as easily
Panicking in small helpers or in funcs that don't return error
has proved useful to keep code easier to maintain,
particularly for cases that should typically never happen.

However, in these cases we can error just as easily.
In particular, I was getting a panic whenever I forgot
that I was running garble with Go master (1.23), which is over the top.
2 months ago
Daniel Martí 975f608c3d CHANGELOG: add entry for v0.12.1 2 months ago
Daniel Martí 66b61406c1 obfuscate syscall again to fix x/sys/unix
When updating Garble to support Go 1.22.0, CI on MacOS spotted
that the syscall package was failing to build given that it uses
assembly code which is only allowed in some std packages.

That allowlist is based on import paths, and we were obfuscating
the syscall package's import path, so that was breaking GOOS=darwin.
As a fix, I added syscall to runtimeAndDeps to not obfuscate it.

That wasn't a great fix; it's not part of runtime and its dependencies,
and there's no reason we should avoid obfuscating the package contents.
Not obfuscating the contents in fact broke x/sys/unix,
as it contains a copy of syscall.Rlimit which it type converted with.

Undo that fix and reinstate the gogarble.txtar syscall test.
Implement the fix where we only leave syscall's import path alone.
Add a regression test, and add a note about adding x/net and x/sys
to check-third-party.sh so that we can catch these bugs earlier.

Fixes #830.
2 months ago
Daniel Martí 69bc62c56c start using some Go 1.22 features
We no longer need to worry about the scope of range variables,
we can iterate over integers directly, and we can use cmp.Or too.

I haven't paid close attention to using these everywhere.
This is mainly testing out the new features where I saw some benefit.
3 months ago
Daniel Martí ad2ecc7f2f drop Go 1.21 and start using go/version
Needing to awkwardly treat Go versions as if they were semver
is no longer necessary thanks to go/version being in Go 1.22.0 now.
3 months ago
pagran d76bc2eb47 add trash block generator docs 3 months ago
Daniel Martí f3f57e361d
CHANGELOG: finish up for a release
The trash block generator docs aren't ready yet, they will come soon.
This is not a release blocker, given that the control flow obfuscator
is experimental and opt-in for now.
3 months ago
Daniel Martí b469dcaf9d
bump deps for the upcoming release
As usual, and this is also a good idea for the x repos to better
support Go 1.22.
3 months ago
Daniel Martí 55921a06d4 fix building for GOOS=darwin on Go 1.22.0
It seems like building with Go 1.22.0 for GOOS=darwin started
running into some issues with the syscall package's use of ABIInternal
in assembly source code:

    > exec garble build
    [stderr]
    # syscall
    [...].s:16: ABI selector only permitted when compiling runtime, reference was to "runtime.entersyscall"

The error can be reproduced from another platform like GOOS=linux
as long as we have any test that cross-compiles std to GOOS=darwin.
We had crossbuild.txtar which only ensured we covered GOOS=windows
and GOOS=linux, so add a third case to ensure MacOS is covered too.

This will slow down the tests a bit, but is important for the sake
of ensuring that we catch these bugs early, even without MacOS on CI.
In fact, we hadn't caught this earlier for Go 1.22 precisely because
on CI we only tested on Go tip with GOOS=linux, for the sake of speed.

Adding the rest of the package import paths from objabi.allowAsmABIPkgs
to our runtimeAndDeps generated map solves this error.
3 months ago
Daniel Martí 7a67952494 CHANGELOG: draft release notes for v0.12.0 3 months ago
Daniel Martí e6299c5ac3 CI: start testing on 1.22 now that it's released 3 months ago
Daniel Martí 9cb4a6f0c8 amend panic message after decodeHash got renamed 3 months ago
pagran e8fe80d627
add trash block generator (#825)
add trash block generator

For making static code analysis even more difficult, added feature for
generating trash blocks that will never be executed. In combination
with control flow flattening makes it hard to separate trash code from
the real one, plus it causes a large number of trash references to
different methods.

Trash blocks contain 2 types of statements:
1. Function/method call with writing the results into local variables
and passing them to other calls
2. Shuffling or assigning random values to local variables
3 months ago
Daniel Martí c43cf74195 add package godoc
So that pkg.go.dev and `go doc` have something to show.
Copying the first sentence from the README for brevity.
4 months ago
Daniel Martí bdfa619f77 support inline comments in asm #include lines
That is, the assembly line

    #include "foo.h" // bar

would make garble run into an error, as we would try to parse
the #include directive before we stripped comments,
effectively trying to unquote the string

    "foo.h" // bar

rather than just the included filename

    "foo.h"

Add test cases for asm but also cgo, while at it.

Fixes #812.
4 months ago
Daniel Martí de65196495 fix support for go1.22rc1
In early December, a new internal package linknamed from runtime
was introduced, internal/chacha8rand. Re-generate the tables.

Note that due to the same group of CLs and refactors,
math/rand and net are no longer linknamed from runtime in Go 1.22.
They are still in Go 1.21, so keep those entries around for now.
We can remove math/rand/v2, as it doesn't yet exist in 1.21.

Fixes #820.
4 months ago
pagran 3a9c9aa3d4
fix shuffle obfuscation compiler optimization
In some cases, compiler could optimize the shuffle obfuscator,
causing exposing the obfuscated literal.
As a fix, added xor encryption of array indexes.
5 months ago
Paul Scheduikat 96d2d8b0de
track types used in make assigned to a reflected type
Fixes #690.
5 months ago
Mrs4s 0752f9e5df fix ios build 5 months ago
Daniel Martí de2c23b2c0 README: start a section on the use cases for a Go obfuscator
This type of question has popped up a number of times before,
particularly when someone unfamiliar with obfuscators in other languages
first hears about the existence of one for Go.
5 months ago
Daniel Martí 02175c5018
CHANGELOG: finalise for v0.11.0 5 months ago
Daniel Martí d283d8479c add and test initial support for Go 1.22
The Go 1.21 linker patches luckily rebased on master as of
de5b418bea70aaf27de1f47e9b5813940d1e15a4 just fine.
The addition of the strings import in the second patch was removed,
since the file in Go 1.22 now has this package import.

We can remove the Go 1.20 linker patches too, since we no longer support
that Go version in the upcoming release.

Start treating runtime/internal/startlinetest as part of the runtime,
since otherwise its test-only trickery breaks "garble build std":

    # runtime/internal/startlinetest
    [...]/XS7r7lPHkTG.s:23: ABI selector only permitted when compiling runtime, reference was to "HGoWHDsKwh.AlfA2or7Nnb"
    asm: assembly of $WORK/.tmp/garble-shared1535203339/HGoWHDsKwh/XS7r7lPHkTG.s failed

While here, update actions/checkout and staticcheck in CI.
5 months ago
Daniel Martí 9378ec959a CHANGELOG: start drafting the next release notes 5 months ago
pagran 36ada88a79 add control flow hardening docs 5 months ago
Paul Scheduikat bec8043790
track converted types when recording reflection usage
Fixes #763.
Fixes #782.
Fixes #785.
Fixes #807.
5 months ago
Daniel Martí 4271bc45ae avoid panic when embedding a builtin alias
TypeName.Pkg is documented as:

    Pkg returns the package to which the object belongs.
    The result is nil for labels and objects in the Universe scope.

When a struct type embeds a builtin alias type, such as byte,
this would lead to a panic since we assumed we could use the Pkg method.

Fixes #798.
6 months ago
Daniel Martí 6f0e46f80b strip struct tags when hashing structs for type identity
This was a long standing TODO, and a user finally ran into it.
The fix isn't terribly straightforward, but I'm pretty happy with it.

Add a test case where the same struct field is identical
with no tag, with the "tagged1" json tag, and again with "tagged2".
While here, we add a test case for a regular named field too.

Fixes #801.
6 months ago
Daniel Martí 08b3d9db61 add a couple of reminder TODOs for go/... packages 6 months ago
Daniel Martí 126618a0d5 drop support for Go 1.20
Go 1.21.0 was released in August 2023, so our upcoming release
will no longer support the Go 1.20 release series.

The first Go 1.22 release candidate is also due in December 2023,
less than a month from now, so dropping 1.20 will simplify 1.22 work.
6 months ago
Daniel Martí abcdc1fcbf re-generate go_std_tables.go with Go master
Two new packages linknamed with the runtime package,
one new intrinsic function, and one that is being removed in Go 1.22
but we want to keep around as long as we support Go 1.21.

Also note that, since math/rand/v2 simply does not exist until Go 1.22,
we need to adjust appendListedPackages to not fail on older versions.
6 months ago
Daniel Martí e712e720ce use x/tools version from go.mod in go:generate
Otherwise we have to update that `@semver` string
alongside the regular x/tools updates in go.mod.
There's no reason to separate the two versions either.
6 months ago
Daniel Martí c314fcb61c update deps
In particular, the x/tools update fixes support for Go 1.22,
due to https://go.dev/issue/62167 happening in August 2023.
6 months ago
pagran 5e80f12be7
implement flattening hardening
Without hardening, obfuscation is vulnerable to analysis via symbolic
execution because all keys are opened, and it is easy to trace their
connections. Added extendable (contribution-friendly) hardening
mechanism that makes it harder to determine relationship between key and
execution block through key obfuscation.

There are 2 hardeners implemented and both are compatible with literal
obfuscation, which can make analysis even more difficult.
6 months ago
Daniel Martí 978fd6d518 appease Go 1.22's stricter base64 sanity checks
We were using an alphabet with a duplicate character on purpose.
Go 1.21 was perfectly fine with that, but 1.22 started noticing:

    panic: encoding alphabet includes duplicate symbols

I can't fault the new sanity check, because it makes sense in general.
What we are doing here is slightly bizarre, because we don't care
about decoding the name hashes at all.

Appease the sanity check by replacing dashes with duplicate characters
as a follow-up step. While here, use "a" rather than "z",
which is more common and less likely to be noticeable.
7 months ago
Daniel Martí 82834ace20 testdata: skip runtime rebuild test on darwin
CI ran into the failure again; reopened #609 for now.
7 months ago
Daniel Martí 716322cdf8 all: start suggesting Go 1.21 and testing on it
Also note that the first release is now 1.21.0,
so we no longer need to use the awkward 1.21.x notation in warnings.
7 months ago
Daniel Martí 344cdd5e7b make `go test -race` fast again on Go 1.21
On my laptop, `go test -short -race` on Go 1.20 used to take about 62s.
Jumping to Go 1.21, I was surprised to see an increase to 152s,
more than double - which was weird given how often the CPU was idle.

This manifested when updating our CI to start testing on Go 1.21.
Where Go 1.20 on Linux took about 10m to run `go test -race`,
Go 1.21 hit the 20m timeout every single time.

After a bit of googling, I was reminded of https://go.dev/issues/20364
as well as https://go.dev/doc/articles/race_detector#Options:

    atexit_sleep_ms (default 1000): Amount of milliseconds to sleep in the main goroutine before exiting.

This default is a bit aggressive for Go, but usually harmless,
having each test binary sleep for 1s after the package has been tested.

However, this 1s sleep after main runs is horrendous for garble's tests;
the testscripts run `garble build` many times, running the test binary.
It then runs `go build -toolexec=garble`, which runs the test binary
many more times: for every compiler, linker, etc invocation.

This means that our testscripts would include dozens of 1s sleeps,
in many cases blocking the continuation of the entire test.
This seemed to not be happening on earlier Go versions due to a bug;
Go 1.21's race mode started obeying this default properly.

The added change sets atexit_sleep_ms to something more reasonable
if GORACE isn't set at all; 10ms doesn't disable this check entirely,
but its overhead is orders of magnitude less noticeable than 1000ms.
`go test -short -race` on Go 1.21 drops back down to 68s for me.
7 months ago
Hritik Vijay 66bdc8b124 Use go install instead of garble install
garble install command does not exist
7 months ago
Daniel Martí 23c8641855 propagate "uses reflection" through SSA stores
Up until now, the new SSA reflection detection relied on call sites
to propagate which objects (named types, struct fields) used reflection.
For example, given the code:

    json.Marshal(new(T))

we would first record that json.Marshal calls reflect.TypeOf,
and then that the user's code called json.Marshal with the type *T.

However, this would not catch a slight variation on the above:

    var t T
    reflect.TypeOf(t)
    t.foo = struct{bar int}{}

Here, type T's fields such as "foo" and "bar" are not obfuscated,
since our logic sees the call site and marks the type T recursively.
However, the unnamed `struct{bar int}` type was still obfuscated,
causing errors such as:

    cannot use struct{uKGvcJvD24 int}{} (value of type struct{uKGvcJvD24 int}) as struct{bar int} value in assignment

The solution is to teach the analysis about *ssa.Store instructions
in a similar way to how it already knows about *ssa.Call instructions.
If we see a store where the destination type is marked for reflection,
then we mark the source type as well, fixing the bug above.

This fixes obfuscating github.com/gogo/protobuf/proto.
A number of other Go modules fail with similar errors,
and they look like very similar bugs,
but this particular fix doesn't apply to them.
Future incremental fixes will try to deal with those extra cases.

Fixes #685.
9 months ago
pagran afe1aad916 Removing obsolete TODO
indirect import issue has already been fixed
9 months ago
pagran 9612b29423
add generic function support for control flow obfuscation 10 months ago
pagran 260cad2a3f
add "max" flag value and limits for control flow obfuscation parameters 10 months ago