wtorek, 4 lutego 2025

picoCTF - WhitePages

W tym poście chciałbym opisać rozwiązanie zadania White Pages z działu Forensics picoCTF.


Do zadania został dołączony plik txt, który wydaje się pusty. Nie jest on jednak pusty, tylko jest zapisany samymi spacjami. Aby to zweryfikować możemy użyć programu Notepad++:

Po otwarciu w formacie hex, programem HxD, wygląda to następująco:


Dane w programie znajdują się dwa rodzaje spacji. Jedna z nich to E28083 (U+2003 EM Space), druga to 0x20 (spacja w ASCII). 

Wobec tego, że są to dwa rodzaje spacji, to najbardziej przypomina to zapis binarny. Wobec tego jedną wartość zamienię na 1, drugą na 0. 

Do tego celu można użyć programu word, notatniki czy innego, kroki są następujące:

- Usuwam spację, dodaną podczas kopiowania tekstu.
- Zamieniam ciąg znaków E28083 na 0.
- Zamieniam ciąg znaków 20 na 1.

Po zmianach dostaje następujące dane w formacie binarnym:

00001010000010010000100101110000011010010110001101101111010000110101010001000110000010100000101000001001000010010101001101000101010001010010000001010000010101010100001001001100010010010100001100100000010100100100010101000011010011110101001001000100010100110010000000100110001000000100001001000001010000110100101101000111010100100100111101010101010011100100010000100000010100100100010101010000010011110101001001010100000010100000100100001001001101010011000000110000001100000010000001000110011011110111001001100010011001010111001100100000010000010111011001100101001011000010000001010000011010010111010001110100011100110110001001110101011100100110011101101000001011000010000001010000010000010010000000110001001101010011001000110001001100110000101000001001000010010111000001101001011000110110111101000011010101000100011001111011011011100110111101110100010111110110000101101100011011000101111101110011011100000110000101100011011001010111001101011111011000010111001001100101010111110110001101110010011001010110000101110100011001010110010001011111011001010111000101110101011000010110110001011111001100110110010100110010001101000011001000110011001100000011100000110001011001000110011000111001011000010110010001100001011000100011001001100001001110010110010000111001001101100110000101100110011001000110000100110100011000110110011001100001011001000011011001111101000010100000100100001001

Teraz należy przekonwertować dane na hex. W tyn celu można wykorzystać np. taki program w języku c:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. void binaryToHex(const char *binary, char *hex, const int dataLength) {
  6.     for (int i = 0; i < dataLength; i += 4) {
  7.         char chunk[5] = {0};
  8.         strncpy(chunk, binary + i, 4);
  9.         int value = strtol(chunk, NULL, 2);
  10.         sprintf(hex + (i / 4), "%X", value);
  11.     }
  12. }
  13.  
  14. int main() {
  15.     const char *binaryData = "Binary data as string";
  16.    
  17.     int binaryLength = strlen(binaryData);
  18.     char hexOutput[binaryLength / 4 + 1]; // Każde 4 bity = 1 znak hex
  19.     memset(hexOutput, 0, sizeof(hexOutput));
  20.    
  21.     binaryToHex(binaryData, hexOutput, binaryLength);
  22.    
  23.     printf("Hex data: %s\n", hexOutput);
  24.     return 0;
  25. }

Po jego wywołaniu z danymi otrzymanymi z konwersji, otrzymujemy następujące dane w formacie hex:

0A09097069636F4354460A0A0909534545205055424C4943205245434F5244532026204241434B47524F554E44205245504F52540A09093530303020466F72626573204176652C20506974747362757267682C2050412031353231330A09097069636F4354467B6E6F745F616C6C5F7370616365735F6172655F637265617565645F657175616C5F33653234323330383164663961646162326139643936616664613463666164367D

Teraz sprawdzam czy, w przekonwertowanych danych znajduje się ciąg picoCTF{ (70 69 63 6F 43 54 46 7B). Po sprawdzeniu, szukany string znajduje się w formacie hex:

7069636F4354467B6E6F745F616C6C5F7370616365735F6172655F637265617565645F657175616C5F33653234323330383164663961646162326139643936616664613463666164367D

Po konwersji z hex na ascii, odczytuje wyszukiwaną flagę:


Można całe zadanie wykonać, korzystając z jednego programu w C, który po kolei wykonuje konwersje przedstawione powyżej:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. void replace_hex_values(const char *input, char *output) {
  6.     while (*input) {
  7.         if (strncmp(input, "E28083", 6) == 0) {
  8.             *output++ = '0';
  9.             input += 6;
  10.         } else if (strncmp(input, "20", 2) == 0) {
  11.             *output++ = '1';
  12.             input += 2;
  13.         } else {
  14.             *output++ = *input++;
  15.         }
  16.     }
  17.     *output = '\0';
  18. }
  19.  
  20. void binaryToHex(const char *binary, char *hex, const int dataLength) {
  21.     for (int i = 0; i < dataLength; i += 4) {
  22.         char chunk[5] = {0};
  23.         strncpy(chunk, binary + i, 4);
  24.         int value = strtol(chunk, NULL, 2);
  25.         sprintf(hex + (i / 4), "%X", value);
  26.     }
  27. }
  28.  
  29. void hexToAscii(const char *hexDat, char *asciiDat, const int dataLength) {
  30.     for (int i = 0; i < dataLength; i += 2) {
  31.         char byte[3] = { hexDat[i], hexDat[i + 1], '\0' };
  32.         asciiDat[i / 2] = (char)strtol(byte, NULL, 16);
  33.     }
  34.     asciiDat[dataLength / 2] = '\0';
  35. }

  36. int main() {
  37.     char input[] = "<dane bez spacji ze spacjami>";
  38.     char output[sizeof(input)/2];
  39.     char hexOutput[sizeof(input)/8];
  40.     char asciiData[sizeof(input)/2];
  41.    
  42.     memset(output, 0, sizeof(output));
  43.     memset(hexOutput, 0, sizeof(hexOutput));
  44.     memset(asciiData, 0, sizeof(asciiData));
  45.  
  46.     replace_hex_values(input, output);
  47.     printf("Bin data:\n%s\n", output);
  48.    
  49.     printf("============================================\r\n");
  50.    
  51.     int binaryLength = strlen(output);
  52.     binaryToHex(output, hexOutput, binaryLength);
  53.     printf("Hex data:\n%s\n", hexOutput);
  54.    
  55.     printf("============================================\r\n");
  56.     hexToAscii(hexOutput, asciiData, binaryLength);
  57.     printf("Ascii data:\n%s\n", asciiData);
  58.  
  59.     return 0;
  60. }

Dane wyjściowe wyglądają następująco:

Bin data:
00001010000010010000100101110000011010010110001101101111010000110101010001000110000010100000101000001001000010010101001101000101010001010010000001010000010101010100001001001100010010010100001100100000010100100100010101000011010011110101001001000100010100110010000000100110001000000100001001000001010000110100101101000111010100100100111101010101010011100100010000100000010100100100010101010000010011110101001001010100000010100000100100001001001101010011000000110000001100000010000001000110011011110111001001100010011001010111001100100000010000010111011001100101001011000010000001010000011010010111010001110100011100110110001001110101011100100110011101101000001011000010000001010000010000010010000000110001001101010011001000110001001100110000101000001001000010010111000001101001011000110110111101000011010101000100011001111011011011100110111101110100010111110110000101101100011011000101111101110011011100000110000101100011011001010111001101011111011000010111001001100101010111110110001101110010011001010110000101110100011001010110010001011111011001010111000101110101011000010110110001011111001100110110010100110010001101000011001000110011001100000011100000110001011001000110011000111001011000010110010001100001011000100011001001100001001110010110010000111001001101100110000101100110011001000110000100110100011000110110011001100001011001000011011001111101000010100000100100001001
============================================
Hex data:
0A09097069636F4354460A0A0909534545205055424C4943205245434F5244532026204241434B47524F554E44205245504F52540A09093530303020466F72626573204176652C20506974747362757267682C2050412031353231330A09097069636F4354467B6E6F745F616C6C5F7370616365735F6172655F637265617465645F657175616C5F33653234323330383164663961646162326139643936616664613463666164367D0A0909
============================================
Ascii data:

                picoCTF

                SEE PUBLIC RECORDS & BACKGROUND REPORT
                5000 Forbes Ave, Pittsburgh, PA 15213
                picoCTF{<tutaj jest flaga>}