Wright nas sombras

Esta é uma história sobre uma das tarefas que preparamos para a fase de qualificação da CTFZone , realizada no final de novembro. Você pode ler sobre o processo de preparação da qualificação aqui .

Você começa com dois arquivos: decrypt_flag.py e ntfs_volume.raw. Vamos dar uma olhada no script. Ele abre um arquivo chamado key.bin e, em seguida, usando um loop, tenta obter uma sequência binária de 34 bytes de cada deslocamento dentro do arquivo, que é usado como entrada para a função PBKDF2. Cada chave retornada é usada como uma chave XOR para descriptografar a cadeia criptografada costurada no código. Se o hash MD5 descriptografado corresponder ao valor predefinido em um formato descriptografado, o script utilizará os dados recebidos para gerar e imprimir o sinalizador.

Então, você precisa encontrar o arquivo key.bin. É impossível simplesmente classificar todas as compensações dentro do arquivo de imagem (ntfs_volume.raw), pois o processo de encontrar a chave será muito lento. Isso não é proibido pelas regras, mas você certamente não terá tempo até o final do CTF.

O arquivo de imagem contém uma tabela de partição MBR de partição única. Seu deslocamento é 2048 setores de 512 bytes e contém o sistema de arquivos NTFS, mas o arquivo key.bin não está lá:

$ fls -o 2048 -r -p ntfs_volume.raw | grep -F key.bin | wc –l
0

O NTFS armazena nomes de arquivos codificados em UTF-16LE. Vamos tentar pesquisar nele!


Resultados da pesquisa para registros de arquivos

Após estudar os resultados da pesquisa, focamos nos registros de arquivos que começam com a assinatura FILE [1]. Aqui está a única entrada desse tipo:


Registro encontrado

O objetivo já está próximo! Temos um registro de arquivo, mas precisamos de dados. No NTFS, eles são armazenados no atributo $ DATA, que pode ser residente ou não residente [2]. Para o registro encontrado, esse atributo começa no deslocamento 0 × 3AADD00 e indica dados não residentes (isso significa que as informações são armazenadas fora do registro do arquivo).

Então, onde exatamente estão os dados do arquivo desejado? Para responder a essa pergunta, é necessário decodificar os chamados pares de mapeamento ou execução de dados (pares “comprimento do bloco - deslocamento do bloco”) [3]. As execuções de dados do arquivo desejado são as seguintes (observe o deslocamento 0 × 3AADD40): 22 53 01 A0 4E 21 05 31 C1 11 38 30 00. Ou, se as reorganizarmos:

1.	22 53 01 A0 4E
2.	21 05 31 C1
3.	11 38 30 00

O arquivo consiste em três fragmentos, cujo tamanho do primeiro é 339 clusters, e começa com o cluster # 20128. Para o nosso código usando PBKDF2, esse snippet é grande. Conforme indicado no cabeçalho do sistema de arquivos, o tamanho de um cluster é 4096 bytes:

$ fsstat -o 2048 ntfs_volume.raw | grep 'Cluster Size'
Cluster Size: 4096

Vamos dar uma olhada nos dados desse deslocamento (em bytes):
2048 * 512 + 20128 * 4096 = 83492864. Extrairemos qualquer quantidade significativa de informações (por exemplo, 128 bytes) a partir daqui, inseriremos em um novo arquivo, que chamaremos key.bin, executar o script ... Nada teve sucesso.

Talvez o arquivo não tenha sido armazenado no atual, mas na versão anterior do sistema de arquivos (formatação anterior) - não esqueça que não vimos o registro sobre o arquivo excluído com o mesmo nome. Qual era o tamanho do cluster antes? Vamos procurar o cabeçalho do sistema de arquivos com a assinatura NTFS [4]. Talvez tenhamos sorte e realmente encontremos o cabeçalho da formatação anterior.


Resultados da pesquisa para o cabeçalho do sistema de arquivos

A primeira e a última posição nos resultados referem-se ao sistema de arquivos atual, mas os cabeçalhos do sistema de arquivos localizados entre eles parecem pertencer à formatação anterior. E eles têm um tamanho de cluster diferente!


O cabeçalho do sistema de arquivos da versão anterior.

Esse tamanho de setor é gravado com um deslocamento de 0 × 4554800B: 00 02 ou 512. Mas esse tamanho de cluster é gravado com um deslocamento de 0 × 0x4554800D: F7 ou 247.

Portanto, temos o tamanho do cluster (em bytes) 512 * 247 = 126464. Algum tipo de bobagem! Se você acredita no analisador NTFS [5], esse valor deve ter um sinal e ser processado de maneira especial, portanto o tamanho real do cluster (em setores) é 1 << - (- 9) = 512. Ou, se em bytes, 512 * 512 = 262144 Agora parece mais crível.

Os dados começam aqui neste deslocamento (em bytes):
2048 * 512 + 20128 * 262144 = 5277483008. Vamos tentar novamente fazer o mesmo truque com as informações armazenadas lá ... Novamente, uma falha! O que está errado? Temos CTF aqui, significa "não" tudo pode ser.

A tarefa pela qual estamos lutando é chamada Nas sombras. É possível que tenha algo a ver com cópias de sombra do volume. Portanto, temos um arquivo do sistema de arquivos que existia anteriormente neste volume. Infelizmente, simplesmente não podemos pegar e montar sua cópia de sombra, mas sabemos o deslocamento exato em que os dados começam! Isso é 5277483008 ou, dentro da seção, 5277483008 - 2048 * 512 = 5276434432.

De acordo com as especificações do formato VSS [6], os blocos de dados redirecionados são descritos na estrutura do descritor de blocos que contém um campo de 64 bits no qual o deslocamento original (dentro do volume) é armazenado e também um campo de 64 bits que descreve o deslocamento do bloco de destino (dentro do volume). Vamos procurar por 5276434432 como um pequeno número endian de 64 bits.

Existem apenas dois resultados nos resultados e apenas um deles está localizado em um deslocamento uniforme.


Descritor de blocos encontrados

Deslocamento do bloco de destino: 00 00 9B 03 00 00 00 00, ou apenas 60489728. Deslocamento final: 60489728 + 2048 * 512 = 61538304. A partir daqui, exporte uma certa quantidade de dados para um novo arquivo chamado key.bin e ...

$ ./decrypt_flag.py
ctfzone{my_c0ngr4t5_t0_u,w311_d0n3_31337}

Feito!

Referências


  1. https://flatcap.org/linux-ntfs/ntfs/concepts/file_record.html
  2. https://flatcap.org/linux-ntfs/ntfs/attributes/data.html
  3. https://flatcap.org/linux-ntfs/ntfs/concepts/data_runs.html
  4. https://flatcap.org/linux-ntfs/ntfs/files/boot.html
  5. https://github.com/msuhanov/dfir_ntfs/blob/94bb46d6600153071b0c3c507ef37c42ad62110d/dfir_ntfs/BootSector.py#L58
  6. https://github.com/libyal/libvshadow/blob/master/documentation/Volume%20Shadow%20Snapshot%20(VSS)%20format.asciidoc#431-block-descriptor

Source: https://habr.com/ru/post/undefined/


All Articles