Boa tarde, queridos leitores.
O registro é um dos sistemas Windows mais visíveis e significativos. Dificilmente existe uma pessoa que nunca ouviu falar dele. Tendo programado no Windows por cerca de 20 anos, pensei que sabia tudo sobre ele. Mas, de tempos em tempos, aparece algo novo que me mostra como eu estava errado. Portanto, hoje quero falar sobre as formas incomuns de trabalhar com o registro que conheci ao pesquisar rootkits e que me surpreenderam.
A primeira história. Nomes de valores e chaves do registro
Todos sabemos que no Windows existem algumas regras para nomear objetos, sejam arquivos, diretórios ou chaves do Registro. Os nomes dos arquivos não podem conter o caractere "\". Os nomes não podem estar vazios. Os nomes têm algumas restrições de comprimento, etc.
Involuntariamente, estendemos essas restrições a todos os sistemas Windows e as observamos ao trabalhar com o registro. E aqui está o nosso erro. Surpreendentemente, existem poucas restrições no registro ao criar nomes. Por exemplo, você pode usar o caractere \ no nome dos valores
Surpreso? Não? Então, o que você dirá se eu lhe mostrar que o símbolo "\ 0" pode ser usado no nome de um valor? Sim, sim, exatamente o caractere nulo. O que é tradicionalmente usado para indicar o fim de uma linha.
Para isso, precisamos da função NtSetValueKey exportada do ntdll.dll
HKEY hKey = 0; RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey); UNICODE_STRING uName; uName.Buffer = L"Test\0Zero"; uName.MaxLen = uName.Length = 9 * sizeof(wchar_t); NTSTATUS status = 0; status = NtSetValueKey( hKey, &uName, 0, REG_SZ, (void*)lpData, DataSize); RegCloseKey(hKey);
Para executar a função NtSetValueKey, você precisa de direitos de administrador. Como resultado, um valor com o nome Test \ 0Zero aparecerá em seu registro.
Alguns desenvolvedores da Microsoft também ficarão surpresos, porque o editor de registro padrão não pode exibir um valor de registro tão incomum.
Segunda história
A segunda história que vou contar hoje aconteceu em 2013.
A princípio, uma pequena digressão. Na Kaspersky Lab, sou membro da equipe que, entre outras coisas, cria o Kaspersky Rescue Disk. Para curar o Windows no Linux, precisamos analisar os arquivos do registro. E para verificar a operação correta desse mecanismo, usamos muitos testes. Entre eles, há um bastante simples:
- No Windows, escrevemos valores de teste no registro.
- Copie o arquivo de seção do registro no diretório de teste.
- Iniciamos o programa que executa a remoção dos valores de teste.
- Carregamos a bucha modificada no registro para verificar a remoção.
E um belo dia, atualizamos na bancada de testes do Windows para a versão 8.1 e o teste parou de excluir os valores de teste. Como assim, fiquei surpreso. Copiei o arquivo com a seção de registro para o meu computador de trabalho - sem valores! Meu primeiro pensamento: preciso adicionar chaves alteradas ao teste de Flush. Adicionada uma chamada para RegFlushKey, reiniciado o teste - sem valores!
RegFlushKey não está funcionando, pensei. Mas, como se viu, eu estava apenas parcialmente certo.
O truque foi que, no Windows 8.1, a Microsoft alterou o mecanismo para salvar as alterações no registro. Anteriormente, todas as alterações do registro eram acumuladas na memória e, quando a chave era fechada, quando o RegFlushKey era executado ou após algum tempo o sistema salvava as alterações no arquivo de seção do registro. No Windows 8.1, as alterações em vez do arquivo bush do registro são salvas em arquivos com o mesmo nome com as extensões .LOG, .LOG1 e .LOG2, e meu código ignorava esses arquivos naqueles dias.
Nesses arquivos, as alterações se acumulam por cerca de uma hora. E somente depois disso, o Windows inicia a tarefa de integrar alterações no arquivo principal. Essa tarefa é chamada de reconciliação e inicia a cada 40 minutos ou quando o Windows é encerrado. Chamar a função RegFlushKey não dispara a tarefa de reconciliação. Para forçar o início da tarefa de integração de alterações, é necessário chamar ZwSetSystemInformation com o argumento não documentado SystemRegistryReconciliationInformation.
ZwSetSystemInformation( 0x9b,
Para executar a função ZwSetSystemInformation, você precisa de direitos de administrador. E a arquitetura do arquivo executável deve corresponder à arquitetura do sistema. A chamada dessa função a partir de um programa de 32 bits no Windows de 64 bits falhará.
Terceira história
Algum tempo atrás, descobrimos um rootkit que prescreveu o lançamento de seu driver no registro. Nossos produtos excluíram as chaves de registro correspondentes, mas após a reinicialização, as chaves estavam em seus lugares. Parece que ele coloca suas funções de retorno de chamada em alterações no registro e restaura suas chaves após as alterações, pensei. Mas acabou que não. Mais precisamente, sim. O rootkit definiu funções de retorno de chamada, mas elas não tinham nada a ver com a tarefa de recuperação de chave. Tudo foi simplificado e mais elegante.
O driver rootkit, na inicialização, renomeou o arquivo de seção do registro SYSTEM para HARDWARE. Criei meu arquivo SYSTEM e salvei periodicamente a ramificação HKLM / System usando a função RegSaveKey. Ao salvar, ele restaurou suas chaves. Ao reiniciar o Windows, o sistema carregou o arquivo SYSTEM e iniciou o driver rootkit. É lindo? Nice.
Procurado
PS Aqui estamos procurando um
desenvolvedor-pesquisador em uma equipe que esteja trabalhando com um mecanismo anti-spam e também precisamos de
um engenheiro de testes .