Bem vindos ao Blog da comunidade ITsafe



Boa Leitura


Blog em em português sobre construção . Por favor se encontrar algo que necessite correção entre em contato. Os vídeos do blog ainda estão em hebraico, mas em breve estaremos traduzindo com a mesma qualidade que traduzimos os cursos.


Google CTF JS2.0

O segundo desafio do Google sobre o assunto javascript
Neste tutorial, vou apresentar a você minha solução para o desafio JS SAFE 2.0 do GoogleCTF2018. Todos os anos, costumo enfrentar uma série de desafios fascinantes em uma variedade de tópicos gerais:

  • CRYPTO
  • MISC
  • PWN
  • RE
  • WEB

Tento todos os anos resolver pelo menos 1-2 desafios da web, são desafios relativamente difíceis em comparação com outras competições CTF das quais participo.

O objetivo deste desafio é contornar todas as técnicas anti-depuração do arquivo js_safe_2 que recebemos no início do desafio.

No final da competição gravei um vídeo demonstrando a solução:

Este desafio começa quando você obtém o arquivo js_safe_2 assim:
O cofre que pede uma senha
Para encontrar a função que lida com a entrada de dados no campo de entrada, clique em inspecionar e vá para a guia Event Listeners:
Função open_safe
Clique na função e ela nos moverá para-source:
Botão que conduz à função open_safe
Vamos procurar open_safe no arquivo e ver o seguinte código:
O código-fonte da função open_safe que executa a função x após receber uma senha
Neste código temos uma expressão regular que se ela não existir ou se a função x retornar False então o cofre nos imprime Acesso negado caso contrário obteremos Access granted.

A função x está configurada e pode ser vista minified, então podemos ver prettify usando o navegador:
Dividindo a função em seis partes
Eu dividi o código 7 em partes para você, para tornar mais fácil entender o que este código faz:

  1. No início do código, 3 funções auxiliares são definidas para o software, elas mudaram as funções para sua estrutura em python para que fossem mais fáceis de usar..
  • A função Ord converte um caractere em seu valor decimal.
  • A função chr converte um valor decimal em um caractere, o inverso da ord.
  • A função str converte a variável-String.
  1. Na segunda parte vemos uma função interessante que recebe algum texto e executa sobre ele 2 operações matemáticas que parecem relativamente estranhas.

Normalmente, quando você vê um pedaço de código como este, trata-se de um algoritmo existente que executa algo familiar, então eu pesquisei no google a palavra algorithm % 65521 E encontrei o algoritmo Adler-32:
Uma pesquisa no Google mostra que este é um adler-32
A partir disso, pode-se deduzir que a função realiza um cálculo de assinatura para algum texto, de modo que se algo enviar a h um sinal de que o código está tentando assiná-lo, o resultado da assinatura será 2 bytes de b outros 2 bytes de a.

  1. Esta função realiza XOR entre informações que aceita e os quatro caracteres na assinatura, encadeia-los e retornar. Código relativamente simples, não há nada a acrescentar aqui..

  2. Loop de anti-depuração cujo trabalho é promover "a" em 1000 e no caminho, se as ferramentas do desenvolvedor estiverem abertas, ele nos impede de depurar chamando a função debugger.

Para contornar a parte do código, tudo o que precisamos fazer é alterar o tempo de execução "a" para 999 e, portanto, "a" função não irá interferir em nosso processo:
Comando debugger
5. O comando a seguir altera x para o resultado da assinatura de:
`` str(x)`
Que é o código fonte da própria função:
O código-fonte da função
Sobre isso assinamos com adler e recemos:
130,30,10,154
6. Implementação de outra técnica anti-depuração que converte a expressão regular em texto e, ao imprimir, passa para a função c que conecta o navegador.

  1. Usando with e rodadando o seguinte código:
    `` with (source)
    return eval('eval(c(source,x))')
    `
    A função with prepara a fonte para o escopo de modo que não tenhamos que fazer uma chamada para source.source. Para obter mais informações, consulte o vídeo de resolucao do desafio no início deste tutorial.

Além disso, a função também realiza:
eval(c(source,x))` Que realmente executa o conteúdo de: c(source,x) Conhecemos os valores porque são os resultados da assinatura da função e da expressão regular definida, se os colocarmos no código a seguir: ![Obteremos х==c('¢×&Ê´cʯ¬$¶³´}ÍÈ´T—©Ð8ͳÍ|Ԝ÷aÈÐÝ&›¨þJ',h(х))//᧢](/img/tutorials/google_ctf_js2.0-11.png) Foi assim que obtivemos o código: `` х==c('¢×&Ê´cʯ¬$¶³´}ÍÈ´T—©Ð8ͳÍ|Ԝ÷aÈÐÝ&›¨þJ',h(х))//᧢
Este código executa novamente a operação h em х apenas desta vez é o x da nossa entrada e nele executa a operação xor este segmento de código também será convertido em código python com a seguinte lógica:
Primeiro criamos uma fila de tarefas com 8 realizadores.:
`` from queue import Queue
from threading import Thread

worker_thread = 8
my_queue = Queue()
`

Em seguida, definiremos nossa tarefa - procurar os caracteres apropriados a e b que, após inserir o código adler-32, nos darão uma assinatura lógica que contém o FLAG, a distancia para a e b está entre 0 e 65521 porque é o meio de adler- 32:
``

for a in range(5600, 65521):
for b in range(0, 65521):
    data = [chr(b >> 8) , chr(b & 0xFF) ,chr(a >> 8) , chr(a & 0xFF)]
    my_queue.put(data)
                                            

`

Assim que tivermos definido a tarefa, iremos escrever o código dos realizadores, os realizadores farão o cálculo xor na assinatura que recebemos e verificar se ela se ajusta à expressão regular do nosso programa que vimos no início, se realmente houver uma correspondência, o código imprimirá o resultado.
``

    def worker_func(q):
    while True:
        data = q.get()

        print_at_exit = True
        looking_for = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_@!?-"

        a = '¢×&Ê´cʯ¬$¶³´}ÍÈ´T—©Ð8ͳÍ|Ԝ÷aÈÐÝ&›¨þJ'
        b = data

        output = []
        for i in range(len(a)):
            xor = chr(ord(str(a[i])) ^ ord(str(b[i % 4])))
            if not xor in looking_for:
                print_at_exit = False
                break

            output.append(xor)

        if print_at_exit:
            print ("".join(output))

        q.task_done()

`

O código leva cerca de uma hora para encontrar o FLAG, é claro que você pode atualizar o código e usar-
multiprocessing` Para que possamos executar o código em vários processos e, assim, obter o resultado em menos tempo, recomendo usar: multiprocessing.Pool E: `` pool.apply_async
Para resolver o exercício muito mais rápido.

O código do desafio:

Compartilhe este post