[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!