team pong

Dutch CTF "team pong" write-ups and other stuff

Hack.lu CTF 2012 – #4 Reduced Security Agency

leave a comment »

Some of our guys broke into the Reduced Security Agency and stole the source of their highly secure login system. Unfortunately no one of them made it uninfected back and so we only have a part of the source. Now it's your turn to break their system and login to the agency.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 /**
 * Copyright: ErEsAh Securse-ID Token
 **/

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <gmp.h>

unsigned int
gen_auth(mpz_t key, mpz_t modulus, mpz_t nonce)
{
	time_t now = time(NULL);
	unsigned int range = now / 3600;
	unsigned int token;

	mpz_t t;
	mpz_init(t);

	mpz_set_ui(t, range);
 
	mpz_t auth;
	mpz_init(auth);
	
	mpz_add(t, t, nonce);
    mpz_t newmod;
    mpz_init(newmod);
    mpz_set_ui(newmod, 13371337);
	mpz_powm(auth, t, key, newmod);
	token = mpz_get_ui(auth);

	return token;
}

void
chartompz(mpz_t result, char *msgptr)
{
	unsigned int size = strlen(msgptr);
	mpz_t msg;
	mpz_t tmp;
	mpz_init(tmp);
	mpz_init(msg);
	int i;

    printf("strlen = %d\n", size);
	for (i = 0; i < size; i++) {
		mpz_set_ui(tmp, (int)msgptr[i]);
		mpz_mul_2exp(tmp, tmp, 8*i);
		mpz_add(msg, msg, tmp);
	}

	mpz_set(result, msg);
}

char *
mpztochar(mpz_t code)
{
	int i, j;
    mpz_t tmp2;
    mpz_t and255;
    mpz_init(tmp2);
    mpz_init(and255);
    mpz_set_ui(and255, 255);
    int length = mpz_sizeinbase(code, 2);
    length = (length / 8) + 1;
	
	char *text;
	text = malloc((length)*sizeof(char));
	if (!text) {
		return NULL;
	}

    unsigned int tmp3;

    for(i = 0; i < length; i++) {
        mpz_set(tmp2, code);
        mpz_cdiv_q_2exp(tmp2, tmp2, i*7);

        for (j = 0; j < i; j++) {
            mpz_div_ui(tmp2, tmp2, 2);
        }

        mpz_and(tmp2, tmp2, and255);
        tmp3 = mpz_get_ui(tmp2);
        text[i] = (char) tmp3;
    }
	text[length] = '\0';
	return text;
}

void
gen_pubkey(mpz_t result, mpz_t key, mpz_t modulus)
{
    mpz_t pubkey;
    mpz_init(pubkey);
    mpz_invert(pubkey, key, modulus);
	mpz_set(result, pubkey);
}

int
gen_seckey(mpz_t result)
{
	mpz_t key;
	int i = 0, j;
	unsigned int seed, random;
	FILE *frand;
	mpz_init2(key, 2048);

	gmp_randstate_t state;
	gmp_randinit_default(state);
	frand = fopen("/dev/random", "r");
	if (frand == NULL) {
		printf("fopen() failed\n");
		return -1;
	}
	
	fread(&seed, sizeof(seed), 1, frand);
	fclose(frand);
	gmp_randseed_ui(state, seed);

	j = 2047;
	while(i != j) {
		random = gmp_urandomb_ui(state, 1);
		if(random) {
			mpz_setbit(key, i);
			i++;
		}
		else if(!random) {
			mpz_clrbit(key, j);
			j--;
		}
	}

	mpz_set(result, key);
	return 0;
}

void
encrypt(mpz_t result, mpz_t base, mpz_t key, mpz_t modulus)
{
	mpz_t msg;
	mpz_init(msg);

    mpz_t ciphertext;
    mpz_init(ciphertext);

    printf("encrypting...\n");
    mpz_powm(ciphertext, base, key, modulus);

	mpz_set(result, ciphertext);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Studying this code we find a couple of for very strange facts:
– gen_seckey always produces keys with of the form 00…0011…11
– gen_auth uses 13371337 as modulus

In an RSA based system the only number which may be chosen completely random is the decryption exponent d. Thus it seems likely that gen_seckey is used to calculate d. We try all different variants of pow(2,x)-1 to find d=2^1024-1

The token needen for authentication is generated by pow(time()/3600+nonce , d) mod 13371337. Given that we have just found d, we can connect to the ssh server and calculate the token needed to log in.

Written by teampong

November 9, 2012 at 1:03 pm

Posted in Uncategorized

Leave a comment