Note: I've removed references to the original name of the competition to avoid people finding this post while trying to solve it.
The other day a friend pointed out a competition to me. It was a CTF; i.e. a capture-the-flag competition, where one has to break into various systems to get the "flag", which is a piece of text. By collecting flags you get more points and may unlock more challenges.
This one was pretty easy. It certainly was not as complicated as the DEFCON CTF quals or SIGINT CTF last year, however it had some elements in common with the simpler challenges in these CTFs. As someone who is still new to the world of information security, I thought I'd give it a try; I might learn something. While some challenges were straightforward, many made me think for quite a while.
Without further ado, the challenges and my solutions:
Hint #2: Flag is inside a file, but which file?
The other day a friend pointed out a competition to me. It was a CTF; i.e. a capture-the-flag competition, where one has to break into various systems to get the "flag", which is a piece of text. By collecting flags you get more points and may unlock more challenges.
This one was pretty easy. It certainly was not as complicated as the DEFCON CTF quals or SIGINT CTF last year, however it had some elements in common with the simpler challenges in these CTFs. As someone who is still new to the world of information security, I thought I'd give it a try; I might learn something. While some challenges were straightforward, many made me think for quite a while.
Without further ado, the challenges and my solutions:
1: Begin
Hint: You need to Alter E then A and think like Windows not Linux, no PHP knowledge required for this question.Hint #2: Flag is inside a file, but which file?
Here, we were taken to this page
The PHP code is one that takes the text "Hello world" and converts it to "Hell!!". This was a red herring, just looking at the source code would reveal the answer
Basically the "This is where you are very close to the flag!" was pretty literal, since the link to the file containing the flag was right underneath the text. Opening the file
drowssap.DWP
, I found the flag to be slumdog_millionaire!
.
There was an alternate way of solving this if you take into account the hints. Apache directory listing was not turned off, and one could simply open the containing directory in the browser and see the DWP file, plain as day.
Commentary on the design: I wasn't really fond of the exclamation mark in the flag. Most CTFs have text flags with underscores, or alphanumeric flags with some special characters. Punctuation is rarely part of the flag, because the punctuation could also be part of the sentence telling you what the flag is. This including of exclamation marks is pretty widespread in this CTF. This gets really confusing; and a CTF shouldn't be about having to try various portions of text after you have in essence completed the challenge. For this reason, many CTFs follow a standard format for their flags. For example, last year's SIGINT CTF said that all flags would start with something like
So that wraps up #2.
Commentary: This was a pretty good newbie problem since both the realization that the flag is in the source code and its extraction can be done in many ways.
What we see here are some comparison statements, each followed by a "jump if not equal to" statement. A literal hex number is compared with a part of a register, and if the two are not equal, the program jumps out, ending itself. This seems to be a likely candidate for the string comparison. Collecting all the literals together we get the hex string
Commentary: I had fun here. I believe that we were expected to do it differently, using ollydbg's powerful toolset, but regardless mucking around in not-too-complicated assembly is enjoyable. Reversing is a rather useful and important skill, this exercise gives an introduction from which others can learn.
The page was a simple login form:
Commentary on the design: I wasn't really fond of the exclamation mark in the flag. Most CTFs have text flags with underscores, or alphanumeric flags with some special characters. Punctuation is rarely part of the flag, because the punctuation could also be part of the sentence telling you what the flag is. This including of exclamation marks is pretty widespread in this CTF. This gets really confusing; and a CTF shouldn't be about having to try various portions of text after you have in essence completed the challenge. For this reason, many CTFs follow a standard format for their flags. For example, last year's SIGINT CTF said that all flags would start with something like
SIGINT_
and would be from a fixed set of characters. This makes all those "is that the flag?" moments unnecessary, and you can concentrate on the actual challenge.2: Nologin
Hint: You mite need to disable a feature in ur browser which prompts for the password.
This took us to a page which kept doing this:
after some inspection it was obvious that the javascript prompt was not really doing anything but block the page. There was no communication with the network, thus the flag must be client side and found in the source. Solution: I fetched the page via
On fetching the page, this is what I saw at the bottom:
wget
and looked at the source. I could have used other tricks to disable the prompt, however these require timing and Chrome has an annoying habit of temporarily disabling other things like the dev tools when there is a prompt.On fetching the page, this is what I saw at the bottom:
var p = prompt('Enter Password: ','here'); if (p == "yes_its_correct") alert('The flag is: and_you_thot_javascript_was_fun'); else window.location.reload();
So that wraps up #2.
Commentary: This was a pretty good newbie problem since both the realization that the flag is in the source code and its extraction can be done in many ways.
3: Strong
Hint: Yes you are right, what you see is the real password, but are u copy pasting it?
In this one, there was a page with a text box that we had to enter a password into.
Of course, the first thing I did was copy paste the text "very strong", "easy to crack" and "very strong but easy to crack!" into the box. None worked, however I noticed that the last one was truncated. This was due to a
maxlength
attribute on the text box, which was easily removed, giving the flag what_you_c_is_the_passwd
.
Commentary: Similar as #1, the text had an exclamation mark (though this was not the flag text). This was also pretty good newbie problem, not everyone knows about editing HTML on the spot and this is a good introduction.
4: 3 Users
Hint: Try downloading the source code and changing the names
This one had a login page with a dropdown of 3 items to select the user. The password was given, however there was a restriction on the username that was displayed when you try to log in.
This one had a login page with a dropdown of 3 items to select the user. The password was given, however there was a restriction on the username that was displayed when you try to log in.
The usernames in the dropdown were reshuffled names of the ones who were allowed by the server. Editing the HTML on the fly and fixing any one name gave the flag as
Commentary: Still pretty basic, by now I would expect some more challenging ones. At this point I'm pretty sure anyone who didn't know HTML manipulation would have learned it.
the_thrii_musketeers
Commentary: Still pretty basic, by now I would expect some more challenging ones. At this point I'm pretty sure anyone who didn't know HTML manipulation would have learned it.
5: Stega
Hint: Download the pics in the same folder
We were taken to this page:
Opening the images in new tabs and scroll-switching between the two revealed the hidden message (animation), "LOL APE". Removing the space created the flag.
6: Reverseit
Hint: Read the tutorial :P
There was a tutorial on ollydbg and a link to an exe. Basically, we had to reverse engineer the application and find the correct password for it.
Unfortunately, I was on my Ubuntu boot, and being lazy I didn't want to reboot to Windows just to use ollydbg. I could run the exe with WINE, and for that matter ollydbg too, but I decided to try my hand at it with
So, on running
gdb
, the in-built disassembler that I have very little experience with. Till now in CTFs I have not participated much in reversing, while I know which tools to use I am not too familiar with the x86 assembly, pretty clumsy with the tools, and apt to get lost in the code. So this was a pretty new experience for me. Fortunately I have learned the 8085 assembly and know a bit about modern assembly.So, on running
gdb
on the program and then disas main
, I got the following disassembled code. Most of it wasn't really necessary to look at, what we're interested in are the jump statements. There are a bunch of jne 0x4014b6 <main+200>
s in the middle, all going to the same location -- most probably these are nested ifs or something similar. The relevant bit is:
0x00401496 <+168>: cmpb $0x41,-0x18(%ebp) 0x0040149a <+172>: jne 0x4014b6 <main+200> 0x0040149c <+174>: cmpb $0x62,-0x17(%ebp) 0x004014a0 <+178>: jne 0x4014b6 <main+200> 0x004014a2 <+180>: cmpb $0x68,-0x16(%ebp) 0x004014a6 <+184>: jne 0x4014b6 <main+200> 0x004014a8 <+186>: cmpb $0x69,-0x15(%ebp) 0x004014ac <+190>: jne 0x4014b6 <main+200> 0x004014ae <+192>: cmpb $0x6b,-0x14(%ebp) 0x004014b2 <+196>: jne 0x4014b6 <main+200>
What we see here are some comparison statements, each followed by a "jump if not equal to" statement. A literal hex number is compared with a part of a register, and if the two are not equal, the program jumps out, ending itself. This seems to be a likely candidate for the string comparison. Collecting all the literals together we get the hex string
41:62:68:69:6b
(colons separate letter), which converts to "Abhik", which turns out to be the key.Commentary: I had fun here. I believe that we were expected to do it differently, using ollydbg's powerful toolset, but regardless mucking around in not-too-complicated assembly is enjoyable. Reversing is a rather useful and important skill, this exercise gives an introduction from which others can learn.
7: Ground Zero
Hint: is 1 = 1 ? What does the doctor give you when you are ill (am not talking abt tablets)The page was a simple login form:
Even if you didn't get it from the hint, the first thing one tries on a login form in a CTF is SQL injection. Most CTFs have very little injection (or the ones that they have are still hard), but it's always something you try out, just in case.
After some mucking around, I was able to get the input with username
Manishearth
and password ' or '1'=1;#
to work. For some reason the usual MySQL commenting style, --
, wasn't working (I'm pretty sure the db was MySQL), but the pound symbol worked.
The flag was
sunny_days_kill_the_db
Commentary: A pretty simple injection exercise, but very useful for those new to it.
8: Unauthorized
Hint: Im hungry, what should I eat?
This was a simple page that said "You are not authorized!". Looking at the cookies, there is an
auth
session cookie:
This can be edited (I used the Edit This Cookie Chrome Extension but there are many others) to yes, and you get the flag as
Hint: Its hidden!c00kies_are_sweet
.
Commentary: A good introduction to cookie manipulation. Some frameworks (I recall seeing this in a Sinatra webapp in a CTF) have vulnerabilities where you can get enough details to forge session cookies. While one would never have such an easily forged "auth" cookie on the client side, the fact that cookies can be forged easily opens up a new window to things.
9: minorTweak
Another login box , this time with a registration form.
Registering normally would create an account which one can log in to, but there was nothing special there.
This one was pretty easy, there was a hidden input element called
level
in the registration form.
Setting it to one and registering got you to a page which listed all users and passwords. One of the passwords was a flag:
Commentary: This was essentially about finding HTML worth manipulating again. By now I was a bit tired of these, since for simple apps these stand out from a quick look at the source.
10: What Now?
Hint: You need to post it
Here we had a username and password, but no place to put it. Or so it seemed. Submitting a simple POST request to
whatnow.php
with the username and password parameters didn't work.
However, what did work was tacking on an extra key-value pair to the POST request,
submit:submit
. Submit buttons in HTML forms are full-fledged input elements (This is by design, one may want to use more than one submit button and have the choice get recorded), with names and values, and the value of a submit button is also displayed on the button. By default, most people use <input type=submit name=submit value=Submit>
, so plugging in the extra key value pair led to the flag, "stop_me_if_uoy_can".11: Strange Crack
Hint: Is it an exe file?
There was a simple page linking to an exe that doesn't work.
This was fairly straightforward, though it is a good exercise in understanding file types. Almost all binary files have some text in them. Part if it is supposed to be easily searchable text (like artist data for a sound file), part of it has to do with the format and protocol. Usually there is some string that uniquely identifies its correct format. Here, running
strings flag.exe
led to:RIFF WAVEfmt LIST( INFOINAM IART Binary_Pirates data z L .
The first two strings uniquely identify it as a WAV file. Renaming to WAV and running it led to some squabbly gibberish, however on opening in Audacity and considerably slowing down the speed, the words "The flag is waves2009" could be heard.
Commentary: I really liked the file format bit. While not uncommon in CTFs (where it is just a first step to a more elaborate problem that is usually beyond my grasp), understanding that the extension is not all that can help you learn the file format is pretty important. However, the file was pretty garbled and, when slowed down to normal speed, the "waves" bit had been spoken pretty quickly and was mashed together, making it hard to understand even after tweaking the speed/tempo a bit. I guess some more enunciation would have been good.
12: Browser
Hint: You might need to install something
The page was an error page, which advised the user to use the csd_bpgc_v4.1 browser.
Without pausing to check if this CSD thing really was a browser (apparently it's not, it is the user agent of a bot), I simply used User Agent Switcher to make Chrome pretend to be the browser. This worked, and the flag was found.
Commentary: User agent manipulation is again a form of client side manipulation, but it's a useful one to use while testing applications. Of course, it doesn't emulate the browser, however it makes the server think that the browser is different.
13: OBL Network Login
Hint: What do you do when you forget to have lunch/dinner and start feeling hungry, (assume that maggi is not available)
Here there was a login page with the username and password already out there.
Logging in worked, but there was nothing interesting once logged in.
There was a reference to an access log in the comments
Looking at access.log, there were three users: roran, eragon, and binary_pirate. Eragon was an admin.
Of course, I now have to log in as Eragon. SQL injection wasn't working, so I had a look at the cookies. There was a separate login_user cookie that contained a hex string. It looked like a hash, so I checked and it was indeed the md5 hash of the username. So all I had to do was edit the cookie to the md5 of "eragon", after which I got the flag, kage_bunshin_no_jutsu.
Commentary: While I managed this one pretty quickly, this probably was a matter of luck. This was a wonderful mix of "forgetfulness" and an insecure implementation of session cookies. Unlikely in practice but there are many vulnerabilities along these lines found today.
14: RARE crack
Hint: you need to FORCE it
We were given a rar file which was password protected with the first half of a Goan phone number.
This looked like something brute forceable (especially obvious if you look at the hint). We know that the number is a 5 digit one starting with a 9 (Unfortunately, as a Mumbaikar, I don't know the exact Goan cell phone number ranges). This could be easily brute forced using
unrar
and itertools
, or alternatively a modified version of rarcrack. I kept the latter running in the background, while I tried to find out the phone number ranges for Goa and wrote the former. Never really got to use it though, I got the result as 96732, which gave me access to a text file containing the flag, GJQKMNAVQEXKRFPOISBWERF.
Conclusion: Brute forcing is pretty boring, since it can be done with various tools and just takes time. As an introduction to the topic this is pretty good, though. This could have been made slightly more challenging by having the password start with a zero, making the method of forlooping through the integers no longer work.
15: Encrypto
Hint: What is so special of the number 49?
This obviously wasn't a substitution cipher as there was a double space involved. After trying out various simple ciphers, I tried the Caesar Box cipher, which worked. This cipher involves writing the characters out in a square, and reading down the columns.
In this case, the box looks like:
In this case, the box looks like:
F E M H C I _ R _ E E U S A O S _ _ L _ _ M U T R O O S _ B O I U N T T L _ D S L E H I T I _ Y P
Which gives the text "FROM THE SUBLIME TO THE RIDICULOUS IS ONLY A STEP", giving the flag "its_the_caesar_box"
Being too lazy to write out the box myself, I used the following JS code:
a="FEMHCI_R_EEUSAOS__L__MUTROOS_BOIUNTTL_DSLEHITI_YP" "\n"+a.substr(0,7)+"\n"+a.substring(7,14)+"\n"+a.substring(14,21)+"\n"+a.substring(21,28)+"\n"+a.substrig(28,35)+"\n"+a.substring(35,42)+"\n"+a.substring(42,49)
Commentary: I liked this one. While it dealt with an old and rarely used cipher, it was pretty fun.
16: Crack-o-mania
Hint: See the instructions after reversing
In this one we were given an exe to download, which we had to figure out the password to.
With the same techniques as #6, I got this disassembled code. While the code was more complicated, with a lot of printing and other stuff, the main bit was the same as last time:
0x004015b9 <+459>: cmpb $0x45,-0x38(%ebp) 0x004015bd <+463>: jne 0x40171c <main+814> 0x004015c3 <+469>: cmpb $0x4e,-0x37(%ebp) 0x004015c7 <+473>: jne 0x40171c <main+814> 0x004015cd <+479>: cmpb $0x54,-0x36(%ebp) 0x004015d1 <+483>: jne 0x40171c <main+814> 0x004015d7 <+489>: cmpb $0x45,-0x35(%ebp) 0x004015db <+493>: jne 0x40171c <main+814> 0x004015e1 <+499>: cmpb $0x52,-0x34(%ebp) 0x004015e5 <+503>: jne 0x40171c <main+814> 0x004015eb <+509>: cmpb $0x2d,-0x33(%ebp) 0x004015ef <+513>: jne 0x40171c <main+814> 0x004015f5 <+519>: cmpb $0x50,-0x32(%ebp) 0x004015f9 <+523>: jne 0x40171c <main+814> 0x004015ff <+529>: cmpb $0x41,-0x31(%ebp) 0x00401603 <+533>: jne 0x40171c <main+814> 0x00401609 <+539>: cmpb $0x53,-0x30(%ebp) 0x0040160d <+543>: jne 0x40171c <main+814> 0x00401613 <+549>: cmpb $0x53,-0x2f(%ebp) 0x00401617 <+553>: jne 0x40171c <main+814> 0x0040161d <+559>: cmpb $0x57,-0x2e(%ebp) 0x00401621 <+563>: jne 0x40171c <main+814> 0x00401627 <+569>: cmpb $0x4f,-0x2d(%ebp) 0x0040162b <+573>: jne 0x40171c <main+814> 0x00401631 <+579>: cmpb $0x52,-0x2c(%ebp) 0x00401635 <+583>: jne 0x40171c <main+814> 0x0040163b <+589>: cmpb $0x44,-0x2b(%ebp) 0x0040163f <+593>: jne 0x40171c <main+814> 0x00401645 <+599>: cmpb $0x3a,-0x2a(%ebp) 0x00401649 <+603>: jne 0x40171c <main+814> 0x0040164f <+609>: cmpb $0x28,-0x29(%ebp) 0x00401653 <+613>: jne 0x40171c <main+814> 0x00401659 <+619>: cmpb $0x0,-0x28(%ebp) 0x0040165d <+623>: jne 0x40171c <main+814>
The ascii codes for the literals in the
Commentary: I believe this one would have been trickier via ollydbg, since the contestants had been trained to use the "find strings" feature. In this case the "ENTER-PASSWORD:" would have seemed to be part of the output and not the input, so the question would have to be solved by stepping through. With
cmpb
statements translate to "ENTER-PASSWORD:(", which is the key.Commentary: I believe this one would have been trickier via ollydbg, since the contestants had been trained to use the "find strings" feature. In this case the "ENTER-PASSWORD:" would have seemed to be part of the output and not the input, so the question would have to be solved by stepping through. With
gdb
it was more or less the same problem, just with more assembly to sift through. Still had fun with this one.17: Warn
Hint: Look above
(I have found a vulnerability, but not yet solved this one)
We were taken to a page with a login screen that provided credentials:
(I have found a vulnerability, but not yet solved this one)
We were taken to a page with a login screen that provided credentials:
On login, a message appears "You need to warn the server with the message 'vulnerable'.". Interesting.
After mucking around a bit, I realized that the page was vulnerable to array-ification of the inputs. Editing the
one can log in with any username or password.
Why does this work? This is made evident from the warning messages shown when you try it:
So I've not been able to complete the challenge, though I have found a vulnerability.
Commentary: Since this one has stumped me, I like it a lot :) Array injection
After mucking around a bit, I realized that the page was vulnerable to array-ification of the inputs. Editing the
name
s of the inputs so that they become arrays,Why does this work? This is made evident from the warning messages shown when you try it:
PHPs
strcasecmp()
is being used here to check for the password, and it does not like array inputs. The way it works is that it returns zero if the strings are equal, and -1 if they are not. However, if an input is invalid, it also returns something which evaluates to a false<.code>; so passing an array to it can be used to bypass the string check.
However, I was unable to warn the server with that message even by making every vulnerable field (username, password, submit, all of the free request headers) read "vulnerable"
So I've not been able to complete the challenge, though I have found a vulnerability.
Commentary: Since this one has stumped me, I like it a lot :) Array injection
18: Patient's Nightmare
Hint: This is an old php server and allows simultaneous queries
Here, we are shown another login form
On submitting the page, some blending-in-with-background text appears with SQL code
rubs palms SQL injection time!
So this one is different from most simple SQL injection logins in that most of them can be bypassed by tacking on an
The following query worked:
(with the password as "def")
The flag was
Commentary: The UNION query is not usually known to newbies, making this a rather challenging problem. I found it easy, but fun.
Download the file, try to crack it till you get the message, "correct!".
Concatenate the strings you entered and submit it to the scoring server. Do not leave any blank space in your answer.
Here, we are shown another login form
On submitting the page, some blending-in-with-background text appears with SQL code
rubs palms SQL injection time!
So this one is different from most simple SQL injection logins in that most of them can be bypassed by tacking on an
or '1'=1
or anything else which evaluates to true because they usually are of the type where you SELECT * FROM users WHERE username='$user' AND password='$pass'
. But here, they are SELECT
ing the password and comparing it via PHP. So we have to make the SQL query return a fake password. This is doable with a UNION
query.The following query worked:
' union select 'def' as password;#
(with the password as "def")
The flag was
the_nightmare_cms_true
Commentary: The UNION query is not usually known to newbies, making this a rather challenging problem. I found it easy, but fun.
Problem 19
Hint: You need to supply something, something which you should avoid doing with a fool
Here we were given another exe (disassembled code), and the text:
Concatenate the strings you entered and submit it to the scoring server. Do not leave any blank space in your answer.
In this case, looking at the assembly code (or the hint), we had to provide arguments. Specifically, two arguments, as was evident from the lines (compare with 2, and jump away if there aren't enough arguments)
0x00401439 <+75>: cmpl $0x2,0x8(%ebp)
0x0040143d <+79>: jle 0x40165c <main+622>
This is roughly equivalent to a
if(argv.length<2){ return; }
Similar to the last few, there was a huge row of comparison statements
0x00401443 <+85>: mov 0xc(%ebp),%eax 0x00401446 <+88>: add $0x4,%eax 0x00401449 <+91>: mov (%eax),%eax 0x0040144b <+93>: cmpb $0x31,(%eax) 0x0040144e <+96>: jne 0x4015e2 <main+500> 0x00401454 <+102>: mov 0xc(%ebp),%eax 0x00401457 <+105>: add $0x4,%eax 0x0040145a <+108>: mov (%eax),%eax 0x0040145c <+110>: inc %eax 0x0040145d <+111>: cmpb $0x33,(%eax) 0x00401460 <+114>: jne 0x4015e2 <main+500> 0x00401466 <+120>: mov 0xc(%ebp),%eax 0x00401469 <+123>: add $0x4,%eax 0x0040146c <+126>: mov (%eax),%eax 0x0040146e <+128>: add $0x2,%eax 0x00401471 <+131>: cmpb $0x30,(%eax) 0x00401474 <+134>: jne 0x4015e2 <main+500> 0x0040147a <+140>: mov 0xc(%ebp),%eax 0x0040147d <+143>: add $0x4,%eax 0x00401480 <+146>: mov (%eax),%eax 0x00401482 <+148>: add $0x3,%eax 0x00401485 <+151>: cmpb $0x51,(%eax) 0x00401488 <+154>: jne 0x4015e2 <main+500> 0x0040148e <+160>: mov 0xc(%ebp),%eax 0x00401491 <+163>: add $0x4,%eax 0x00401494 <+166>: mov (%eax),%eax 0x00401496 <+168>: add $0x4,%eax 0x00401499 <+171>: cmpb $0x63,(%eax) 0x0040149c <+174>: jne 0x4015e2 <main+500> 0x004014a2 <+180>: mov 0xc(%ebp),%eax 0x004014a5 <+183>: add $0x4,%eax 0x004014a8 <+186>: mov (%eax),%eax 0x004014aa <+188>: add $0x5,%eax 0x004014ad <+191>: cmpb $0x69,(%eax) 0x004014b0 <+194>: jne 0x4015e2 <main+500> 0x004014b6 <+200>: mov 0xc(%ebp),%eax 0x004014b9 <+203>: add $0x8,%eax 0x004014bc <+206>: mov (%eax),%eax 0x004014be <+208>: inc %eax 0x004014bf <+209>: cmpb $0x67,(%eax) 0x004014c2 <+212>: jne 0x4015e2 <main+500> 0x004014c8 <+218>: mov 0xc(%ebp),%eax 0x004014cb <+221>: add $0x8,%eax 0x004014ce <+224>: mov (%eax),%eax 0x004014d0 <+226>: add $0x2,%eax 0x004014d3 <+229>: cmpb $0x64,(%eax) 0x004014d6 <+232>: jne 0x4015e2 <main+500> 0x004014dc <+238>: mov 0xc(%ebp),%eax 0x004014df <+241>: add $0x8,%eax 0x004014e2 <+244>: mov (%eax),%eax 0x004014e4 <+246>: add $0x3,%eax 0x004014e7 <+249>: cmpb $0x64,(%eax) 0x004014ea <+252>: jne 0x4015e2 <main+500> 0x004014f0 <+258>: mov 0xc(%ebp),%eax 0x004014f3 <+261>: add $0x8,%eax 0x004014f6 <+264>: mov (%eax),%eax 0x004014f8 <+266>: add $0x4,%eax 0x004014fb <+269>: cmpb $0x6d,(%eax) 0x004014fe <+272>: jne 0x4015e2 <main+500> 0x00401504 <+278>: mov 0xc(%ebp),%eax 0x00401507 <+281>: add $0x8,%eax 0x0040150a <+284>: mov (%eax),%eax 0x0040150c <+286>: add $0x5,%eax 0x0040150f <+289>: cmpb $0x4d,(%eax) 0x00401512 <+292>: jne 0x4015e2 <main+500> 0x00401518 <+298>: mov 0xc(%ebp),%eax 0x0040151b <+301>: add $0x8,%eax 0x0040151e <+304>: mov (%eax),%eax 0x00401520 <+306>: cmpb $0x48,(%eax) 0x00401523 <+309>: jne 0x4015e2 <main+500>
Each statement is of the approximate form of a move statement that brings a memory location into the register. Some number is added to it, and then the data at that location is compared. Basically, the inputted data was stored in an array, and it was being compared bit by bit
0x004014f0 <+258>: mov 0xc(%ebp),%eax ; move data to register 0x004014f3 <+261>: add $0x8,%eax ; add offset of 8 (can be 4, depends on which of the two argv elements I am accessing) 0x004014f6 <+264>: mov (%eax),%eax ; get memory at register contents 0x004014f8 <+266>: add $0x4,%eax ; add array offset of 4
; can be anything from 2 upwards.
; to access a[1], use inc
; to access a[0], don't add anything 0x004014fb <+269>: cmpb $0x6d,(%eax) ; compare with byte 6D 0x004014fe <+272>: jne 0x4015e2 <main+500> ; exit if not equals
So all I had to do was extract the ascii strings and place them as two arguments.
However, there was a little hitch. The statements from line 298 to 309 are actually for an earlier part of the string. Since they are comparing character-by-character, they can do it in any order. So they did the first letter (we know it is the first since there is no second
add
statement adding an array offset). Moving this character around, we get the string 130Qci HgddmM
.Commentary: This one was fun. You had to first realize that it needed two arguments, then figure out exactly what all those
add
/inc
statements were doing. Once you realized that each one represented a shift in either the argv
array or the string character array, the rest was a cakewalk though noticing that one of the letters was shifted was a bit non obvious.Problem 20
Here, we were given the following ciphertext:
"gmsnmv rsfmvs bh rvacan cmis essk bh gmnnxan gbos ubc usmv gmngm emjs mu sws cb gxuum cvanc ubc cvsrbuxan omvi fsyy oscsyyan gxorsv ksgxan rvacan ybjsn cess ubc ceba emnc fvbuqsk gmxan yxqmvxan cesvs xn rac bus oxuk xu myy cesns osu muk xc xn rsuc mqmxunc gmsnmv"
This seemed like a substitution cipher. It turned out to not be in Modern English, so that made it a bit harder. I can't post details about the entire process here, but I eventually got the substitution array:
{"a":"U","b":"O","c":"T","d":"d","e":"H","f":"W","g":"C","h":"F","i":"K","j":"V","k":"D","l":"l","m":"A","n":"S","o":"M","p":"p","q":"G","r":"B","s":"E","t":"t","u":"N","v":"R","w":"Y","x":"I","y":"L","z":"z"}
and the plaintext:
"caesar beware of brutus take heed of cassius come not near casca have an eye to cinna trust not trebonius mark well metellus cimber decius brutus loves thee not thou hast wronged caius ligarius there is but one mind in all these men and it is bent against caesar"
The flag turned out to be "Et tu Brute, then fall Caesar!"
Commentary: Always nice to have some crypto, however basic.
Conclusion
I had fun, though I found it a bit easy and was frustrated as the levels did not get much harder. Of course, it was meant for newbies to the realm of security, so I guess that's ok. It was a bit haphazardly constructed; like I mentioned before, there was no uniformity in the flags. There were also not as many "real world" type problems as I would have liked (the only ones that qualify are the reversing ones--which were all really the same, sql injection, directory index, server-side validation, and the
strcasecmp()
one). I guess these are more personal gripes as I may have not been in the target audience.I enjoyed the variety though, and could recognize that these questions were great ways to induce comfort with the tools and the mental perspective required to do these things at a higher level. I've been thinking of conducting my own CTF for IITB, but I've always been intimidated by it. As far as I can tell, this one was designed by students too, so kudos to the team who made the CTF for pulling through with this!