¿Existe un diccionario de caracteres Unicode visiblemente similares para el procesamiento de Spam?

7

Tengo un spam que se ve así:

  

мy вυddy'ѕ мoм мαĸeѕ $ 74 / нoυr oɴ тнe lαpтop. εнe нαѕ вeeɴ lαιd oғғ ғor   εeveɴ мoɴтнѕ вυт lαѕт мoɴтн нer pαy cнecĸ w $ѕ $ 19420 jυѕт worĸιɴɢ oɴ   Por ejemplo, a la vez o por correo electrónico. íere'ѕ тнe ѕιтe тo reαd мore   algo.com

Obviamente, esto está usando Unicode para evitar la detección de spam. ¿Hay algún ASCII - > ¿Diccionarios Unicode que pueden ayudar a encontrar letras similares?

Esta es una variación de esta respuesta de desbordamiento de pila, pero es específica del correo no deseado.

    
pregunta random65537 21.05.2013 - 13:28
fuente

2 respuestas

5

Agregaría a mi algoritmo de clasificación de correo no deseado algo que detecte varias codificaciones en la misma palabra / oración. Por ejemplo, lαѕт tiene un% latín l , alfa griego / copto, dze cirílico, te cirílico parece muy sospechoso. Una cosa muy rápida y sucia en python podría hacerse usando unicodedata. Eso es

>>> unicode_str = u"""мy вυddy'ѕ мoм мαĸeѕ $74/нoυr oɴ тнe lαpтop. ѕнe нαѕ 
вeeɴ lαιd oғғ ғor ѕeveɴ мoɴтнѕ вυт lαѕт мoɴтн нer pαy cнecĸ wαѕ $19420 jυѕт 
worĸιɴɢ oɴ тнe lαpтop ғor α ғew нoυrѕ. нere'ѕ тнe ѕιтe тo reαd мore something­.c­o­m­"""

>>> import unicodedata
>>> for uc in unicode_str:
        print uc, unicodedata.name(uc).split(' ')[0], unicodedata.category(uc)
м CYRILLIC Ll
y LATIN Ll
  SPACE Zs
в CYRILLIC Ll
υ GREEK Ll
d LATIN Ll
d LATIN Ll
y LATIN Ll
' APOSTROPHE Po
ѕ CYRILLIC Ll
(...)

Donde "Ll significa letra minúscula" y solo usamos la primera parte del nombre Unicode para que las letras obtengan su categoría. Entonces podemos hacer algo como

>>> def count_letter_encodings(unicode_str):
        unicode_block_set = set()
        for uc in unicode_str:
            category = unicodedata.category(uc)
            if category[0] == 'L':
                unicode_block = unicodedata.name(uc).split(' ')[0]
                if unicode_block not in unicode_block_set:
                    unicode_block_set.add(unicode_block)
        return len(unicode_block_set)

>>> map(count_letter_encodings, unicode_str.split(' '))
[2, 3, 2, 3, 3, 1, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 3, 0, 3, 2, 1, 2, 3, 2, 1, 2, 3, 2, 2, 3, 2, 2, 2, 1]

El hecho de que haya varias palabras con 3 codificaciones de letras diferentes es altamente sospechoso (incluso dos son sospechosas). Así como otras cosas sospechosas; por ejemplo, los guiones suaves alternados por un carácter (punto de código 0xad) en el .com .

Al extraer algunos ejemplos breves de texto extranjero de la web, encontrará que la mayoría de las veces, las palabras solo deberían tener una codificación:

>>> greek_text = u'Ελληνας ϰαὶ δὴ ϰαὶ γράμματα'
>>> spanish_text = u'¿Cómo estas? Espero que todo esté bien. Hace bastantes años que estoy'
>>> russian_text = u'Все люди рождаются свободными и равными в своем достоинстве и правах. Они наделены'
>>> for text in (greek_text, spanish_text, russian_text):
        print map(count_letter_encodings, text.split(' '))
[1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]

Obviamente, tendría que realizar pruebas exhaustivas con el aprendizaje automático, ya que puede haber circunstancias benignas en las que se mezclan las codificaciones, pero esto podría ser una entrada útil para su clasificador de correo no deseado capacitado en un gran conjunto de datos.

    
respondido por el dr jimbob 21.05.2013 - 16:58
fuente
2

Verifico el uso de codificaciones múltiples en la misma palabra (u oración). Eso sería un tono muerto para este tipo de cosas.

De lo contrario, algo como esto podría ayudarlo. Desafortunadamente, es solo una tabla parcial, y tendría que usarlo al revés. Los códigos hexadecimales son UTF-8, por lo que c3a0 significa U+00E0 aquí.

a:  c3a0,c3a1,c3a2,c3a3,c3a4,c3a5,c3a6,c481,c483,c485,
c:  c2a2,c3a7,c487,c489,c48b,c48d
d:  c48f,c491
e:  c3a8,c3a9,c3aa,c3ab,c493,c495,c497,c499,c49b
g:  c49d,c49f,c4a1,c4a3
h:  c4a5,c4a7
i:  c2a1,c3ac,c3ad,c3ae,c3af,c4a9,c4ab,c4ae,c4b0,c4ba
j:  c4b5
k:  c4b7,c4b8
l:  c4ae,c4af,c4ba,c4bc
n:  c3b1,c584,c586,c588,c589,c58b
o:  c3b0,c3b2,c3b3,c3b4,c3b5,c3b6,c3b8,c58d,c58f,c591,c593
p:  c3be
s:  c29a
u:  c2b5,c3b9,c3ba,c3bb,c3bc
x:  c397
y:  c3bd,c3bf
z:  c29e
A:  c380,c381,c382,c383,c384,c385,c386,c480,c482,c484
B:  c39f
C:  c387,c486,c488,c48a,c48c
D:  c390,c48e,c490,
E:  c388,c389,c38a,c38b,c492,c494,c496,c498,c49a,c592
G:  c49c,c49e,c4a0,c4a2
H:  c4a4,c4a6
I:  c38c,c38d,c38e,c38f,c4a8,c4aa,c4ac
J:  c4b4
K:  c4b6
L:  c4b9,c4bb,c4bd,c4bf
N:  c391,c583,c585,c587
O:  c392,c393,c394,c395,c396,c398,c58c,c58e,c590,c592
P:  c39e
R:  c594
r:  c595
S:  c28a
U:  c399,c39a,c39b,c39c,
Y:  c29f,c39d
Z:  c28e

Pensándolo bien, es probable que tengas que agregar una lista de caracteres "ignore-me" que se pueden agregar a una cadena para que sea diferente al parecer similar, por ejemplo, U + 0082. Y ahora que lo pienso, esto podría usarse para derrotar "a lo sumo dos codificaciones en cada oración". Una palabra como "déja vu" se puede usar legítimamente (recuerdo haberla visto desde un editor de Mac), pero la combinación de acento U+0300 se puede usar para hacer que "Víágŕa" parezca algo completamente distinto.

Por lo tanto, primero deben eliminarse todas las "combinaciones", luego se deben ignorar algunos caracteres legítimos (por ejemplo, los puntos suspensivos - los procesadores de texto adoran ... y los diversos estilos de comillas). Finalmente, se pueden contar las codificaciones, o puede reemplazar los caracteres con sus parecidos a OCR como se muestra arriba.

    
respondido por el LSerni 21.05.2013 - 18:38
fuente

Lea otras preguntas en las etiquetas