From ac937cc86a4603479e9c4f0bcfd0ecfd5e72c209 Mon Sep 17 00:00:00 2001 From: Ole Kristian Morud Date: Sat, 27 Jan 2024 21:06:02 +0100 Subject: [PATCH] Initial commit --- Makefile | 18 +++++++++++++++ client.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ compile-blob.sh | 30 ++++++++++++++++++++++++ config.h | 6 +++++ die.h | 19 +++++++++++++++ payload.S | 22 ++++++++++++++++++ run.sh | 18 +++++++++++++++ server.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 234 insertions(+) create mode 100644 Makefile create mode 100644 client.c create mode 100755 compile-blob.sh create mode 100644 config.h create mode 100644 die.h create mode 100644 payload.S create mode 100755 run.sh create mode 100644 server.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..1868e18 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ + +CC = gcc +CFLAGS = -ggdb -O0 -Wall -Wextra -Wno-unused-value + +all : client server + +client : client.c + +server : server.c | payload_blob.h + +%_blob.h : %.S | compile-blob.sh + ./compile-blob.sh $< > $@ + +.PHONY = clean +clean : + rm client server *_blob.h 2>/dev/null || true + + diff --git a/client.c b/client.c new file mode 100644 index 0000000..69fa4b1 --- /dev/null +++ b/client.c @@ -0,0 +1,61 @@ + +#include "config.h" +#include "die.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +static inline int eval(unsigned char* code) +{ + long size = sysconf(_SC_PAGESIZE); + void* start = (void *)((unsigned long)code & ~(size - 1)); + int ok = mprotect(start, size, PROT_READ | PROT_WRITE | PROT_EXEC); + if (ok == -1) die("mprotect");; + + return ((int(*)())code)(); +} + +int main(int argc, char** argv) +{ + struct sockaddr_in serv_addr; + unsigned char buffer[BUF_SIZE] = {0}; + int ok; + char *request = "GET / HTTP/1.1" LINEBREAK + "Host: localhost" LINEBREAK LINEBREAK; + + int sock = socket(AF_INET, SOCK_STREAM, 0); + if (sock == -1) die("socket"); + + serv_addr.sin_family = AF_INET; + serv_addr.sin_port = htons(argc == 3 ? atoi(argv[2]) : PORT); + + ok = inet_pton(AF_INET, argc > 1 ? argv[1] : "127.0.0.1", &serv_addr.sin_addr); + if (ok == -1) die("inet_pton"); + + ok = connect(sock, (struct sockaddr *)&serv_addr, sizeof serv_addr); + if (ok == -1) die("connect"); + + ok = send(sock, request, strlen(request), 0); + if (ok == -1) die("send"); + + ssize_t read_cnt = read(sock, buffer, BUF_SIZE); + if (read_cnt == -1) die("read"); + + ok = close(sock); + if (ok == -1) die("close"); + + for (ssize_t i=0; i/dev/null || (echo command $cmd not found; exit 1 ) +done + +if [ "$#" -ne "1" ]; then + printf "Usage: %s " $0 >/dev/stderr + exit 1 +fi + +as_output=$(mktemp) +ld_output=$(mktemp) +cleanup() { + rm $as_output + rm $ld_output +} +trap cleanup EXIT + +as $1 -o $as_output +ld --oformat binary $as_output -o $ld_output + +( + echo '#pragma once' + echo 'static const unsigned char binary_data[] = {' + tail $ld_output -c +4097 | hexdump -v --format='"" 1/1 "0x%02x,"' + echo '};' +) | clang-format diff --git a/config.h b/config.h new file mode 100644 index 0000000..208313c --- /dev/null +++ b/config.h @@ -0,0 +1,6 @@ + +#pragma once + +#define PORT 8080 +#define LINEBREAK "\n" +#define BUF_SIZE 1024 diff --git a/die.h b/die.h new file mode 100644 index 0000000..57f4e39 --- /dev/null +++ b/die.h @@ -0,0 +1,19 @@ + +#pragma once + +#include +#include +#include + +#define die(msg) die_(msg, __func__, __LINE__) +static int die_(const char* msg, const char* function, int line) +{ + fprintf(stderr, msg); + if (errno) { + perror(" "); + } + fprintf(stderr, "line: %d\n", line); + fprintf(stderr, "function: %s\n", function); + fprintf(stderr, "errno: %d\n", errno); + exit(EXIT_FAILURE); +} diff --git a/payload.S b/payload.S new file mode 100644 index 0000000..8e0a70f --- /dev/null +++ b/payload.S @@ -0,0 +1,22 @@ +.section .text +.globl _start +_start: + pushq %rbp + movq %rsp, %rbp + movabsq $8031924123371070824, %rax + movq %rax, -45(%rbp) + movl $560229490, -37(%rbp) + movb $0, -33(%rbp) + movl $1, -4(%rbp) + leaq -45(%rbp), %rax + movq %rax, -16(%rbp) + movq $13, -24(%rbp) + movl $1, %eax + movl -4(%rbp), %edi + movq -16(%rbp), %rsi + movq -24(%rbp), %rdx + syscall + movq %rax, -32(%rbp) + movl $0, %eax + popq %rbp + ret diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..59ed14a --- /dev/null +++ b/run.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -eu + +make -B + +./server & +sleep 0.01 +server_pid=$! + +if [ "$#" -gt 0 ]; then + gdb client +else + ./client +fi + +kill $server_pid + diff --git a/server.c b/server.c new file mode 100644 index 0000000..fefab42 --- /dev/null +++ b/server.c @@ -0,0 +1,60 @@ + +#include "config.h" +#include "die.h" +#include "payload_blob.h" // defines binary_data[] + +#include +#include +#include +#include +#include +#include +#include + +int main() +{ + int new_socket; + struct sockaddr_in address; + int addrlen = sizeof(address); + char buffer[BUF_SIZE] = {0}; + + // Creating socket file descriptor + int server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (server_fd == -1) + die("socket failed");; + + // Forcefully attaching socket to the port 8080 + int opt = 1; + int ok = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, + &opt, sizeof opt); + if (ok == -1) die("setsockopt");; + + address.sin_family = AF_INET; + address.sin_addr.s_addr = INADDR_ANY; + address.sin_port = htons(PORT); + + bind(server_fd, (struct sockaddr *)&address, sizeof(address)); + if (ok == -1) die("bind failed"); + + ok = listen(server_fd, 3); + if (ok == -1) die("listen"); + + while (1) { + ssize_t n; + new_socket = accept(server_fd, (struct sockaddr*)&address, + (socklen_t*)&addrlen); + if (new_socket == -1) die("accept"); + + n = read(new_socket, buffer, BUF_SIZE); + if (n == -1) die("read"); + + n = write(new_socket, binary_data, sizeof binary_data); + if (n == -1) die("write"); + + ok = close(new_socket); + if (ok == -1) die("close"); + } + + return EXIT_SUCCESS; +} +