是否可以在令牌中插入数组值?

Paw*_*bkr 7 raku

我正在研究homoglyphs 模块,我必须构建可以找到对应于 ASCII 等效项的同形文字的正则表达式。

因此,例如我有没有同形文字替代品的字符:

my $f = 'f';
Run Code Online (Sandbox Code Playgroud)

和可以混淆的字符:

my @o = 'o', '?', '?'; # ASCII o, Cyrillic o, Greek omicron
Run Code Online (Sandbox Code Playgroud)

我可以轻松构建正则表达式来检测同形文字短语“foo”:

say 'Suspicious!' if $text ~~ / $f @o @o /;
Run Code Online (Sandbox Code Playgroud)

但是,如果我不知道在编译时要检测的值,我应该如何编写这样的正则表达式?假设我想检测在邮件中包含同形文字“现金”字样的网络钓鱼。我可以使用所有替代方法构建序列:

my @lookup = ['c', '?', '?', '?'], ['a', '?', '?'], 's', 'h'; # arbitrary runtime length
Run Code Online (Sandbox Code Playgroud)

现在显然以下解决方案不能将数组元素“解包”到正则表达式中:

/ @lookup / # doing LTM, not searching elements in sequence
Run Code Online (Sandbox Code Playgroud)

我可以通过手动引用每个元素并组合替代项的文本表示来解决此问题,以获取可以作为正则表达式进行评估的字符串。并使用字符串插值从中构建令牌:

my $regexp-ish = textualize( @lookup ); # string "[ 'c' | '?' | '?' | '?' ] [ 'a' | '?' | '?' ] 's' 'h'"
my $token = token { <$regexp-ish> }
Run Code Online (Sandbox Code Playgroud)

但这很容易出错。是否有任何更清晰的解决方案可以从编译时未知的任意数量的元素中动态组合正则表达式

jjm*_*elo 5

Unicode::Security模块通过使用Unicode 联盟表来实现混淆。它实际上没有使用正则表达式,只是在这些表中查找不同的字符。


use*_*601 4

我不确定这是最好的使用方法。

\n\n

我还没有在 中实现易混淆1Intl::模块,尽管我确实计划最终解决它,但我可以想象令牌的两种不同方式。2

\n\n
my token confusable($source) {\n  :my $i = 0;                                    # create a counter var\n  [\n    <?{                                          # succeed only if\n      my $a = self.orig.substr: self.pos+$i, 1;  #   the test character A\n      my $b = $source.substr: $i++, 1;           #   the source character B and\n\n      so $a eq $b                                #   are the same or\n      || $a eq %*confusables{$b}.any;            #   the A is one of B\'s confusables\n    }> \n    .                                            # because we succeeded, consume a char\n  ] ** {$source.chars}                           # repeat for each grapheme in the source\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这里我使用了动态哈希%*confusables,它将以某种方式填充 \xe2\x80\x94\xc2\xa0 这将取决于您的模块,甚至可能不一定是动态的(例如,具有签名:($source, %confusables)或引用模块变量等。

\n\n

然后您可以让您的代码按如下方式工作:

\n\n
say $foo ~~ /<confusable: \'foo\'>/\n
Run Code Online (Sandbox Code Playgroud)\n\n

这可能是解决问题的最佳方法,因为它会给你更多的控制\xe2\x80\x94\xc2\xa0我在你的模块上达到了峰值,很明显你想要启用2对1字形关系,最终您可能希望直接在字符上运行代码。

\n\n

如果您只接受一对一的关系,则可以使用更简单的令牌:

\n\n
my token confusable($source) {\n  :my @chars = $source.comb;            # split the source \n  @(                                    # match the array based on \n     |(                                 #   a slip of\n        %confusables{@chars.head}       #     the confusables \n        // Empty                        #     (or nothing, if none)\n     ),                                 #\n     @a.shift                           #   and the char itself\n   )                                    #\n   ** {$source.chars}                   # repeating for each source char\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

@(\xe2\x80\xa6)结构使您可以有效地创建要进行插值的临时数组。在这种情况下,我们只需将易混淆的内容与原始内容一起放入即可,仅此而已。但你必须小心,因为不存在的哈希项将返回类型对象(Any),这会弄乱这里的事情(因此// Empty

\n\n

在任何一种情况下,您都需要将参数与令牌一起使用,因为动态构建正则表达式充满了潜在的陷阱和插值错误。

\n\n
\n\n

1 Unicode 将同形异义词称为“视觉上相似的字符”和“容易混淆的字符”。

\n\n

2这里的动态哈希%confusables可以通过多种方式填充,并且不一定需要是动态的,因为它可以通过参数填充(使用类似签名:($source, %confusables)或引用模块变量)。

\n