Here are my notes/answers for leviathan. Was surprised at the ease of these challenges as I remember attempting them a couple of months ago and being absolutely clueless after level 1. Guess that’s a nice sign of improvement!
‘ls -a’ reveals a directory called ‘.backup’ which contains a file ‘bookmarks.html’. Doing a ‘cat bookmarks.html | grep leviathan1’ reveals the password is rioGegei8m
In the home directory there is an ELF 32-bit LSB executable called ‘check’ and we know this by running the file command to determine it’s filetype. To see what this executable will do we can use the ltrace command to execute it and look for any specific library calls. For those of you who don’t know, ltrace is a library call tracer. It does this by running the specificed command and intercepting/recording the dynamic library calls by the executed process. It is also capable of intercepting and printing system calls executed by the program. Luckily, we can see a strcmp() function comparing the first three letters of our input to the string “sex”. We can assume “sex” is the password for the executable so let’s give that a try. Inputting this will switch our user to leviathan2.
We can now receive the password for this user by reading /etc/leviathan_pass/leviathan2
Now we have an executable ‘printfile’ which does exactly as one might expect. Running the command such as ‘printfile /tmp/test.txt’ will print the contents of ‘test.txt’ similarly to how the command ‘cat’ would.
Running ‘ls -l’ we can see the permissions for this executable consist of a setuid-bit being set on the file. Looking at the owner of the file and seeing that it is ‘leviathan3’ might make you think this challenge is over. Unfortunately as we can see by trying ‘ltrace ./printfile whatever’ the executable is using the access() function to determine if the current user has access to the file path. This disregards the setuid bit and thus prevents us from simply printing the password file. /etc/leviathan_pass/leviathan3’ we get “You cant have that file…” therefore there is some kind of conditional check within the program. Looking directory above this we can see ‘access(“/etc/leviathan_pass/leviathan3”, 4)’ which will determine whether or not the calling process can access the file pathname. Looking at the manual for this function we see that ‘-1’ is returned if a deny or error occurs and a ‘0’ is returned if permission is granted. Below we clearly see a ‘-1’.
Now how can we print the password file and bypass the access() function. Relating the printfile executable to the cat command I was thinking about printing two files; maybe it won’t check for access on the second file? I made two test files in /tmp/cramhack/ and let’s see what happens when I try to print both of these using ltrace.
What we can see is access(“testing.txt second.txt”) returned ‘-1’ which is deny. But, what is interesting is that it did not do an access() on each file it did an access() on our entire input. Therefore if there was a file named “testing.txt second.txt” and we had permission to read it then this would maybe be accepted? Let’s try just that.
Would you like at that, it worked. I’m sure there is more than one way to do this but, I found the easiest way to do this was to use a symbolic link (symlink or soft link). A symlink is the creation of a special file type that serves as a reference to another file or directory. Similarly, a hard link creates a reference to a specific location of data. To create a symlink we can use the ‘ln’ command with a flag ‘s’. The following will create a reference to ‘/etc/leviathan_pass/leviathan3’ file with the reference filename of ‘cram’. If you were unaware, the symlink takes the file permissions of the file you are referencing and thus, we are not allowed to simply cat the reference file or use printfile on it.
Now all we have left to do is create a filename such as “testing.txt cram” and we can execute printfile on this filename.
Similarly to past levels we have an executabe. Executing it with ltrace reveals just how easy this level is. We see that the first strcmp() is set to fail on execution. The strcmp() after the password prompt however reveals the password to be “snlprintf”. Therefore we can simply enter this and we will be given a shell. Be sure to execute this without ltrace when you have found “snlprintf” as I was not properly given a leviathan4 user shell when using ltrace. From here we can simply cat /etc/leviathan_pass/leviathan4.
Let’s login and do an ‘ls’. We will see nothing, which is why I always recommend to do an ‘ls -a’ to reveal hidden files. One file sticks out to me which is ‘.trash’. Change to this directory using ‘cd .trash’ and there is a file in here named ‘bin’ which we can determine is an executable by typing ‘file bin’. Executing bin we see that some binary is printed to the console. Using ‘ltrace ./bin’ we can see a bit more about the executable and this will reveal “fopen(“/etc/leviathan_pass/leviathan5”, “r”)” which is telling us that the executable is reading this file.
Let’s convert this binary to ascii and see if this is in fact the password for the next level.
There are plenty of ways to do this but I simply used a web-based conversion here: https://www.binaryhexconverter.com/binary-to-ascii-text-converter
Alright we have another executable ‘leviathan5’. On execution we get ‘Cannot find /tmp/file.log’ and using ltrace we can see “fopen(“/tmp/file.log”, “r”)” which tells us that it is trying to read from this file. Let’s make this file and put some random text in it. Now using ‘strace’ we ee a lot more details. We open ‘/tmp/file.log’ in read only mode, the file is read, and then the file is written before deleting ‘/tmp/file.log’.
Doing an ‘ls -l’ we see that the setuid-bit is set and that the owner is leviathan6. Perhaps we can use a symlink again and have this executable read/write the password file for leviathan6? Let’s give it a try.
I’ve done enough ctf challenges to know that a 4 digit code loves to be brute forced so let’s do just that. I like python but this is basic enough to be done a million different ways. I saved the following as ‘brute.py’ and ran it using ‘python brute.py’
I wasn’t really expecting this but getting the correct pin started a shell as leviathan7 so that was all we needed. Now just cat /etc/leviathan_pass/leviathan7 like the past levels.
Nothing on this level other than a congratulations text file so we are all done 🙂