Derrotar SVGCaptcha


79

Me deparei com SVGCaptcha e imediatamente soube que era uma má ideia.

Gostaria que você mostrasse o quão ruim é essa idéia, extraindo o código de validação das imagens SVG que o código produz.


Uma imagem de exemplo é semelhante a esta: Aqui está a fonte da imagem de exemplo:
8u4x8lf

<?xml version="1.0" encoding="utf-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
        "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
    <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
             width="200" height="40"
    > <rect x="0" y="0" width="200" height="40" 
        style="stroke: none; fill: none;" >
        </rect> <text style="fill: #4d9363;" x="5" y="34" font-size="20" transform="translate(5, 34) rotate(-17) translate(-5, -34)">8</text>
<text style="fill: #be8b33;" x="125" y="29" font-size="21" transform="translate(125, 29) rotate(17) translate(-125, -29)">f</text>
<text style="fill: #d561ff;" x="45" y="35" font-size="20" transform="translate(45, 35) rotate(-2) translate(-45, -35)">4</text>
<text style="fill: #3de754;" x="85" y="31" font-size="21" transform="translate(85, 31) rotate(-9) translate(-85, -31)">8</text>
<text style="fill: #5ed4bf;" x="25" y="33" font-size="22" transform="translate(25, 33) rotate(16) translate(-25, -33)">u</text>
<text style="fill: #894aee;" x="105" y="28" font-size="25" transform="translate(105, 28) rotate(9) translate(-105, -28)">1</text>
<text style="fill: #e4c437;" x="65" y="32" font-size="20" transform="translate(65, 32) rotate(17) translate(-65, -32)">x</text>
</svg>

A entrada é a imagem SVG, que é um formato de texto.

A única restrição real é que seu código deve produzir os valores na ordem correta .
Os <text>elementos de entrada estão em ordem aleatória, portanto, você deve prestar atenção ao xatributo na <text>tag


Pontuação é o número de bytes no código


Como o código atualmente faz duas transformações que se cancelam, você pode ignorá-las, mas se você as levar em consideração, vá em frente e faça uma redução de 30% na sua pontuação.


3
Na verdade, você não declarou explicitamente quais são as entradas e saídas: estou presumindo o arquivo SVG e as letras nele contidas? E não está claro para mim se são necessárias respostas para realmente implementar a especificação SVG ou se elas podem assumir que o SVG é gerado pela versão atual do SVGCaptcha e, portanto, as transformações podem ser ignoradas.
Peter Taylor

Sugiro que limita a saída para STDOUT ou valor de retorno de função, e tornando- code-golf
TheDoctor

1
Não, as perguntas precisam de um critério de vitória objetivo e quantificável para estar no tópico deste site.
Alex A.

7
Não tenho certeza de quão relevante é o processamento de imagens aqui.
SuperJedi224

18
Esta questão é agora o quarto resultado quando pesquisando 'svgcaptcha' :)
Azul

Respostas:


18

Bash , 63 56 39 bytes

cat<<_|grep -o 'x=.*>'|cut -c4-|sort -n|grep -o '>.</t'|cut -c2

grep -o 'x=.*>'|cut -c4-|sort -n|grep -o '>.</t'|cut -c2

grep -o 'x=.*<'|sort -k1.4n|rev|cut -c2

Nota: exige cat, grep , sort, rev, e cut. Recebe entrada de stdin. A saída é separada por quebras de linha no stdout. Certifique-se de pressionar CTRL + D (não COMMAND + D no Mac) quando terminar de inserir o CAPTCHA. A entrada deve ser seguida por uma nova linha e depois '_'.

EDIT : salvou 13 bytes.

EDIT 2 : economizou 20 bytes graças a @manatwork !


O coreutils GNU sortsuporta a posição dos caracteres no keydef: cut -c4-|sort -nsort -k1.4n.
manatwork

@manatwork Obrigado, atualizei a resposta.
Coder256

13

CJam, 26 bytes

q"x="/2>{'"/1=i}${'>/1=c}/

Experimente online no intérprete CJam .

Como funciona

q     e# Read all input from STDIN.
"x="/ e# Split it at occurrences of "x=".
2>    e# Discard the first two chunks (head and container).
{     e# Sort the remaining chunks by the following key:
  '"/ e#   Split at occurrences of '"'.
  1=  e#   Select the second chunk (digits of x="<digits>").
  i   e#   Cast to integer.
}$    e#
{     e# For each of the sorted chunks:
  '>/ e#   Split at occurrences of '>'.
  1=  e#   Select the second chunk.
  c   e#   Cast to character.
}/    e#

8

JavaScript, 95 93 91 bytes

l=[],r=/x="(\d*).*>(.)/g;while(e=r.exec(document.lastChild.innerHTML))l[e[1]]=e[2];l.join``

editar: -2 bytes mudando documentRootpara lastChild; -2 bytes mudando join('')para join``, obrigado Vɪʜᴀɴ

Digite o código no console do navegador em uma página que contenha o SVG em questão e grave na saída do console.


document.rootElementestá sendo retomado indefinido. Eu tentei Firefox e Safari
Downgoat

Isso foi testado apenas no Chrome, analisarei o que poderia ser alterado.
Nick16:

Parece funcionar no Firefox, SVG é o único conteúdo do arquivo?
Nickson

Ok, tentei no Chrome, agora funcionou. +1. Você também pode salvar dois bytes alterando os ('')dois backticks: ``
Downgoat

Esta é de 78: t=>(l=[],r=/x="(\d*).*?>(.)/g,eval("while(e=r.exec(t))l[e[1]]=e[2];l.join``"))(leva string XML como parâmetro, retorna texto da imagem)
DankMemes

7

Perl, 40 bytes

Código de 39 bytes + 1 para -n

$a[$1]=$2 for/x="(.+)".+(.)</g}{print@a

Exemplo:

perl -ne '$a[$1]=$2 for/x="(.+)".+(.)</g}{print@a' <<< '<example from above>'
8u4x81f

Homem que está cheio de avisos se você os ativar. Excelente uso da natureza negligente padrão do Perl.
Brad Gilbert b2gills

@ BradGilbertb2gills Sim, tento não testar os avisos, estou tão surpreso que qualquer código de golfe às vezes funciona!
Dom Hastings



3

Befunge, 79 bytes

Parece que deveria ser possível jogar golfe a pelo menos mais um byte disso, mas já estou trabalhando há alguns dias e isso é o melhor que pude.

<%*:"~"*"~"_~&45*/99p1v-">":_|#`0:~<
#,:#g7-#:_@^-+*"x~=":+_~99g7p>999p#^_>>#1+

Experimente online!

Explicação

Código fonte com caminhos de execução destacados

*Faça a direção de execução da direita para a esquerda e envolva para iniciar o loop principal.
*Leia um caractere de stdin e teste o valor de final de arquivo.
*Se não for o fim do arquivo, verifique se é um >.
*Se não for um >, adicione-o ao valor na pilha que rastreia os dois últimos caracteres e verifique se o par atual corresponde x=.
*Caso contrário, multiplique por 126 e mod com 126 2 para eliminar o valor mais antigo do par e abrir espaço para o próximo caractere.
*Enrole novamente para repetir o loop principal.
*Quando um x=par for encontrado, pule o próximo caractere (a citação), leia um número inteiro (o x valor ) e divida por 20. Isso se torna o deslocamento atual que é salvo para mais tarde.
* Quando um> for encontrado, leia o próximo caractere (normalmente uma das letras captcha) e salve-o no deslocamento atual em uma "matriz". Redefina o deslocamento para 9, para que a letra captcha não seja substituída quando >forem encontrados caracteres posteriores .
*Finalmente, quando o final do arquivo for atingido, itere sobre os 7 valores salvos na matriz e os produza um por um. Isso deve fornecer todas as letras captcha na ordem correta.

Estou examinando alguns dos detalhes aqui, já que os caminhos do código se sobrepõem de maneiras um pouco difíceis de explicar, mas deve fornecer uma idéia geral de como o algoritmo funciona.


2

Python2, 129 bytes

import re,sys
print''.join(t[1] for t in sorted(re.findall(r'(\d+), -\d+\)"\>(.)\</t',sys.stdin.read()),key=lambda t:int(t[0])))

Pega a fonte HTML em stdin, produz código em stdout.


Como isso classifica a saída? Os <text>elementos estão em uma ordem aleatória e o único requisito real é que você precise colocá-los na ordem correta. Isso significa que você deve usar o comando xfrom <text>e seguir as transformações.
Brad Gilbert b2gills

@ BradGilbertb2gills Perdi isso da primeira vez, corrigido agora.
orlp

2

Mathematica, 106 bytes

""<>(v=ImportString[#~StringDrop~157,"XML"][[2,3,4;;;;2]])[[;;,3]][[Ordering[FromDigits/@v[[;;,2,2,2]]]]]&

Nota: A entrada precisa estar exatamente no formato especificado pelo exemplo.


2

V , 28 26 25 24 bytes

d5j́x=
ún
J́">
lH$dÍî

Experimente online!

Explicação:

d5j              delete first 6 lines
   Í<0x81>x=     In every line, replace everything up to x=" (inclusive) by nothing
ún               Sort numerically
J                Join line (closing </svg>) with next line
 Í<0x81>">       In every line, replace everything up to "> by nothing
l␖H$d            Visual block around closing </text> tags, delete
     Íî          In every line, replace \n by nothing.

HexDump:

00000000: 6435 6acd 8178 3d0a fa6e 0a4a cd81 223e  d5j..x=..n.J..">
00000010: 0a6c 1648 2464 cdee                      .l.H$d..

2

QuadS , 49 bytes

c[⍋⊃x c←↓⍎¨@1⍉(⊢⍴⍨2,⍨.5×≢)3↓⍵]
x="(\d+)
>(.)<
\1

Experimente online!

Localiza valores x (dígitos seguidos depois x=") e "letras" (fixados por tags de fechamento e abertura) e depois executa o seguinte APL (onde está a lista dos valores x encontrados e letras, em ordem de aparência):

3↓⍵ solte os três primeiros elementos (espaços ao redor de <rect/rect>e o <rectvalor 'sx).

() Aplique a seguinte função tácita nisso:

 o número de itens restantes

.5× reduzir pela metade

2,⍨ acrescentar dois

⊢⍴⍨ remodelar para essa forma (ou seja, uma matriz n × 2)

 transpor (para uma matriz 2 × n)

⍎¨@1 execute cada string na primeira linha (transformando-as em números)

 divida a matriz em dois vetores (um por linha)

x c← armazene esses dois em x (valores de x) ec (caracteres) respectivamente

 escolha o primeiro (x)

 classificar (os índices em x que classificariam x)

c[... ] use isso para indexar emc

ε nlist (achatar), porque cada letra é uma string, por si só


A expressão APL equivalente de todo o programa QuadS é:

c[⍋⊃x c←↓⍎¨@1⍉(⊢⍴⍨2,⍨.5×≢)3'x="(\d+)"' '>(.)<'S'\1'⊢⎕]

1

Java 8, 197 173 bytes

import java.util*;s->{String a[]=s.split("x=\""),r="";Map m=new TreeMap();for(int i=2;i<a.length;m.put(new Long(a[i].split("\"")[0]),a[i++].split(">|<")[1]));return m.values();}

Produz um java.util.Collectionde caracteres.

Explicação:

Experimente online.

import java.util*;            // Required import for Map and TreeMap
s->{                          // Method with String as both parameter and return-type
  String a[]=s.split("x=\""), //  Split the input by `x="`, and store it as String-array
         r="";                //  Result-String, starting empty
  Map m=new TreeMap();        //  Create a sorted key-value map
  for(int i=2;                //  Skip the first two items in the array,
      i<a.length;             //  and loop over the rest
    m.put(new Long(a[i].split("\"")[0]),
                              //   Split by `"` and use the first item as number-key
          a[i++].split(">|<")[1]));
                              //   Split by `>` AND `<`, and use the second item as value
    return m.values();}       //  Return the values of the sorted map as result

1

Gema , 65 caracteres

x\="<D>*\>?=@set{$1;?}
?=
\Z=${5}${25}${45}${65}${85}${105}${125}

Em Gema, não há classificação, mas felizmente nem é necessário.

Exemplo de execução:

bash-4.4$ gema 'x\="<D>*\>?=@set{$1;?};?=;\Z=${5}${25}${45}${65}${85}${105}${125}' < captcha.svg
8u4x81f

1

XMLStarlet , 46 caracteres

xmlstarlet sel -t -m //_:text -s A:N:U @x -v .

Espero que esta seja uma solução válida, pois o XMLStarlet é um transpilador que gera e executa o código XSLT, que é uma linguagem completa de Turing.

Exemplo de execução:

bash-4.4$ xmlstarlet sel -t -m //_:text -s A:N:U @x -v . < captcha.svg 
8u4x81f

1

PHP, 96 bytes

Dado que $ié a string de entrada

preg_match_all('|x="(\d+).*(.)\<|',$i,$m);$a=array_combine($m[1],$m[2]);ksort($a);echo join($a);

1
Em vez de array_combine()+ ksort()você poderia usar array_multisort()como esta: array_multisort($m[1],$m[2]);echo join($m[2]);. Mas observe que as soluções devem lidar com entrada e saída (a menos que o idioma o faça automaticamente), em vez de esperar encontrar a entrada em uma variável ou simplesmente deixar o resultado em uma variável. Consulte meta relacionada .
manatwork

1

Limpo , 277 150 bytes

Yay padrão de correspondência!

import StdEnv,StdLib
?s=map snd(sort(zip(map(toInt o toString)[takeWhile isDigit h\\['" x="':h]<-tails s],[c\\[c:t]<-tails s|take 7 t==['</text>']])))

Experimente online!

Define a função ?, receber [Char]e dar [Char].

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.