Sunday, December 11, 2016

Cybersocks Regional 2016 - Challenge 1 - Write-Up


File : https://drive.google.com/open?id=0B_TlESfLlYGQY05TWmlNSHhXS1k

Unfortunately, we didn't manage to solve this question while at the competition. So to redeem the 'sin' here is the write-up.

We had been given a somewhat raw file (encrypt.bin), which it size around 1GB++ size.

Using 'file' command doesn't give us something good.
shahril:ch1$ file encrypt.bin 
encrypt.bin: data

So back to the basic! View it using any hex editor.



There is a lot of  As characters there. If you scroll much further, you will see that there is a lot of chunk of bytes with As characters.

Maybe this file had been xored with an A characters before? This makes sense because if the original file has a lot of zero bytes, and if all of that zero bytes is xor with an 'A' character, the result will always going to be an 'A' character also. This assumption works on a lot of files, but not all (it will not work to the file containing randomly generated bytes).

However, we also have another problem. On the internet, a lot of xor-decoding tools can't handle such a big file in order to xor it back to original file. Most of the tools that I tried will throw a "Memory exhausted"-something like that error before the operation finished. My early assumption is that most of the tool stored the resultant xored bytes into the memory before it writes to the disk.

So, how can we deal with that problem? We write our own decoding program. It shouldn't be that hard.


#include <stdio.h>

/*
 * Thanks Shahriman Caah for the recommendation
 * that using C is faster for large IO operation
 */

int main() {

    char buf[1024];
    int bRead, filesize;
    FILE *fi = fopen("./encrypt.bin", "r");
    FILE *fo = fopen("./out.bin", "w");
    char xor_key = 'A';

    // get filesize
    fseek(fi, 0, SEEK_END); // seek to end
    filesize = ftell(fi);
    fseek(fi, 0, SEEK_SET); // seek back to beginning
    
    for(int i = 0; (bRead = fread(buf, sizeof(char), sizeof(buf), fi)) > 0;) {
        for(int x = 0; x < bRead; x++) buf[x] = buf[x]^xor_key;
        fwrite(buf, sizeof(char), bRead, fo);
        i += bRead;
        printf("\r%.4lf%%", (double)i/filesize*100); 
    }

    printf("\nAll finished!\n");
    return 0;
}

Let's look again,

shahril:ch1$ ls
bce2a76d4b0804b0cc01cb8f8385b7fb_.7z  encrypt.bin  xor.py

We have the code, compile & then run it,

shahril:ch1$ gcc xor.c -o xor -O3
shahril:ch1$ time ./xor
100.0000%
All finished!

real    0m4.309s
user    0m1.160s
sys     0m0.952s

Take a look again at the 'out.bin' file using Hex editor.


You must be kididng me!!! (pun intended) The header now shows 'KDMV' and it contains some junk data below it!!!

So run the `file` command again,

shahril:ch1$ file out.bin 
out.bin: VMware4 disk image

It is then obvious now.

With no further ado, load it up using Virtualbox.


While the Virtualbox load it up, this loading wallpaper appears,


What a memory!!

After the desktop appears, there are flag.txt inside it. Could it contain the flag? (tradam-dam-dam)

Arghhh, what again?!! (pun intended)


So finally! We have the final flag `do_you_like_ransomware?`.

Till we meet again. :)
Regards.

Tuesday, December 6, 2016

KPMG Cyber Security Challenge 2016 - Questions Uploaded (Unofficial)

We have managed to collect some questions that were recently out at the competition. So by the spirit of "Sharing is Caring", we'd uploaded all questions that we have into Google Drive, just in case anyone wants to try this year questions in the future.

Questions :
https://drive.google.com/open?id=0B_TlESfLlYGQdnV5ZVVDUTdTNHM

For the write-ups, you can try to look at the previous post from Mokhdzani :
https://justanotherctfnewbie.blogspot.com/2016/11/kpmg-cyber-security-challenge-2016.html

The repository isn't completed though with all the questions. So if you have questions that we don't and want to contribute, please don't hesitate to contact me : mohd_shahril_96 [at] yahoo [.] com. I'll gladly add that to the repo. :)

Regards.

Sunday, October 23, 2016

UTPHAX'16 Pre-liminary Challenge 4 (Encryptilicous) Write-Up

Challenge Files :  https://drive.google.com/open?id=0B_TlESfLlYGQakdRQnljVnVVbjg

Anyone who reversed the binary should come to the conclusion that it is just using xor encrypt (very simple encryption algorithm) to encrypts the data, with having the key 'dafa' hardcoded into the binary.

However, most of us might be confused with the fact that the output isn't same with the value returns by the encryptor function.

Observation

Let us observe below behavior, suppose that I want to encrypt "kkkk" with the encryptor program.

shahril:q4$ wine encryptor.exe > kkkk.bin
kkkk
shahril:q4$ cat kkkk.bin | xxd -c 20
00000000: 456e 7465 7220 7465 7874 2079 6f75 2077 616e 7420  Enter text you want 
00000014: 746f 2065 6e63 7279 7074 3a0f 0d0a 0d0d 0a0d 0a    to encrypt:........

The output is the part that I highlighted, so the output will be :

0xf 0xd 0xa 0xd 0xd 0xa 0xd 0xa

Observing the above output, you must feel weird. How can suddenly "kkkk" produces 8 bytes hex while it should produce only 5 bytes hex (the xor-ed string + null terminator).

Hmm. something must be wrong here....

Firstly I thought that this behavior was produced by the encryptor.exe itself. So I studied the binary to observe whether this behavior is intended by the author or not.


So from above GIF, the encryptor function returns string containing the :

0xf 0xa 0xd 0xa

So above output hex length (4) + null terminator (1) = (5) output that we expected from the program.

So what is wrong here?

Null Terminator/Line Ending

There are one thing that needs to be clear out first, the behavior of line terminator between Windows and Unix-like OS is different.

Windows uses \r\n or 0xd 0xa for its line terminator.
Unix-like (Mac or Linux) uses \n or 0xa for its line terminator.

Read more here : http://www.cs.toronto.edu/~krueger/csc209h/tut/line-endings.html

The different between line terminator behavior might confuse many of us, especially for those who didn't know that Windows uses different line ending than most OS do.

For those who had been programming inside Windows before, you all must have the experience where some naïve editor such as Windows's Notepad doesn't line terminate the \n byte. It only terminates when we put \r\n (carriage return + newline) inside the text file.

Identifying The Problem

After observing the encryptor.exe with PE file identifier, it said the program was compiled using GCC MINGW-64w compiler under Windows.


To make the problem much more easier to observe, let us create a simple program using C, that will print only a newline character to the stdout (screen).

#include <stdio.h>
int main() {
    printf("\n");
    return 0;
}

We need to compile the source into two binary programs, which both ELF (under Linux) and PE (under Windows).


shahril:q4$ cat test.c 

#include <stdio.h>
int main() {
    printf("\n");
    return 0;
}

shahril:q4$ gcc test.c -o test_unix
shahril:q4$ x86_64-w64-mingw32-gcc test.c -o test_win.exe

And we try to run both of the programs, and pipe the stdout data into xxd (hex viewer).

shahril:q4$ ./test_unix | xxd -c 3
00000000: 0a       .
shahril:q4$ wine test_win.exe | xxd -c 3
00000000: 0d0a     ..
note: 0d0a is \r\n

From above output, we can conclude that, the Mingw GCC under Windows produces \r\n newline while Unix produces just \n newline.

Solution

So we know that encryptor.exe must also have converted the original \n into \r\n when it outputting the data into the stdout (screen).

We also know that encrypted.bin is the output from encryptor.exe.

However, encrypted.bin now contains the \r\n bytes that originally is just a \n. So how can we deal with this problem?

There is one tool inside Linux, that can automatically convert the \r\n bytes into \n. YES! dos2unix!

Let take a look again into the hex dump content of encrypted.bin :

shahril:q4$ cat encrypted.bin  | xxd
00000000: 250d 0d0a 180b 1416 040b 110d 0a04 070d  %...............
00000010: 0a 

The part that I highlighted is the \r\n hex bytes inside the encrypted.bin. So applying dos2unix into the encrypted.bin should remove the exceeded \r in front of \n byte.

shahril:q4$ dos2unix -f encrypted.bin 
dos2unix: converting file encrypted.bin to Unix format ...

Take a look again inside patched encrypted.bin content.


shahril:q4$ cat encrypted.bin  | xxd
00000000: 250d 0a18 0b14 1604 0b11 0a04 070a       %............

After having the good boy file, then we need to emulate the original encryptor.exe to decrypt the contents of converted encrypted.bin. So that purpose I created a simple Python script.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import sys, os

def main():

    # get file name from argument 1
    file = sys.argv[1]

    # get size in byte
    size = os.fstat(os.open(file, os.O_RDONLY)).st_size

    with open(file, "r") as f:

        byte = f.read(1)
        i = 0

        # i < size-1 => to skip processing last null terminator
        while byte and i < size-1:

            result = chr(ord(byte) ^ ord("dafa"[i % 4]))
            sys.stdout.write(result)

            byte = f.read(1)
            i += 1

    print ""

if __name__ == "__main__":
    main()

So, run the script, and we got the nice flag appears inside our terminal. :)

shahril:q4$ python decrypt.py encrypted.bin 
Allyoupeoplec

So the flag is "Allyoupeoplec"!

Till we meet again :)

Shahril, Alfarabi 2.0, UiTM Perlis

Friday, November 20, 2015

UTPHax'15 [Group Stage] [Round 1] [binary]

For this write-up, we were given one executable binary from organizer for the first round which you can get it below,

8891b3cde3085a3fe8706585f78f162420f98177.exe

The very first rule in solving this kind of questions is we need to analyze it to determine information that needed to solve this binary. Example of information that we surely need is to determine whether our binary is 32 bit or 64 bit, or type of packer used to protect/compress the binary.

To do this kind of analysis, we can use various tools that specialized in analyzing this type of binary, like an example the famous PEiD, which many people using it. For me personally, I usually use Exeinfo PE  by aslsoft, which is kind a bad beast which have tons of features. Another one that I prefer to use is Detect It Easy by NTInfo, which can run natively for both Windows and Linux platform. I will leave that choice for you to decide, but no worries, because most EXE analyzer will much do the same thing :)

So load up our binary with analyzer, which I using Detect It Easy for this example


my apologize for da potato image :(

From the scanner, at the compiler section, it shows us "MingW GCC" is the compiler that compiled our binary, and at linker section, GNU Linker is linker who linked all compiled objects into one single binary file. If we see more, "EXE32 console" is also there.

So from the information that we got, we can deduce that our binary is 32-bit application, and no packer was detected (because scanner only show "MingW GCC"). From this information, we can simply study the binary, without worrying much to unpack the binary.

Let's try to test our binary by open it up, here is screenshot from the interface

Note : I'm solving this binary from my Ubuntu Linux, so there's wine text appear before the binary name (to enable me run basic Windows binaries in Linux), if you're using Windows, simply just enter binary name and press enter.




After we insert some random user input, error message Wrong keys at 0 is appear on the screen




However, from the above error message, there is unusual number appear at the end of error message, which from our case, is 0. So what's it? It's some kind of random number? Character index? We don't know it yet and we will find out later :)

So, like any other binary challenge, we need to reverse engineer it to find out how this binary works, how key checking works behind the hood.

For this process, we need a debugger that can allow us to do so, the most famous one is Ollydbg, if you're from CTF or reverse engineering community, surely you will hear that name somewhere ;). Ollydbg is a versatile debugger, which have many people using it including security researchers and malware analysts. It also has tons of useful plugins that can aid us in analyzing unknown binary. By the way, I'm using OllyDbg 2.01 in case you want an interface that looks same with mine. ;)

So, open up your OllyDbg, interface will pretty much look like this


Open up the binary by clicking File -> Open and select binary from file selector dialog. After you done it, OllyDbg interface will look like this


So as you can see, it's containing shit load ton of weird assembly language. If you can't understand any of it, better if you try to read some of basic reverse binary & Assembly from daisuke's blog. :)

So, at this point, we need to find our main program execution, without much hassle, our main function is already below at address 00401500!



the highlighted section is our main function

Some of you might ask, how can I know that section is our primary program execution part? Simple, by looking at our previous running console application (see image previously), there is exist one message "Crackme1 Challenge. Enter...", by simply looking at the code that I highlighted, there is also exist the same reference string, so we can safely deduce that part of the assembly is our main execution program.

However, there is also exist another way, by backtracking all reference strings, which also can take us into the same section, but I will leave that for you to discover as it's not in this write-up scope to cover. :)

So, set up breakpoint at the first assembly instruction (00401500) at our main function, so when program execution reach at first main assembly instruction, it will automatically stop running (pausing), enabling us to step through the code :)


Let's analyze what's assembly is doing, from first highlighted 3 instruction


It's known as function epilogue, which its task to set up a new stack frame, and save previous caller stack frame into the stack. AND ESP,FFFFFFF0 is to align stack address into 16-bit alignment, if you play a lot with binary that was produced by GCC, you can see it almost on every function epilogue :)



For next 7 instructions, our binary put 7 hex bytes into the stack, currently we don't know what the purpose of binary by doing so, so let's skip and proceed with another 



For next instruction, we can see the binary is printing out string value to the user (by using printf()) and taking user input (through gets()) which will be save on LOCAL.21.

For next instruction, LOCAL.1 is set to zero, and afterward JMP SHORT 004015C0 is taken to the address 004015C0, which will check if LOCAL.1 is less than equal to 6


If condition is true (LOCAL.1 <= 6), it will jump back below to previous code section at 00401553, so by using our common sense, this is a loop! and LOCAL.1 is the index of our loop! And this loop will run 7 times (remember less than or equal) :)

So let's study what is the content of the loop, 


At this point, EDX will store address of pointer to our user input, while EAX is the index to access EDX string, which can be seen at this instruction MOVZX EAX,BYTE PTR DS:[EAX], eax will get each byte from edx[eax] (edx is string pointer, eax is index previously before overwritten by single character)



After eax got single character from EDX string pointer, here is our main part, the character is xored with 0x41 and the result will be store inside ECX.




After that, xored character byte inside ECX will be store in memory address LOCAL.26+3, with EDX act as string pointer and EAX as string index.




Here is another important part, from the first 4 instruction above that I highlighted, EDX will take xored character from memory LOCAL.26+3, and EAX will take bytes from memory LOCAL.23+1, but, what is LOCAL.23+1? Do you remember first 7 instructions at the very beginning of our function, which binary will try to store unknown 7 bytes into the stack? YES!! LOCAL.23+1 is referring to that byte

After both EDX (xored character) and EAX (bytes from LOCAL.23+1) got their own value, comparison between those 2 registers is happen, and Jump with Equal (je) condition is taken if both their value same.


From assembly in picture above, we can see, if jump is not taken, (if EDX and EAX is not equal), our program will throw error message, and will automatically exit using exit() function.

WAIT A MINUTE! Do you remember at our testing previously? Where unknown number is thrown away with message error, by looking at printf error instruction, that number is actually LOCAL.1, which is our loop index! So that number is actually a hint, referring to what index is falsely compared :)

After jump is taken, it will go to location 004015BB, which will increment our LOCAL.1 and compare if index is less than or equal with 6, if condition is true, loop will happen again :)

By getting all information above, we can construct a simple C pseudocode that rewrite complex assembly into code that's easy to understand :)


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
printf("Crackme1 Challenge. Enter the secret key:")
input key

LOCAL.1 = 0

while(LOCAL.1 <= 6)
{
  edx = key[LOCAL.1]
  edx = edx ^ 0x41

  // get bytes from LOCAL.23+1
  eax = (LOCAL.23+1)[LOCAL.1]

  // compare and throw error if not eq
  if(edx != eax)
  {
    printf("Wrong keys at %d", LOCAL.1)
    exit()
  }
  
  LOCAL.1++;
}

printf("You win!");

So what's content of LOCAL.23+1? easy, we can simply find it using OllyDbg feature which is Follow In Dump



And after follow, we can clearly see the bytes from hex dump menu, which I highlighted below


As you can see, I highlighted seven bytes because if we look back at our assembly instruction, our binary insert 7 bytes of data into the memory/stack, so the first seven bytes is the only what important for us :)

Hex that we extract is : 0x09 0x20 0x22 0x2A 0x70 0x71 0x70

Note that above hex is still not the flag that we want. After getting so far, and extracting all information that we needed to solve this binary, how can we solve it? The technique that binary author used to encrypt the key is known as XOR cipher, which is example below

Let say, we want to cipher 0x90 with key 0x35, we simply 0x90 ^ 0x35 = 0xA5, so 0xA5 is our ciphered byte, if we want to decipher it back, we just xor the ciphered byte with same key, 0xA5 ^ 0x35 = 0x90, we ended up getting back our original data :)

So, in our binary here, what's the key? .... haaa the key is 0x41, which used to xor our user input!

Getting all hex we want, and key, we just simple decipher all bytes back. For that task, I wrote simple PHP script which can done that task


After we xored hex dump with our key, the result we got is 

0x48 0x61 0x63 0x6b 0x31 0x30 0x31

But this is not the flag that we want, looking at the hex pattern, what can you deduce? Yesss it's ASCII characters!

By simply modifying my PHP to print ASCII instead of raw hex, we got our nice flag :)


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?php

$memory = array(0x09, 0x20, 0x22, 0x2A, 0x70, 0x71, 0x70);
$xored = "";

foreach($memory as $each)
  $xored .= chr($each ^ 0x41) . " ";

echo $xored . "\n";

?>


The flag is Hack101 :)

So this is the end of my write up for this binary, hope somebody can learn something through my simple write-up, and if you found any problems or wrong info inside my write-up or simply any other questions, don't hesitate to comment below!

Regards,
Just Another CTF Newbie

Edit (2 / Feb / 2016 ) :
There was a mistake in my code, in my first PHP screenshot example, conversion result for PHP by default is decimal, but I mistakenly padded '0x' in-front of each resulted decimal number.
I had corrected that mistake, thanks to Ariff Yasri for pointing out this one for me.



Hello World

Hi there :)

My name is 'Just Another CTF Newbie', my intention in creating this blog is to publish my write-ups for any past Capture-The-Flag competitions that I joined.

My hope for this blog is, I can communicate with other CTF members as well as sharing/comparing their solutions with mine, also I hope I can keep learning much more by writing my own write-up. If you have any comments, or found any mistakes on my write-up, or even if you need help, don't hesitate to contact me!

Last but not least, I apologize in advance for any poor language usage in my future posts. :)

Regards,
Just another CTF newbie