When running a 100% statically-linked binary (that does not link to the dynamic loader ld-linux-x86-64.so) in shadow, the LD_PRELOAD env variable will be ignored. This means that the shim library that we try to preload and inject will never be initialized, so we won't have a control channel between shadow and the managed process.
We may be able to hack around it by using ptrace upon forking the managed process to inject the shim into the process at init time. We would have a flow like
fork() -> exec() -> ptrace() -> [in child] dlopen("libshim.so") -> ptrace(detach)
From this point, we would rely on seccomp in the shim for function interception (LD_PRELOAD may still be ignored at this point).
Except, because dlopen would not be available, we would have to instead manually mmap some space, open the shim, copy the contents into memory, and call the constructor ourselves.
More information here:
https://stackoverflow.com/questions/24355344/inject-shared-library-into-a-process
(Thanks @rwails!)
When running a 100% statically-linked binary (that does not link to the dynamic loader
ld-linux-x86-64.so) in shadow, theLD_PRELOADenv variable will be ignored. This means that the shim library that we try to preload and inject will never be initialized, so we won't have a control channel between shadow and the managed process.We may be able to hack around it by using
ptraceupon forking the managed process to inject the shim into the process at init time. We would have a flow likefork() -> exec() -> ptrace() -> [in child] dlopen("libshim.so") -> ptrace(detach)From this point, we would rely on
seccompin the shim for function interception (LD_PRELOADmay still be ignored at this point).Except, because
dlopenwould not be available, we would have to instead manually mmap some space, open the shim, copy the contents into memory, and call the constructor ourselves.More information here:
https://stackoverflow.com/questions/24355344/inject-shared-library-into-a-process
(Thanks @rwails!)