É interessante para quem pretende fazer scripts de Greasemonkey utilizar a biblioteca jQuery para agilizar o desenvolvimento. Para isso o código comentado a seguir vai ajudar:
// Verifica se o jQuery pode ser usado
function GM_wait() {
if(typeof unsafeWindow.jQuery == ‘undefined’) { window.setTimeout(GM_wait,100); }
else { $ = unsafeWindow.jQuery; letsJQuery(); }
}
GM_wait();
function letsJQuery() {
// pode usar o $ aqui ;D
}
Obs: se você utiliza outro navegador existem outras opções para executar “user scripts”. Uma delas é o GreaseKit para WebKit (Safari).
Atualmente os captchas usados no Megaupload não são muito “difíceis” de resolver (de fato eles são muito ruins – exemplos abaixo).
Existem porém pontos interessantes aqui:
A API getImageData do HTML 5 é usada para pegar informações sobre os pixels da imagem. No HTML 5 é permitido adicionar uma imagem no elemento canvas (de onde então pose-se extrair informações sobre cada pixel usando JavaScript).
O script implementa uma rede neural, escrita em puro JavaScript.
As informações do pixel, extraídas da imagem usando canvas, são jogadas dentro da rede neural em uma tentativa de adivinhar o caractere usado – algo parecido com Optical Character Recognition (OCR).
Se abrirmos o código fonte podemos perceber que o funcionamento recai em como o captcha é implementado. Como mencionado anteriormente esse não é um captcha muito bom. Ele tem 3 letras, cada uma em uma cor diferente, usando uma possibilidade de 26 caracteres e eles são todos do mesmo tipo gráfico.
O primeiro passo é fácil de entender: O captcha é copiado dentro do canvas e então convertido para escala de cinza.
O canvas é então quebrado em três matrizes de pixels - cada uma contendo um caractere (isso é bem fácil de fazer - uma vez que cada caractere é de uma cor diferente, eles são separados pela diferença de cores usadas).
// Muda todos pixels de tal cor para a cor branca
if (image_data.data[i] == colour) {
image_data.data[i] = 255;
image_data.data[i+1] = 255;
image_data.data[i+2] = 255;
} else { // Todo o resto vira preto
image_data.data[i] = 0;
image_data.data[i+1] = 0;
image_data.data[i+2] = 0;
}
}
}
}
Finalmente qualquer pixel solto é removido da imagem (retornando um caractere limpo). Isso é feito procurando por pixels brancos (que eram da cor da letra) que são cercados de preto (que não bateram com nenhuma cor de letra). Se esse for o caso o pixel é simplesmente removido.
Estamos bem próximos de ter uma forma que pode alimentar uma rede neural, mas não estamos lá ainda. O script agora vai fazer uma forma bem crua de detecção de borda na forma, procurando pelos pixels que cercam o caractere e então o transformando em um retângulo. Nesse trecho a matriz também é reduzida para 20 por 25 pixels.
Então, após todo esse trabalho, o que nós temos? Uma matriz de 20 por 25 pixels contendo um único retângulo preenchido com preto e branco. Terrivelmente excitante.
Agora alguns pontos estratégicos são extraído da matriz para serem usado como "receptores" (eles que alimentarão a rede neural). Como exemplo, o receptor deve olhar para o pixel da posição 9x6 e verificar se ele está "ligado" ou não. Somente 64 estados (muito menos do que a matriz de 20 por 25 inteira) são então jogados para dentro da rede neural.
A questão que você deve estar se perguntando agora é: Por que não fazer somente uma simples comparação de pixels? Por que "isso de" redes neurais? Bom, o problema é que com toda essa redução da informação um monte de ambiguidade existe. Se você rodar a demonstração do script vai perceber que a comparação simples de pixels vai falhar mais que a nossa rede.
A próxima etapa é tentar adivinhar a letra. A rede é então alimentada com 64 valores boleanos (coletados das letras) juntamente com uma serie de valores pre-computados. Um dos conceitos por trás do funcionamento de redes neurais é que você reutiliza valores de execuções anteriores. É como se o autor do script rodasse ele várias vezes e coletasse uma serie de resultados para conseguir um valor ótimo. O resultado em si não tem nenhuma funcionalidade por si só mas ele ajuda a derivar o valor final.
A rede neural utiliza os 64 valores extraídos dos caracteres do captcha para comparar com valores pré-computados de cada letra do alfabeto. O resultado retornado dessas comparações é parecido com ‘98% de chances para A’, ‘36% de chances para B’, etc..
Repetindo com todas letras do captcha o objetivo é atingido. Ele não é 100% perfeito (imagino que resultados melhores seriam alcançados se a letra não fosse transformada em um simples retângulo antes da execução do algoritmo) mas é bom pelo que é – e impressionante considerando que tudo acontece 100% no navegador usando padrões emergentes.
Como nota – o que acontece aqui é bem especifico para esse captcha. Essa técnica deve funcionar em mais alguns captchas mal implementados, mas além disso a complexidade da maioria dos captchas é muito avançada (principalmente para qualquer analise no lado do cliente).
Eu estou esperando trabalhos interessantes derivados desse projeto – isso carrega bastante potencial.