[NetGarage] Level 02

Style: Wargame
Website: http://io.netgarage.org

Access: ssh level2@io.netgarage.org

Let’s talk about level 2 of the NetGarage Wargame. When you look in /levels, you’ll notice that there are two ways to complete this level: the level02 and level02_alt binaries. Let’s start with the first, since going in order is cool…sometimes.

LEVEL02

Let’s begin by running the program, of course.

That’s pretty nice of them to provide us the source code. So considerate of them.

level2@io/levels:~$ cat level02.c  
 //a little fun brought to you by bla  
 #include   
 #include   
 #include   
 #include   
 void catcher(int a)  
 {  
     setresuid(geteuid(),geteuid(),geteuid());  
     printf("WIN!\n");  
     system("/bin/sh");  
     exit(0);  
 }  
 int main(int argc, char **argv)  
 {  
     puts("source code is available in level02.c\n");  
     if (argc != 3 || !atoi(argv[2]))  
         return 1;  
     signal(SIGFPE, catcher);  
     return abs(atoi(argv[1])) / atoi(argv[2]);  
 }

There’s things we should notice. First, if argc (number of arguments on the command line) is not equal to 3, or if the 2nd argument that is passed with the binary is equal to 0 once the string is converted to an integer, then the program will end. This means that our second argument can not equal 0.

So according to the code, in order to get a shell, we need to get the catcher function to execute. It appears that function will execute if we manage if the program catches a SIGFPE. But since we may not be sure that means, we can probably look it up online. OR….we could just use our shell and run the command“man signal” to learn about our signals. In that man page, we’ll find this:

According to POSIX, the behavior of a process is undefined after it ignores a SIGFPESIGILL, or SIGSEGVsignal that was not generated by (2) or raise(3). Integer division by zero has undefined result. On some architectures it will generate a SIGFPE signal. (Also dividing the most negative integer by -1 may generate SIGFPE.) Ignoring this signal might lead to an endless loop.

So in order to generate SIGFPE, we can divide the most negative number by -1. Luckily for us, division is included in the last line of the code, where the first argument is divided by the second. It seems we could normally generate this by integer division by 0, but since a zero will cause the program to exit, let’s use -1.

So what is the most negative number? Well, we could Google it. OR…we can just use our shell again. This time, let’s use a little Python.”

python -c "import sys; print (-sys.maxint - 1)"

Let’s walk through this. First, we are using Python because it contains the system’s max integer in its “sys” module. To run a line of Python, we use python -c. Next, we need to import sys so that Python can use the module. Finally, we are going to print (-sys.maxint – 1). In human terms, this says “Take the maximum integer for my architecture, make it negative, and subtract ‘1’”. You can look into how integers work in almost any programming resource, and they’ll all pretty much tell you the same thing. But the important thing to note is that there is always one more negative integer than positive integer, and that is why we need to subtract by 1.

Running that line on a 32-bit system will get you -2147483648, or (-2^31 – 1). If you try that command on a 64-bit system, you will get -9223372036854775808, or (-2^63 – 1). Now that we have our two arguments, time to run the command:

And there we go! Gained a shell, and able to see the password!

[NetGarage] Level 01

Style: Wargame
Website: http://io.netgarage.org

Access: ssh level1@io.netgarage.org

As described on the website, NetGarage is a Linux-based shell wargame, in which you must solve each level to move on to the next one. This is a write-up of LEVEL 1. Upon logging in, you’ll discover that the all the binaries, including the level01 binary, is located /levels.

So let’s try running the program as is:

Absolutely nothing. Chances are we got the passcode wrong, since it was just a random guess. There’s two ways we could go about solving this.

GDB DEBUGGING

My first thought was brute force since there are only 999 possibilites, but I figured I’d do the more technical approach first using gdb. Naturally, the first step here is to disassemble the main function of the program.

Here we see that a value in a register (likely the value we provide) is being compared to some constant in the program (likely the correct passcode). There’s plenty of sites or calculators to convert hex to decimal, but since we have a bash shell, might as well put it to use:


Breaking it down, we are performing a very quick conversion. The “16”  is the base, which is more commonly known as hex. The “10f” is the value of the constant in the program. Seems like we have a three digit number, and thus, the password!

Brute Force

Alternatively, we could solve this with brute force. Normally, I’d use Python for this, but we can use a basic bash for loop to do the job.

for i in $(seq -w 0 999); do echo $i; echo $i | ./level01 ; sleep 0.5; clear; done

Let’s walk through this between semicolons. The first section “for i in $(seq -w 0 999)” creates the condition under which the loop will run. Here, we are using the seq command to sequentially count from 0 to 999. However, since we need to input a 3 digit code, we need to make sure the width of the code is 3. We do that by using the “-w” command. This will turn into 000, 1 into 001, and so forth.

Next, we “do echo $i”.  Think of the “do” and “done” in this code as the { } limits you find in almost every language to keep scope of the loop. So for each number generated by seq, we are going to “do” everything until this iteration of the loop is “done”. The only reason for this section is so we can keep track of our current attempt number.

Then, we “echo $i | ./level01″ This will “pipe (|)” the current number into our program. This means we can expect our program to run 999 times total. Next, we sleep 0.5″ to give the program time to display the output, and to give us time to visually process it. The “clear” command is then used to wipe the screen, just to keep things clean. Then we are “done”.  Here is what the output looks like when we successfully brute force the answer.