Skip to content

Fail to execute #2

Description

@HalosGhost

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).

ptrace() - failed to write value 0xccccccccccc0ff48 to 0x0000000000400000

When executing with -v, I get the following:

Trying to assemble(8):
inc rax
@nasm is pid 6057
Process 6057 has exited with status 0
Got asm(3):
48 ff c0                                                H..
ptrace_write: 0x0000000000400000 = 0xccccccccccc0ff48
ptrace() - failed to write value 0xccccccccccc0ff48 to 0x0000000000400000

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?

Activity

  1. yrp604 commented on Mar 5, 2016

    @yrp604
    Owner

    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.

  2. HalosGhost commented on Mar 5, 2016

    @HalosGhost
    Author

    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.

  3. yrp604 commented on Mar 5, 2016

    @yrp604
    Owner

    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;
    
  4. HalosGhost commented on Mar 5, 2016

    @HalosGhost
    Author

    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.

  5. yrp604 commented on Mar 5, 2016

    @yrp604
    Owner

    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?

  6. HalosGhost commented on Mar 5, 2016

    @HalosGhost
    Author

    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
    
  7. yrp604 commented on Mar 5, 2016

    @yrp604
    Owner

    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.

  8. HalosGhost commented on Mar 5, 2016

    @HalosGhost
    Author

    No worries, and thank you for the help!

  9. yrp604 commented on May 3, 2016

    @yrp604
    Owner

    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.

  10. HalosGhost commented on May 3, 2016

    @HalosGhost
    Author

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions