Thursday, December 11, 2014

Microcorruption - Johannesburg


I noticed that again at the end of <login> on line 0x458C they insist on adding to the stack pointer address and returning from there. The weakness continues to be that there is an address stored just outside of the buffer range that the program uses to return to, and as before that if you overwrite that address you can take control. This is likely to be our way in.

For the sake of looking at other things, I also checked <test_password_valid>. There is some fiddling with sr, r15 and a call to 7d to check pw. If pw had been successful there would have been some value put into r15 and then sign extended and rechecked in login. But it never is so that's a false lead.

The manual indicates that they are not allowing passwords that are 'too large'. A simple test of our previous winning entry shows that indeed there is some kind of error checking for an input that is 'too large' – as our previous winning entry is rejected.

They still use <strcpy> so they limit our use of 0x00 (null delimiter). However if we enter a password that is too long it is still stored in a temporary location prior to being copied onto the stack. Of course when the copy happens, anything after the null delimiter is not included. So again we have that limitation.

You have to read the code a little on this one to find the key:


4578:  f190 6a00 1100 cmp.b     #0x6a, 0x11(sp)
The program presets address location 0x43fd to 6a, it then checks after the wrong password to see if that memory address still has 0x6a. The assumption is that a password that is too long will have overwritten that memory location with some other value.

It doesn't actually check to make sure that you limited your input to 16 characters, anywhere.

So our requirements for spoofing input restriction are:

  • no 0x00 (except as ending input if desired)
  • memory address 0x43fd must remain as (or be overwritten to) 0x6a

As long as we meet those requirements, our entire 'password' will be considered as valid input. Notice how the actual requirements differ significantly from the written requirements. Given those two constraints we are now free to inject our shell code. As before the stack pointer is moved to just past the buffer space and the code returns whatever address is provided in address 0x43fe.

Our shell code will be very similar to the previous code, no need to reinvent the wheel, although we will need to make some minor adjustments to account for a different length (given the additional requirement) and also out call address needs to be changed to 0x45a4 because “call 0x0010” is in a different place because the code in this version is different that the code from the prevoius version (so things now have slightly different line numbers).

3f40fffe1f53024fb012a44541414141416aec43

I made the leader board in June of 2014 under a pseudonym with that bit of machine language code, although I am not using my blog handle in this particular game (I'm playing the game with my son). 

However, we could have been lazy too. Conveniently, they provided us with a function called “<unlock_door>”, maybe we just call that directly instead and fill the password with the filler they want.

6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a6a4644

Wednesday, November 26, 2014

Bash Scripting: Runaway Check

Runaway Check Tutorial
TheCAT
11/26/2014

Objective: automate the process of examining all running processes on a list of linux/unix based servers and obtaining a list of processes that fall outside guidelines. These guidelines can be found on internal documentation like the DCM, but basically indicate there are cutoffs for CPU use, memory use and so on. The results should indicate which user and what process and machine are involved. At that point further consideration can be given on a case by case basis.

The goal of this lecture is to give you some legos to build things with. The legos you get here today will be most of the legos you need to build a runaway script with, but these legos can be used for other things. Cause who doesn't like legos; except unseen legos in the middle of the night with barefeet.

Minimum Command Requirements:

ssh
ps

Optional Command Requirements:

netgrouplist
ssh-keygen
ssh-agent
ssh-add
uptime
grep
echo
awk
sed
cut
>>
>

Possible Syntax:

for do done
if then else
` `
$

Tools:
vim/emacs/nano


Likely the end results of this script will be more complicated than the previous lesson's results. Again, when considering functionality examine the guidelines for runaway scripts in our in-house documentation.


Overview:

One way to tackle this is to use an ssh for-loop. Basically we set up a for-loop with every computer involved and ssh to that machine get the desired output, parse it to our satisfaction, and dump the results into a RESULTS.txt. From there as previously indicated we would examine things on a case by case basis.

Recall we will need some starting syntax at the top of our file:

#! /bin/bash

and we will ultimately need to chmod our script to be executable:

me@machine$ chmod 700 my_script.bash

That being said let's talk about keys.


Keys:

If you haven't got an ssh-key you will need one. Currently there are over 50 machines that need to be examined and you can't be entering in your password every time you run the script ... for each machine.

So, ssh to your favorite machine, I recommend  a cs compute powerhouse not an irc box or lab box. Once there,  generate an ssh-key if you don't have one.

yourname@machine$ ssh-keygen -t rsa -b 4096

and when prompted for a passphrase, give it a decent one that you can remember. Accept the default file name given.

Now let's get your key onto machines where it has to go. The thing is though your key has a passphrase associated with it, so every time you use your key you now have to answer the passphrase - so how is that different than just entering the password to the machine?

We can use an agent to bypass that. The agent will store our passphrase for us so we don't have to enter it over and over.

yourname@machine$ ssh-agent bash
yourname@machine$ ssh-add -t 3600
Enter passphrase for /u/yourname/.ssh/id_rsa:
yourname@machine$

First we started an agent with a new bash shell. Go ahead and up-arrow. All your previous commands are gone. If you type exit (don't do this now) it will appear that nothing happened, but actually it closes the agent shell.  Then we allowed the agent to have access to our key for 3,600 seconds. The clock is ticking.

So now let's transfer our public key to the machines we want to get to. We are going to do this in a for-loop on the command line to practice our syntax.

yourname@machine$ for machine in aaa bbb ccc; do ssh-copy-id yourname@$machine; done

We will still have to enter our password to ssh to those machines, but only one last time. Why did I pick those three machines? Hint: NFS mounted directories.

Since our directories are NFS mounted, did we actually have to use ssh-copy-id at all?

Now we can get around without passwords as long as we have an agent running. You need to remember the agent when running/ testing your script.


But what machines to use? This is in the DCM but we'll go over it a bit more here.

From your favorite machine:

yourname@machine$ netgrouplist -l

This gives you a listing of all our machines grouped by various categories. We are concerned with the following three: linux-login-sys, ece-secure-sys and cs-secure-sys.

yourname@machine$ netgrouplist cs-secure-sys

Because our inventory and the names of machines changes constantly, we want to make certain we use whatever is most current. As such we are either going to (A) dynamically import this list of machines from these three lists straight into our script or (B) put them all in one list and use the contents of that list in our
script. Remember the name of each machine is part of a for-loop just like it was in our command line example.

Here is how you could get a list into the script, you use backticks:

#! /bin/bash
for list in `netgrouplist -l`; do
     echo $list
done

Go ahead make this script, chmod it accordingly and run it. How would you change it to get a list of machines instead of a list of lists? How would you change it to get three lists of machines?

What if you want to put the list results in a file? There are many commands that put their results at stdout (the screen). But what if you want those results in a file?

Change the above script as follows:

#! /bin/bash
for machine in `netgrouplist cs-secure-sys`; do
     echo $machine >> RESULTS.out
done

Now run it

yourname@machine$ ./your_script.bash
yourname@machine$ ls
RESULTS.out

We could have gotten the same thing as follows:

yourname@machine$ netgrouplist cs-secure-sys >> MYRESULTS.out

The >> is called a redirection operator and it redirects stdout to a file of your choosing, specifically it appends data to that file - it doesn't over write it. If no file by that name exists, it is created.

The > operator is very similar EXCEPT that it overwrites data. Any old data in the file will be lost.


Now that we can get to machines let's get that data about those processes.

yourname@machine$ ps
yourname@machine$ ps -ef
yourname@machine$ man ps

As you can see ps is a very powerful tool. Once you have a chance to read the man pagea bit, take a look at the examples portion. You should be able to get some ideas about how to construct your ps.

I am specifically NOT going to tell you what the flags are for ps that you will want. You should read the man page and get some ideas, then experiment with the results locally, and incorporate that into your script.

Look at the requirements document (DCM) and see what matches in the man page. Once you have built your script and come up with ideas that work (on your own) I will be happy to answer any questions about how to make it better.

For now we will practice the fundamentals with ps -ef

But ps gives us some out put and we want to be able to separate that output based on results. One thing we can do to eliminate some out put is with grep.  Grep stands for Grab REgular exPressions. No, I am lying, but it should.

So we can use grep to exclude things - like maybe anything that is a daemon or root (if we want), with -v ie

yourname@machine$ ps -ef | grep -v root > test.out

In reality, if we are looking for runaway processes, do we really want to reject a process because it is being run by root? What if that process owned by root is busted or worse - shouldn't be running as a root process. I would want to know about a process consuming 100% cpu even if it is run by root.

Now we know how to get some results to play with, let's do that.


#! /bin/bash
for machine in `netgrouplist cs-secure-sys`; do
     ssh $machine ps -ef >> temp.out
done
awk '($1 !~/USER/) && ($2 > 32000)' temp.out >> RESULTS.out
rm temp.out

What did we get?

yourname@machine$ cat RESULTS.out

You now have most of the tools you need to construct a runaway script. You will need to spend more time with ps and awk (or sed) to actually get the info you need and parse it. Consider adding uptime as well.







 





Wednesday, November 19, 2014

Bash Scripting: Printer Test Script


Print Script Tutorial Lecture
TheCAT
11/19/2014

Objective: Send a printer test page to a group of networked printers. Ideally, the test page has a date and user name. Additionally it should be in color and span the depth and breadth of the page. This script can then be used in conjunction with lab checks to ensure that the printers in the labs are in good working order and so that an individual that encounters the page can understand its purpose.


Minimum Command Requirements:
man
lp or lpr
chmod

Optional Commands:
date
cat
convert
lpoptions
& many more possible


Possible Syntax:
for, do, done
if then else fi
case esac
exit
shift

Tools:
nano/vim/emacs
a .jpg or two


Side note: A print script can range from 5 lines to 150 or more. You can use any language and there are no hard and fast rules beyond the objectives – which are more of a guideline.


First let's look at what lp and lpr do.

user@machine$ man lp

user@machine$ man lpr

While I personally think that lp is a little more versatile offering a lot of options I actually used lpr for my script – no real rhyme or reason there so consider either one a viable alternative.

So you can see that you are ultimately going to have to provide some data to the command like the name of the printer and the file to print.

But what to do when there is more than one printer?

Well, we could just run the command multiple times, each time updating the name of the printer to reflect the next printer on our list of printers. In fact that is exactly what we are going to do, but we aren't going to do it by hand, we are going to put it in a script.

One method for doing something a lot of times is to put it in a for-loop. In this case each iteration of the loop corresponds to printing the same file to a new printer.

You now have the foundation for the entire script; the rest is just refining the bits of what we discussed so far. And for that we will work individually... more on this at the very end. Other questions to ask yourself



* What are the printers?

       - do these live in the script?

       - do they live in a separate file?

* What file to use?

       - do I create my own image?

       - Text or picture?

* How to get the date on it?

* How to get a name on it?

* Do I test all the printers at once?


But before we start coding (and after we finish solving the problem) let's start with something we will need at the top of any script: the magic cookie. No not that chocolate yummy thing. This is a line at the top of our file that reads as follows:


#! /bin/bash

This tells kernel to run the script in a bash shell. So when you run a command from the command line, there is a fork command that creates and entirely new shell which is an exact copy of the shell currently running. We want to make certain that when the script is run, that the new shell is also a bash shell. This falls under the execve command that follows (but we now we are way out of scope)...

Lastly let's discuss chmod. Change file mode allows us to set permissions for a file. On our systems when you create a new file the permissions default to: -rw------- meaning only we can read and write to it, but cannot execute. For a text file this isn't terrible, but since we are building a script we will want to make it executable. Additionally there is the consideration of whether we want other people to run our script. Do you want to let other cats run it? Or anyone at all? For now let's assume that we want to make it so that only we can run it. When we are done, we will want to:


chmod 700 my_script 

Now let's get to work and start thinking about how to set up what we need based on the previous bullet point questions....


For Loop Syntax

for item in apple banana cherry; do
    echo $item
done


for number in {1..9}; do
    echo $number
done

for f in `ls`; do 
    echo $f
done



Monday, November 10, 2014

Microcorruption - Montevideo


Again, they have the same strange add 0x10 to the stack pointer at the very end of the execution of login. This allows us, as before, to overflow the buffer and inject a return address that we want. If this were a software version the address we could put in there would be “unlock door” but since this is a hardware version we have to again get 0x7F into the SR and call 0x10 <_trap_interrupt> to open the lock. Pretty much the same as before, so let's try the same code.

Of course it doesn't work, and as we can see they have added strcpy into the mix which effectively copies all information up to and including the null terminator – but it stops there. So we only get one occurrence of 00 and it has to be at the end.

But other than that our methodology should be intact, we just have to adjust the code. We can still have the filler up front, then the re-deirect to our code as before, but we have to be a little more creative to work around the 00 entries in our password.

Ideas:

So we have some filler, the address to our shell code, another bit of filler and then our code:

3f40 fffe mv #xfffe, r15 ← load fffe into register 15
1f53 increment r15 ← increment to ff00
024f mv r15, sr ← move to status register
b012 1000 call 0x10 ← has to be the last thing

So putting it together we have the following parts:

41414242434344444545464647474848 filler
0244 address to our
4141 filler
3f40fffe1f53024fb0121000 injected shell code

41414242434344444545464647474848024441413f40fffe1f53024fb0121000

Wow, that's a really long password. Perhaps we can think of something shorter?

So rather than inject our shell code after the password, why not make our shell code the password itself? At the end we can redirect the program counter (instruction pointer) to the start of our shell code. Of course we will need to watch out for null terminators which means we can't call 0x10 from inside, but the provided code already does for us at address 455c. All we have to do is jump there.

So, instead of starting our code with 4141 (AA) let's start with the injected code and as the filler. We also change the jump to address (to an address within the code that does it for itself). The last portion is the address where the beginning of the password is stored. Here's an entry that works and is much shorter.

3f40fffe1f53024fb0125c45   41414141    ee43

←           shell code          → ←  filler   → ← starting address of shell code →

Tuesday, November 4, 2014

Microcorruption - Whitehorse


I probably should have read the manual (right, who does that?) before now. But better late than never. The manual on pages on 4 and 5 talks about how 0x7F is the code to unlock the door – not a function call but basically a hardware interrupt that accomplishes the same thing. Additionally there is mention of 0x7D and 0x7E which set a byte in memory if the entered password matches. Look for those to come into play at some point. We actually already saw these in Cusco, although that knowledge wasn't fully necessary at that point.

As in a Cusco, there is still an instruction (after the password has been checked and after the “wrong password” message is displayed) that adds 10 to the stack pointer. So the stack pointer jumps forward x10 to address 3cc6, and the next instruction is to return to the value held at the address 3cc6. The assumption is apparently that you have not entered a password longer than x10 bytes and put your own value in that address. But as the saying goes: when you assume you make an 'ass' out of 'u' and 'me'..

So we can put what we want in 3cc6 because nothing prevents us from entering a longer password than 16 characters – that is nothing prevents us from overflowing the buffer. Last time we did this we put the starting address of the “unlock door” function. This time however there is no unlock door function, but there is ample room to put code that we write in assembly.

So first we want to get control of the instruction pointer. Put the address at that point to the area of the buffer that we have overflowed, that is point the instruction pointer at the code we are overflowing into the buffer. This is called injecting code.

So what do we want to do? As you may recall from Cusco, hardware interrupt x7e when placed in the SR (stack register) and called with the interrupt trap causes the password to be checked. Hardware interrupt x7d sets a password in memory indicating that the password was correct, and x7f straight up unlocks the door.

Let's do the following:
Point the instruction pointer at memory we control.
Get x7f into the SR **
Call the interrupt trap.

We can look at the existing instructions in the code to cobble the bits and pieces together – or if you want a project you can learn this version of assembly and roll your own. But the basic structure of the code we can use is as follows

3e40 007f mv #x7f00, r14
0f4e mv r14, r15
024f mv r15, sr
32d0 0080 bis (highbit), sr **
b012 1000 call 0x10

**Note: the manual says x7F opens the door, but on my version of the game they had an extra part in there that set the high bit to 1 yielding xFF as the value required to unlock the door. The only way you figured this out was by looking at the code within <INT>


453e:  32d0 0080      bis       #0x8000, sr
so while you were examining <conditional_unlock> where it loads x7e onto the stack and calls <INT> you can see as you step through it that x7e gets loaded into the SR (from r15) and they flip the high bit on and then call the trap.

You can trim down the code above if you work through it – I don't want to take all the fun out – but a successful entry based on the code above can look like:

41414242434344444545464647474848c83c3e40007f0f4e024f32d00080b0121000

Microcorruption - REYKEYAVIC


In the end, one line of code shows you how to open the lock. Security through obscurity ... isn't. Sure don't be the tallest nail near the hammer, but that shouldn't be your entire game plan.

What follows is my thought process while analyzing the code, scroll to the end for the facepalm. 

do_clear – writes 00 to x100 bytes starting at x247c to initialize that portion of memory to x0 values. While I personally feel that initializing things like variables and pointers is good, safe practice in coding, it does serve to highlight that this area of memory may be important to the encryption/ decryption/ password recognition process.

Main – puts x4520 into r14 and then into r15. If this is meant as an address it puts you halfway into “do_nothing”. Then promptly overwrites r14 with xf8 and r15 with 2400. Then calls ENC.

ENC – begins by writing values 0 to x100 in sequential order to bytes starting at x247C and rising. Given that we just spent all that time writing zeros to them, only to then re-initialize them all again with specific values is … uh … part of the game I guess. Moving along then....

44a4: R8 = 0
… an algorithm?
44b0: references troll text: “ThisIsSecureRight?” and puts “T” (x54) in R10
44b4: sign extend R10 … this shouldn't produce any result on an ascii character as the highest is x7f. However if a non ascii character is entered there may be things.
44b6: R10+R13->R13 (54, 54)
44b8: Set high order bits to zero, resulting in new byte. So if we sign extend, then add, then overflow the register and set the high order bits back to zero, we can get a new ascii character. Adding xffff to x53, then anding with xff yields x52.

x247c: There appears to be something being put starting here again...

444a: call 2400 program is now executing code that it appears to have generated in the previous portions.

Then I see it, the snippet of code that says: Compare d7c5 <---- this is the password for opening the door. 

Face, palm.

Wednesday, September 10, 2014

Microcorruption - Cusco

As before we should go on the assumption that we aren't going to get the password - and so we don't concern ourselves with what the actual password is but only with details about how the program processes the password that you give it.

The kind of things that we might want to consider are:
* how long of a password can we put in there?
   - does a long password blow out of the stack?
   - what is the starting address of the password relative to the code?
* how does the program handle special characters?
   - unicode?
   - special delimiters?
* what functions does the program use to deal with the input that you provide it?
* are there any data structures being used to store that data that we can exploit to our advantage?
* does register under/overflow have a use?

These are just a few of the kinds of things we can begin to think about. For this level we will really only need to consider the first couple involving length of the password - more on that in a minute.

We have to have a good understanding of the code to see where the weakness is. Since this level represents an incremental update from the previous version, it seems that a reasonable place to start looking is where we looked last time... in login:


4520:  b012 5244      call #0x4452 <test_password_valid>
4524:  0f93           tst r15
4526:  0524           jz #0x4532 <login+0x32>
4528:  b012 4644      call #0x4446 <unlock_door>
452c:  3f40 d144      mov #0x44d1 "Access granted.", r15
4530:  023c           jmp #0x4536 <login+0x36>
4532:  3f40 e144      mov #0x44e1 "That password is not correct.", r15
4536:  b012 a645      call #0x45a6 <puts>
453a:  3150 1000      add #0x10, sp
453e:  3041           ret


At line 4520 the program calls "test_password_valid". It might seem like looking in test_password_valid is a good idea - after all we have previously found the password or some variant of it there. No such luck this time, there is a hardware call to do that comparison and that hardware black box puts some value into memory and program flow eventually looks at that value.

That value ends up in R15 and is then examined and if the zero bit is set based on the results of the test in line 4524 (meaning the password was wrong) then we jump to 4532 where we get the address of a string and at 4536, we 'puts' that message to stdout add 10 to the stack pointer and get out.

It merits looking at program flow for a right password also.  If the zero bit is not set when we get to 4526 (meaning the password was right) we fall through to unlock_door get the address of a message and JMP to 4536 where we 'puts' that message to stdout, add 10 to the stack pointer and get out.

In both cases, success or fail, the stack pointer is incremented by 10 to 0x43FE whereupon the instruction pointer returns to that address and executes WHATEVER CODE IS THERE...

The idea is of course that the stack pointer is incremented beyond the user password to an address for program execution which in both cases is 0x443C which is stop_prog_execution.

But what if some other address was inserted into 0x43FE? Well, the instruction pointer would return to that address and start executing that code instead. What if someone put the starting address for unlock_door instead of stop_prog_execution into 0x43FE? Then, whether or not the password was right the door would be unlocked.

It is a simple matter to find the starting address of unlock_door and (remembering that we are little endian) fill the password with 16 characters of garbage and overwrite memory location 0x43FE with 4446. It is also convenient that 44 corresponds to ascii D and 46 to ascii F.

Our winning entry is then:

1234567890abcdefFD

Friday, September 5, 2014

Microcorruption - Hanoi

These next few levels, if you aren't familiar with delving into assembly code, are a great place to start stepping through the code to get an understanding of program flow.

From looking at the code we can see that there are some basic structures that we will see over and over again in the coming levels.

trap


The trap interrupt is a software call to a hardware interrupt that results in some action being taken based on the status of certain registers - in this case the contents of the status register are used. The action taken is either to unlock the lock or set some value in another register (like r15) indicating that the supplied password was correct.

We will use this trap interrupt whenever we can. Page 8 of the manual starts the listing of valid status register contents. While some of the beginning entries seem unusable, the last entry is clearly gold: "interface with deadbolt trigger to unlock door..."

If you can set sr to 0x7F and call the trap, you win.

low level init, do copy data, do clear bss

These are some housekeeping routines called at the start of the program that aren't useful for our purposes.

main


Mostly we can expect that this is where the action would begin. Throughout the various levels we will see a variety of program styles. Some will have main filled and very few function calls, whereas this particular level the only purpose of main is to call login and then drop through to:

stop_prog_exec


Terminal point for program execution. If you get here, you failed.

unlock_door


As you can see from the code the action of unlocking the door is exactly as described above: Get 0x7F into the sr and (eventually via INT) call the trap. This doesn't always occur - hardware implementations generally don't have this function in any meaningful fashion.  But if it exists and you can get the code to call it, you win.

INT


Putting this out of order because it goes with unlock door nicely, this performs some housekeeping of preserving register state and calling the trap.

**note** As I mentioned in another posting the game changes over time to prevent people from cutting and pasting entries. In the version I played, 0x7F isn't actually the status that needs to be in the sr. I needed 0xFF to be in the sr - even though the manual said 0x7F. Generally I will refer to 0x7F as being required, but my code will always change to 0xFF.

putchar, getchar, getsn, puts


assembly implementation of C standard io lib functions. Used for user i/o. We will take advantage of their weaknesses and the code that uses them unwisely. There will come a time when the program asks for a 16 character limit password, but will ultimately accept any length which allows us to overflow the buffer. The combination of that limited expectation without following through on i/o limitations allows this kind of buffer overflow exploit. This is how we will be getting our desired value into the sr.


test_password_valid


we can expect to have to endure this function every time, but nothing of any real note happens in here.

login


The start and end of the action generally speaking. There is some point usually in this function where a branch is taken or not the ultimately allows the weakness. It varies by level, but ultimately occurs here - not in test_password as one might expect.

Having an understanding of program flow and the parts each of these functions is important. Knowing that login generally contains the meat allows us to focus on that for our weakness. Let's look at the code:We see that the true comparison for whether or not the door will be unlocked happens at line 455a and has nothing to do with test_password_valid function. The true comparison checks for a hardcoded value (0x9B) at a fixed address (0x2410). If that value is at that address code execution falls through the jne branch to "access granted" followed by a call to the unlock_door function.

4544:  b012 5444      call #0x4454 <test_password_valid>
4548:  0f93           tst r15
454a:  0324           jz $+0x8
454c:  f240 6100 1024 mov.b #0x61, &0x2410
4552:  3f40 d344      mov #0x44d3 "Testing if password is valid.", r15
4556:  b012 de45      call #0x45de <puts>
455a:  f290 9b00 1024 cmp.b #0x9b, &0x2410
4560:  0720           jne #0x4570 <login+0x50>
4562:  3f40 f144      mov #0x44f1 "Access granted.", r15
4566:  b012 de45      call #0x45de <puts>
456a:  b012 4844      call #0x4448 <unlock_door>


We also know that the starting address of where our input string occurs is 2400. Because the code doesn't actually prevent us from entering more than 16 characters (despite using getsn which can take a limiting size) we can fill addresses 2400-240F with garbage and put 9b at 2410, which will result in unlock door being called.

Here is a sample winning string (don't forget to check the box 'hex encoded') which does exactly that.


414243444546474849505152535455569b

Monday, August 4, 2014

Microcorruption - Overview, level 1, level 2


Overview


This is a war game where you are tasked with defeating a lock - it's a computerized lock that sounds really forbidding but ultimately turns out to have more holes than a sieve. The game does a good job of staying playable for new people as it has several versions that are all pretty much the same but the minor differences prevent cut and paste jobs.

Additionally, the makers of the game do a nice job of leading the player down different paths to explore not only different attack vectors but also prevent the same one from working over and over again.

As a side note, I originally started this game with the intention that my son would learn a little about computing. He didn't make it much past the first few levels - apparently prying locks open to steal imaginary bearer bonds isn't exciting enough. I suppose that is a good thing on some levels. But he did learn about the binary, octal and hexadecimal number system - which is a solid start. You can view our (my, at this point) progress as "SamnDad" on the website.

Some notes about the environment:

<action src dest>

This is the format for the assembly language for the game. This style is generally considered the reverse of Intel x86 assembly language which  puts the destination before the source.

little endian

0x1234 goes into the registers as 3412

Despite not having intel style syntax for the language the processor is little endian like many Intel processors.

Thanks Texas Instruments for being weird.
 
cmp a b yields flags based on result of: b-a ...  Good to remember for flags.

Useful websites for delving into the particulars of the processor:



New Orleans – level 1


I set a breakpoint at main and again at create_password. Create_password seemed like a good place to start, and I thought it was odd that it ran before the getsn() was called and as I watched the memory it filled in a string of letters as a I stepped it through. Naturally I tried that string, and it worked.

Interestingly the game appears to be designed for there to be a preferred solution because when I tried to overflow the buffer and trample the code, it cut me off at 100 characters despite that I entered 300 characters. This overflow works in later levels but not earlier levels. And so the game appears to be designed to train you to look for certain things.

Key learning elements: how the interface works, stepping through code and using the tools and understanding the user interface.

Sydney – level 2


The program stores the incoming password and puts it at 43a0, above which starting at 4400 is the code itself.  
Sets SP to point at 43a0 (first letters of incoming _password) and preserves SP in r15 where the incoming pass starts.
Compares a literal (0x4624 - F$) to 0x00(r15) which means r15+0 offset. As it turns out that literal is part of the password.

Jumps to (44ac) if not zero.
Whereupon it clears r14 and puts r14 into r15 and returns...
r15 has 0.
r15 is tested for 0, and if not zero goes to unlock door.
R15 0 goes to fail.

This repeats 4 times basically, so the password is hard coded not in memory but in the code itself in the form of looking for things to test against.

So: 4624 6a70, 574c, 5554
or: F$jpWLUT

EXCEPT that endian-ness counts:

2446706a4c575455
$FpjLWTU

Key learning elements: endian-ness, identifying key components of the code and stepping through those parts, flags and comparison.


Notably, buffer overflow is prevented at these early levels.

Wednesday, July 9, 2014

PXE - Preboot eXecution Environment - Let's PXE! (Part 2)

LET'S PXE!

Now that DHCP is working, it's time to get to the PXE stuff. I got the image file striaght from Ubuntu for my server. I found the files here:
http://cdimage.ubuntu.com/netboot/12.04/

I used curl for single files and wget (poorly but somewhat effectively) for an AMD64 build. I figured one build to start and see if I could just get that working even. Curled the pxe version from ubuntu proper (above).

I used the basic format of curl, done as root (probably foolish). In retrospect it
would have been smarter to curl it as a user into a temporary dir and then move it as root or sudo. Anyhow:

curl url/file > file


or you can

curl -O url/file to keep the existing name.

wget -r -l 0 url/  (copies *everything*) but if you point it right at the stuff you
want, you can kill it halfway through, copy over the other things and delete the extra junk which is what I did.

It is probably easier to just curl the 20 or so small boot-screens files than to use wget.

To start with you can put the kernel, initrd and boot-screens directory in
/var/lib/tftpboot/ Go ahead, just dump it in for now.

Assuming you have curled initrd and linux from ubuntu, now edit
/var/lib/tftpboot/pxelinux.cfg/default to look like this:

$ sudo vim /var/lib/tftpboot/pxelinux.cfg/default

# D-I config version 2.0
# include ubuntu-installer/amd64/boot-screens/menu.cfg
# default ubuntu-installer/amd64/boot-screens/vesamenu.c32
include boot-screens/menu.cfg
default boot-screens/vesamenu.c32
prompt 0
timeout 0
label ubuntu distro xxxx
  menu default
  kernel linux
  append initrd=initrd.gz

so, now in /var/lib/tftpboot/ we should have the following, all of it from ubuntu:

$ ls -l

drwxr-xr-x 2 root root        4096 May 12 08:25 boot-screens
-rw-r--r-- 1 root root 21256771 May 12 02:21 initrd.gz
-rw-r--r-- 1 root root  5778968 May 12 02:22 linux
-rw-r--r-- 1 root root    26461 Apr 19 13:22 pxelinux.0
drwxr-xr-x 2 root root     4096 May 12 07:19 pxelinux.cfg


FOR NOW, just read the following - or come back to it later and skip down to:
*fire up your client!*

WHAT THINGS ARE - ubuntu boot-screens

# boot-screens - a directory of text files that show dialogue for OS selection
# vesamenu.c32 - an executable that gets the ball rolling: as far I can tell this is a glorified jpg, but you need it.
# f1.txt - f10.txt - text files mostly for errors during load
# *.cfg    - primarily text files that allow specific configuration beyond the default screen. You may choose to update the paths in these to accurately reflect where the kernels are. For instance, the path provided by most of these cfg files says something like:

menu default
kernel ubuntu-installer/amd64/blahblahblah/ubuntu64/linux


but you should change them to where the linux file really is. On my server that same line reads: 

menu default
kernel ubuntu64/linux


The following detail caused me a fair bit of grief: 

RECALL that the path to all files in PXE are considered to start at /var/lib/tftpboot/  REGARDLESS of whether the path begins with / or not....    / does not operate as an absolute path with tftp in this case.

WHAT THINGS ARE - pxelinux.cfg



pxelinux.0  -  a modified version of part of an open source project called syslinux. Although pxelinux.0 is primarily a Linux loader, it is capable of loading other operating systems. It operates by using configuration files located on a TFTP server to provide boot instructions.

pxelinux.cfg - the directory where those config files that say which operating system to use (based on the choice you select on your client).

/var/lib/tftpboot/pxelinux.cfg/default - where the magic happens. this is important. this is where you set up what the options for OS will be. Each entry choice has the form:
label <label name>
    menu <which menu to use>
    kernel <relative path to kernel for this choice from /var/lib/tftpboot/>
    append initrd=<relative path to initrd for this chioce from /var/lib/tftpboot>

So, using my example of how I configured my directories and where I put my OS choices as indicated previously in the directory structure sample, the menu choice for the 64 bit Ubuntu 14.04 OS looks like this:

label 64 bit ubuntu 14.04
  menu default
  kernel 14ubuntu64/linux
  append initrd=14ubuntu64/initrd.gz

as many as you want, just configure them here and put the corresponding files in the matching locations.


FIRE UP YOUR CLIENT!



Since you have enabled DHCP you should just be able to plug your client box into your network, hit f12, select your OS and follow the instructions. If it were that easy, the text would have ended by now

 

C L I E N T


You need a box that is pxe capable, I worked with a lot of ancient equipment and not all of it had that capability.  Anything 64 bit is probably a safe bet, but check the bios to ensure your client can do it.

A couple of different difficulties you may run into with your client:

 - is your client pxe capable?
 - is your client configured to pxe?
    * perhaps you have to hit f12?
    * have you adjusted the bios to try pxe first rather than look to the drives?
    * do you need to adjust the NIC settings in the bios?
 - can you tail the logs on the pxe server to verify that your client and server are talking?
      * on my server (batman): $ tail -f /var/log/syslogs    > May 12 07:33:48 batman dhcpd: DHCPDISCOVER from 00:1a:xx:xx:xx:xx via eth0
    > May 12 07:33:49 batman dhcpd: DHCPOFFER on 1xx.2xx.xxx.xxx to 00:1a:xx:xx:xx:xx via eth0
    > May 12 07:33:52 batman dhcpd: DHCPREQUEST for 1xx.2xx.xxx.xxx (1xx.2xx.xxx.xxx) from 00:1a:xx:xx:xx:xx via eth0
    > May 12 07:33:52 batman dhcpd: DHCPACK on 1xx.2xx.xxx.xxx to 00:1a:xx:xx:xx:xx via eth0
 - if you don't see this sort of conversation between your client and the server, then perhaps:
      * your client isn't plugged into a swtich port that is on the same vlan as the server
      * other plug problems, bad cable
      * dhcp not configured correctly on the server
      * the switch is ancient and is S... L...O... W... . . . . . make sure the light has a chance to turn green. This happened to me, really.


SERVING MORE THAN ONE OS


If you want to have your server host multiple OS there are a variety of ways to go about this. I preferred putting all my different OS kernels and initrd files into their own directories - a little more work but ultimately nice and clean. Alternatively you could give each of them a unique identifier and dump it all into one directory. The reality is that how the client knows where they are and what to load is based in the config files.

that being said here is what my /var/lib/tftboot dir looks like

/var/lib/tftpboot$ ls -l
drwxr-xr-x 2 root root  4096 May  8 04:19 12ubuntu32
drwxr-xr-x 2 root root  4096 May  8 03:52 12ubuntu64
drwxr-xr-x 2 root root  4096 May 12 02:22 14ubuntu64
drwxr-xr-x 2 root root  4096 May 12 07:06 boot-screens
drwxr-xr-x 2 root root  4096 May  8 02:46 coreos
-rw-r--r-- 1 root root 26461 Apr 19 13:22 pxelinux.0
drwxr-xr-x 2 root root  4096 May 12 07:19 pxelinux.cfg

in each directory is its own initrd and kernel:

/var/lib/tftpboot/14ubuntu64$ ls -l
-rw-r--r-- 1 root root 21256771 May 12 02:21 initrd.gz
-rw-r--r-- 1 root root  5778968 May 12 02:22 linux



WHERE IS EVERYTHING AGAIN?


dhcp activity:   server        /var/log/syslog          dir
dhcp leases:     server        /var/lib/dhcp            dir
dhcp config:     server        /var/lib/dhcp/dhcpd.conf file
dhcp service:    server        isc-dhcp-server          service
hosts you know:  server/client /etc/hosts               file
pxe config:      server        /var/lib/tftpboot/pxelinux.cfg/default         file
OS options:      server        /var/lib/tftpboot/MY_OS/ (kernel and initrd)



TREMENDOUS THANKS!

blkperl - my primary mentor

https://help.ubuntu.com/community/PXEInstallServer
http://blog.alainodea.com/en/ipxe-smartos

Also good:
http://askubuntu.com/questions/412574/pxe-boot-server-installation-steps-in-ubuntu-server-vm
https://help.ubuntu.com/community/UbuntuLTSP/StaticIPsWithDHCP
https://help.ubuntu.com/community/isc-dhcp-server

tailing the logs can be helpful too: sudo tail -f /var/log/syslog

Additional hugely complicated reading:
http://www.openbsd.org/faq/faq6.html




Thursday, July 3, 2014

PXE - Preboot eXecution Environment - Setting Up DHCP

PXE - Setting Up DHCP


For fun in one of the labs I set up my own PXE server and made notes about the problems that I encountered in doing so. If you aren't really sure what PXE is, a decent description exists at wikipedia. In a nutshell the client sends/ broadcasts a request for a Network Bootstrap Path. The server authenticates that the request comes from a legit source and, if so, sends the path to the client. The client then executes the path and installs the given OS.

I am running an older 64 bit Dell Poweredge with Ubunutu 12.04.

To get started you will want to do a little bit of reading if you haven't already. I found the following two posts to most informative:

https://help.ubuntu.com/community/PXEInstallServer

http://blog.alainodea.com/en/ipxe-smartos

So do a little bit of background reading if you haven't yet, but odds are you already looked at those which is why you are here. If you already have DHCP configured skip those parts.

Got DHCP?


After I read these through a few times, I noted that I had several constraints. I needed at least one box to be the client. Several desktops exist in the lab that will likely serve (they did not). Additionally when I started, DHCP in the lab was broken so I had to see if I could get that resolved too.

You'll need:


isc-dhcp-server which is the dhcp server and handles networking. You'll also need tftpd-hpa which is Trivial File Transfer Protocol and it handles the transfer of the OS from the server to the client.

$> sudo apt-get install isc-dhcp-server 
$> sudo apt-get install tftpd-hpa   

Create or edit  /etc/default/tftpd-hpa with the following content (may already exist):

    # /etc/default/tftpd-hpa
    TFTP_OPTIONS="--secure --verbose"
    TFTP_USERNAME="tftp"
    TFTP_DIRECTORY="/var/lib/tftpboot"
    TFTP_ADDRESS="0.0.0.0:69"


Most of it was already there, but I added verbose.
   
$> sudo service tftpd-hpa restart
     

Editing dhcpd.conf


Now create or edit /etc/dhcp/dhcpd.conf

with the following content (adjust the subnet, range and domain-name as required):

    server ip:     1xx.2xx.2xx.2xx  // this will be same as 'next-server'
    gateway:    1xx.2xx.2xx.1xx
    subnet:        1xx.2xx.2xx.1xx
    netmask:    255.255.255.xxx
    filename:    determined by OS we will be loading basically.

So you'll need the information about your gateway, subnet and netmask. I found that information by asking around. So the file will look something like:


#----------------------------------------------------
subnet 1xx.2xx.2xx.1xx netmask 255.255.255.xxx {
  pool {
    range 1xx.2xx.2xx.2xx 131.2xx.2xx.2xx;  
    next-server 1xx.2xx.2xx.2xx;
    filename="pxelinux.0"
  }
}
#-----------------------------------------------------


But since no one was going to be authoritative about Dynamic Host Configuration Protocol in the labs, I asked if I could and so got permission. Now the file looks like this:

#-----------------------------------------------------
 18 # If DHCP server is the official DHCP server for the local
 19 # network, the authoritative directive should be uncommented.
 20  authoritative;
 :
 :
 34 subnet 1xx.2xx.2xx.1xx netmask 255.255.255.2xx {
 35 # option definitions common to all supported networks...
 36 # subnet mask advises client to use that mask
 37 # broadcast-address: where all clients receive messages from
 38 # option routers tells the client that the gateway is there
 39 default-lease-time 600;
 40 max-lease-time 7200;
 41 option subnet-mask          255.255.255.2xx;    # /27 - cidr
 42 option broadcast-address    1xx.2xx.2xx.2xx;    # town crier
 43 option routers              1xx.2xx.2xx.1xx;    # the gateway
 44 option domain-name-servers  1xx.2xx.2xx.2xx;    # DNS server
 45 option domain-name          "foo.bar.org";      # our domain!
 46   pool {
 47     range 1xx.2xx.2xx.1xx 1xx.2xx.2xx.2xx;      # I control
 48     # range 2xx-2xx; if not authoritative so I can be less

 49     # controlling :)
 50     next-server 1xx.2xx.2xx.2xx;                # pxe server
 51     filename="/pxelinux.0";                     # pxe loader
 52   }
#----------------------------------------------------------------------------------

The pxe server is the next-server and is presumably your server that you control. The client is the one who (assuming you have a PXE enabled machine - check the bios) when you hit f12 gets an ip now from your dhcp server and then is provisioned by the server with the OS you select. You can test what you have so far by plugging in a box and seeing if you get assigned an IP address.

Next Up: LET'S PXE!

Wednesday, July 2, 2014

Bandit - overthewire.org final stages

The key to most of these final stages was snooping around in the areas described. Using cat to view a file or strings to look into the guts of an executable was an important step in being able to discern what was going on at the level.
For example, for level 21, you wanted to get to the right place then take a look at the script that was being run.


bandit21@melinda:/etc/cron.d$> cat /usr/bin/cronjob_bandit22.sh 
#!/bin/bash

chmod 644 /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

cat /etc/bandit_pass/bandit22 > /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv 

Now that we see that the password is being placed in a file in /tmp. /tmp is meant to be like a scratch pad or an extra hand to briefly hold onto something. We can see however that the script then does a chmod or 'change mode' which sets permissions on the file in to be readable by anyone. For a perms primer try:
http://www.tldp.org/LDP/GNU-Linux-Tools-Summary/html/x9543.htm

Now that you know where the file containing the password is just take a look at it:

$> cat /tmp/t7O6lds9S0RqQh9aMcz6ShpAoZKF7fgv

Level 23: The trick here is that since you know what is being run by virtue of being able to view the script you can duplicate the output of the script. The output of the script is the name of a file in which the next password is created. So, by duplicating the output of the script you have the file name where the data is stored.

$> echo I am user bandit23 | md5sum

8ca319486bfbbc3663ea0fbe81326349 -

$> cat /tmp/8ca319486bfbbc3663ea0fbe81326349

Finally we hit the last level which wants us to write a script. I guess I had written a few specifically for the game by this point even though the game says this will be your first one. A bash script starts with a sh-bang! That is: #! and then is generally followed by /bin/bash, so the first line of a bash script should look pretty much like:

#!/bin/bash

More on that here: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_02_02.html

So you could write a simple script to do the thing that gives you the answer and it certainly is good practice to do so if you haven't written very many, and it's always fun to explore the environment of the game by seeing how it reacts when you give it the script  .... 
or you can game the game.

And isn't that what hacking is really all about? Why write a script when a thousand other people before you already have? As we know the code of the script you would write are the same as what everyone else has already written and the answer already stored in a predictable location. Use what we did in level 23 to achieve the same result, the file may still be hanging around in /tmp with the answer just waiting for you to find it. The same vulnerability of temp that we learned about in level 23 still exists to be exploited.

Hope you have enjoyed the tour of bandit. And don't keep . in your path!

Thursday, June 12, 2014

Bandit - overthewire.org 15-19


Level 15 wants you to use SSL. At the time of writing this, the heartbleed fiasco is still in recent memory, and I actually did this level only a month or so before the news broke. Funny that the site actually indicates that "HEARTBEATING" is a problem, as it turns out heartbleed was the real problem. *rimshot*

Despite that, the level was straight forward with the command format:

openssl s_client -quiet -connect localhost:port

Level 16 was a little more fun because I got to write a script, which may not have been the most efficient way, but was pretty short and good practice for fun:

#!/bin/bash

for port in {31000..32000}; do                       

        echo "cluFn7wTiGryunymYOu4RcffSxQluehd"  |  \
        timeout 2 openssl s_client -quiet -connect  \

        localhost:$port                             \
        2>/dev/null >>/tmp/geo250/results.txt
done


Line by line this does the following:
* sets the magic cookie indicating that this is a bash script.
* assigns a number to port and for each number
* echoes the required password to
* the server at the port specified previously in the loop (but only hold the connection open for 2 seconds tops) using openssl and then
* dump any error messages in the trash and the good stuff in a file called results
* repeat until done.

Man pages and a little help from your pal google can bring you up to speed on the details if you want to delve deeper into openssl.

In the file you get the private key for the next level. You'll want to use that key as if it were your own. I copied results.txt to my machine and edited it so that only private key info was in the file. Chmod 600 results.txt so that it is private and then you can ssh -i /path_to/results.txt user@host.com to get in.

Level 18 was pretty fun too: you try to log in, then you get trolled and booted. However, if the password is valid you can still run commands on the server, you just have to do it by putting the command as part of the ssh command just by appending it to the ssh command. For example:

$> ssh user@host.org ps ps -ef | grep foo >> logfile.txt 

will ssh to host.org as user and run the command: "ps -ef | grep foo" and put the results in a file called logfile on your machine. So, in this case to get the password from the file on the machine you could run a command like:

ssh bandit18@bandit.labs.overthewire.org cat password
which will dump the password to your screen. After which the connection will be closed - in fact with this kind of command, the connection will be closed even if you don't have someone trying to boot you out and troll you. Now that you havae the password, the world (or at least the next level) is your oyster.

Thursday, May 29, 2014

Bandit - overthewire.org 10-14

I really enjoyed bandit, as there were many commands that I just don't get to use with any kind of day to day regularity. Most of my training has been self directed as they don't teach Linux in physics or computer science; you are expected to know it or learn it yourself.

For example, the level 11 the password was encrypted using rot13. Fortunately I had heard of that protocol years ago and all that remained really was to write a one liner to decode the file, which for fun I turned that into a script called rot13.sh that takes a file as argument 1 and generates a new file given by argument 2. Careful, you can clobber things because it doesn't really check to make sure of anything at all.


#!/bin/bash
# ultimate secret encryption protocol rot13
set -e
if [ -z "$2" ]; then
    cat $1 | tr 'A-Za-z' 'N-ZA-Mn-za-m'
else
    cat "$1" | tr 'A-Za-z' 'N-ZA-Mn-za-m' > "$2"
fi



Learning things on your own is fun and rewarding, but sometimes it is nice to have direction. To that end becoming involved with an organization dedicated to providing IT has been extremely helpful for me. I have taken advantage of as much of their training program as possible. But even then, sometimes basic things get skipped over, like the command: file.

File target

will tell you what kind of file the target is: a bin(ary), ASCII text, gzip or what have you because you can't necessarily tell by the extension. The extensions are meant to be helpful indicators but they are by no means enforced. This was a fairly important command for level 12. Because the file had been compressed multiple times you needed to use the file command to determine how which compression tool to use next, and when you were done compressing. The file command looks at various properties of the file itself in an attempt to determine the information. You can consult the man pages (of course!) for more information on the specifics there, as I recall there are magic cookies waiting if you do.

Lastly, level 13 gives you someone's private key. Ouch! If you have that it is probably better than the password itself assuming that the other person uses ssh to move around. You just have to copy the key into your .ssh directory, chmod 700, then ssh -i ~/.ssh/privatekey user@destination.org.

Keys are a great thing, and if you haven't set your own private key up, try it just for fun. It's just a file so it doesn't take up any room really, but you want to keep it protected if you are ever going to use it. There are lots of good instructions out there about how to:

ssh-keygen -b 4096 

what it does, and so on. Some of my favorite additional commands once you are up and running are

ssh-agent bash 

and

ssh-add -t 3600

to add an hour of no password prompting, particularly if I am running ssh for-loops for things. Probably at some point there will be something more robust than this, but by setting your bit level nice and high you are presumably making it hard for people to eavesdrop. And yes, the encryption offered by RSA keys rivals my super secret encryption protocol rot13 even.



Wednesday, May 7, 2014

Bandit - overthewire.org 1-9

"Bandit" at http://overthewire.org/wargames/ is a great introductory war game if you haven't tried this kind of thing before. You use basic linux/unix skills to get the password to the next level, and every level the challenge evolves and gets a little harder or different. All of this takes place from the command line.

I won't go over the first few levels, if you are interested in this sort of thing and know what ssh and a terminal are, you can get through them with no difficulty. But don't get get put off by how simple they are because there are still some fun things ahead.

Starting at level 5, we are using find to find the password for the next level on the server. Find is a really fun command - I might use it as follows if I don't really have a clue where to start looking for something:

find / target 2> /dev/null | grep target > results.txt

which says "look everywhere for the target, be quiet about it, just give me what I am looking for without all the other things and put it in result.txt please". Of course there are less intense search methods like locate and which as well.

For the levels 5 and 6, I got to use some specific flags that I don't normally use: -readable, -group, -size, and -user. They are all fairly straightforward with -size having a few additional options, which you can of course look up. In particular, I solved them with the following commands, respectively:

find / * -readable -size 1033c 2> /dev/null
find -user bandit7 -size 33c -group bandit6 2> /devl/null

Levels 7, 8, 9 were a little different thematically in that you didn't actually need to find the file, but rather find that data within the file using strings and grep. Grep is common enough: cat foo | grep bar is a basic use where foo is the file and bar is the word you want to find. Strings is perhaps a little more on the reversing side of the house; a good preview of looking at a binary to see if anything in there looks promising - sometimes there is some low hanging fruit to be had with it. 

However I thought the most interesting challenge of the three was level 8. The idea was that they had hidden a needle in a stack of needles. The file is some 1,000 line (or more text file) where there are 100 or so different and unique strings, and the rest of the lines are duplicates of those 100 or so patterns. Except for one line which is the target - the needle hidden in the stack of needles.

To solve it I used: 

cat data.txt | sort -n | uniq -u 

I had an idea that those two would be what was required, in fact I have a one liner that I use to get the number of different logins on a computer: 

who | cut -d' ' -f1 | sort -u | wc -l

Which brings me to a point about these kind of games. Even if you aren't interested in reversing, CTF or pwning your own, you can really learn a lot from these exercises. For starters just getting more and different problems to solve using tools you are familiar with already will help you attain mastery with those tools because you will be using them in a different manner than you are accustomed to, which may perhaps lead to learning to use different flags than you normally would.

And for those of you who are beginners, you can vastly expand your knowledge of the tools. Just by playing the game you will be learning new things, thinking creatively about how to solve a problem, and gaining a better understand of the vulnerabilities you have to consider when working as a system administrator.