System Call & Shellcode

tags: Security PWN

Online Resources

exsited shellcode

System call

table

Shellcode

Manual

Assembly

amd64 Write

global _start

section .text
_start:
    xor rax, rax
    xor rbx, rbx
    xor rcx, rcx
    xor rdx, rdx
    jmp str
    
write:
    mov rax, 1
    inc rdi
    pop rsi
    mov rdx, 12
    syscall
    
    mov rax,60
    syscall
    
str:
    call write
    db 'Hello world', 0
nasm -f elf64 -o main.o main.asm
ld -m elf_x86_64 main.o -o main

i386 ORW

; main.asm
global _start
_start:
    ;open("/etc/passwd", 0);
    ;hex(u32(b"/etc")) => 0x6374652f
    ;Put the system call sys_open() number 5, in the EAX register.
    ;Put the filename in the EBX register.
    ;Put the file access mode in the ECX register.
    ;Access mode : read-only (0), write-only (1), and read-write (2).
    ;Put the file permissions in the EDX register.
    push 0x00647773 
    push 0x7361702f 
    push 0x6374652f 
    mov ebx, esp
    mov ecx, 0
    mov edx, 0
    mov eax, 5
    int 0x80
    ;The system call returns the file descriptor of the created file in the EAX register, in case of error, the error code is in the EAX register.


    ; read(fd, buf, sizeof(buf));
    ; Put the system call sys_read() number 3, in the EAX register.
    ; Put the file descriptor in the EBX register.
    ; Put the pointer to the input buffer in the ECX register.
    ; Put the buffer size, i.e., the number of bytes to read, in the EDX register.
    mov ebx, eax
    mov ecx, esp
    mov edx, 10000
    mov eax, 3
    int 0x80
    ; The system call returns the number of bytes read in the EAX register, in case of error, the error code is in the EAX register.


    ; write(1, buf, len);
    ; Put the system call sys_write() number 4, in the EAX register.
    ; Put the file descriptor in the EBX register.
    ; Put the pointer to the output buffer in the ECX register.
    ; Put the buffer size, i.e., the number of bytes to write, in the EDX register.
    
    mov ebx, 1      ; File descriptor for standard output
    mov ecx, esp
    mov edx, eax
    mov eax, 4
    int 0x80
    ; The system call returns the actual number of bytes written in the EAX register, in case of error, the error code is in the EAX register.

    ; ==> exit(0);
    mov eax, 1
    mov ebx, 0
    int 0x80
$ nasm -f elf32 -o main.o main.asm
$ yasm -f elf32 -o main.o main.asm
$ ld -m elf_i386 -o main main.o

create shellcode

pwntools

from pwn import *

context.arch = "amd64"
context.os = "linux"
context.log_level = "DEBUG"

shellcode_asm = """
push 0x00647773 
push 0x7361702f 
push 0x6374652f 
mov ebx, esp
mov ecx, 0
mov edx, 0
mov eax, 5
int 0x80

mov ebx, eax
mov ecx, esp
mov edx, 10000
mov eax, 3
int 0x80

mov ebx, 1
mov ecx, esp
mov edx, eax
mov eax, 4
int 0x80

mov eax, 1
mov ebx, 0
int 0x80
"""
log.info(asm(shellcode_asm))

output

[DEBUG] cpp -C -nostdinc -undef -P -I/usr/local/lib/python3.7/dist-packages/pwnlib/data/includes /dev/stdin
[DEBUG] Assembling
    .section .shellcode,"awx"
    .global _start
    .global __start
    _start:
    __start:
    .intel_syntax noprefix
    push 0x00647773
    push 0x7361702f
    push 0x6374652f
    mov ebx, esp
    mov ecx, 0
    mov edx, 0
    mov eax, 5
    int 0x80
    mov ebx, eax
    mov ecx, esp
    mov edx, 10000
    mov eax, 3
    int 0x80
    mov ebx, 1
    mov ecx, esp
    mov edx, eax
    mov eax, 4
    int 0x80
    mov eax, 1
    mov ebx, 0
    int 0x80
[DEBUG] /usr/bin/x86_64-linux-gnu-as -64 -o /tmp/pwn-asm-q7affql_/step2 /tmp/pwn-asm-q7affql_/step1
[DEBUG] /usr/bin/x86_64-linux-gnu-objcopy -j .shellcode -Obinary /tmp/pwn-asm-q7affql_/step3 /tmp/pwn-asm-q7affql_/step4
[*] b"hswd\x00h/pash/etc\x89\xe3\xb9\x00\x00\x00\x00\xba\x00\x00\x00\x00\xb8\x05\x00\x00\x00\xcd\x80\x89\xc3\x89\xe1\xba\x10'\x00\x00\xb8\x03\x00\x00\x00\xcd\x80\xbb\x01\x00\x00\x00\x89\xe1\x89\xc2\xb8\x04\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80"
from pwn import *

context.update(arch='i386', os='linux')
code = '''
    push 0x61616161
    mov eax, 4
    mov ebx, 1
    mov ecx, esp
    mov edx, 4
    int 0x80
    mov eax, 1
    mov ebx, 0
    int 0x80'''
print(repr(asm(code)))

test shellcode

char *ptr = "haaaa\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\x89\xe1\xba\x04\x00\x00\x00\xcd\x80\xb8\x01\x00\x00\x00\xbb\x00\x00\x00\x00\xcd\x80";
int main() {
    void (*f)() = (void (*)()) ptr;
    f();
    return 0;
}
gcc -m32 test_shellcode.c  -o shell -z execstack

msfvenom

Metasploit note

Windows shellcode

Basics of Windows shellcode writing