RSS

CSAW CTF 2013 – Miscellaneous 200

0 Comments | This entry was posted on Sep 29 2013

For this challenge the first thing I did was as most would do, open the image in an image viewer program (specifically the Windows default image viewer, nothing fancy.) I didn’t see anything eye-catching, and when viewing the file in a hex editor I didn’t see anything immediately out of the ordinary either, there was nothing packed in with the PNG, it looked as a normal PNG would look, with lots of arbitrary junk data, and apparently indicating the image was taken from an IPhone 5. I didn’t realise how important this would be for me to notice at that point in time, but it definitely helped.

Next, I used a program that utilizes ‘libpng’, a very reputable and extensible PNG reference library that has existed and been tested for some years now, to analyze the more technical data for the PNG.

I got a notification that read something about the CRC in the IHDR chunk (the first few bytes of the PNG): “Incorrect crc for IHDR chunk (is c1d0b3e4, should be fcc410a8)”

I then tried changing this integer value with a hex editor at offset 0x1D to the following 4 bytes {0xFC 0xC4 0×10 0xA8}, and in doing so actually gave me more errors, including CRC errors for IDAT chunks, and there were a lot of them. Coincidentally, I decided to make sure that I was heading in the right direction and making sure that the CRC expected was actually the original, and perhaps it was changed deliberately for this challenge. So I checked the data that was currently there in the image header:

- 8 bits/sample (normal)
- truecolor+alpha
- non-interlaced

The one other thing that didn’t seem right, judging by the fact that the tEXt chunk points to an IPhone 5 running IOS 6.1.4, was that the image size was 3264×1681. This does not match any of the standard aspect ratios: 16:10, 16:9, 4:3 etc… And I also figured that editing this image in most image editors to crop it down to a portion of that full image would have possibly removed some of the remains of what the IPhone embedded within that image as a ‘mark’, upon resaving. (Everybody loves to advertise their copyright in there, you know how it goes.)

Through more research an IPhone 5′s camera roll aspect ratio is 4:3. The calculation gave me the idea that the image had somehow been chopped down height-wise.

3264*3/4 = 2448
2448 != 1681

Now, obviously there is no way to get that pixel data back once the image is chopped data-wise, so I tried changing the image size in the header from 3264×1681 to 3264×2448, and by opening the image again in some image viewer, voila! The key was written on the whiteboard the entire time. :)

Revisiting that hint they gave for this challenge part-way through my investigation also backed up this theory, but it wasn’t until I edited the header to match a 4:3 aspect ratio that it was apparent for what that down arrow really meant. All I knew was that this had nothing to do with width or anything horizontal.

There were exactly 2 bytes that needed changing in order to solve this challenge in the end, starting at offset 0×16, that indicate the height of the image. The values, originally, {0×06 0×91}, that needed to be changed to any sufficiently large value big enough to view that ‘hidden’ key on the whiteboard. I just matched it up to a 4:3 aspect ratio and changed those bytes to {0×09 0×90}.

Leetmore CTF 2012: Packets 200 (Epic Arc Pt. 2)

0 Comments | This entry was posted on Oct 18 2012

From the URL we extracted in the Part – I of the challenge, we got a second Wireshark capture log. The task was again to provide MD5 hash of the file being transferred.

Opening in Wireshark, we found that it was a FTP transfer log.

Epic Arc 200

Right clicking on the highlighted entry and selecting “Follow TCP Stream” extracts the entire data transfer. As, FTP protocol opens a new TCP connection as soon as the file transfer begins and closes the TCP connection as soon as the file transfer ends, capturing the TCP session ensures that ONLY the file bytes are taken out, nothing else, nothing else.


Epic Arc 2002

We saved the raw bytes thus extracted in a file, the MD5 of which was our flag for this challenge.

Solution: 77F92EDB199815B17E2FF8DA36E200DF

Leetmore CTF 2012: Web 100 (Pentagon Authentication)

0 Comments | This entry was posted on Oct 18 2012

This webchallenge asks for a password. The validation is done in javascript. If the correct password is passed, the flag is displayed. The HTML of the page was:









If no password is supplied, the loop is broken and the page doesn’t prompt for password anymore.

if (SuppliedPassword === null) {
break;
}

Password is exactly 12 characters long.

if (SuppliedPassword.length == 12) {
PasswordIsCorrect = true;
}

N = Number, C = Character

 0  1  2  3 4  5  6  7 8  9  10 11
 N N  N       N        N  

 if (! IsNumber(SuppliedPassword.charAt(0))) {
PasswordIsCorrect = false;
}
if (! IsNumber(SuppliedPassword.charAt(10)) || ! IsNumber(SuppliedPassword.charAt(1))) {
PasswordIsCorrect = false;
}
if (! IsNumber(SuppliedPassword.charAt(6)) || ! IsNumber(SuppliedPassword.charAt(2))) {
PasswordIsCorrect = false;
}

C(0) + C(1) + C(2) + C(6) + C(10) = 12

if (Number(SuppliedPassword.charAt(0)) + Number(SuppliedPassword.charAt(1)) + Number(SuppliedPassword.charAt(2)) + Number(SuppliedPassword.charAt(6)) + Number(SuppliedPassword.charAt(10)) != SuppliedPassword.length) {
PasswordIsCorrect = false;
}

 0  1  2  3 4  5  6  7 8  9  10 11
 N N  N       N  d      N  

var PasswordPrompt = "Enter the password";
.
.
.
if (SuppliedPassword.charAt(7) != PasswordPrompt.charAt(PasswordPrompt.length - 1)) {
PasswordIsCorrect = false;
}

C(8) = C(7) + 1

 0  1  2  3 4  5  6  7 8  9  10 11
 9 1  1  i  n   1  d e  j  0 b

if (SuppliedPassword.charCodeAt(7) != SuppliedPassword.charCodeAt(8) - Number(SuppliedPassword.charAt(0)) / Number(SuppliedPassword.charAt(0))) {
PasswordIsCorrect = false;
}

N(1) = N(2) = N(6)

if (Number(SuppliedPassword.charAt(2)) != Number(SuppliedPassword.charAt(6)) || Number(SuppliedPassword.charAt(6)) != Number(SuppliedPassword.charAt(1))) {
PasswordIsCorrect = false;
}

Either (N(1) = 0 OR N(10) = 0 OR BOTH = 0

if (Number(SuppliedPassword.charAt(1)) * Number(SuppliedPassword.charAt(10)) != 0) {
PasswordIsCorrect = false;
}

N(0) – N(10) = 1

if (Number(SuppliedPassword.charAt(1)) - Number(SuppliedPassword.charAt(10)) != SuppliedPassword.charAt(3).length) {
PasswordIsCorrect = false;
}

Combining the above two, N(1) = 1, N(10) = 0

 0  1  2  3 4  5  6  7 8  9  10 11
 N 1  1       1  d  e    0  

Also, C(0) + C(1) + C(2) + C(6) + C(10) = 12, hence C(0) = 12 – (1 + 1+ 1) = 9

 0  1  2  3 4  5  6  7 8  9  10 11
 9 1  1       1  d  e    0  

var TodaysSecretPassphrase = "Climbing is dangerous";
.
.
.
if (SuppliedPassword.charAt(11) + SuppliedPassword.charAt(3) + SuppliedPassword.charAt(4) != TodaysSecretPassphrase.substr(Number(SuppliedPassword.charAt(0)) / 2, 3)) {
PasswordIsCorrect = false;
}

 0  1  2  3 4  5  6  7
 C l  i  m  b i n  g

It concatenates C(11), C(3), C(4) and compares with the substring “bin”

 0  1  2  3 4  5  6  7 8  9  10 11
 9 1  1  i  n   1  d  e    0 b

C(9) is in lowercase

if (! IsLowercase(SuppliedPassword.charAt(9))) {
PasswordIsCorrect = false;
}

C(9) is not in the list of the characters found in QuoteOfTheDay

var QuoteOfTheDay = "the beige hue on the waters of the loch impressed all, including the zapped french queen, before she heard that symphony again, as kind young arthur wanted. keen oxygen vendor.";

if (QuoteOfTheDay.indexOf(SuppliedPassword.charAt(9)) != -1) {
PasswordIsCorrect = false;
}

So, here’s a nice Python script to find the character.

>>> QuoteOfTheDay = "the beige hue on the waters of the loch impressed all, including the zapped french queen, before she heard that symphony again, as kind young arthur wanted. keen oxygen vendor.";
>>> qotd_set = set()
>>> for c in QuoteOfTheDay:
... qotd_set(c)
...
>>> for c in QuoteOfTheDay:
... qotd_set.add(c)
...
>>> qotd_set
set([' ', ',', '.', 'a', 'c', 'b', 'e', 'd', 'g', 'f', 'i', 'h', 'k',
'm', 'l', 'o', 'n', 'q', 'p', 's', 'r', 'u', 't', 'w', 'v', 'y', 'x',
'z'])
>>> qotd_list = list()
>>> for c in qotd_set:
... qotd_list.append(c)
...
>>> qotd_list.sort()
>>> print qotd_list
[' ', ',', '.', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

C(9) = j

 0  1  2  3 4  5  6  7 8  9  10 11
 9 1  1  i  n   1  d  e  j  0 b

Entering the password “911in 1dej0b” displays the flag, but it disappears after a 5 seconds. To fix this, save the HTML and delete this part of the code to disable the timer:

ar count = 4;
var int = setInterval(function () {
if (!count) {
document.getElementsByTagName('div')[0].innerHTML = "****************************";
document.getElementsByTagName('b')[0].innerHTML = "##########################";
document.getElementsByTagName('big')[0].innerHTML = "-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-";
clearInterval(int);
return;
}
document.getElementsByTagName('big')[0].innerHTML +=count--+".. ";
}, 400);

Now the flag is calculated by the remaining portion of the Javascript

if (PasswordIsCorrect) {
var a = 4, b = 8, c, d, e = 3, f = 7, g = 9, h = 4, i = 1, j = 7, k, l, o, l, o, l, o, l, r = 9, s = 5, n = 123;
for (i = 0; i < 1337; i++) {
b = a = d = a = s = s = 1337;
f = e = d = e = r = a = l = Number(SuppliedPassword.charAt(s / 222));
h = e = d = g = e = h = o = g = s = Math.tan(g*e*r*i*n*e) + Math.sin(l−a−s−e−r);
if (i > Number(SuppliedPassword.charAt(1)) * Number(SuppliedPassword.charAt(0))) {
break;
}
}
for (j = 0; j > o; j−−) {
f = SuppliedPassword.substr(4, 1) + (f − f);
s += f.substr(f, f);
f += s[0] + SuppliedPassword[8] + "v" + SuppliedPassword.charAt(3);
g = (TodaysSecretPassphrase.substr(12, 3) + 'c' + f[3]).replace(/\x61/, f.charAt(3));
f = f + g + String.fromCharCode(s.charCodeAt(0)) + f[1];
f += f[8] + (f[f.length − 1] * 1 + 1) + /y/.source + f.charAt(f.length / 2 + 5);
f = f + "th";
f += String.fromCharCode(SuppliedPassword[9].charCodeAt(0) − 1) + String.fromCharCode(SuppliedPassword[11].charCodeAt(0) + 17);
f = f + f[f.length / 3 + 2 * 1 * 2] + s.substr(3, 4)
}

Solution: n0-evidence-0n1y-this-8030

CSAW CTF 2012: Web 1

0 Comments | This entry was posted on Oct 07 2012

Here we were given a login form and a piece of text instructing us to bypass the authentication.

http://128.238.66.216/c4ca4238a0b923820dcc509a6f75849b/



Lara Anderton needs to break into PreCrime to free her husband, but they just installed a fancy new security system. Help her break into it!

When the login form appeared for the first time, we watched its cookies using Mozilla Firefox addon “Live HTTP Headers”. We found a couple of them:


auth=0

user: Lara+Anderton

First we tried to set auth = 1 and “Replay”-ed the POST request. The result was
Eyeballs.*

Again the next attempt was to set auth=1 and user=admin. This time we didn’t return empty handed. It displayed the following text


*Eyeballs.*key{I'd like a word with my husband.}

Solution: I'd like a word with my husband.

CSAW CTF 2012: Exploitation 1

0 Comments | This entry was posted on Oct 04 2012

Here the challenge was

nc 128.238.66.218 54321

Read the key out of ./key in the current working directory

Also we were given a binary called exploitation-release

Given the challenge, instead of doing reversing the binary, we blindly tried a buffer overflow by entering a lot of  ’a', and that worked! It immediately gave out the key.

CSAW CTF 2012: Recon 3

0 Comments | This entry was posted on Oct 03 2012

So, this was the challenge we had to solve:

Julian Cohen – 100 Points Julian Cohen

Obviously, we were given in the search the username HockeyInJune

After scratching our heads and searching his twitter, his github, his websites, we remember a general hint that was given: “Hint for Recon: Lots of judges really like Reddit.”

So, I started searching on Reddit and found one of his comments pointing to a webpage 

You don’t like roosters? :(

NSFWhttp://cockcab.com/

on http://www.reddit.com/user/HockeyInJune/comments/

On that page we saw the key. Challenge solved! 

CSAW CTF 2012: Reversing 1

0 Comments | This entry was posted on Oct 02 2012

For this problem, we had to patch an executable named csaw2012reversing.exe for 100 points.

After loaded in OllyDbg, we solved this problem by NOP-ing calls at virtual address 0x00D21106

Solution: welcome_to_csaw!

CSAW CTF 2012: Recon 1

0 Comments | This entry was posted on Oct 02 2012

We were only provided with the google search string on Jordan Wiens.

From Jordan’s Twitter account, we noticed that he has used the nick @psifertex there. Googling with psifertex led us to http://psifertex.com/. But the site contained nothing but the following text:

Nothing to see here, move along.

 What to do next? Let’s see what site’s robots.txt file says. Hmm, something was there.

User-agent: *
Disallow: /
Disallow: /csaw

It means that there is a directory /csaw there. Pretty interesting. We blindly tried to access the index.html there. What we found was the following:

Some Understanding Becomes Dominant On Manipulation And Inquisitive Naming

Don't bother brute forcing file paths, you'll never find it that way.

Collecting the initial letters of the first line gives the word: SUBDOMAIN. But, still the question was: which one?

We tried to google for the subdomain(s) of psifertex: site:psifertex.com, but the only subdomain we found was Corrupt The Youth. The source of the home page had this line commented:

Stuck! We tried nslookup psifertex.com and got 69.163.249.183 as response. Accessing http://69.163.249.183/ threw the following error:

Site Temporarily Unavailable

We apologize for the inconvenience. Please contact the webmaster/ tech support immediately to have them rectify this.
error id: "bad_httpd_conf"

We tried the quoted text above as the key, but no luck.

Also we found a download section with a bunch of rubbish documents lying around and one admin login form, too.

As the last resort, we started bruteforcing for possible unlisted subdomains:

http://csaw.psifertex.com
http://csawctf.psifertex.com
http://csawctf.psifertex.com
http://key.psifertex.com

The last one was the one which we were hunting for.

Solution: secret sonambulist

CSAW CTF 2012: Reversing 3

0 Comments | This entry was posted on Oct 02 2012

Here the challenge was to get the key out of a binary called CSAWQualification.exe for 300 points.

We used the same ILSpy decompiler that we used to solve one previous challenge. Following was the output from the decompiler:

// CSAWQualification.Program
private static void Main(string[] args)
{
Console.WriteLine("Do you really just run random binaries given to
you in challenges?");
Console.ReadLine();
Environment.Exit(0);
MD5CryptoServiceProvider mD5CryptoServiceProvider = new
MD5CryptoServiceProvider();
AesCryptoServiceProvider aesCryptoServiceProvider = new
AesCryptoServiceProvider();
foreach (string current in Directory.EnumerateDirectories(Program.target))
{
byte[] first =
mD5CryptoServiceProvider.ComputeHash(Encoding.UTF8.GetBytes(current.Replace(Program.target,
"")));
if (first.SequenceEqual(Program.marker))
{
byte[] rgbKey =
mD5CryptoServiceProvider.ComputeHash(Encoding.UTF8.GetBytes("sneakyprefix"
+ current.Replace(Program.target, "")));
ICryptoTransform cryptoTransform =
aesCryptoServiceProvider.CreateDecryptor(rgbKey, new byte[]
{
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15
});
byte[] bytes = cryptoTransform.TransformFinalBlock(Program.data, 0,
Program.data.Length);
Console.Write(Encoding.UTF7.GetString(bytes));
}
}
Console.ReadLine();
}

// CSAWQualification.Program
static Program()
{
// Note: this type is marked as 'beforefieldinit'.
Program.data = new byte[]
{
15,
83,
222,
204,
130,
169,
253,
55,
165,
229,
219,
240,
206,
78,
102,
131,
243,
100,
115,
102,
231,
76,
235,
175,
2,
193,
249,
172,
174,
172,
227,
120,
67,
118,
87,
221,
124,
97,
202,
124,
191,
209,
164,
8,
61,
224,
193,
83,
13,
137,
114,
140,
42,
65,
247,
237,
202,
71,
66,
38,
58,
205,
158,
199,
246,
205,
178,
248,
21,
55,
82,
239,
36,
107,
104,
230,
193,
63,
157,
178,
224,
48,
198,
4,
66,
221,
12,
211,
215,
103,
209,
14,
117,
139,
111,
162
};
Program.marker = new byte[]
{
255,
151,
169,
253,
237,
224,
158,
175,
110,
28,
142,
201,
246,
166,
29,
213
};
Program.target = "C:\\Program Files\\";
}

We noticed that because of lines like Environment.Exit(0), program was exiting prematurely.  We were somehow forced to install Visual Studio this time.  :-P Then we commented out the “culprit” lines of code, recompiled it to get the output.

CSAW CTF 2012: Reversing 2

0 Comments | This entry was posted on Oct 02 2012

Here the challenge was to get the key out of a binary named CSAWQualificationEasy.exe for 200 Points.

The binary is a .NET compiled program, so we used ILSpy to decompile it.

Below is the disassembled code for the main program segment

// CSAWQualificationEasy.Program
private static void Main(string[] args)
{
Console.WriteLine("Okay, going to compute the key. Have to remember
to write it out at the end! I keep forgetting!");
string arg = "";
byte[] array = Program.encrypted;
for (int i = 0; i < array.Length; i++)
{
byte b = array[i];
arg += Convert.ToChar((int)(b ^ 255));
}
Console.ReadLine();
}

If we would have Visual Studio installed on the system, it could be as easy as changing the Console.ReadLine() to Console.WriteLine(arg) and recompile it. As we did not have the M$ compiler installed and were too lazy to get such a bulky package installed, we rewrote it in Python.

The "encrypted" array contains this:

// CSAWQualificationEasy.Program
private static byte[] encrypted = new byte[]
{
171,
151,
154,
223,
148,
154,
134,
223,
150,
140,
223,
198,
156,
207,
198,
153,
199,
203,
206,
201,
158,
205,
205,
207,
201,
205,
205,
206,
154,
202,
207,
157,
198,
199,
154,
204,
203,
201,
207,
203,
200,
157,
200
};

Accordingly, the Python script was 

# Encrypted bytes array of the .NET program:
encrypted_list = [ 171, 151, 154, 223, 148, 154, 134, 223, 150, 140,
223, 198, 156, 207, 198, 153, 199, 203, 206, 201, 158, 205, 205, 207,
201, 205, 205, 206, 154, 202, 207, 157, 198, 199, 154, 204, 203, 201,
207, 203, 200, 157, 200 ]

# This will contain the output string:
decrypted = ""

# Reimplement the for loop to decrypt the string:
for encrypted_chr in encrypted_str:
decrypted = decrypted + chr(encrypted_chr ^ 255)

# Print decrypted string
print decrypted

The output from the script was the solution itself.

Solution: 9c09f8416a2206221e50b98e346047b7

CSAW CTF 2012: Trivia 2

0 Comments | This entry was posted on Oct 02 2012

What is the name of the Google's dynamic malware analysis tool for Android applications?

We solved this one through a search on Bing for “dynamic malware analysis tool for Android applications”

The three line preview for each link gave already some feeling where it is worth to look at. Iirc on the third page was the link for a web page where the correct solution “Bouncer” could be found.

Solution: Bouncer