Initial commit

This commit is contained in:
2024-01-27 21:06:02 +01:00
commit ac937cc86a
8 changed files with 234 additions and 0 deletions

18
Makefile Normal file
View File

@@ -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

61
client.c Normal file
View File

@@ -0,0 +1,61 @@
#include "config.h"
#include "die.h"
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/socket.h>
#include <unistd.h>
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<read_cnt; i++)
fprintf(stderr, "%02x ", buffer[i]);
fprintf(stderr, "\n");
eval(buffer);
return 0;
}

30
compile-blob.sh Executable file
View File

@@ -0,0 +1,30 @@
#!/bin/sh
set -eu
for cmd in ld as clang-format; do
command -v $cmd &>/dev/null || (echo command $cmd not found; exit 1 )
done
if [ "$#" -ne "1" ]; then
printf "Usage: %s <asm file>" $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

6
config.h Normal file
View File

@@ -0,0 +1,6 @@
#pragma once
#define PORT 8080
#define LINEBREAK "\n"
#define BUF_SIZE 1024

19
die.h Normal file
View File

@@ -0,0 +1,19 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#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);
}

22
payload.S Normal file
View File

@@ -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

18
run.sh Executable file
View File

@@ -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

60
server.c Normal file
View File

@@ -0,0 +1,60 @@
#include "config.h"
#include "die.h"
#include "payload_blob.h" // defines binary_data[]
#include <errno.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
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;
}