# Crackmesone

## CryptPad

That one is a notepad-like exe that has an encrypted file containing the flag. The Cryptpad can encrypt (and not decrypt) files for us. Taking a look in IDA, this function stood out to me as being encryption related:\ <br>

```
char __stdcall sub_4014EB(_BYTE *a1, int a2, int a3)
{
  unsigned int v3; // ecx
  _BYTE *v4; // esi
  int v5; // eax
  char result; // al
  _BYTE *v7; // esi
  _BYTE *v8; // edi
  DWORD v9; // ecx
  int v10; // edx
  int v11; // ecx
  _BYTE *v12; // esi
  int v13; // ecx
  int v14; // ebx
  int v15; // ebx
  _BYTE *v16; // esi
  int v17; // eax
  int v18; // ecx
  char v19; // dl
  _BYTE *v20; // edx
  int v21; // eax
  int v22; // ebx
  int v23; // ecx
  int v24; // ecx
  char v25; // dh
  char v26; // dl
  _BYTE *v27; // esi
  _BYTE *v28; // edi
  DWORD v29; // ecx
  int v30; // edx
  _BYTE *v31; // edi
  _BYTE *v32; // [esp-8h] [ebp-Ch]
  int v33; // [esp-4h] [ebp-8h]

  if ( a3 )
  {
    if ( a3 != 1 )
      return MessageBoxA(0, 0, 0, 0);
  }
  else
  {
    v3 = *(_DWORD *)&a1[a2 - 1];
    v4 = &a1[a2 - 1 - v3];
    qmemcpy(byte_4024C5, v4, v3);
    v5 = *((_DWORD *)v4 - 1);
    *((_DWORD *)v4 - 1) = 0;
    a2 = v5;
  }
  v7 = a1;
  v8 = byte_4024C5;
  v9 = NumberOfBytesWritten;
LABEL_6:
  v10 = 0;
  do
  {
    *v7++ ^= *v8++;
    if ( ++v10 == 8 )
      goto LABEL_6;
    --v9;
  }
  while ( v9 );
  v11 = 256;
  do
  {
    byte_403795[(unsigned __int8)-(char)v11] = -(char)v11;
    --v11;
  }
  while ( v11 );
  v12 = &unk_403695;
  v13 = 256;
  v14 = 0;
  do
  {
    if ( v14 >= 8 )
      v14 = 0;
    *v12++ = byte_4024C5[v14++];
    --v13;
  }
  while ( v13 );
  v15 = 0;
  v16 = v12 - 256;
  v17 = 0;
  v18 = 256;
  do
  {
    LOBYTE(v15) = byte_403795[v17] + v16[v17] + v15;
    v19 = byte_403795[v17];
    byte_403795[v17] = byte_403795[v15];
    byte_403795[v15] = v19;
    ++v17;
    --v18;
  }
  while ( v18 );
  v20 = a1;
  v21 = 0;
  v22 = 0;
  v23 = a2;
  do
  {
    v33 = v23;
    v24 = (unsigned __int8)(v21 + 1);
    v32 = v20;
    v25 = byte_403795[v24];
    LOBYTE(v22) = v25 + v22;
    v26 = byte_403795[v22];
    byte_403795[v24] = v26;
    byte_403795[v22] = v25;
    LOBYTE(v24) = byte_403795[(unsigned __int8)(v25 + v26)] ^ a1[v21];
    v20 = v32;
    v32[v21++] = v24;
    v23 = v33 - 1;
  }
  while ( v33 != 1 );
  v27 = a1;
  v28 = byte_4024C5;
  v29 = NumberOfBytesWritten;
LABEL_20:
  v30 = 0;
  do
  {
    result = *v28 ^ *v27;
    *v27++ = result;
    ++v28;
    if ( ++v30 == 8 )
      goto LABEL_20;
    --v29;
  }
  while ( v29 );
  if ( a3 == 1 )
  {
    v31 = &a1[a2 - 13 + RandomBufferLength];
    *(_DWORD *)v31 = a2;
    v31 += 4;
    qmemcpy(v31, byte_4024C5, 8u);
    v31[8] = 8;
    return RandomBufferLength + a2;
  }
  return result;
}
```

This is actually more readable using IDA's graph mode.\
\
What this does is: XOR8( RC4( XOR8( plaintext ) ) )\
Where XOR8 is just a XOR with an 8 byte key.\
\
When a3 == 1 we're in encryption mode and we use the static key:\
\
`byte_4024C5 =` DE BC 0A 89 67 45 23 01

And after the encryption, we append a footer to the file:\
\
\[ original\_size (4 bytes) ]\
\[ key (8 bytes) ] ( copied from byte\_4024C5)\
\[ 8 ]

This caught my eye in particular when comparing the hex of the flag.enc with one of aaaa I generated:\ <br>

```
C9 98 8F C7 A6 1C 02 6B E2 06 F3 52 49 16 27 59 45 5C 4C 47 BC 4E 28 A6 2F 71 C7 D8 06 85 42 03 08 50 7D 93 F5 FE E5 99 48 4E 82 2B E2 00 57 26 16 F6 B4 1C 00 00 00 E8 17 1B F4 50 3F 3D 70 08
```

And:\ <br>

```
02 8B 0F 4D E5 B0 AC 6E 6C 20 EA AD 88 3A DF 65 16 F1 79 15 42 D9 23 16 B9 B5 08 08 11 3E 33 78 03 B1 DE 31 ED BE 8B 02 17 0C 67 D4 70 D7 CD F3 11 54 81 06 00 00 00 13 08 9A CE F4 C2 7F 4B 08
```

The 3 null bytes showing up in the footer caught my interest.

The 06 right before the 3 null bytes as well: I encrypted 5 a's and a null byte so size 06 meaning our flag is size 1C if we follow that logic.\
\
We can write a python script to parse out the footer and apply xor8 rc4 xor8 with our key and decrypt  flag.enc: \ <br>

```
def rc4(data: bytes, key: bytes) -> bytes:
    # KSA
    S = list(range(256))
    j = 0
    key_len = len(key)

    for i in range(256):
        j = (j + S[i] + key[i % key_len]) % 256
        S[i], S[j] = S[j], S[i]

    # PRGA
    i = 0
    j = 0
    output = bytearray()

    for byte in data:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        k = S[(S[i] + S[j]) % 256]
        output.append(byte ^ k)

    return bytes(output)


def xor8(data: bytes, key: bytes) -> bytes:
    return bytes(b ^ key[i % 8] for i, b in enumerate(data))


def decrypt_file(path):
    with open(path, "rb") as f:
        data = bytearray(f.read())

    # Extract footer
    key = data[-9:-1]         # 8 bytes
    original_size = int.from_bytes(data[-13:-9], "little")

    encrypted_data = data[:original_size]

    # Reverse the algorithm
    stage1 = xor8(encrypted_data, key)
    stage2 = rc4(stage1, key)
    plaintext = xor8(stage2, key)

    return plaintext


decrypted = decrypt_file("flag.enc")
open("decrypted.bin", "wb").write(decrypted)

```

We end up with:\
\
CMO{r0ll\_y0ur\_0wn\_b4d\_c0d3}\
\ <br>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://warsang.gitbook.io/awesome-security-blog/crackmesone.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
