Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/link: on Windows, generate dynamic base executables also on amd64 and x86 #27144

Closed
rasky opened this issue Aug 22, 2018 · 26 comments
Closed

Comments

@rasky
Copy link
Member

@rasky rasky commented Aug 22, 2018

As part of windows/arm support, in CL125468 cmd/ld has learnt how to generate dynamic base executables, that is binaries that can be relocated at any virtual memory address. This allows the Windows kernel to turn on ASLR.

The support has been activated only on windows/arm. It should be activated also on amd64 and x86, so that Go binaries on Windows can benefit from ASLR.

/cc @alexbrainman

@ianlancetaylor ianlancetaylor changed the title cmd/ld: on Windows, generate dynamic base executables also on amd64 and x86 cmd/link: on Windows, generate dynamic base executables also on amd64 and x86 Aug 22, 2018
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Aug 22, 2018
@gopherbot
Copy link

@gopherbot gopherbot commented Dec 5, 2018

Change https://golang.org/cl/152759 mentions this issue: cmd/link: include relocs on Windows on all architectures

@capnspacehook
Copy link

@capnspacehook capnspacehook commented Oct 19, 2019

I'm assuming this is still unplanned, and not scheduled for 1.14? Is there anything I could do to help get this merged in, the CL looks very straightforward, I guess just the original submitter of the CL hasn't replied in months?

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Oct 19, 2019

When the trybots were run for the CL mentioned above, the CL failed on Windows systems. Somebody will need to debug that.

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Oct 20, 2019

I'm assuming this is still unplanned, and not scheduled for 1.14? Is there anything I could do to help get this merged in, the CL looks very straightforward, I guess just the original submitter of the CL hasn't replied in months?

I would like this implemented.

And we don't need John to finish his CL. We could create a new CL.

@capnspacehook, why do you want this change? How will you use it?

The only issue is still bothering me. I think this change should be default, not hidden behind "never used during day to day work" flag. Otherwise people will never use this facility.

On the other hand, having Go code always load at the same address is often useful when debugging.

Perhaps we should make this default, and allow for some go command flag to make Go code use fixed addresses. John's CL selected to use -buildmode=pie vs -buildmode=exe to control this. But -buildmode=exe is default on windows now. Should we make -buildmode=pie default on windows? I think it will be confusing to windows users. They don't know what pie is comparing to exe. Ian?

/cc @zx2c4 for input.

Thank you.

Alex

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Oct 20, 2019

Indeed this should be turned on by default. Most debuggers and reverse engineering tools can rebase fine and figure stuff out. Recent versions of IDA Pro do this a lot faster than it used to be too.

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Oct 20, 2019

Indeed this should be turned on by default. Most debuggers and reverse engineering tools can rebase fine and figure stuff out.

I am fine with that, if others do not object.

@ianlancetaylor , if we want to make all Windows executables use random addresses ( https://en.wikipedia.org/wiki/Address_space_layout_randomization ) by default, do we need proposal here?

Thank you.

Alex

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Oct 20, 2019

It doesn't need a proposal, but I'm not sure it's the right thing to do. What do other compilers do? In particular, what do GCC and clang do?

@capnspacehook
Copy link

@capnspacehook capnspacehook commented Oct 22, 2019

@alexbrainman I am really interested in the added security benefits of PIE windows executables; as you mentioned ASLR and inhibiting reverse engineering more.

As for what to do, I agree that PIE mode for Windows executables should be default. But I think using the pie and exe buildmodes would be confusing, maybe buildmode=exe would stay the default when GOOS=windows, but a flag could be introduced that makes binaries load at a fixed address for debugging?

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Oct 22, 2019

@alexbrainman I am really interested in the added security benefits of PIE windows executables; as you mentioned ASLR and inhibiting reverse engineering more.

ASLR, yes. "Inhibiting reverse engineering" - what?

@capnspacehook
Copy link

@capnspacehook capnspacehook commented Oct 22, 2019

Sorry, I just meant ASLR will make reverse engineering a bit more difficult, if I understand correctly. Now that I think about it, I think I got RE mixed up with binary exploitation... my bad

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Oct 25, 2019

What do other compilers do? In particular, what do GCC and clang do?

I do not know about clang. But I tried Mingw GCC C, and Microsoft C and C#.

According to https://stackoverflow.com/questions/8554014/how-to-know-whether-a-dll-uses-aslr-or-not

GCC does not produce ASLR binaries by default:

C:\>dumpbin /headers mingw.exe | sed "/OPTIONAL HEADER VALUES/,+30!d"
OPTIONAL HEADER VALUES
             20B magic # (PE32+)
            2.30 linker version
            1E00 size of code
            3800 size of initialized data
             A00 size of uninitialized data
            14E0 entry point (00000000004014E0)
            1000 base of code
          400000 image base (0000000000400000 to 0000000000411FFF)
            1000 section alignment
             200 file alignment
            4.00 operating system version
            0.00 image version
            5.02 subsystem version
               0 Win32 version
           12000 size of image
             400 size of headers
           1B418 checksum
               3 subsystem (Windows CUI)
               0 DLL characteristics
          200000 size of stack reserve
            1000 size of stack commit
          100000 size of heap reserve
            1000 size of heap commit
               0 loader flags
              10 number of directories
               0 [ 0] RVA [size] of Export Directory
            8000 [ 7C4] RVA [size] of Import Directory
               0 [ 0] RVA [size] of Resource Directory
            5000 [ 27C] RVA [size] of Exception Directory
               0 [ 0] RVA [size] of Certificates Directory

C:\>

But both Microsoft C and C# both generate ASLR by default:

C:\>dumpbin /headers ms_c.exe | sed "/OPTIONAL HEADER VALUES/,+30!d"
OPTIONAL HEADER VALUES
             20B magic # (PE32+)
           14.16 linker version
           13200 size of code
            D200 size of initialized data
               0 size of uninitialized data
            1388 entry point (0000000140001388)
            1000 base of code
       140000000 image base (0000000140000000 to 0000000140023FFF)
            1000 section alignment
             200 file alignment
            6.00 operating system version
            0.00 image version
            6.00 subsystem version
               0 Win32 version
           24000 size of image
             400 size of headers
               0 checksum
               3 subsystem (Windows CUI)
            8160 DLL characteristics
                   High Entropy Virtual Addresses
                   Dynamic base
                   NX compatible
                   Terminal Server Aware
          100000 size of stack reserve
            1000 size of stack commit
          100000 size of heap reserve
            1000 size of heap commit
               0 loader flags
              10 number of directories
               0 [ 0] RVA [size] of Export Directory

C:\>dumpbin /headers ms_csc.exe | sed "/OPTIONAL HEADER VALUES/,+30!d"
OPTIONAL HEADER VALUES
             10B magic # (PE32)
           48.00 linker version
             600 size of code
             800 size of initialized data
               0 size of uninitialized data
            24DE entry point (004024DE)
            2000 base of code
            4000 base of data
          400000 image base (00400000 to 00407FFF)
            2000 section alignment
             200 file alignment
            4.00 operating system version
            0.00 image version
            4.00 subsystem version
               0 Win32 version
            8000 size of image
             200 size of headers
               0 checksum
               3 subsystem (Windows CUI)
            8540 DLL characteristics
                   Dynamic base
                   NX compatible
                   No structured exception handler
                   Terminal Server Aware
          100000 size of stack reserve
            1000 size of stack commit
          100000 size of heap reserve
            1000 size of heap commit
               0 loader flags
              10 number of directories

C:\>

Alex

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Oct 25, 2019

Took a bunch of flags to do it: https://git.zx2c4.com/wireguard-windows/diff/Makefile?id=7b6fcc0184e58626007b581be04ac7f5312861ea Using export-all-symbols is a nasty hack; tor works around it a bit more elegantly: https://gitweb.torproject.org/builders/tor-browser-build.git/tree/projects/binutils/enable-reloc-section-ld.patch I'll see if we can get that added to the musl.cc toolchain. CC @zv-io

The result:

image

@zv-io
Copy link

@zv-io zv-io commented Oct 25, 2019

I rebuilt a few of the musl.cc toolchains with this patch applied on top of the current musl.cc binutils 2.33.1. Please test and confirm this works, and if so, this patch will be included in subsequent releases. I won't be updating this comment when that happens; check the homepage.

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Oct 26, 2019

If GCC doesn't generate PIE by default, it's not obvious to me that go should. Clearly we should make sure that go build -buildmode=pie builds a PIE. But I don't yet see why go build (which for a main package is equivalent to go build -buildmode=exe) should build a PIE.

The question here is not whether PIE is more secure. It's what the default behavior should be.

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Oct 26, 2019

If GCC doesn't generate PIE by default, it's not obvious to me that go should.

I don't think you should dismiss the fact that Microsoft compilers do generate PIE by default. Most Windows executables are built by Microsoft tools.

Clearly we should make sure that go build -buildmode=pie builds a PIE.

Sure, we could do that. But I don't see why Go developers would use this command option. ASLR is supposed to help make Windows more secure. Developers don't care about their users OS security. It is OS admin responsibility to make system secure. Developers will use whatever default build mode is.

Also current windows-arm version of Go already uses PIE by default

https://go-review.googlesource.com/c/go/+/125648

I think our current go command flags are just confusing in that area.

Alex

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Oct 26, 2019

The question here is not whether PIE is more secure. It's what the default behavior should be.

I can't see a compelling reason at all not to produce PIE executables for all Go users, vanilla and cgo, as the default option. Sure we can have a switch to disable PIE for the weird cases where people don't want it, but as @alexbrainman points out, PIE (and DEP, for that matter) is the default situation on Windows since a very long time. Differing from that and providing a less secure experience with Go out of the box is bad news. The fact that Go was producing 90s-style executables by default certainly caught me by surprise.

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Oct 26, 2019

Alright, WireGuard for Windows 0.0.35, just now released to users, enables DEP and high-entropy ASLR, on both amd64 and 386. I'll report back if anybody indicates awful breakage -- the largeish userbase is usually pretty reactive. I suspect things will be mostly okay.

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Oct 26, 2019

@alexbrainman Fair enough.

Does anybody think it would be a bad idea to change the default to be PIE on Windows?

Does anybody have a suggestion as to how it should work? Would we keep the current -buildmode options and change the default for a main package to be -buildmode=pie, while -buildmode=exe would continue to build a non-PIE?

@ianlancetaylor
Copy link
Contributor

@ianlancetaylor ianlancetaylor commented Oct 26, 2019

Probably the question of the default should be a separate issue.

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Oct 26, 2019

ARM does it unconditionally. What if we just did it that way?

Or do you think providing the option is important?

@gopherbot
Copy link

@gopherbot gopherbot commented Oct 26, 2019

Change https://golang.org/cl/203602 mentions this issue: cmd/link: enable ASLR on Windows executables

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Oct 27, 2019

Does anybody think it would be a bad idea to change the default to be PIE on Windows?

I think we should create new proposal for that, and see what happens.

The only downside I see, we might discover some bugs.

Does anybody have a suggestion as to how it should work? Would we keep the current -buildmode options and change the default for a main package to be -buildmode=pie, while -buildmode=exe would continue to build a non-PIE?

That sounds good to me. As long as -buildmode=pie is the default, and users don't need to type it, I think we will be alright.

ARM does it unconditionally. What if we just did it that way?

Or do you think providing the option is important?

I have an impression that we don't have choice for ARM.

And I think it is important, that we have easy way to disable ASLR if required. I would use that myself while debugging. And, if we follow Ian's suggestion, it is just -buildmode=exe option away.

Alex

@capnspacehook
Copy link

@capnspacehook capnspacehook commented Oct 27, 2019

AFAIK, Windows ARM bins have to be relocatable. And I think Ian's suggestion makes a lot of sense

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Oct 27, 2019

Probably the question of the default should be a separate issue.

Done: #35192

@zx2c4
Copy link
Contributor

@zx2c4 zx2c4 commented Oct 27, 2019

Change https://golang.org/cl/203602 mentions this issue: cmd/link: enable ASLR on Windows executables

This CL is now called "cmd/link: allow ASLR on Windows executables", and I've moved the default stuff to https://go-review.googlesource.com/c/go/+/203606 for discussion in #35192 .

@gopherbot
Copy link

@gopherbot gopherbot commented Jan 11, 2020

Change https://golang.org/cl/214397 mentions this issue: cmd/go, cmd/link: implement -buildmode=pie on windows

@gopherbot gopherbot closed this in 95f3821 Mar 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants
You can’t perform that action at this time.