Open HalosGhost opened 8 years ago
Hm, what is kernel.grsecurity.harden_ptrace? Alternatively if you run it as root, does it work?
According to the docs that sysctl shouldn't affect ptrace in this case (because the tracee is a child process of the tracer) but Im curious. If it's enabled, does disabling it make the problem go away?
When you run it verbosely, it should give you the child pid. Does that process still exist after the failed write?
What does '.read 0x400000 1' return? (from inside rappel).
I don't have a grsec machine handy at the moment, but will get one spun up after the weekend if we still can't resolve it.
kernel.grsecurity.harden_ptrace
is 1
. Running rappel
as root did not fix the issue. Changing that sysctl value to 0
had no effect. the PIDs appear to be gone afterward (no zombies afaict), and .read 0x400000 1
returned the following: 0x0000000000400000: cc
This seems like a really cool project, so I'll be excited to test it if the issue can be solved.
Hm, can you try a patch for me?
diff --git a/elf_amd64.c b/elf_amd64.c
index 546841c..52ef9f1 100644
--- a/elf_amd64.c
+++ b/elf_amd64.c
@@ -74,7 +74,7 @@ const size_t gen_elf_amd64(
Elf64_Phdr *const phdr = (Elf64_Phdr *) ((uint8_t *) e + sizeof(Elf64_Ehdr));
phdr->p_type = PT_LOAD;
- phdr->p_flags = PF_X | PF_R;
+ phdr->p_flags = PF_X | PF_R | PF_W;
phdr->p_offset = PAGE_SIZE;
phdr->p_vaddr = start - pg_align_dist;
phdr->p_paddr = 0;
that resulted in a hang and an eventual throw of a similar ptrace error. However, a new message shows up in dmesg
as a result (it made PaX angry):
[302058.373172] grsec: denied RWX mmap of /home/halosghost/.rappel/rappel-exec.VuEudR by /home/halosghost/.rappel/rappel-exec.VuEudR[3:20588] uid/euid:1000/1000 gid/egid:1000/1000, parent /home/halosghost/prj/rappel/bin/rappel[rappel:20587] uid/euid:1000/1000 gid/egid:1000/1000
[302058.373271] PAX: execution attempt in: (null), 00000000-00000000 00000000
[302058.373274] PAX: terminating task: (null)(3):20588, uid/euid: 1000/1000, PC: 0000036257e64a37, SP: 000003cbad98a248
[302058.373287] PAX: bytes at PC: ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
[302058.373307] PAX: bytes at SP-8: ???????????????? ???????????????? ???????????????? ???????????????? ???????????????? ???????????????? ???????????????? ???????????????? ???????????????? ???????????????? ????????????????
[302058.373323] grsec: bruteforce prevention initiated for the next 30 minutes or until service restarted, stalling each fork 30 seconds. Please investigate the crash report for /home/halosghost/prj/rappel/bin/rappel[3:20588] uid/euid:1000/1000 gid/egid:1000/1000, parent /home/halosghost/prj/rappel/bin/rappel[rappel:20587] uid/euid:1000/1000 gid/egid:1000/1000
I gave a shot to setting PaX to give rappel
RWX rights, but the same message showed up.
Ok, I think I know whats happening.
Rappel creates an elf runs it, and rewrites it at runtime to include the result of assembled instructions. The text segment of the created elf, by default is read/execute. Normally ptrace can write to read/execute pages, because its ptrace and it doesn't really care what memory protections the tracee thinks it has. You can see some evidence of this -- the ptrace_read() call works, but the ptrace_write() fails. Im guessing this is because PaX hardens memory accesses.
The patch I gave you changed the generated elf to map the text section RWX. My guess is this would remove the ptrace_write() error, but PaX kills it, probably due to MPROTECT.
I'll poke at it it next week in depth and confirm this, but if this is fact the reason I don't see an easy way around it. The benefits MPROTECT provides are solid, and probably outweighs the utility of using rappel.
fwiw you should still be able to use it in pipe mode, right? i.e 'echo "inc rax; inc rax" | rappel' works?
Fair enough! running through a pipe outputs without any ptrace error and does not hang. However, it does not reflect the execution of the instructions passed (e.g., rax
is not incremented at all from the line you mention. It also finishes with the following:
Process died with signal: 9
Exited: 9
Man, I really need to test with grsec. Thanks for the report, and sorry it's been such a hassle. Will let you know when I understand a bit more whats going on.
No worries, and thank you for the help!
So two months later I finally got around to figuring this out. This is controlled by PAX_MPROTECT (https://pax.grsecurity.net/docs/mprotect.txt).
Honestly, having PAX_MPROTECT is probably better than running rappel in interactive mode. Now to figure out why the pipe mode doesn't work...
In any case, thanks a lot for the report. I'll update the readme to indicate that it's not supported under grsec.
Well, PaX is an optional extension, so it'd be unsupported under PaX, not grsec. However, PaX allows configuration to specifically whitelist particular applications. I am happy to do so for rappel, because this is such a cool tool. Rather, I would recommend documenting whitelisting rappel in /etc/paxd.conf
.
When I try to execute any instruction (for example,
inc rax
), I get the following output before the list of registers (which do not change).When executing with
-v
, I get the following:I am wondering if this is because of Grsec's PaX, but if it is, there was nothing registered in
dmesg
as there usually is. Any idea what might be going wrong?