Skip to content

Instantly share code, notes, and snippets.

@Siirko
Last active August 14, 2022 18:00
Show Gist options
  • Save Siirko/58aa856e5c98f57ab166491575c3b490 to your computer and use it in GitHub Desktop.
Save Siirko/58aa856e5c98f57ab166491575c3b490 to your computer and use it in GitHub Desktop.
Shellctf-2022-Writeup-Reversing-swift

CTF - Write up

  • Shell ctf 2022
  • Categorie : Reversing
  • Chall name : swift

Introduction

We're given :

  • A binaries in ELF format called swift

  • A hint Wikipedia says "Taylor Alison Swift (born December 13, 1989) is an American singer-songwriter."

  • And output.txt that contains the output that encrypt() would print for the correct key. 0.135335 0.367879 2.718282 7.389056 0.049787 1.000000 148.413159 0.367879 0.367879 2.718282 20.085537 148.413159

Decompilation

Decompiled with IDA Freeware, and we can see 3 interesting functions :

  • main
int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[40]; // [rsp+0h] [rbp-30h] BYREF
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  strcpy(v4, "wbppcugz{F4zp0i5_w3l1p5_sW_4_xHhO7j0r}");
  printf("%s\n%s\n%s\n", "alright here you go: ", v4, "wait, do you not want to know the key?");
  return 0;
}
  • encrypt
unsigned __int64 __fastcall encrypt(__int64 a1)
{
  int i; // [rsp+1Ch] [rbp-84h]
  double v3[13]; // [rsp+20h] [rbp-80h]
  _BYTE v4[12]; // [rsp+8Ch] [rbp-14h] BYREF
  unsigned __int64 v5; // [rsp+98h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  qmemcpy(v4, "GVKCUSIVNABM", sizeof(v4));
  for ( i = 0; i <= 11; ++i )
  {
    v3[i] = func(*(char *)(i + a1) - (char)v4[i]);
    printf("%f ", v3[i]);
  }
  putchar(10);
  return __readfsqword(0x28u) ^ v5;
}
  • func
double __fastcall func(int a1)
{
 int v2; // [rsp+8h] [rbp-1Ch]
 double v3; // [rsp+Ch] [rbp-18h]
 double v4; // [rsp+14h] [rbp-10h]
 double v5; // [rsp+1Ch] [rbp-8h]

 v3 = 1.0;
 v4 = 0.0;
 v5 = 1.0;
 v2 = 1;
 while ( v3 != v4 )
 {
   v4 = v3;
   v5 = (double)a1 / (double)v2 * v5;
   v3 = v3 + v5;
   ++v2;
 }
 return v3;
}

What can we learn from these reversed functions :

  • the cipher is wbppcugz{F4zp0i5_w3l1p5_sW_4_xHhO7j0r} .
  • func is probably doing some Taylor young series calculation according to the hint that we're given.
  • It seems that we have a vigenere key GVKCUSIVNABM but it is not the good one.

Rewriting and testing

Function encrypt is the key here to get the correct vigenere key, but we need to rewrite it to use it :

void encrypt(char* a1){
    char cipher[13];
    double answer[13];
    strcpy(cipher, "GVKCUSIVNABM");
    for (int i = 0; i <= 11; ++i )
    {
        answer[i] = func((unsigned int)((char*)a1)[i] - (char)cipher[i]);
        printf("%f\n", answer[i]);
    }
}

That's what I've came across with the help of some friends who are knowledgable in C. If we test it :

int main(){
    char* test="GVKCUSIVNABM";
    encrypt( test);
    return 0;
}

we have 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 .

So we can now write a little function that will try every letter and find the good one that will match the output.txt

void build_key(char* key)

double output_pass[] = { 0.135335, 0.367879, 2.718282, 7.389056, 0.049787, 1.000000, 148.413159, 0.367879, 0.367879, 2.718282, 20.085537, 148.413159 };  
char* colision="GVKCUSIVNABM";

void build_key(char* key){
    char letter = 'A';
    for(int i = 0; i <= strlen(colision) - 1; i++){
        for(int j = 0 ;;  j++){
            char new_letter = letter + j;
            double check = func((unsigned int)new_letter - (char)colision[i]);
            if(essentiallyEqual(check, output_pass[i], 0.000001)){
                key[i] = new_letter;
                break;
            }
        }
    }
}

Note :

  • The function essentiallyEqual corresponds just to a function that help us to compare double, more info here.

main.c

If we gather all the informations, we have our main.c ready to be compiled !

#include <stdio.h>  
#include <stdint.h>  
#include <string.h>  
#include <stdbool.h>  
#include <math.h>  

double output_pass[] = { 0.135335, 0.367879, 2.718282, 7.389056, 0.049787, 1.000000, 148.413159, 0.367879, 0.367879, 2.718282, 20.085537, 148.413159 };  
char* colision="GVKCUSIVNABM";  

double func(int a1){
   int v2;
   double v3;
   double v4;
   double v5;

   v3 = 1.0;
   v4 = 0.0;
   v5 = 1.0;
   v2 = 1;
   while(v3!=v4){
       v4 = v3;
       v5 = (double)a1/(double)v2*v5;
       v3 = v3 + v5;
       ++v2;
   }
   return v3;
}


bool essentiallyEqual(double a, double b, double epsilon)  
{  
   return fabs(a - b) < epsilon;  
}  

void build_key(char* key){
   char letter = 'A';
   for(int i = 0; i <= strlen(colision) - 1; i++){
       for(int j = 0 ;;  j++){
           char new_letter = letter + j;
           double check = func((unsigned int)new_letter - (char)colision[i]);
           if(essentiallyEqual(check, output_pass[i], 0.000001)){
               key[i] = new_letter;
               break;
           }
       }
   }
}

int main(){
   char key[strlen(colision)];
   build_key(key);
   printf("The key is : %s\n", key);
   return 0;
}

and the output is :

The key is : EULERSNUMBER

To decrypt the flag, you can go here (don't forget to choose Variant Beaufort Cipher !).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment