Open rkervella opened 2 years ago
I have an in memory executable loader for Mac OS that might be useful. See: https://github.com/usiegl00/tamatoa I can re-write it in go if you'd like.
I'd love to see an implementation of this in Go. I'm currently using https://github.com/binject/universal to load dylibs, but there's still issues I need to sort out as most of the time the host process (sliver implant) crashes.
My experiments are here if you want to have a look.
Binject universal is using the same technique to load dylibs as tamatoa. You should be able to load machos by just modifying the header. This is how metasploit does it: https://github.com/rapid7/metasploit-framework/blob/4c0133d26d8007678b311d0dd82fa0c125347e4f/external/source/shellcode/osx/stager/main.c#L106
Yes I mean we can load MachO, that's not the issue. The issue is keeping the implant alive. Memory allocated on the heap by the loaded dylibs are garbage collected by the Go runtime afterwards, which makes it crash because it doesn't recognize the layout of the GC'ed object.
Is there a way to pause the GC for a set amount of time? (i.e. SetGCPercent(-1) then SetGCPercent(100)) See: https://pkg.go.dev/runtime/debug#SetGCPercent If not, can we call pthread_create to execute the dylib in a new thread?
Disabling GC for the entire process is not a tenable solution.
Disabling GC for the entire process is not a tenable solution.
Agreed with @moloch-- , I'd like to find a solution that doesn't rely on these quirks if possible. Calling pthread_create
could be an idea indeed, I'd need to look into it.
Another option would be to call fork
before running and then use a shared memory location to get the output.
Made some progress on the MacOS front by fixing universal's behavior for MacOS 12 and up, thanks to @usiegl00 's PR to metasploit. Once this PR is merged, we'll be able to use universal to load dylibs. It doesn't resolve the issues I had with heap interactions, but the side effect is we can load CGO compiled dylibs, which should allow us to do all we want in Go / CGO.
We can probably even use this technique to pass a callback function to the extension code.
Do you guys have any plans of implementing this any time soon? The PR to load dylibs should looks like it's been merged. I have some nice cross-platform extensions ready written in Rust (shameless blog promo on how to write them), would be nice to use in Linux implants as I've been using them quite a bit as of late :)
Do you guys have any plans of implementing this any time soon? The PR to load dylibs should looks like it's been merged. I have some nice cross-platform extensions ready written in Rust (shameless blog promo on how to write them), would be nice to use in Linux implants as I've been using them quite a bit as of late :)
There is a work in progress to use purego to load shared libraries on Linux and MacOS, I don't have an ETA on merging that though. The current issue is puregoz doesn't seem to work with garble right now, so there's a tradeoff. Also, specifically on Linux, this would mean dropping the shared library in a memory file descriptor and then load it. But that's all still work in progress (check here if you want to play with it).
On another note, I've started working on the sliver-sdk to facilitate writing extensions. Right now we have template for Go and Rust, but the idea is to add more.
Make extensions work for MacOS.