-
Notifications
You must be signed in to change notification settings - Fork 17.7k
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
ObjFile on stripped binaries #42954
Comments
Could you clarify what the problem is?
What is "the objfile tool"?
That Could you clarify what program/command you run that you see unexpected result? Thanks. |
Sure, sorry my wording wasn't exact. The issue is this:
The binary in question has its .symtab section zeroed out (sometimes this is referred to as stripping symbols): The reason this matters is because internally the objfile package attempts to resolve the pclntab by using this .symtab section: go/src/cmd/internal/objfile/objfile.go Line 148 in 2d0258d
which calls (for PE's) go/src/cmd/internal/objfile/pe.go Lines 111 to 119 in 2d0258d
That symbol resolution fails, and therefore no golang symbols are parsed and the objdump tool faults. This is a poor failure case though as the pclntab section is (usually) still there! It can be located by performing a bytescan over the .text section for the magic pclntab magic. When this byte scan is done the objdump tool is able to work perfectly fine even on binaries where symbols are stripped like this. |
The patch is fairly simple, in objfile.go PCLineTable():
As an aside, if the members of the LineTable: Lines 40 to 69 in 89f687d
and the symtab Table: Line 127 in 89f687d
could be capitalized to be exported I would appreciate it! I use this for some internal security tooling and have to maintain a set of patches to export these internal details. |
How exactly was your symbol table stripped? Can you show us the exact commands you used starting with building your binary? I'm not a fan of finding sections by looking for magic numbers. Magic numbers are useful if you know where they are and are just verifying them (e.g. at the start of file), but looking for them among a large corpus has a serious false positive problem. For example, the instruction sequence:
Has one of your magic sequences in it. |
I work in security and often deal with malicious samples that are stripped by bad actors, this isn't a process i do. However you can generate a binary without symbols via: A future version of go could be really nice if it added a magic for the moduledata structure too :) |
Still need an answer to this.
Works fine for me (darwin/amd64, go1.13.6):
Why use |
On ELF, we look for ".gosymtab" section (NOT ".symtab"), instead of "runtime.symtab" symbol ( https://tip.golang.org/src/cmd/internal/objfile/elf.go#L67 ). Can we do the same for PE? I also don't think that looking for magic numbers are the right answer here. |
@randall77 I am on windows/linux but it's kind of irrelevant here as the symbol table (.gosymtab, .symtab, whatever) can be stripped and the pclntab still be present. This issue highlights that the symbol table (.gosymtab, .symtab, whatever) is used to locate the .pclntab section which can fail. This failure to locate the pclntab doesn't mean it isn't there however, and we can find it to still make objdump useful.
I specifically care about getting the pclntab metadata here as it gives function names and start/stop boundaries.
as a reverse engineer it is incredibly easily to tell by just looking at the assembly patterns in IDA PRO there's at least two unhandled failure cases:
Now, the symbol table being corrupt/stomped doesn't matter as the pclntab is independent of that. |
Please don't confuse ".gosymtab" and ".symtab". They are always two different sections, on any platform (PE/ELF/Mach-O/etc.). What strip tool do you use? I don't think it should strip ".gosymtab" section on any platform. (However, the section should be empty anyway.) "runtime.symtab" is a symbol, which should be at the beginning of the ".gosymtab" section. Please be careful with the names. Thanks. |
It's very relevant. Now that I know "windows", I can reproduce:
|
@cherrymui I am simply using the linker flags i specified earlier. I am sorry if I am not using the correct terms, I am referring to .gosymtab as a section for linux elf, and .symtab as a section for PE. These are what i refer to as the symbol tab as it seems GO uses them to store symbols inside of (such as to locate runtime.pclntab) @randall77 same happens for linux but it fails finding the symbol table entirely:
|
I don't think I understand the motivation for fixing this at all. For the Go project generally, that is. The fact that they are a malicious user is unfortunate, but not IMO enough motivation to have our general-purpose tools sidestep someone's attempt to remove symbolic information. |
(It might be better to have |
They should not be the same section. They should serve completely different purpose. If they are, it seems a bug in the linker.
What I'm proposing is that we should not try to locate runtime.pclntab at all. We should put the pclntab in a separate section and locate that section instead, which we do for ELF and Mach-O. |
Agreed. This seems what the system |
@randall77 fair enough, i think any tool should try as hard as possible before it fails, but that's not a philosophical direction i control. There's a real bug in the linux case though i think as the .gosymtab section being present or not is irrelevant (and it errors early) The windows case is a bit trickier, @cherrymui your suggestion of going to a section based discovery vs a symbol based discovery I like personally. It avoids this co-dependancy of symbols <-> pclntab and also bring the windows file format inline with what linux and macho do |
Closing as it's been shown there's no interest in resolving this. Hopefully this serves as documentation to some future person though. ✌️ |
On GO binaries with stripped .symtab sections the objfile tool fails to located the pclntab and fails to print embedded symbols. The table can still be found however by byte scanning the .text section of the binary for the header magic for the table:
go/src/debug/gosym/pclntab.go
Lines 169 to 170 in 89f687d
The gosym NewTable method does not require the .symtab section to correctly parse the pclntab table and is still useful for this case of stripped binaries. It may simply be passed an empty byte array as it's first argument:
go/src/cmd/internal/objfile/objfile.go
Line 152 in 2d0258d
I propose that a simple byte scan be added in objfile.go if the .pcln() method fails to locate the table by the standard symbols lookup. By falling back to byte scanning the tool can still print much useful information.
The text was updated successfully, but these errors were encountered: