O Protocolo do Back Orifice (BO)

Notas Introdutórias

O Protocolo

A troca de dados entre o cliente e o servidor BO se faz atravéz de pacotes UDP criptografados. O formato destes pacotes é simples, assim como também é o esquema de criptografia utilizado. O servidor normalmente se liga à porta UDP 31337, mas pode ser configurado para utilizar outra. Todos os pacotes do BO -- do cliente para o servidor e vice-versa --, têm o mesmo formato básico. Note que mesmo que nenhuma senha seja acertada no servidor e no cliente, os pacotes sempre trafegam criptografados.

Formato dos Pacotes

Os pacotes do BO são compostos de um cabeçalho de 17 bytes que contém características do pacote mais os dados (pelo menos 1 byte). O pacote é finalizado com um byte de CRC (???).

Campos do pacote:

Mnemônico Tamanho em bytes
MAGICA 8
TAM 4
ID 4
T 1
DADOS variável
CRC 1

Campos do Cabeçalho

MAGICA - É uma sequência de 8 bytes que identifica o pacote do BO. Esta sequência é fixa e deve ser o valor "*!*QWTY?" (asterisco, ponto-de-exclamação, asterisco, "Q", "W", "T", "Y", ponto-de-interrogação).

TAM - É um inteiro de 32 bits com tamanho total do pacote, incluindo o cabeçalho. Este valor deste campo não pode ser menor que 19 (o tamanho do cabeçalho mais pelo menos 1 byte de dados e o CRC).

ID - É um inteiro de 32 bits contendo a identificação do pacote UDP. Em pacotes divididos, ele é usado para numerar seqüencialmente as partes (???). Também é usado pelo cliente BO para sincronizar pacotes de respostas com o pedido enviado.

Os "inteiros de 32 bits" usados no cabeçalho de pacotes do BO não são transmitidos na "ordem de rede", mas sim com o byte menos significativo primeiro. Por exemplo, o "inteiro" 0x11bb55ee é transmitido nesta ordem: 0xee, 0x55, 0xbb e 0x11.

T - É o tipo de operação que o pacote carrega. Neste campo, os 2 bits mais significativos são usados para sinalizar algumas condições do pacote, como a divisão de pacotes grandes. Os 6 bits restantes identificam uma operação do BO.

Operações do BO

Mnemônico Valor Significado
TYPE_ERROR 0x00 Erro (???)
TYPE_PING 0x01 Pacote de "ping"
TYPE_SYSREBOOT 0x02 Reiniciar o sistema
TYPE_SYSLOCKUP 0x03 Congelar o sistema
TYPE_SYSLISTPASSWORDS 0x04 Listar as senhas do sistema
TYPE_SYSVIEWCONSOLE 0x05 Observar o console (???)
TYPE_SYSINFO 0x06 Obter informações sobre o sistema
TYPE_SYSLOGKEYS 0x07 Registrar teclas digitadas
TYPE_SYSENDKEYLOG 0x08 Enviar registro de teclas digitadas
TYPE_SYSDIALOGBOX 0x09 Mostrar caixa de mensagens
TYPE_REGISTRYDELETEVALUE 0x0a Apagar um valor no registro
TYPE_REDIRADD 0x0b Criar redirecionamento (proxy) TCP
TYPE_REDIRDEL 0x0c Apagar redirecionamente TCP
TYPE_REDIRLIST 0x0d Listar redirecionamentos TCP
TYPE_APPADD 0x0e Inicar aplicativo
TYPE_APPDEL 0x0f Terminar aplicativo
TYPE_NETEXPORTADD 0x10 Compartilhar um recurso ("share") do computador para a rede
TYPE_NETEXPORTDELETE 0x11 Cancelar compartilhamento
TYPE_NETEXPORTLIST 0x12 Listar compartilhamentos
TYPE_PACKETRESEND 0x13 Reenviar o pacote (???)
TYPE_HTTPENABLE 0x14 Ativar servidor HTTP
TYPE_HTTPDISABLE 0x15 Desativar servidor HTTP
TYPE_RESOLVEHOST 0x16 Resolver nome de host
TYPE_FILEFREEZE 0x17 Compactar um arquivo
TYPE_FILEMELT 0x18 Descompactar um arquivo
TYPE_PLUGINEXECUTE 0x19 Executar um "plug-in"
TYPE_PROCESSLIST 0x20 Listar os processos (programas) em execução
TYPE_PROCESSKILL 0x21 Terminar um processo
TYPE_PROCESSSPAWN 0x22 Iniciar um processo
TYPE_REGISTRYCREATEKEY 0x23 Criar chave no registro
TYPE_REGISTRYSETVALUE 0x24 Atribuir um valor a uma chave no registro
TYPE_REGISTRYDELETEKEY 0x25 Apagar chave no registro
TYPE_REGISTRYENUMKEYS 0x26 Mostrar chaves do registro
TYPE_REGISTRYENUMVALS 0x27 Mostar valores do registro
TYPE_MMCAPFRAME 0x28 Captura uma imagem estática (.BMP) do dispositivo de captura de vídeo
TYPE_MMCAPAVI 0x29 Captura uma seqüencia de vídeo (.AVI) do dispositivo de captura de vídeo
TYPE_MMPLAYSOUND 0x2a Toca um arquivo de som (.WAV)
TYPE_MMLISTCAPS 0x2b Mostra dispositivos de captura de imagem/vídeo presentes
TYPE_MMCAPSCREEN 0x2c Captula a tela em arquivo (.BMP)
TYPE_TCPFILESEND 0x2d Início de envio de arquivo via TCP
TYPE_TCPFILERECEIVE 0x2e Início de recebimento de arquivo via TCP
TYPE_PLUGINLIST 0x2f Listar "plug-ins" (em execução)
TYPE_PLUGINKILL 0x30 Terminar "plug-in"
TYPE_DIRECTORYLIST 0x31 Listar diretório
TYPE_FILEFIND 0x34 Procurar arquivo
TYPE_FILEDELETE 0x35 Apagar arquivo
TYPE_FILEVIEW 0x36 Visualizar o conteúdo de um arquivo
TYPE_FILERENAME 0x37 Renomear arquivo
TYPE_FILECOPY 0x38 Copiar arquivo
TYPE_NETVIEW 0x39 Listar disposivos de rede, nomes de domínio e compartilhamentos
TYPE_NETUSE 0x3a Conectar recurso de rede
TYPE_NETDELETE 0x3b Cancelar conexão de recurso de rede
TYPE_NETCONNECTIONS 0x3c Listar conexões de rede
TYPE_DIRECTORYMAKE 0x3d Criar diretório (pasta)
TYPE_DIRECTORYDELETE 0x3e Remover diretório
TYPE_APPLIST 0x3f Listar aplicativos em execução

Dois Bits mais Significativos do Tipo do Pacote

Mnemônico Máscara Significado
PARTIAL_PACKET 0x80 Último pacote da série (???)
CONTINUED_PACKET 0x40 Pacote tem continuação (???)
Estes dois flags são normalmente combinados nos pacotes "internos". Por exemplo, um pacote grande que é fragmentado em 4 pacotes seriam enviados com os seguintes flags:
1. PARTIAL_PACKET
2. PARTIAL_PACKET | CONTINUED_PACKET
3. PARTIAL_PACKET | CONTINUED_PACKET
4. CONTINUED_PACKET

Dados

O campo de dados de pacotes do BO vem imediatamente após o cabeçalho. Ele é composto por uma seqüencia de caracteres simples, terminadas pelo caracter com código ASCII 0 (zero) -- NUL. Este terminador é obrigatório, o que faz com que o campo de dados tenha sempre pelo menos 1 byte (???).

O conteúdo do campo de dados merece interpretação diferente, dependendo se o pacote vai do cliente para o servidor ou se é o contrário (???). Em pacotes do cliente para o servidor, até duas seqüencias podem ser enviadas, sendo estas separadas pelo caracter NUL. Em pacotes do servidor para o cliente, há apenas uma seqüencia (???) com a resposta do comando.

"Campos" de dados

Tipo do pacote Campo 1 Campo 2
TYPE_ERROR (???) (???)
TYPE_PING N/A N/A
TYPE_SYSREBOOT N/A N/A
TYPE_SYSLOCKUP N/A N/A
TYPE_SYSLISTPASSWORDS N/A N/A
TYPE_SYSVIEWCONSOLE (???) (???)
TYPE_SYSINFO N/A N/A
TYPE_SYSLOGKEYS Arquivo N/A
TYPE_SYSENDKEYLOG N/A N/A
TYPE_SYSDIALOGBOX Texto Título
TYPE_REGISTRYDELETEVALUE Nome do valor N/A
TYPE_REDIRADD Porta de entrada Endereço:porta
TYPE_REDIRDEL Identificação N/A
TYPE_REDIRLIST N/A N/A
TYPE_APPADD Executável Porta TCP
TYPE_APPDEL Identificação N/A
TYPE_NETEXPORTADD Compartilhamento Diretório, senha, anotação
TYPE_NETEXPORTDELETE Compartilhamento N/A
TYPE_NETEXPORTLIST N/A N/A
TYPE_PACKETRESEND (???) (???)
TYPE_HTTPENABLE Porta Diretório raiz do servidor
TYPE_HTTPDISABLE N/A N/A
TYPE_RESOLVEHOST Nome do host N/A
TYPE_FILEFREEZE Arquivo de entrada Arquivo de saída
TYPE_FILEMELT Arquivo de entrada Arquivo de saída
TYPE_PLUGINEXECUTE DLL:Função Argumentos
TYPE_PROCESSLIST N/A N/A
TYPE_PROCESSKILL Identificação N/A
TYPE_PROCESSSPAWN Executável e parâmetros Visível1
TYPE_REGISTRYCREATEKEY Chave N/A
TYPE_REGISTRYSETVALUE Nome do valor Tipo,valor2
TYPE_REGISTRYDELETEKEY Chave N/A
TYPE_REGISTRYENUMKEYS Chave N/A
TYPE_REGISTRYENUMVALS Chave N/A
TYPE_MMCAPFRAME Arquivo .BMP Disposivo,largura,altura,bits
TYPE_MMCAPAVI Arquivo .AVI Disposivo,segundos,largura,altura,bits
TYPE_MMPLAYSOUND Arquivo .WAV N/A
TYPE_MMLISTCAPS N/A N/A
TYPE_MMCAPSCREEN Arquivo .BMP N/A
TYPE_TCPFILESEND Arquivo Endereço:porta
TYPE_TCPFILERECEIVE Arquivo Endereço:porta
TYPE_PLUGINLIST N/A N/A
TYPE_PLUGINKILL Identificação N/A
TYPE_DIRECTORYLIST Diretório N/A
TYPE_FILEFIND Nome (wildcards permitidos) Raiz
TYPE_FILEDELETE Nome do arquivo N/A
TYPE_FILEVIEW Nome do arquivo N/A
TYPE_FILERENAME Nome antigo (???) Nome novo (???)
TYPE_FILECOPY Arquivo fonte Arquivo destino
TYPE_NETVIEW N/A N/A
TYPE_NETUSE Recurso da rede Senha
TYPE_NETDELETE Recurso N/A
TYPE_NETCONNECTIONS N/A N/A
TYPE_DIRECTORYMAKE Nome do novo diretório N/A
TYPE_DIRECTORYDELETE Nome do diretório N/A
TYPE_APPLIST N/A N/A
1 Se o segundo parâmetro estiver presente, a aplicação é feita visível. Do contrário ela executa escondida.

2 O tipo pode ser "B" para binário, "D" para palavra-dupla (DWORD) e "S" para uma seqüencia de caracteres ("string"). Em campos binários, o valor é uma sequência de dois-a-dois dígitos hexadecimais (e.g. "ab 11 5f"); em campos palavra-dupla, o valor é o próprio em decimal; no tipo "S", o valor é a própria seqüencia de caracteres.

CRC

Após o campo de dados segue 1 byte contendo o CRC (???) do pacote. O servidor BO parece ignorar o valor deste byte.

Criptografia

Todo pacote do BO é criptografado. Todo o pacote (incluíndo o cabeçalho) é criptografado. O esquema de criptografia utilizado é simples e é baseado em uma senha secreta que deve ser conhecida por ambas as partes. A senha é usada apenas para criptografar os pacotes; a senha nunca trafega na rede.

A criptografia é feita aplicando a operação XOR (ou exclusivo) entre cada byte do pacote e o valor seqüencial retornado por um gerador de número aleatórios. Este gerador é inicializado com um valor dependente da senha secreta utilizada nas comunicações. Desta forma, de posse da mesma senha, tanto o gerador de números aleatórios do cliente como o do servidor vai ser alimentado com o mesmo valor inicial, fazendo com que estes gerem a mesma seqüencia que poderá, então, ser usada para criptografar/decriptografar o pacote.

Este esquema de criptografia não é forte. Como todo o conteúdo de um pacote é criptografado e este sempre contém uma seção fixa (MAGICA) no cabeçalho, de posse de um pacote criptografado pode-se deduzir facilmente a seqüencia de número aleatórios gerados e utilizar-se de força bruta para descobrir o valor inicial do gerador de números aleatórios já que a faixa de valores que este pode assumir é pequena. Os métodos utilizados para decriptografar um pacote do BO sem a senha geradora estão fora do escopo deste documento e não serão cobertos nele, sendo deixados como exercício para o leitor.

O Gerador de Números Aleatórios

O protocolo do BO utiliza a seguinte função geradora de números aleatórios:
BORAND(x) = (x * 214013) + 2531011

Onde "A * B" denota multiplicação de A por B e "+" adição.

O valor do parâmetro inicial é derivado da senha de comunicação (ver abaixo). O valor subseqüente é sempre o resultado do valor imediamente anterior. Assim, uma seqüencia de números aleatórios X1, X2, ..., Xn pode ser obtida da seguinte forma:

X1 = BORAND(IV)
X2 = BORAND(X1)
X3 = BORAND(X2)
    ...
Xn = BORAND(Xn - 1)

Onde IV é o valor inicial do gerador e Xn é o n-ésimo número aleatório gerado.

Valor Inicial do Gerador

O valor inicial a ser usado no gerador de números aleatórios do BO é gerado tendo como base a senha de comunicação. Se nenhuma senha estiver em uso, o valor especial 31337 é utilizado como valor inicial. Senão, o seguinte algorítmo obtém o valor inicial de uma senha S:
X = 0
Y = número de caracteres de S
Z = 0
ENQUANTO X < Y
	Z = Z + S[X]
	X = X + 1
FIM

X = 0
ENQUANTO X < Y
	SE X é impar
		Z = Z - (S[X] * (Y - X + 1))
	SENAO
		Z = Z + (S[X] * (Y - X + 1))
	FIM
	Z = Z % 0x7fffffff
	X = X + 1
FIM
Z = (Z * Y) % 0x7fffffff
IV = Z
Onde "S[n]" denota o n-ésimo caracter da senha, "A % B" o resto da divisão de A por B e "IV" o valor inicial procurado.

Nota: o gerador de números aleatórios é iniciado com o valor inicial para cada pacote a ser enviado/recebido.

Nota: as variáveis X, Y e Z são inteiros de 32 bits. Isso significa que os bits mais significativos acima do 32o bit, gerados pelas operações do algorítmo, serão ignorados.

Criptografando/decriptografando

O seguinte algorítmo é uma demostração de como um pacote do BO pode ser criptografado ou decriptografado:
L = tamanho do pacote BO
X = 0
Z = IV
ENQUANTO X < L
	Z = BORAND(Z)
	P[X] = P[X] ^ ((Z >> 16) & 0xff)
	X = X + 1
FIM
Onde "P[n]" denota o n-ésimo byte do pacote, "A ^ B" a operação XOR (ou exclusivo) entre A e B, "A >> B" a rotação de A por B bits à direita e "A & B" a operação E bit a bit entre A e B.

Transferência de Arquivos via TCP

A transferência de arquivos usando TCP (operações TYPE_TCPFILESEND e TYPE_TCPFILERECEIVE) é feita pelo servidor abrindo a porta especificada como parâmetro do comando.

Quando o cliente envia um pacote TYPE_TCPFILESEND, o servidor abre o arquivo especificado e inicia a espera de uma conexão TCP na porta especificada. Então, o cliente conecta naquela porta TCP e inicia o envio do arquivo.

Quando o cliente quer receber um arquivo, ele envia um pacote TYPE_TCPFILERECEIVE especificando o nome do arquivo desejado e a porta TCP. O servidor então abre a porta e começa a enviar o arquivo assim que alguém (provavelmente o cliente) conecta nela.

O fluxo de dados TCP não é criptografado.

Todo este papo sobre envio/recebimento de arquivos via TCP é "(???)".

Referências

Copyright/disclaimer

Copyright © 1998 para Flávio Veloso. Todos os direitos reservados.

Este documento e seu conteúdo, ou partes, pode ser copiado, utilizado ou ser tomado como base para outros documentos/trabalhos livremente sem necessidade de autorização do autor, desde que o crédito de autoria seja dado ao mesmo. Também, quaisquer cópias deste documento podem ser alteradas, traduzidas, corrigidas, etc., sem a necessidade de autorização do autor desde que a(s) alteração(ões) seja(m) mencionada(s) explicitamente (o que não elimina a necessidade de crédito ao trabalho do autor).

Você assume todo o risco e resposabilidade ao usar qualquer informação obtida neste documento. Em nenhum momento o autor pode garantir que este documento está totalmente correto e não poderá ser responsabilizado se este não estiver. Se você descobrir alguma falha neste documento, ou tiver alguma informação que possa contribuir para aprimorá-lo, fale comigo no endereço flaviovs@centroin.com.br. Qualquer informação que ajude a eliminar algum dos "(???)" será muito bem-vinda!

Agradecimentos

Meus agradecimentos às seguintes pessoas que me ajudaram a corrigir ou melhorar este documento:
Markus <markus@?????????.nl>
J.M. Colàs <jmcolas@mx3.redestb.es>

-x-x-

Última atualização em 8 de janeiro de 1999