2 min read

[CTF] WU - SHIT I GOT TO GO!

CTF InterCampus Ynov 2024

Difficulty Level : Insane

Challenge Category : Malware

Description :

During routine system maintenance, I accidentally executed this suspicious program. Shortly after, I discovered that all my files had been encrypted. Can you extract the script responsible for the encryption.
Can you analyze the script and recover the flag.

DISCLAIMER !!!! REAL MALWARE BE CAREFUL !!!

Challenge Overview

You are provided with a PowerPoint file containing embedded macros. At first glance, opening the file does not reveal any noticeable activity. However, upon closer inspection, the macros reveal the presence of three modules, each containing distinct PowerShell scripts.

The scripts implement an RSA encryption scheme involving the following variables:

  • e: The public exponent
  • d: The private exponent
  • Z: A value related to the RSA modulus (n).

A crucial hint is discovered within the macros, indicating that d and Z together encode information about the prime factors P and Q of n. These primes are critical for understanding and breaking the RSA encryption.

Challenge Objective

To solve the challenge, you must reverse-engineer the RSA process and brute-force a missing factor k in the equation:

n = (k * e * d - 1) + Z - 1

Where:

  • n: RSA modulus
  • e: Public exponent
  • d: Private exponent
  • Z: Value derived from the prime factors (P and Q)
  • k: An unknown integer factor to be brute-forced.

The goal is to determine the missing factor k, which enables the reconstruction of n and, consequently, the RSA private key.

Tools and Techniques

  • Macro Analysis: Tools like oletools or VBA Editor to extract and analyze the PowerShell scripts embedded in the macros.
  • Brute-Forcing k: A Python or PowerShell script to iterate over potential k values and solve the equation.
  • Libraries : pycryptodome & tqdm

Python Script for Brute-Forcing k

from Crypto.Util.number import *
from tqdm import *

Z = 23708477623422123989911840509603682236427243837909957142649477995756613551417771108814520918899394732450559929795498438009915928437053853511525438092891944
e = 65537
d = 17409852817563021737163902989212279100735120175418641008244781705876293551110148109904232413623854677476746990875790644057589605168375455792794919949833451395040211778229858312334988138987353959934801123972615827275654741061592388665207758027411963916915266233226516186035198670053990698284286950107833088273
ct = 112569996888684048707974554874760082093999450193432783850566443882311920857206710400131003272094451780670160584517262126075672560570102442431915552711774933491099227555584450258514686020607237282307281443480739470228480229923701086866291637098549717882217161302754466078414381717166307312901131329539364669836

for k in trange(1, e):
    n = ((e * d - 1) // k) + Z - 1
    flag = long_to_bytes(pow(ct, d, n))
    if b"FLAG" in flag:
        print(flag)
        break