Post

Hidden Cipher 1

Hidden Cipher 1

1. File download: hiddencipher.zip

File Analysis

Initial identificacion of binery shows it is a x64-bit linux executable that has been stripped.

1
2
❯ file hiddencipher
hiddencipher: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), statically linked, no section header

Continue with analsys we use pwntool to gather more informacion. Analysing the results we notice hiddencipher file was packet using UPX

1
2
3
4
5
6
7
8
9
❯ pwn checksec hiddencipher
[!] Did not find any GOT entries
[*] 'hiddencipher'
    Arch:       amd64-64-little
    RELRO:      No RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        PIE enabled
    Packer:     Packed with UPX

Behavior analysis

We execute the hiddencipher file, it show us a cipher value:

1
2
3
❯ ./hiddencipher
Here your encrypted flag:
235a201d70201548251358110c552f135409

With this information we know that our objetive is to dechiper the output.

Static Analisys

Unpacking file

We proceeded to unpack the file using UPX utility with the -d command.

1
2
3
4
5
6
7
8
9
10
❯ ./upx -d hiddencipher
                       Ultimate Packer for eXecutables
                          Copyright (C) 1996 - 2026
UPX 5.1.1       Markus Oberhumer, Laszlo Molnar & John Reiser    Mar 5th 2026

        File size         Ratio      Format      Name
   --------------------   ------   -----------   -----------
     16568 <-      7196   43.43%   linux/amd64   hiddencipher

Unpacked 1 file.

Decompiled pseudocode

Analysing the code generated by IDA, we observer the following logic:

  • %02x: Used to print the value as 2-character hexadecimal string.
  • ptr + i: Pointer Arithmetic used to iterate through the list of characters
  • (i % 6 + secret): Selects characters from the repeating secrets key.
  • ^: Applies a bitwase XOR operation.
1
2
for ( i = 0; n > i; ++i )
    printf("%02x", *((_BYTE *)ptr + i) ^ *(_BYTE *)(i % 6 + secret));

By analysing the get_secret function, we recovered the secret key: S3Cr3t.

1
secret = get_secret()
1
2
3
4
5
6
7
8
9
10
11
12
get_secret proc near
endbr64
push    rbp
mov     rbp, rsp
mov     byte ptr cs:s_0, 53h ; 'S'
mov     cs:byte_4012, 33h ; '3'
mov     cs:byte_4013, 43h ; 'C'
mov     cs:byte_4014, 72h ; 'r'
mov     cs:byte_4015, 33h ; '3'
mov     cs:byte_4016, 74h ; 't'
mov     cs:byte_4017, 0
lea     rax, s_0

Decrypting script

After analysing the login, we development a C program to decipher the flag. The program reads the hex values and applies the XOR operation using the key S3Cr3t.

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
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

const char filepath[] = "cipher_flag.txt";
const char secret[] = "S3Cr3t";

int main(){
    FILE *fp;
    fp = fopen(filepath, "rb");
    if (!fp){
        fprintf(stderr, "Error to open file.");
        return -1;
    }

    long len_flag = 0;
    fseek(fp, 0, SEEK_END);
    len_flag = ftell(fp);
    rewind(fp);

    char *flag = malloc(sizeof(char) * len_flag + 1);
    fread(flag, sizeof(char), len_flag, fp);
    flag[len_flag] = '\0';

    for ( int index_flag = 0; index_flag < len_flag; index_flag += 2 ){
        char byte_str[3];
        int value = 0;
        byte_str[0] = flag[index_flag];
        byte_str[1] = flag[index_flag + 1];
        byte_str[2] = '\0';
        value = strtol(byte_str, NULL, 16);

        char result = value ^ *(index_flag/2 % 6 + secret);
        printf("%c", result);
    }

    fclose(fp);

    return 0;
}

Execution

1
2
❯ gcc -o solve solve.c && ./solve
picoCTF{xor_unpack_XXXXXXXXX}
This post is licensed under CC BY 4.0 by the author.