Monday, September 29, 2014

SU CTF 2014 - Secure Coding-2 write-up

original source

Rules & Notes

  • MISSION: You should fix vulnerabilities of the given source code, WITHOUT changing its normal behavior.
  • RULE0: When an honest user gives a non-malicious (but maybe incorrect) input which does not trigger the vulnerabilities,
    the output of uploaded fixed code should be the same as before.
  • RULE1: When the attacker gives his/her attack vector, your program should not crash or do dangerous actions (explained below),
    but continue its execution and exit normally at the end. In this situation, your program is allowed to output anything.
  • RULE2: A (poorly-tested) source code may crash even when interacting with a normal user. You should fix these cases too.
    (NOTE: the output should be correct in this case)
  • Dangerous actions (stated above) includes buffer overflows, writing to unallocated memory address, reading uninitialized memory,
    and any other programming mistakes leading to crash/instability.
  • Some prevention techniques, detect the attack and prevent memory corruption but throw an exception which terminates the program,
    leading to denial of service. You should avoid such termination and the program should recover from the attack, continue execution,
    and exit normally at the end.

FIXED CODE:
update: this code is still vulnerable but earned the flag for us.
verifier: http://ctf.sharif.edu:53840/problem.php?problem=ctf5quals_seccoding2
#include <stdio.h>
#include <string.h>
#include <stdlib.h>


void continueHandler(const wchar_t * expression,
 const wchar_t * function, const wchar_t * file,
 unsigned int line, uintptr_t pReserved)
{
 // just continue
}

void safefree(char **ptr)
{
 if (*ptr != NULL)
 {
  free(*ptr);
  *ptr = NULL;
 }
}

int main()
{
 char tmp[50];

 printf("Line Editor\n");
 printf("-----------\n\n");

 int size;
 printf("Line size: ");
 //=============================================================
 // set limit for scanf
 scanf("%3d", &size); // [3-...-9]
 //=============================================================
 
 //=============================================================
 // exit program if lenght is zero or negative
 if (size <= 0)
  return -14;
 //=============================================================

 gets_s(tmp, sizeof(tmp));

 char *line = (char *)malloc(size + 1);

 _set_invalid_parameter_handler(continueHandler);

restart:
 line[0] = 0;

 while (1)
 {
  printf("Enter the offset (or \"quit\"): ");
  gets_s(tmp, sizeof(tmp));

  if (!strcmp(tmp, "quit"))
  {
   printf("OUTPUT LINE: %s\n\n", line);
   //=============================================================
   // After restart ,line(variable) does not exist, and crash occurs on (line[0] = 0) statement
   // so move [call safefree()] to end of the code
   // safefree(&line);
   //=============================================================
   break;
  }

  //=============================================================
  // use unsigned int instead of int
  unsigned int offset;
  //=============================================================
  if (!(offset = atoi(tmp)) || offset - 1 > (int)strlen(line))
  {
   printf("ERROR\n");
   continue;
  }

  printf("Enter the text: ");
  gets_s(tmp, sizeof(tmp));

  //=============================================================
  // Use (strcpy_s) instead (_snprintf_s); to prevent format string attack
  if (strcpy_s(line + (offset - 1), size - (offset - 1) + 1, tmp) != 0)
  //=============================================================
  {
   printf("ERROR\n");
   line[size] = 0;
   continue;
  }
 }

 printf("Restart (y/n): ");
 scanf("%s", tmp);
 if (tmp[0] == 'y')
 {
  gets_s(tmp, sizeof(tmp));
  goto restart;
 }

 //=============================================================
 safefree(&line);
 //=============================================================

 return -14;
}

Sunday, September 28, 2014

SU CTF 2014 - Commercial Application! write-up

Download

The apk is not protected. we used www.decompileandroid.com to get the source.
sqllite db in located in assets/db.db which contains IV and key:

a5efdbd57b84ca36
37eaae0141f1a3adf8a1dee655853714

we changed the src/edu/sharif/ctf/security/KeyVerifier.java to make it decrypt the  VALID_LICENCE



import java.util.*;
import java.lang.*;
import java.io.*;
import java.security.MessageDigest;
import java.util.Arrays;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.crypto.spec.IvParameterSpec;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

class Ideone {
  static String IV = "a5efdbd57b84ca36";
  static String encryptionKey = "37eaae0141f1a3adf8a1dee655853714";
  public static void main(String[] args) {
    try {
      byte[] cipher = hexStringToBytes("29a002d9340fc4bd54492f327269f3e051619b889dc8da723e135ce486965d84");
      System.out.println("cipher:  ");
      for (int i = 0; i < cipher.length; i++)
        System.out.print(new Integer(cipher[i]) + " ");
      String decrypted = decrypt(cipher, encryptionKey);
      System.out.println("");
      System.out.println("decrypt: " + decrypted);
    } catch (Exception e) {
      System.out.println(e.getMessage());
      e.printStackTrace();
    }
  }

  public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKeySpec key = new SecretKeySpec(hexStringToBytes(encryptionKey), "AES");
    cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(IV.getBytes()));
    return cipher.doFinal(plainText.getBytes("UTF-8"));
  }

  public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
    SecretKeySpec key = new SecretKeySpec(hexStringToBytes(encryptionKey), "AES");
    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(IV.getBytes()));
    return new String(cipher.doFinal(cipherText), "UTF-8");
  }
  public static byte[] hexStringToBytes(String s) {
    int i = s.length();
    byte abyte0[] = new byte[i / 2];
    int j = 0;
    do {
      if (j >= i) {
        return abyte0;
      }
      abyte0[j / 2] = (byte)((Character.digit(s.charAt(j), 16) << 4) + Character.digit(s.charAt(j + 1), 16));
      j += 2;
    } while (true);
  }
  public static String bytesToHexString(byte abyte0[]) {
    StringBuilder stringbuilder = new StringBuilder();
    int i = abyte0.length;
    int j = 0;
    do {
      if (j >= i) {
        return stringbuilder.toString();
      }
      byte byte0 = abyte0[j];
      Object aobj[] = new Object[1];
      aobj[0] = Integer.valueOf(byte0 & 0xff);
      stringbuilder.append(String.format("%02x", aobj));
      j++;
    } while (true);
  }

}

result:
cipher:  
41 -96 2 -39 52 15 -60 -67 84 73 47 50 114 105 -13 -32 81 97 -101 -120 -99 -56 -38 114 62 19 92 -28 -122 -106 93 -124 
decrypt: fl-ag-IS-se-ri-al-NU-MB-ER

SU CTF 2014 - Touran City-1 write-up

Due to economic downturns and lack of resources, Monsters Inc. has decided to scare kids regularly door to door, instead of using their teleport technology. Their office in Touran City has developed an Android app, which is used by the head office to communicate with the monsters (i.e. transmit new assignments to them). Recently, the Touran City Police Department (TCPD) tracked and captured a thief and found a cell phone on him. It seems that the thief had stolen the cell phone from one of the Monsters Inc. employees. A backup of the cell phone is attached.
Can you find out whose phone is this?

Flag: Full Name of the Monster

Solution:

The attached file is standard android backup without password. we can convert it to tar file with this command:

dd if=phone-backup bs=24 skip=1 | openssl zlib -d > phone-backup.tar

the backup contains an apk file which sound interesting:
/apps/inc.monsters.commandservice/a/inc.monsters.commandservice-1.apk

it also contains a file containing username and password:
/apps/inc.monsters.commandservice/sp/inc.monsters.commandservice.xml



apk file has no protection and can be easily decompiled. we used www.decompileandroid.com
in source files, from src/inc/monsters/commandservice/TrackerService.java this line pops out:
endpoint = "http://ctf.sharif.edu:8085/webservice.php";
went to http://ctf.sharif.edu:8085/ and logged in using retrieved info from xml file.
the website sets a silly cookie called isAdmin and by setting int to yes, you become admin in it.

in page source we searched for “c6bce”.
the flag is :  Lenna Aubut

SU CTF 2014 - Decrypt the message! write-up

The life that I have
Is all that I have
And the life that I have
Is yours.

The love that I have
Of the life that I have
Is yours and yours and yours.

A sleep I shall have
A rest I shall have
Yet death will be but a pause.

For the peace of my years
In the long green grass
Will be yours and yours and yours.

decrypted message: emzcf sebt yuwi ytrr ortl rbon aluo konf ihye cyog rowh prhj feom ihos perp twnb tpak heoc yaui usoa irtd tnlu ntke onds goym hmpq

Solution:

This is a WWII poem code encryption. more details.
The key length must be 25 characters:
yours shall pause peace years 
The flag becomes:
if you think cryptography is the answer to your problem then you do not know what your problem is
Happy hunting!

UPDATE: Balalaika Cr3w wrote cool script for the decryption phase:

#!/usr/bin/env python
import string

encrypted = ["sebt", "yuwi", "ytrr", "ortl", "rbon", "aluo", "konf", "ihye", "cyog",
 "rowh", "prhj", "feom", "ihos", "perp", "twnb", "tpak", "heoc", "yaui", "usoa", "irtd",
  "tnlu", "ntke", "onds", "goym", "hmpq"]

passphrase = "yoursshallpausepeaceyears"
alph = string.ascii_lowercase
count = 1
passkey = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
for a in alph:
 for i in xrange(len(passphrase)):
  if passphrase[i:i+1] == a:
   passkey[i] = count
   count +=1

print "Key is " + str(passkey)

result =""
for i in xrange(4):
 for j in xrange(len(passkey)):
  test = j + 1
  for k in xrange(len(passkey)):
   if test == passkey[k]:
    result = result + encrypted[k][i:i+1]

print "Decrypted message is " + result

SU CTF 2014 - Hear With Your Eyes write-up

sound.wav

Open sound.wav file with an audio analyzer tool. For this case we used Spectro:


happy hunting!

SU CTF 2014 - reverse me write-up

Question:

Reverse me and find a valid serial number!
flag : [A valid serial number]

Solution:

The given file is ASPacked which is pretty easy to unpack via Immunity Debugger:
  • Step Into (F7) the first instruction pushad
  • In the dump, below the disassembler, right-click and select Go to -> Expression (Ctrl+G)
  • type esp and hit enter
  • Select the first four bytes, right-click and select Breakpoint -> Hardware, on access -> Dword
  • Select Debug -> Run (F9)
    bottom status bar says “Hardware breakpoint 1″
  • Step Into (F7) until retn to the OEP address
  • right-click in the disassembler and select Analysis -> Analyse code (Ctrl+A)

Now we need to find the address of the function which works on the serial number. (00401199)

Then you should trace each character one from first and one from last in the serial number and make calculations to find the right serial number.


happy hunting!

SU CTF 2014 - 2048 write-up

Question:

What is the ip of the victim? 
Falg is: md5(ip)

Solution:

Scrolling down the code in IDA two funtions pop out:
  • bot_run
  • attack


there is a "system" call in the attack function which tries to run this command:
wget http://ctf.sharif.edu/{code}/target.txt
by more inspection  one must notice the binary MD5 must not change and the generated {code} is time-dependent. 

in check time function 
Calculates 52c35a80 = 1388534400 
-->  UNIX time --> Wednesday 1st January 2014 12:00:00 AM 
Set time, and got correct file:
http://ctf.sharif.edu:2048/7266de4447eba9a354622271cff2dde5/target.txt
target.txt contain an IP address which was 95.211.102.203 and the flag becomes 5cfed0f91a2b71a5d79aa681eaf10adb

happy hunting!