The Witchcraft Compiler Collection
github.com
github.com
There was a live demo of wcc "unlinking" an ELF executable into a portable library that was then linked with and called by another library. Looking forward to where this project goes in the future! He did mention that help expanding this project would be much appreciated, as it takes time to reverse the relocation patterns of various binary formats, so please help out if you find this interesting!
EDIT: Talk outline here provides some nice context https://www.defcon.org/html/defcon-24/dc-24-speakers.html#Br...
If I understand correctly, this is a novel way of speeding up reverse engineering by creating the missing middle step of compiling a binary - object code. Normal decompilers go from machine code to source code, which is difficult to work with. Going from machine code back to object code is not supposed to be easy or even possible. (ELF is only supported right now because reverse-engineering the linking process for different architectures takes a lot of work.)
WCC unlinks machine code into a library, allowing you to interact with the object code and reliably include and call its functions from your own code, as if it were a shared system library rather than a black box.
There's no substantial compiling or decompiling necessary to go from shared object to executable and back. One need only add or remove the appropriate symbols from the object and (perhaps even optionally) change the object type.
Have you ever tried to directly execute your libc.so.6 on a linux system? You can.
There's nothing at all novel about this process, other than making it easy for folks who've never read the manual for their linker.
Edit: Someone downvoted this observation; I imagine they think I'm unfairly trivializing this so I'll add: Read the source code. This tool we're discussing is a simple ~100 line program. It's not complicated: https://github.com/endrazine/wcc/blob/master/src/wld/wld.c
The main issue with that latter part is that 64 bit code can contain 32 bit relocation fixups, and such addresses will be impossible for the linker to relocate outside the 32 bit memory space, and your mileage may vary whether your load time linker will be able to even try to handle that or not on a 64 bit platform.
If your code is free of 32 bit relocations, there "shouldn't" be any reasons for them not to be usable as shared objects even if they contain relocations instead of use PIC (whether any specific load time linkers unnecessarily enforce restrictions on this is another matter).
Shared library is as much of a black box as an executable.
This is not what I'd call an "API dump"; all prototypes return void pointers and allow any arguments.
Hence, it's just as much of a blackbox as the original executable is because you have no idea what the functions do, what arguments they take and what values they return.
Let's build upon the author's example in order to demonstrate the above (imagine for a moment that ls(1) is a third party, unbundled application which clashes with vendor's own ls(1) as delivered with the operating system):
% wcc -c /bin/ls -o /tmp/ls.o
(GCC) % gcc -shared -Wl,-R'$ORIGIN:$ORIGIN/../../lib:$ORIGIN/../../lib:/opt/local/lib' /tmp/ls.o -o /tmp/ls
(Sun Studio) % cc -G -Wl,-R'$ORIGIN:$ORIGIN/../../lib:$ORIGIN/../../lib:/opt/local/lib' /tmp/ls.o -o /tmp/ls
[1] https://docs.oracle.com/cd/E19455-01/817-5431/6mksv3nvi/inde...[2] http://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.html#etc... http://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.html#opt... http://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.html#var...
And the readme.md! I love how the author shows an example after every explanation! If only every readme.md was written that well!
Since shared object libraries must be generated as position independent code, how does converting an executable which was not generated as position independent code work though?
Recently I wrote a Rust library and wrote the header by hand for C. It sounds like this could at least get things started. Though my guess is it would generate the right 'const ' vs. plain '' for pointers.
Is there a better way to do this? Right now the alternative I'm thinking about is creating opening sockets from the Rust and GO side and talking to them via TCP.
But the end result I want is a single binary for the target platform and no install complications other than putting the binary on a stock unix machine.
I'm sure there's a better way.
I wouldn't use wcc for that ever, only for reverse engineering and similar things.
https://golang.org/cmd/go/#hdr-Description_of_build_modes
go build -buildmode=c-archive
or go build -buildmode=c-shared