Olá pessoal, sou Nikita Kurtin, curadora do
departamento de TI e segurança da escola israelense
HackerU .
E continuo falando sobre testes cibernéticos da empresa israelense líder no campo do ponto de verificação de segurança da informação. Em um
post anterior, descrevi como passei por quatro testes, e neste quero falar sobre os próximos três que consegui passar.
Para aqueles que perderam o primeiro post, vou lhe contar neste verão que a
Checkpoint publicou uma série de testes cibernéticos.
O desafio terminou oficialmente até o final de setembro de 2018.
As tarefas foram divididas em seis categorias:
• lógica
• Web
Programação
Rede
• Reversão
Surpresa
Duas tarefas para cada direção. Como já
escrevi , a Checkpoint já havia conseguido ganhar respeito e interesse de minha parte, então decidi aceitar esses desafios. No entanto, devido ao emprego, fui capaz de realizar apenas 8 de 12 tarefas (de quatro categorias diferentes). E eu consegui resolver 7 deles.
E assim:
Desafio: Quebra-cabeça
Descrição:
Finalmente encontramos você!
Precisamos montar esse quebra-cabeça e, como diz a profecia - somente você é capaz disso.
O quebra-cabeça é muito bizarro. Consiste em uma placa com 10 colunas e 10 linhas. No total - 100 partes. E cada um deles carrega um mistério! As partes consistem em quatro partes: superior, inferior, direita e esquerda. Cada batida é um número. Por exemplo:
Superior - 12, direita - 3, inferior - 4 e esquerda - 5.
Para que o quebra-cabeça se desenvolva, todos os detalhes devem ser colocados no tabuleiro para que cada peça corresponda ao mesmo valor.
Além disso, uma fração que não une nada, mas faz parte do limite do quadro, deve ser definida como 0. As frações restantes não podem ter um valor zero. Aqui está um exemplo válido de 4 partes:

No topo do tabuleiro, todos os lobos que formam a borda são zero.
Considere a parte superior esquerda. Seu lobo direito é 9 e o lobo adjacente (lobo esquerdo da parte superior direita) também é 9.
Infelizmente, todos os nossos detalhes são embaralhados. Eles são fornecidos no seguinte formato:
ID do cubo [fração]; ID do cubo, [compartilhamentos]; ... ID do cubo, [compartilhamentos]
Onde o ID do cubo é números de 0 a 99 e as frações consistem em números organizados em ordem: superior, direita, inferior, esquerda.
Por exemplo, observe o seguinte quadro embaralhado:

Aqui está a linha que descreve este quadro:

Precisamos que você monte o quebra-cabeça!
Escreva-nos uma linha que seria exatamente assim:
ID do cubo, quantas vezes ele precisa ser girado no sentido horário; id do cubo, quantas vezes ele precisa ser girado no sentido horário; ... id do cubo, quantas vezes ele precisa ser girado no sentido horário
A linha com a solução para esta placa ficará assim:

A linha acima corresponde ao seguinte quebra-cabeça (resolvido):

Considere a parte superior esquerda. Na linha, corresponde à designação "2.2". Como usamos o cubo número 2 da entrada:

Mas nós giramos no sentido horário duas vezes e obtemos [0,19,5,0].
Agora considere a parte superior do meio. Na linha, corresponde à designação "1.0". Portanto, pegamos o cubo número 1 da entrada:

E não torça nada (sim, torça 0 vezes) - significa que ele já está na posição correta.
Entendeu?
Agora nos ajude a montar o quebra-cabeça!
É assim:

Boa sorte
Teoricamente, esse problema pode ser resolvido de várias maneiras diferentes. Encontre o seu e compartilhe-o. Pensei em várias opções e, finalmente, cheguei às seguintes conclusões:
O primeiro. A qualquer momento, só preciso definir um cubo. Para cada cubo, sempre saberei com certeza dois lados: o superior e o esquerdo. No início, é 0 e 0. O próximo cubo no topo também terá 0 e, à esquerda, haverá um dígito correspondente ao número do lobo direito do cubo anterior.
O segundo Devido ao grande número de variações diferentes entre os cubos, eu deveria tentar fazer o menor número possível de etapas e me livrar de uma verificação sem sentido no primeiro resultado negativo.
O terceiro. Para trabalhar com cubos diferentes, sempre preciso lembrar sua posição inicial (id), o número de voltas desde o ponto inicial e, aparentemente, o número de lados (superior, direito, inferior, esquerdo).
Quarta. A entrada inicial é uma sequência. E a saída também é uma string (e não a posição atual).
Com base nisso, desenvolvi a seguinte estratégia para mim:
Mova-se linearmente - da esquerda para a direita até atingir o canto direito. Em seguida, desça uma linha e comece à esquerda com o número inferior do cubo, localizado acima.
A conformidade deve ser verificada após cada rotação. Portanto, se você já completou 4 turnos e ainda não há uma única partida para este cubo, eu continuo com a próxima. Cada cubo verificado pode potencialmente ser verificado com todos os outros detalhes, para isso eu posso repetir recursivamente a inicialização de cada um deles com um conjunto completo de todos os outros cubos.
Para rastrear todas as manipulações com os dados de origem, escolhi um método de programação orientado a objetos no qual um cubo é um objeto com um ID, o número de rotações e quatro lados: superior, direito, inferior e esquerdo.
Em vez de copiar o estado inicial e evitar contagens falsas após várias rodadas, sempre aumentava a contagem em um. Mas quando verifiquei o número final de rotações, usei o módulo (restante da divisão) por 4.
Por exemplo, se uma rotação é necessária (de [1,2,3,4] a [4,1,2,3]), mas, no início, três rotações foram realizadas erroneamente (atualmente [2,3,4,1] ), da próxima vez serão necessários 2 (do atual [2,3,4,1] para o necessário [4,1,2,3]). 3 mais 2 é 5. E 5% 4 = 1, e é isso que você precisa.
Eu sempre preciso acompanhar os cubos usados e impedir novas verificações. Para isso, eu uso uma tabela de cubos de identificação. E se o cubo que está sendo comparado corresponder, eu o removerei da lista.
Selecionei as seguintes estruturas de dados:
HashMap - para ligar o id (posição inicial) e um cubo construído a partir da string de entrada.
Pilha - para verificar os cubos de identificação relacionados.
Matriz - para testar temporariamente o resultado.
Cubo de código do objeto:

Funções de manipulação de string:

A lógica da solução para encontrar cubos correspondentes:

Resultado:
Desafio: Ping Pong
Descrição:
Aposto que você não é rápido o suficiente para me vencer.
Aqui é onde estou:
nc 35.157.111.68 10158Ao executar este comando, você obtém:

À primeira vista, parece que essa é uma tarefa para trabalhar com fluxos.
No entanto, depois de receber os primeiros dados, parece que ele cai no Tempo Limite e depois completamente - será coberto.
Quando os dados terminam, um novo separador de linhas é exibido.
Recriei o fluxo usando o código Python.
Parece funcionar, então adicionei um código iterativo que repete o algoritmo de pingue-pongue e esperarei até que o sinalizador apareça.

Depois de um grande número de reorganizações de pingue-pongue (talvez mais de mil) entre o cliente e o servidor, finalmente faço as coisas.
Desafio: "Protocolo"
Descrição:
Oi ai
Precisamos extrair os dados secretos de um servidor especial. Não sabemos muito sobre ele, mas conseguimos interceptar o tráfego que suporta a comunicação com este servidor.
Também sabemos que o caminho para este arquivo secreto é: /usr/PRivAtE.txt
Você pode encontrar o arquivo sniff aqui (link para o arquivo).
Por favor, diga-nos qual é o segredo!
Boa sorteEu baixei o arquivo e o abri usando o Wireshark

E checou as negociações registradas

Isso me permitiu descobrir o que estava acontecendo.

Notei que havia negociações entre o IP 35.157.111.68 através da porta 20120 e a porta SSH 22. Eu deveria verificar essa porta 20120, decidi, e depois mudar para SSH (depois percebi que isso não era necessário).
Eu usei o comando nc para verificar esse IP e porta e recebi uma resposta: "0 8 Bem-vindo"

Como eu não sabia ao certo o que ele esperava, voltei a Wireshark para ver se havia alguma pista.
Filtrei todos os pacotes de dados para 35.157.111.68 na porta 20120 e encontrei uma conversa de fácil leitura:





Recriei tudo isso usando a linha de comando nc:

Percebi que a resposta para minha solicitação “2 3 XOR” era diferente da resposta no arquivo.
Repeti todo o procedimento várias vezes para ver se a resposta mudava sempre.


Como eu pensava, os 4 valores obtidos eram diferentes a cada vez, assim como os dados finais.
Os quatro valores obtidos parecem ser a chave para decifrar os dados finais.
Também notei que os números antes de cada pacote de dados não são aleatórios.
Parece o seguinte.
O primeiro número significa ordem: 0 -> primeiro, 1 -> segundo, 2 -> terceiro, etc ...
O segundo número significa a duração da frase 8 -> "Bem-vindo", 5 -> "Olá" -> etc.
Imaginei que essa não é a chave da descriptografia. Como os dados finais são uma linha contínua de blocos de 4 valores HEX e a chave XOR também é de 4 valores HEX. Talvez eu possa iterar sobre cada um e dividi-lo em bytes separados e depois mordê-los com bytes da chave.
E eu tentei descriptografar:

Tudo acabou, mas não havia sinalizador nos dados recebidos.

Reli as regras e lembrei que o caminho para esse arquivo secreto é o seguinte: /usr/PRivAtE.txt
Repeti o procedimento novamente, mas desta vez solicitei o caminho "/usr/PRivAtE.txt"

Tentei novamente descriptografar os dados finais:

E a bandeira estava em minhas mãos:

Você conseguiu? Escreva suas idéias e opções, ficarei feliz em comentar.