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.
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.
@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
Brilliant. Great job. Have I reached 20 characters yet?
Wow, after an insane amount of research and coming back to this post I can finally make sense out of it. Brilliant post @0x00pf!
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.
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
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
very interesting article, thank you !
This topic was automatically closed after 30 days. New replies are no longer allowed.