Sunday 7 February 2016

CTF Writeup - Sharif University CTF 2016 - Android App (RE 100)


  • Name - Android App
  • Category - Reverse Engineering
  • Points - 100
  • Description - Find the Flag!!
  • Binary - Download here

This challenge is a good exercise for those of you who would like to start REing android apps. Once again the application accepts a serial number and validates it:


Extract the apk file and open classes.dex with Jadx. You can use dex2jar and jdgui for this but I found that Jadx gives better results. The part we're interested in resides in the button's listener, onClick() in class a:

public void onClick(View view) {
    String str = new String(" ");
    str = this.a.b.getText().toString();
    Log.v("EditText", this.a.b.getText().toString());
    String str2 = new String("");
    int processObjectArrayFromNative = this.a.processObjectArrayFromNative(str);
    int IsCorrect = this.a.IsCorrect(str);
    str = new StringBuilder(String.valueOf(this.a.d + processObjectArrayFromNative)).append(" ").toString();
    try {
        MessageDigest instance = MessageDigest.getInstance("MD5");
        instance.update(str.getBytes());
        byte[] digest = instance.digest();
        StringBuffer stringBuffer = new StringBuffer();
        for (byte b : digest) {
            stringBuffer.append(Integer.toString((b & 255) + 256, 16).substring(1));
        }
        if (IsCorrect == 1 && this.a.e != "unknown") {
            this.a.c.setText("Sharif_CTF(" + stringBuffer.toString() + ")");
        }
        if (IsCorrect == 1 && this.a.e == "unknown") {
            this.a.c.setText("Just keep Trying :-)");
        }
        if (IsCorrect == 0) {
            this.a.c.setText("Just keep Trying :-)");
        }
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
}

Our input is read from the textfield (line 3) and passed to the IsCorrect() function (line 7). Unfortunately this function is part of the adnjni library (\lib\armeabi folder); it would've been too easy if it was written in Java. Load the library in IDA and locate the function Java_com_example_ctf2_MainActivity_IsCorrect(). The first section looks like this:

v9 = (char *)(*(int (**)(void))(*(_DWORD *)a1 + 676))();
v12 = 101;
v13 = 102;
v14 = 53;
v15 = 55;
v16 = 102;
v17 = 51;
v18 = 102;
v19 = 101;
v20 = 51;
v21 = 99;
v22 = 102;
v23 = 54;
v24 = 48;
v25 = 51;
v26 = 99;
v27 = 48;
v28 = 51;
v29 = 56;
v30 = 57;
v31 = 48;
v32 = 101;
v33 = 101;
v34 = 53;
v35 = 56;
v36 = 56;
v37 = 56;
v38 = 55;
v39 = 56;
v40 = 99;
v41 = 48;
v42 = 101;
v43 = 99;
v44 = 0;
v4 = 0;
v45 = 53;
v10 = j_j_strcmp(v9, &v12);

Notice that at the bottom (line 37), 2 strings are being compared. Variable v9 contains our input string and variable v12 contains the string shown on lines 2 to 34. Once again, converting from decimal to ASCII we get ef57f3fe3cf603c03890ee588878c0ec.

And hence:

CTF Writeup - Sharif University CTF 2016 - SRM (RE 50)


  • Name - SRM
  • Category - Reverse Engineering
  • Points - 50
  • Description - The flag is : The valid serial number
  • Binary - Download here

Yep it's a Windows binary! It's not everyday we encounter a Windows binary in a CTF. Run it:


Looks like a keygen. Inputting garbage in both fields pops up the following message box:


In IDA we notice that the validation logic resides in the DialogFunc() function. The first check is done on the email address.


The functions accept any valid email address so test@test.com will do (for now ?). The error message now is different:


Next is the Serial Number validation. The code is quite simple:
if ( strlen(v11) != 16
  || v11[0] != 67
  || v23 != 88
  || v11[1] != 90
  || v11[1] + v22 != 155
  || v11[2] != 57
  || v11[2] + v21 != 155
  || v11[3] != 100
  || v20 != 55
  || v12 != 109
  || v19 != 71
  || v13 != 113
  || v13 + v18 != 170
  || v14 != 52
  || v17 != 103
  || v15 != 99
  || v16 != 56 )
{
  sub_4030C7(&Text, 256, &v28);
}
else
{
  sub_4030C7(&Text, 256, &v25);
  sub_403121(&Text, 256, v11);
}

The serial number has to be 16 characters long (line 1). The checks are not sequential but they do follow a pattern: 1st, last, 2nd, 2nd to last, 3rd, 3rd to last, etc. At this point either go through it step by step or order the variables: v11[0], v11[1], v11[2], v11[3], v12, v13, .., v23. Converting from decimal to ASCII we get CZ9dmq4c8g9G7bAX. Input the email and serial number:

CTF Writeup - Sharif University CTF 2016 - dMd (RE 50)


  • Name - dMd
  • Category - Reverse Engineering
  • Points - 50
  • Description - Flag is : The valid input
  • Binary - Download here

Running the 64-bit ELF:

root@kali: ~/Desktop
root@kali:~/Desktop# ./dMd Enter the valid key! testing123 Invalid Key! :( root@kali:~/Desktop#

Nothing complicated. We need to find the correct key. Loading it in IDA, we're greeting with a long list of checks, one for each byte of a string. An excerpt for bytes 4 to 7 is shown below:



To make things easier, the pseudo code looks like this:

v44 = *MK_FP(__FS__, 40LL);
std::operator<<<std::char_traits<char>>(6308448LL, 4204712LL, envp);
std::operator>><char,std::char_traits<char>>(6308160LL, &v43);
std::allocator<char>::allocator(&v39);
std::string::string(&v40, &v43, &v39);
md5(&v41, &v40);
v42 = std::string::c_str((std::string *)&v41);
std::string::~string((std::string *)&v41);
std::string::~string((std::string *)&v40);
std::allocator<char>::~allocator(&v39);
if ( *(_BYTE *)v42 != 55
  || *(_BYTE *)(v42 + 1) != 56
  || *(_BYTE *)(v42 + 2) != 48
  || *(_BYTE *)(v42 + 3) != 52
  || *(_BYTE *)(v42 + 4) != 51
  || *(_BYTE *)(v42 + 5) != 56
  || *(_BYTE *)(v42 + 6) != 100
  || *(_BYTE *)(v42 + 7) != 53
  || *(_BYTE *)(v42 + 8) != 98
  || *(_BYTE *)(v42 + 9) != 54
  || *(_BYTE *)(v42 + 10) != 101
  || *(_BYTE *)(v42 + 11) != 50
  || *(_BYTE *)(v42 + 12) != 57
  || *(_BYTE *)(v42 + 13) != 100
  || *(_BYTE *)(v42 + 14) != 98
  || *(_BYTE *)(v42 + 15) != 48
  || *(_BYTE *)(v42 + 16) != 56
  || *(_BYTE *)(v42 + 17) != 57
  || *(_BYTE *)(v42 + 18) != 56
  || *(_BYTE *)(v42 + 19) != 98
  || *(_BYTE *)(v42 + 20) != 99
  || *(_BYTE *)(v42 + 21) != 52
  || *(_BYTE *)(v42 + 22) != 102
  || *(_BYTE *)(v42 + 23) != 48
  || *(_BYTE *)(v42 + 24) != 50
  || *(_BYTE *)(v42 + 25) != 50
  || *(_BYTE *)(v42 + 26) != 53
  || *(_BYTE *)(v42 + 27) != 57
  || *(_BYTE *)(v42 + 28) != 51
  || *(_BYTE *)(v42 + 29) != 53
  || *(_BYTE *)(v42 + 30) != 99
  || *(_BYTE *)(v42 + 31) != 48 )


An md5 hash of our input (line 6) is computed and evaluated byte by byte. Converting decimal to ASCII we get: 780438d5b6e29db0898bc4f0225935c0. Using hashkiller, we get md5(md5("grape")). We only need one md5 so the input must be md5("grape"): b781cbb29054db12f88f08c6e161c199

root@kali: ~/Desktop
root@kali:~/Desktop# ./dMd Enter the valid key! b781cbb29054db12f88f08c6e161c199 The key is valid :) root@kali:~/Desktop#

Friday 5 February 2016

Arduino - Analog I/O

Sensors allow microcontrollers to receive information from the outside world. Surprisingly, we've already used one of the most simple sensors, the push-button. These input devices can vary their resistivity or voltage depending on external factors such as light, sound, temperature, humidity, etc. In this post we'll be dealing with resistive sensors. As an example, a photoresistor's resistance decreases the more light it senses, meaning that the voltage allowed through increases proportionally with light intensity (Ohm's law). This is important as microcontrollers can only measure voltage.

Most of these sensors vary their resistance gradually and hence the voltage allowed can be 0V, 5V, or anything in between. This can be measured using the 5 analog pins: A0 to A5.

Reading Analog Input


The function to read Analog input is not much different than it's Digital counterpart:
  • analogRead (pin) - Returns voltage level of an INPUT pin.
    • pin - The pin in question; can be A0, A1, ..,or A5
    • Return Values - An integer between 0(0V) and 1023(5V);
    • Example - int pinValue = analogRead(A0)
Note that Analog pins are capable of outputting digital voltage and hence, if necessary, can be used with functions digitalRead() and digitalWrite() as if they were digital pins. In the next example we'll leverage the analogRead() function to create a circuit which lights an LED if the light intensity sensed by a photoresistor is below some threshold. Construct the following circuit:



For those of you who are not used to the symbols of electronic components, R1 and R3 are resistors, R2 is the potentiometer and D1 is an LED. Upload the code below:

const int lightSensor = A0;
const int ledPin = 9;

void setup (){
    pinMode(lightSensor, INPUT);
    pinMode(ledPin, OUTPUT);
}

void loop (){
    if ( analogRead(lightSensor) < 100 )
        digitalWrite(ledPin, HIGH);
    else
        digitalWrite(ledPin, LOW);
}

If there's enough light in the room, the LED should be off. Test the circuit by switching the lights off; putting your hand on the photoresistor should do the trick too. In this example I've chosen "100" to be the threshold. To choose a threshold that better suits your purposes, output the result of analogRead() to the serial monitor, switch the lights off and on to record the maximum and minimum values and choose accordingly. This is how mine looks:




Another resistive sensor which is quite common in everyday life is the potentiometer, a device which allows us to manually regulate the resistance by twisting a knob. If you're thinking of dimmer switches, you're on the right track. As an exercise use a potentiometer to control the speed at which an LED blinks.

Analog Output ?


Most microcontrollers can only generate digital output, 0V or 5V. At the same time we see a lot of actuators (output devices) around us where a simple ON and OFF is not enough: speed of a motor or brightness of an LED. This can be achieved in 2 ways, either using a Digital to Analog Converter (DAC) chip, which I haven't got at my disposal, or using Pulse Width Modulation (PWM). PWM is a method which uses the average voltage of a wave to fake analog voltage. The following image from arduino.cc explains it very well:



The green lines depict a cycle. As an example, if 5V is held for 25% of a cycle, then the output is 1.25V., if it's held for 50% of a cycle, the output is 2.5V, and so on. To use the exact terminology, the percentage of time the maximum voltage is held is called a Duty Cycle. This technique is called Pulse Width Modulation as we're using the width of the pulse to determine the perceived analog voltage.

If all this theory of how PWM works has confused you, don't worry! There's the function which let's us output analog signals without the need to understand how it works, and yes it's called analogWrite().
  • analogWrite (pin, value) - Assigns a voltage to a pin
    • pin - The PWM pin in question; On the UNO this can be 3, 5, 6, 9, 10, or 11
    • value - An integer between 0(0V) and 255(5V);
    • Example - analogWrite (3, 100)

Note that PWM can only be generated on a subset of the digital pins. These can be identified on the board by the tilde(~) sign next to their number. Let's use analogWrite() to create a fading LED. Wire the usual basic circuit (resistor + LED) and upload the following code:

int brightness = 0;
int ledPin = 9;
int fadeAmount = 5;

void setup() {
    pinMode (ledPin, OUTPUT);
}

void loop() {
    analogWrite (ledPin, brightness);
    brightness = brightness + fadeAmount;
    if (brightness == 0 || brightness == 255)
        fadeAmount = -fadeAmount;
    delay (20);
}


In each iteration of the loop() function, the brightness increases by the fadeAmount variable, in this case 5. When the brightness reaches 0 or 255, minimum and maximum respectively, the fadeAmount changes direction and becomes -5 if it was 5 and vice-versa. Successful implementation will look like this:




Hopefully by now you're confident with analogRead() and analogWrite(). Let's create our last circuit which uses both functions. We'll extend the circuit we've just created to accept analog input via a potentiometer. We'll be using this to control the brightness of an LED. The output section of the circuit is a simple circuit. Make sure to choose a pin which supports PWM. The input section only contains a potentiometer. The following is the full schematic:



R1 is naturally the potentiometer. Upload the following code:

const int analogInPin = A0;
const int analogOutPin = 3;

void setup() {
    pinMode (A0, INPUT);
    pinMode (3, OUTPUT);
}

void loop() {
    int sensorValue = analogRead(analogInPin);
    int outputValue = map(sensorValue, 0, 1023, 0, 255);
    analogWrite(analogOutPin, outputValue);
}


The diligent reader by now would have realized that analogRead() has a range of 0 (0V) to 1023(5V) whereas the range of analogWrite() is 0 (0V) to 255(5V). To easily translate from one range to another we use the map() function.
  • map (value, fromLow, fromHigh, toLow, toHigh) - Maps a range to another; returns the mapped value
    • value - The value to be translated
    • fromLow - The lower bound of the source's range
    • fromHigh - The upper bound of the source's range
    • toLow - The lower bound of the destination's range
    • toHigh - The upper bound of the destination's range
    • Example - int oValue = map (iValue, 0, 1023, 100, 255);
And the circuit in action:

Monday 1 February 2016

Arduino - Debugging via Serial

The ability to debug code is indispensable. This can be quite tricky when working with microcontrollers as they do not have in-built displays, used to observe intermediate results, nor built-in input devices, for data controllability. When programming on a computer we can use print statements to trace issues. We can also input expected and unexpected data to see how the system operates under different scenarios.

The Serial Interface


Debugging in Arduino is done through the serial interface. It communicates on pin0(RX) and pin1(TX) or, more conveniently, via USB. A serial interface is much slower than a parallel one as it sends 1 bit at a time but requires only 2 pins, making it a very popular choice for debugging in the microcontroller world where pins are precious.

For 2 ends to communicate, they require a protocol which is understood by both. The Arduino's serial interface uses the Universal Asynchronous Receiver/Transmitter (UART) protocol. Most microcontrollers these days have hardware support for UART. We won't go into detail about its inner workings, but the following is some useful terminology:
  • Bit Duration (T) - The time each bit is transmitted for; measured in seconds
  • Baud Rate (f) - Number of transmissions per second; the frequency; measured in bits per second
  • Baud Rate/Bit Duration relationship
    • T = 1/f : Bit duration and frequent are inversely proportional to each other
    • Example: if F = 9600 baud, then T is ~104 microseconds
    • Transmission rate is always less than Baud rate due to overhead caused by the start bit(s), stop bit(s) and parity bit(s) which are required by the UART protocol to operate

The Serial Monitor


To access the power of debugging on the Arduino, connect it to the computer and, from the IDE, go to Tools -> Serial Monitor. You should be presented with something similar to the following:



The Serial Monitor is minimalistic. It contains a text field to send data to the device, a message box to display the data received, and a few settings such as the Baud rate. The latter has to match the rate we set in the sketch. Since UART is asynchronous, and hence does not require a clock, the rate has to be predetermined and set to match on both ends. We now jump to the Arduino part and see how the Serial interface can be used to control the Arduino.

The Serial Library


The Serial library permits us programmatically send and receive messages from the Serial monitor. Let's take a look at some of the functions it has to offer:
  • Serial.begin (speed [, config]) - Initialises serial communication
    • speed - Baud rate; must match the Baud rate set in the Serial Monitor
    • config - An optional parameter which configures the data, parity and stop bits. Below are some examples
      • SERIAL_8N1 - 8 data bits; no parity; 1 stop bit (Default configuration)
      • SERIAL_6N2 - 6 data bits; no parity; 2 stop bits
    • Examples - Serial.begin(9600), Serial.begin(9600, SERIAL_8N1)
  • Serial.print (value [, format]) - Prints ASCII text to the Serial Monitor; returns # of chars written
    • value - The value to be sent
    • format - Specifies number base (BIN/OCT/DEC/HEX) or decimal places (0, 1, 2, ...); Optional parameter
    • Examples
      • Serial.print ("Test") - Returns: Test
      • Serial.print (321) - Returns: 321
      • Serial.print (321, BIN) - Returns: 101000001
      • Serial.print (321.123, 2) - Returns: 321.12
  • Serial.println (value [, format]) - Same as print() but adds '\r\n' at the end

Let's use these newly learnt functions to create a circuit which displays ON on the Serial Monitor when a push-button is pressed and OFF otherwise. Set up the schematic used in the previous post.

And upload the following code:

void setup() {
    Serial.begin(9600);
    pinMode(10, INPUT);
}

void loop() {
    if ( digitalRead(10) == HIGH )
        Serial.println ("ON");
    else
        Serial.println ("OFF");
}


The sketch initialises the serial interface with 9600 baud, sets pin10 in INPUT mode and constantly reads it's voltage level. If HIGH, i.e. the push-button is pressed, the Serial Monitor displays ON, else OFF. Make sure the baud rate matches the one set in the IDE. After uploading, the result should look something like this:




Writing to the serial interface is as easy:
  • Serial.available() - Returns number of bytes waiting in the buffer to be read
    • Example - int bufBytes = Serial.available()
  • Serial.read() - Reads a single byte from incoming serial data; returns -1 if no data available
    • Example - int bufByte = Serial.read()
  • Serial.readString() - Reads bytes from serial buffer to string
    • Example - String bufString = Serial.readString()
  • Serial.readBytes (buffer, length) - Reads bytes from serial buffer to buffer; returns # of chars written
    • buffer - The destination buffer; Can be char[] or byte[]
    • length - Number of bytes to read
    • Example - char buf[10]; int bytesRead = Serial.readBytes(buf, 10)
As an example of reading bytes from serial we'll build a Serial-controlled LED: when a 1 is sent to the Arduino, an LED lights, until we send a 0. Wire the following circuit which we've used in the previous post:

Upload the following sketch:

void setup() {
    Serial.begin(9600);
    pinMode(9, OUTPUT);
}

void loop() {

    if ( Serial.available() ){    
        int inputDigit = Serial.read();
        
        if ( inputDigit == 49 )
            digitalWrite(9, HIGH);
        else if ( inputDigit == 48 )
            digitalWrite(9, LOW); 
    }
}

The Arduino will constantly poll for available data to be read from the serial buffer and if there is, it will read a single byte. If the ASCII value of the byte read is 49, which translates to 1, it sends current down pin9, if the ASCII value is 48, i.e. a 0, it will stop sending. Successful implementation will look like this: