0

I made a small elf64 packer which tricks a PT_NOTE segment into a PT_LOAD, injects a shellcode into a .note section (renaming it .woody), and set the executable entrypoint at my shellcode address.

If my shellcode is [0xeb, 0xfe] (jmp $), the packed program will loop when executed, which is fine. The problem comes when I try to jump from my shellcode to the original entrypoint (oep).

I tried several ways to jump there:

push 0xFFFFFFFF
ret
jmp 0xFFFFFFFF

And some others (replacing 0xFFFFFFFF with oep of course). But each time I run the packed executable, I get a Segfault on 'unknown address'. This 'unknown address' is exactly the address where I want to go.

Here's a dump of my added section:

Disassembly of section .woody:

000000000c001000 <.woody>:
 c001000:   68 20 11 00 00          pushq  $0x1120
 c001005:   c3                      retq

The beginning of the .text section's dump:

Disassembly of section .text:

0000000000001120 <_start>:
    1120:   f3 0f 1e fa             endbr64 
    1124:   31 ed                   xor    %ebp,%ebp
    1126:   49 89 d1                mov    %rdx,%r9
    1129:   5e                      pop    %rsi
    112a:   48 89 e2                mov    %rsp,%rdx
    112d:   48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
    1131:   50                      push   %rax
    1132:   54                      push   %rsp
    1133:   4c 8d 05 f6 01 00 00    lea    0x1f6(%rip),%r8        # 1330 <__libc_csu_fini>
    113a:   48 8d 0d 7f 01 00 00    lea    0x17f(%rip),%rcx        # 12c0 <__libc_csu_init>
    1141:   48 8d 3d c1 00 00 00    lea    0xc1(%rip),%rdi        # 1209 <main>
    1148:   ff 15 92 2e 00 00       callq  *0x2e92(%rip)        # 3fe0 <__libc_start_main@GLIBC_2.2.5>
    114e:   f4                      hlt    
    114f:   90                      nop

And the crash I get:

==2814370==ERROR: AddressSanitizer: SEGV on unknown address 0x000000001120 (pc 0x000000001120 bp 0x000000000000 sp 0x7fff206323e0 T0)
==2814370==The signal is caused by a READ memory access.
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer: nested bug in the same thread, aborting.

I can't figure out why I can't execute the original code, the text section is loaded, readable, executable. I have several hints but can't find informations about them:

  • Maybe I can't jump to an instruction endbr64 (security?)
  • Maybe I can't jump from a segment to another, but I don't think so...

Any help would be very appreciated!

lfalkau
  • 896
  • 7
  • 21
  • 1
    Use a proper debugger. Verify mappings in that debugger. Note your address is `0x1120` which sounds like it is a PIE offset not an actual virtual memory address. – Jester Jul 25 '21 at 17:41
  • It works with an executable compiled with `-no-pie`, so I guess you're right, but is there a way to jump to the 'real' virtual memory of oep for a pie executable? – lfalkau Jul 25 '21 at 17:56
  • You claim you tried the simple `jmp`. That should have worked as that is a relative jump. Assuming you calculated the offset correctly :) – Jester Jul 25 '21 at 18:01
  • Actually, I succeed with a `push`/`ret` with -no-pie, not wit `jmp`, I thought `jmp` was absolute... But is it even possible to compute an offset between two sections if the executable is relocatable? – lfalkau Jul 25 '21 at 18:13
  • 3
    Yes, the offsets should be constant. – Jester Jul 25 '21 at 18:42
  • 1
    RIP-relative addressing depends on the fact that the distance between `.text` and `.data` is a link-time constant. ASLR introduces *one* free parameter, the base of the whole thing, not a separate random base for each section. [Why are global variables in x86-64 accessed relative to the instruction pointer?](https://stackoverflow.com/q/56262889) – Peter Cordes Jul 25 '21 at 20:12

0 Answers0