Commit Graph

15 Commits (ea19e39aa49cbd170768505d7b0b0b17132862f1)

Author SHA1 Message Date
Daniel Martí ea19e39aa4 use hashWith for obfuscation position information
Position information was obfuscated with math/rand manually, which meant
that the resulting positions were pretty small like "x.go:34", but they
were also very hard to reverse due to their short length and difficulty
to reproduce.

We now hash them with hashWith and the package's GarbleActionID:

	"main.go:203" hashed with 933ad1c700755b7c3a9913c55cade1 to "mwu1xuNz.go"

The input to the hash is the base filename and the byte offset of the
declaration within the file, meaning that it's unique within a package.
The output filename is long enough to allow easy reversal.

The line number is always 1, since the information needed for reversing
is contained entirely within the filename. It doesn't really matter if
we encode data in the filename or line number, but it's easier for us to
use a string.

For #5.
4 years ago
Daniel Martí ff0bea73b5
all: drop support for Go 1.15.x (#265)
This mainly cleans up the few bits of code where we explicitly kept
support for Go 1.15.x. With v0.1.0 released, we can drop support now,
since the next v0.2.0 release will only support Go 1.16.x.

Also updates all modules, including test ones, to 'go 1.16'.

Note that the TOOLEXEC_IMPORTPATH refactor is not done here, despite all
the TODOs about doing so when we drop 1.15 support. This is because that
refactor needs to be done carefully and might have side effects, so it's
best to keep it to a separate commit.

Finally, update the deps.
4 years ago
Daniel Martí c0c5a75454
testdata: fix flakiness of tiny.txt on Windows (#252)
Sometimes it prints relatively low addresses, like:

	(0xbc200,0xdd658)

We required 6 to 8 hex digits, and sometimes it printed 5. Make the
regular expression more conservative.

Fixes #184.
4 years ago
Andrew LeFevre 081cba38d7 strip a few more unneeded runtime functions
Strip a few more traceback printing related functions in the runtime, new for Go 1.16. Also test that GODEBUG=inittrace=1 does not print anything when -tiny is passed.
4 years ago
Daniel Martí 05d0dd1801
reimplement import path obfuscation without goobj2 (#242)
We used to rely on a parallel implementation of an object file parser
and writer to be able to obfuscate import paths. After compiling each
package, we would parse the object file, replace the import paths, and
write the updated object file in-place.

That worked well, in most cases. Unfortunately, it had some flaws:

* Complexity. Even when most of the code is maintained in a separate
  module, the import_obfuscation.go file was still close to a thousand
  lines of code.

* Go compatibility. The object file format changes between Go releases,
  so we were supporting Go 1.15, but not 1.16. Fixing the object file
  package to work with 1.16 would probably break 1.15 support.

* Bugs. For example, we recently had to add a workaround for #224, since
  import paths containing dots after the domain would end up escaped.
  Another example is #190, which seems to be caused by the object file
  parser or writer corrupting the compiled code and causing segfaults in
  some rare edge cases.

Instead, let's drop that method entirely, and force the compiler and
linker to do the work for us. The steps necessary when compiling a
package to obfuscate are:

1) Replace its "package foo" lines with the obfuscated package path. No
   need to separate the package path and name, since the obfuscated path
   does not contain slashes.

2) Replace the "-p pkg/foo" flag with the obfuscated path.

3) Replace the "import" spec lines with the obfuscated package paths,
   for those dependencies which were obfuscated.

4) Replace the "-importcfg [...]" file with a version that uses the
   obfuscated paths instead.

The linker also needs that last step, since it also uses an importcfg
file to find object files.

There are three noteworthy drawbacks to this new method:

1) Since we no longer write object files, we can't use them to store
   data to be cached. As such, the -debugdir flag goes back to using the
   "-a" build flag to always rebuild all packages. On the plus side,
   that caching didn't work very well; see #176.

2) The package name "main" remains in all declarations under it, not
   just "func main", since we can only rename entire packages. This
   seems fine, as it gives little information to the end user.

3) The -tiny mode no longer sets all lines to 0, since it did that by
   modifying object files. As a temporary measure, we instead set all
   top-level declarations to be on line 1. A TODO is added to hopefully
   improve this again in the near future.

The upside is that we get rid of all the issues mentioned before. Plus,
garble now nearly works with Go 1.16, with the exception of two very
minor bugs that look fixable. A follow-up PR will take care of that and
start testing on 1.16.

Fixes #176.
Fixes #190.
4 years ago
Daniel Martí 39372a8c9b testdata: don't let tests rely on rewriting mod files
In Go 1.15, if a dependency is required but not listed in go.mod/go.sum,
it's resolved and added automatically.

This is changing in 1.16. From that release, one will have to explicitly
update the mod files via 'go mod tidy' or 'go get'.

To get ahead of the curve, start using -mod=readonly to get the same
behavior in 1.15, and fix all existing tests.

The only tests that failed were imports.txt and syntax.txt, the only
ones to require other modules. But since we're here, let's add the 'go'
line to all go.mod files as well.
4 years ago
Andrew LeFevre bca460e36e
Print interfaces/pointers when -tiny is used (#170)
fixes #167
5 years ago
Daniel Martí 7ad246c6fe
testdata: make tiny.txt simpler and faster (#168)
By avoiding the fmt import, we save some work: 'go test -run Script/tiny'
goes down from 0.8s to 0.5s even with a warm build cache.

Since the output changes between runs, we use stderr grep lines instead
of cmp. This way we can also check that the "oh noes" panic is entirely
hidden in the tiny mode.
5 years ago
Andrew LeFevre 047aa254e2
properly remove all filenames when -tiny is passed (#160)
* properly remove all filenames when -tiny is passed

* document filename symbol removal
5 years ago
Daniel Martí c3bee46a26 testdata: use the debugdir flag less often
In tiny.txt, we already check line numbers via stderr, so there's no
need to do that via -debugdir.

In syntax.txt, we only really care about what names remain in the
binary, not the names which remain in the source but don't affect the
binary.

These changes are important because -debugdir adds a non-trivial amount
of work, which will impede build caching once that feature lands. We
will likely make -debugdir support build caching eventually, but for
now, this preliminary change will make 'go test' much faster with build
caching.

And of course, the tests get simpler, which is nice.
5 years ago
Andrew LeFevre 0d182a3dbd remove unnecessary data from runtime if -tiny is passed
Fixes #127. Saves an additional ~1-2% binary size in my testing.
5 years ago
Andrew LeFevre d679944408
Strip all filename and position info when -tiny is passed (#128)
Co-authored-by: pagran <pagran@protonmail.com>
Co-authored-by: lu4p <lu4p@pm.me>
5 years ago
Daniel Martí 511779d8ff testdata: set GOPRIVATE in all but two tests (#104)
basic.txt just builds main.go without a module. Similarly, we leave
imports.txt without a GOPRIVATE, to test the 'go list -m' fallback.

For all other tests, explicitly set GOPRIVATE, to avoid two exec calls -
both 'go env GOPRIVATE' as well as 'go list -m'. Each of those calls
takes in the order of 10ms, so saving ~26 exec calls should easily add
to 200-300ms saved from 'go test -short'.
5 years ago
lu4p ea51e78283 Check that all files use LF line endings in CI 5 years ago
pagran 2735555ab2
Update filename and add line number obfuscation (#94)
Fixes  #2.

Line numbers are now obfuscated, via `//line` comments.
Filenames are now obfuscated via `//line` comments, instead of changing the actual filename.
New flag `-tiny` to reduce the binary size, at the cost of reversibility.
5 years ago