What about Linux? Why all the love for Windows? What is this crap?
The code for linux is a bit different in MSF. They use a modified ELF template that puts the shellcode directly into the end of the file which is built by nasm. Example:
; build with: ; nasm elf_x86_template.s -f bin -o template_x86_linux.bin BITS 32 org 0x08048000 ehdr: ; Elf32_Ehdr db 0x7F, "ELF", 1, 1, 1, 0 ; e_ident db 0, 0, 0, 0, 0, 0, 0, 0 ; dw 2 ; e_type = ET_EXEC for an executable dw 3 ; e_machine dd 1 ; e_version dd _start ; e_entry dd phdr - $ ; e_phoff dd 0 ; e_shoff dd 0 ; e_flags dw ehdrsize ; e_ehsize dw phdrsize ; e_phentsize dw 1 ; e_phnum dw 0 ; e_shentsize dw 0 ; e_shnum dw 0 ; e_shstrndx ehdrsize equ $ - ehdr phdr: ; Elf32_Phdr dd 1 ; p_type = PT_LOAD dd 0 ; p_offset dd $ ; p_vaddr dd $ ; p_paddr dd 0xDEADBEEF ; p_filesz dd 0xDEADBEEF ; p_memsz dd 7 ; p_flags = rwx dd 0x1000 ; p_align phdrsize equ $ - phdr global _start _start: ; MSF puts the shellcode here
We would have to generate a new elf template file each time with our date check called prior to shellcode execution. From there, we would have to call our system call functions. Modification of this code however isn’t going very well. Metasploit uses a core class for setting these elf files and modifying the entire thing just to fit this one feature is…hard to say the least. I had considered first writing my stuff in C, then assembly, but this can all be made simpler in Linux with syscalls. The following code piece does the same as we did with windows, except its much smaller / easier to implement. Before we show off the assemblers, let’s go over syscalls. Everything in Linux is done via syscalls – everything from opening files to resetting the computer. Think of them as like interrupts for DOS (god I am OLD). As per the Linux man pages: “The system call is the fundamental interface between an application and the Linux kernel.”. Any time a program has to do anything special like read a read or write a file, or fork a new process, a syscall is made. Each architecture on linux will have the same system call table. You can find the syscall table for each architecture on github or the net. I used this one for x64 intel. For x86, I used the table here. The sys_time system call is used for obtaining the Unix epoch which is the number of seconds elapsed since 1970. An example would be 1545094801 in decimal or 0x5C184691 in hex. This result is stored in a register EAX on x86 or RAX on x64 intel. Our code calls his syscall and compares it against the time we have stored which is supposed to be one months from now or plus an additional 2592000 seconds. Finally we have an old assembly friend for crashing – EB FE – jump two bytes backward from the current position while also moving two spaces forward. An infinite loop in two instructions. And now without further ado, the code:
section .text global _start _start: ; use syscall for epoch, compare it 30 days in future, check if older, crash ;------------------------------------------------------------------------------ mov al,0x0D ;sys_time is 13 vvvv current epoch plus one month int 0x80 ; only x64 uses syscall instruction, use int 0x80 instead mov ebx, 0x58D15D5F cmp eax, ebx jge rockit mov al, 1 ;exit int 0x80 rockit: db 0xEB db 0xFE
All in all, I have the thing down to 18 bytes with no null bytes.
char *scode = "\xb0\x0d\xcd\x80\xbb\x5f\x5d\xd1\x58\x39\xd8\x7d\x04\xb0\x01\xcd\x80\xeb\xfe";
Here I have the same thing except with x64 code. Not much is different other than the use of the mnemonic ‘syscall’ instead of ‘int 0x80’ and the number of the syscall.
section .text global _start _start: ; use syscall for epoch, compare it 30 days in future, check if older, crash ;------------------------------------------------------------------------------ mov al,0xc9 ;sys_time 201 vvvv current epoch plus one month syscall mov ebx, 0x58D15D5F cmp eax, ebx jge rockit mov al, 1 ;exit syscall rockit: db 0xEB db 0xFE
And here we have our shellcode again:
char scoder* = "\xb0\x0d\xcd\x80\xbb\x5f\x5d\xd1\x58\x39\xd8\x7d\x04\xb0\x01\xcd\x80\xeb\xfe";
Someone once asked me how the heck do you code assembly without the nulls and I said “use the smaller registers so there is no padding”. I could spend a whole blog post on that alone.
So how the hell do we take this and implement it in metasploit? We could always modify the template files by adding our check to the bottom just below ‘start’, and that would work for all files, but it would have to be done for EVERY SINGLE TEMPLATE, so its becomes a pain in the ass. Then someone (HD Moore) told me about the ‘PrependEncoder‘ option present in Metasploit when writing exploits.
Basically it allows us to prepend shellcode to the payload that is executed first. In this case, we are adjusting the size of the stack, but it doesn’t have to be that. Why not add our date check there instead? “\xb0\x0d\xcd\x80\xbb\x5f\x5d\xd1\x58\x39\xd8\x7d\x04\xb0\x01\xcd\x80\xeb\xfe”; would fit great right there.
This is basically where I am at with this. I need to figure out how to programmatically add my code via command line argument to new exploits and payloads. And before you ask, I did think about how I would dynamically add the epoch in hex to the assembly in ruby:
My commit is presently in limbo while I try and figure out how to make use of the PrependEncoder option programmatically so until then, this technique is in my posession and not the world’s.
Until next time, happy hacking!