<?php
$letras = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$numeros = '0123456789';
//Junta letras e números e os separa num array para então criar instância ArrayObject.
$tudo = new ArrayObject(str_split ($letras.$numeros));

$minimo = 5;            //Define o número de caracteres a serem iterados.
$string = 'XXXXX';      //Define o prefixo do resultado.
$iteradores = [];       //Inicializa o array contendo os iteradores.

//Inicializa e armazena o número especificado de iteradores.
for($i=1; $i<=$minimo; $i++){
   $iteradores[] = $tudo->getIterator();
}

//Função de validação aplicada aos iteradores.
function iterar($iter){
    //Do iterador[n](último) ao iterador[1](segundo iterador)... 
    for($i=count($iter) - 1; $i>0; $i--){
        //...se o iterador se esgotou....
        if (!$iter[$i]->valid()) {                 
            $iter[$i]->seek(0);                   //...o renova.
            $iter[$i-1]->next();                  //...itera o seu antecessor.
        }
    }
    return $iter[0]->valid();                     //Retorna o estado do primeiro iterador, enquanto for válido ainda existem combinações a serem geradas.
};

//Enquanto houver combinações...
while(iterar($iteradores)){
    $str = $iteradores[0]->current();                //...obtém o primeiro caractere após o prefixo.
    //...Obtém os caracteres consecutivos da esquerda para direita...
    for($i=0; $i<count($iteradores); $i++){
        $str .= $iteradores[$i]->current();
    }
    $iteradores[count($iteradores) - 1]->next();     //Prepara a nova combinação.

    $base = $string.$str;                            
    echo $base.PHP_EOL;                              
}