击败SVGCaptcha


79

我遇到了SVGCaptcha,立即意识到这是一个坏主意。

我希望您通过从代码产生的SVG图像中提取验证代码来说明这是多么糟糕的主意。


示例图像如下所示: 这是示例图像的来源:
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>

输入的是SVG图像,它是一种文本格式。

唯一真正的限制是您的代码必须以正确的顺序生成值。
输入<text>元素的顺序是随机的,因此您必须注意标记中的x属性<text>


分数是代码中的字节数


由于该代码当前进行了两次相互抵消的转换,因此您可以忽略它们,但是如果您考虑到它们,请继续进行,并将分数降低30%。


3
您实际上尚未明确说明输入和输出是什么:我想知道SVG文件及其中包含的字母吗?而且我不清楚是否需要答案才能真正实现SVG规范,或者他们是否可以假设SVG是由当前版本的SVGCaptcha生成的,因此可以忽略这些转换。
彼得·泰勒

我建议将输出限制为STDOUT或函数返回值,并使其
变为

1
不,问题需要客观,可量化的获胜标准才能成为该网站的主题。
Alex A.

7
我不确定图像处理在这里有多重要。
SuperJedi224

18
谷歌搜索“ svgcaptcha”时,这个问题现在是第四个结果:)
蓝色

Answers:


18

Bash63 56 39字节

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

注:需要cat grepsortrev,和cut。接受来自stdin的输入。输出由stdout上的换行符分隔。完成输入验证码后,请确保按CTRL + D(在Mac上不是COMMAND + D)。输入的内容必须后跟换行符,然后是“ _”。

编辑:保存了13个字节。

编辑2:感谢@manatwork,节省了20个字节!


GNU coreutils sort支持keydef中的字符位置:cut -c4-|sort -nsort -k1.4n
manatwork '18

@manatwork谢谢,我更新了答案。
Coder256

13

CJam,26个字节

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

CJam解释器中在线尝试。

这个怎么运作

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字节

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

编辑:-2个字节更改documentRootlastChild; -2个字节更改join('')join``,谢谢Vɪʜᴀɴ

在包含有问题的SVG的页面上的浏览器控制台中输入代码,写入控制台输出。


document.rootElement正在重新调整未定义。我已经尝试过Firefox和Safari
Downgoat 2015年

该功能仅在Chrome中进行了测试,我将研究可以更改的内容。
Nickson

它似乎可以在Firefox中使用,SVG是文件的唯一内容吗?
尼克森,2015年

好的,可以在Chrome浏览器中进行尝试,现在可以使用了。+1。您还可以通过将('')改为两个反引号来保存两个字节:``
Downgoat 2015年

这是78 :(t=>(l=[],r=/x="(\d*).*?>(.)/g,eval("while(e=r.exec(t))l[e[1]]=e[2];l.join``"))将xml字符串作为参数,返回验证码文本)
DankMemes

7

Perl,40个字节

39个字节的代码+ -n的1个

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

例:

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

如果您将其打开,那只会充满警告。很好地使用了Perl的默认宽松特性。
布拉德·吉尔伯特b2gills,2015年

@ BradGilbertb2gills是的,我尝试不测试警告,我很惊讶,即使是打高尔夫球的代码有时也能正常工作!
唐·黑斯廷斯



3

Befunge,79个字节

感觉应该至少可以再打一个字节,但是我现在已经花了几天的时间了,这是我所能得到的。

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

在线尝试!

说明

突出显示执行路径的源代码

*使执行方向从右到左,然后环绕以开始主循环。
*从标准输入中读取一个字符,并测试文件结束值。
*如果不是文件结尾,请检查它是否为>
*如果不是>,请将其添加到跟踪最后两个字符的堆栈中的值,并检查当前对是否匹配x=
*如果不是,则乘以126并用126 2修改,以删除对中最早的值并为下一个字符腾出空间。
*再次环绕以重复主循环。遇到
*x=对时,跳过下一个字符(引号),读取一个整数(x值),然后除以20。这将成为当前偏移量,将其保存以备后用。
*>遇到a 时,读取下一个字符(通常是一个验证码字母),并将其保存在“数组”中的当前偏移量处。将偏移量重置为9,这样当>遇到更高字符时,验证码字母不会被覆盖。
*最后,当到达文件末尾时,遍历数组中保存的7个值,并将它们一个接一个地输出。那应该给您所有正确的验证码字母。

我在这里掩盖了一些细节,因为代码路径以难以解释的方式相互重叠,但是它应该使您大致了解算法的工作原理。


2

Python2,129个字节

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])))

在stdin上获取HTML源代码,在stdout上生成代码。


如何对输出进行排序?该<text>元素是随机顺序,唯一的真正的要求是,你必须把他们在正确的顺序。这意味着您必须使用xfrom中的<text>并遵循所有转换。
布拉德·吉尔伯特b2gills,2015年

@ BradGilbertb2gills我第一次错过了,现在修复了。
orlp

2

Mathematica,106个字节

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

注意:输入必须与示例指定的格式完全相同。


2

V28 26 25 24字节

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

在线尝试!

说明:

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.

十六进制转储:

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

2

四边形,49个字节

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

在线尝试!

查找x值(在后面的数字行x=")和“字母​​”(由关闭和打开标签固定),然后执行以下APL(其中,找到的x值和字母的列表按出现顺序排列):

3↓⍵ 删除前三个元素(<rect/rect><rect'sx值之间的空格)。

(…… ) 对此应用以下默认功能:

 剩余物品数

.5× 减半

2,⍨ 追加两个

⊢⍴⍨ 重塑为该形状(即n×2矩阵)

 转置(到2×n矩阵)

⍎¨@1 执行第一行中的每个字符串(将它们转换为数字)

 将矩阵分成两个向量(每行一个)

x c← 将这两个分别存储在x(x值)和c(字符)中

 选择第一个(x)

 升级(x的索引将对x进行排序)

c[] 用它来索引c

ϵ nlist(拼合),因为每个字母本身就是一个字符串


整个QuadS程序的等效APL表达式为:

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

1

Java的8,197个 173字节

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();}

输出一个java.util.Collection字符。

说明:

在线尝试。

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个字符

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

在Gema中,没有排序,但幸运的是甚至不需要。

样品运行:

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

1

XMLStarlet,46个字符

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

希望这是有效的解决方案,因为XMLStarlet是编译器,可以生成并执行XSLT代码,这是一种Turing完整的语言。

样品运行:

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

1

PHP,96字节

鉴于这$i是输入字符串

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

1
相反的array_combine()+ ksort(),你可以使用array_multisort()这样的:array_multisort($m[1],$m[2]);echo join($m[2]);。但是请注意,解决方案应该自己处理输入和输出(除非语言自动完成),而不是期望在变量中找到输入或仅将结果留在变量中。参见相关的meta
manatwork '18

1

干净277150字节

耶模式匹配!

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>']])))

在线尝试!

定义功能?,取[Char]和给[Char]

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.