stabbish

:)
git clone https://git.sr.ht/~ashymad/stabbish
Log | Files | Refs | README | LICENSE

commit 5ef5abcd0c2983d10ea677a551381c7e12ab30da
parent 44205c07bf99aac643e5cc740af808a60a59ce8f
Author: Szymon Mikulicz <szymon.mikulicz@posteo.net>
Date:   Tue,  7 Jul 2026 14:46:55 +0200

Header separation

Diffstat:
Msrc/Makefile | 10+++++++---
Asrc/magic.c | 26++++++++++++++++++++++++++
Msrc/magic.h | 24++----------------------
Asrc/payload.c | 35+++++++++++++++++++++++++++++++++++
Msrc/payload.h | 31+------------------------------
Asrc/utils.c | 47+++++++++++++++++++++++++++++++++++++++++++++++
Msrc/utils.h | 48+++---------------------------------------------
7 files changed, 121 insertions(+), 100 deletions(-)

diff --git a/src/Makefile b/src/Makefile @@ -4,11 +4,15 @@ include ../Makefile .PHONY: clean .DEFAULT_GOAL := stabbish -stabbish: main.o busybox/busybox.inc.o +stabbish: main.o payload.o magic.o utils.o busybox/busybox.inc.o $(info $() LD $@) @$(CC) $(CFLAGS) $^ -o $@ -main.o: main.c busybox/busybox.inc.h magic.h payload.h utils.h +main.o: main.c busybox/busybox.inc.h + $(info $() CC $@) + @$(CC) $(CFLAGS) -c $< -o $@ + +%.o: %.c %.h $(info $() CC $@) @$(CC) $(CFLAGS) -c $< -o $@ @@ -28,4 +32,4 @@ busybox/busybox.inc.o: busybox/busybox.inc.s $(BUSYBOX) clean: $(info $() CLEAN $(shell basename $(shell pwd))) - @rm -rf main.o stabbish busybox + @rm -rf *.o stabbish busybox diff --git a/src/magic.c b/src/magic.c @@ -0,0 +1,26 @@ +#include "magic.h" + +#include <unistd.h> + +const struct magic MAGICS[] = { + {"xzcat", 6, {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}}, + {"zcat", 2, {0x1F, 0x8B}}, + {"bzcat", 3, {0x42, 0x5A, 0x68}}, +}; + +struct magic magic_detect(fd file) { + static struct magic try_return = {NULL, 0, {0x00}}; + + unsigned char header[10]; + + size_t trys(header_len, read(file, &header, 10)); + + for (int i = 0; i < tsizeof(MAGICS); i++) { + if (header_len > MAGICS[i].length && + memcmp(header, MAGICS[i].byte, MAGICS[i].length) == 0) { + return MAGICS[i]; + } + } + + return try_return; +} diff --git a/src/magic.h b/src/magic.h @@ -2,7 +2,6 @@ #include <stdlib.h> #include "utils.h" -#include <unistd.h> struct magic { const char *tool; @@ -10,25 +9,6 @@ struct magic { unsigned char byte[16]; }; -const struct magic MAGICS[] = { - {"xzcat", 6, {0xFD, 0x37, 0x7A, 0x58, 0x5A, 0x00}}, - {"zcat", 2, {0x1F, 0x8B}}, - {"bzcat", 3, {0x42, 0x5A, 0x68}}, -}; - -static struct magic magic_detect(fd file) { - static struct magic try_return = {NULL, 0, {0x00}}; - - unsigned char header[10]; - - size_t trys(header_len, read(file, &header, 10)); - - for (int i = 0; i < tsizeof(MAGICS); i++) { - if (header_len > MAGICS[i].length && - memcmp(header, MAGICS[i].byte, MAGICS[i].length) == 0) { - return MAGICS[i]; - } - } +struct magic magic_detect(fd file); - return try_return; -} +extern const struct magic MAGICS[]; diff --git a/src/payload.c b/src/payload.c @@ -0,0 +1,35 @@ +#define _GNU_SOURCE + +#include <elf.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/sendfile.h> +#include <unistd.h> + +#include "payload.h" + +fd elf_payload(const char *path) { + static fd try_return = -1; + + fd trys(in, open(path, O_RDONLY)); + + ElfW(Ehdr) header; + try(read(in, &header, sizeof(header))); + + size_t trys(size, lseek(in, 0, SEEK_END)); + off_t offset = header.e_shoff + (header.e_shentsize * header.e_shnum); + size_t payload_size = size - offset; + + if (payload_size == 0) { + close(in); + return ENOPAYLOAD; + } + + int trys(payload, memfd_create("payload", 0)); + try(sendfile(payload, in, &offset, payload_size)); + try(lseek(payload, SEEK_SET, 0)); + + close(in); + + return payload; +} diff --git a/src/payload.h b/src/payload.h @@ -1,9 +1,4 @@ #pragma once -#include <elf.h> -#include <fcntl.h> -#include <sys/mman.h> -#include <sys/sendfile.h> -#include <unistd.h> #include "utils.h" @@ -15,28 +10,4 @@ #define ENOPAYLOAD -2 -static fd elf_payload(const char *path) { - static fd try_return = -1; - - fd trys(in, open(path, O_RDONLY)); - - ElfW(Ehdr) header; - try(read(in, &header, sizeof(header))); - - size_t trys(size, lseek(in, 0, SEEK_END)); - off_t offset = header.e_shoff + (header.e_shentsize * header.e_shnum); - size_t payload_size = size - offset; - - if (payload_size == 0) { - close(in); - return ENOPAYLOAD; - } - - int trys(payload, memfd_create("payload", 0)); - try(sendfile(payload, in, &offset, payload_size)); - try(lseek(payload, SEEK_SET, 0)); - - close(in); - - return payload; -} +fd elf_payload(string path); diff --git a/src/utils.c b/src/utils.c @@ -0,0 +1,47 @@ +#define _GNU_SOURCE + +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <sys/wait.h> +#include <unistd.h> + +#include "utils.h" + +char *pasprintf(string __restrict str, ...) { + va_list ap; + va_start(ap, str); + + char *out; + if (vasprintf(&out, str, ap) == -1) + out = NULL; + + va_end(ap); + return out; +} + +int memexecv(fd exe, char **argv, char **envp, struct stdstream std) { + int try_return = -1; + pid_t trys(pid, fork()); + + if (pid) { + int wstatus; + waitpid(pid, &wstatus, 0); + if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) { + fprintf(stderr, "Child process exited with code %i\n", + WEXITSTATUS(wstatus)); + return -1; + } + } else { + if (std.in >= 0) + dup2(std.in, 0); + if (std.out >= 0) + dup2(std.out, 1); + if (std.err >= 0) + dup2(std.err, 2); + + exit(fexecve(exe, argv, envp)); + } + + return 0; +} diff --git a/src/utils.h b/src/utils.h @@ -1,18 +1,11 @@ #pragma once -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - #include <errno.h> -#include <stdarg.h> #include <stdio.h> -#include <stdlib.h> #include <string.h> -#include <sys/wait.h> -#include <unistd.h> typedef int fd; +typedef const char *string; #define shift(n) \ if (n < argc) { \ @@ -38,46 +31,11 @@ typedef int fd; #define try(cmd) try2(cmd, != -1) -static char *pasprintf(const char *__restrict str, ...) { - va_list ap; - va_start(ap, str); - - char *out; - if (vasprintf(&out, str, ap) == -1) - out = NULL; - - va_end(ap); - return out; -} - struct stdstream { fd in; fd out; fd err; }; -static int memexecv(fd exe, char **argv, char **envp, struct stdstream std) { - int try_return = -1; - pid_t trys(pid, fork()); - - if (pid) { - int wstatus; - waitpid(pid, &wstatus, 0); - if (!WIFEXITED(wstatus) || WEXITSTATUS(wstatus)) { - fprintf(stderr, "Child process exited with code %i\n", - WEXITSTATUS(wstatus)); - return -1; - } - } else { - if (std.in >= 0) - dup2(std.in, 0); - if (std.out >= 0) - dup2(std.out, 1); - if (std.err >= 0) - dup2(std.err, 2); - - exit(fexecve(exe, argv, envp)); - } - - return 0; -} +char *pasprintf(string __restrict str, ...); +int memexecv(fd exe, char **argv, char **envp, struct stdstream std);