Technicznie, mógł bezpośrednio filtrować base64 zakodowane dane dotyczące słów kluczowych. Nie twierdzę, że jest to praktyczna lub rozsądna rzecz, biorąc pod uwagę istnienie lepszych i prostszych alternatyw (jak opisano np. W odpowiedzi Esy powyżej), ale jest to możliwe.
Sztuką jest uświadomienie sobie, że kodowanie base64 jest deterministycznym odwzorowaniem 3-bajtowych bloków surowych niekodowanych danych na 4-znakowe bloki znaków base64. Zatem za każdym razem, gdy w niezakodowanych danych pojawi się pewna sekwencja 3-bajtowych bloków, ta sama sekwencja 4-znakowych bloków pojawi się w wersji zakodowanej.
Na przykład, jeśli wpiszesz ciąg znaków Quanzhoucooway
do kodera base64 , otrzymasz wynik UXVhbnpob3Vjb293YXk=
. Ponieważ długość danych wejściowych nie jest wielokrotnością 3 bajtów, dane wyjściowe zawierają dopełnienie na końcu, ale jeśli upuszczymy końcowe =
znaki i ostatni rzeczywisty znak base64 k
(ponieważ koduje również niektóre bity dopełniania), otrzymamy ciąg UXVhbnpob3Vjb293YX
który gwarantuje pojawiają się w danych base64 gdy zakodowany bajt tryplety Qua
, nzh
, ouc
, oow
a częściowo tryplet ay
w wejściu pojawią się w tej kolejności.
Ale oczywiście ciąg Quanzhoucooway
może nie zaczynać się dokładnie na granicy trojaczki. Na przykład, jeśli XQuanzhoucooway
zamiast tego zakodujemy ciąg , otrzymamy wynik WFF1YW56aG91Y29vd2F5
, który wygląda zupełnie inaczej. Tym razem długość wejściowa jest podzielna przez trzy, więc nie ma na końcu żadnych znaków dopełniających, ale musimy odrzucić pierwsze dwa znaki ( WF
), z których każdy koduje niektóre bity z poprzedzającego X
bajtu, pozostawiając nam F1YW56aG91Y29vd2F5
.
Na koniec kodowanie base64 XXQuanzhoucooway
daje wynik WFhRdWFuemhvdWNvb3dheQ==
, który ma wypełnienie na obu końcach. Usuwając pierwsze trzy znaki WFh
(które kodują XX
prefiks) i ostatnie trzy znaki Q==
(które kodują zerowanie bitów na końcu), pozostaje nam ciąg znaków RdWFuemhvdWNvb3dhe
. W ten sposób otrzymujemy następujące trzy ciągi zakodowane w base64:
UXVhbnpob3Vjb293YX
F1YW56aG91Y29vd2F5
RdWFuemhvdWNvb3dhe
z których (przynajmniej) jeden musi pojawić się w postaci zakodowanej w standardzie base64 dowolnego ciągu wejściowego zawierającego słowo Quanzhoucooway
.
Oczywiście, jeśli masz pecha, koder base64 może wstawić podział linii między nimi, między dowolnymi dwoma zakodowanymi trojaczkami. (Twój przykładowy komunikat, na przykład, ma jeden pomiędzy F1YW56
i aG91Y29vd2F5
.) Zatem, aby niezawodnie dopasować te ciągi z wyrażeniami regularnymi, potrzebujesz czegoś takiego (przy użyciu składni PCRE):
/UXVh\s*bnpo\s*b3Vj\s*b293\s*YX/ DISCARD
/F1\s*YW56\s*aG91\s*Y29v\s*d2F5/ DISCARD
/R\s*dWFu\s*emhv\s*dWNv\s*b3dh\s*e/ DISCARD
Ręczne generowanie tych wzorców jest dość żmudne, ale napisanie prostego skryptu w ulubionym języku programowania nie byłoby trudne, przynajmniej tak długo, jak długo zapewnia koder base64.
Jeśli naprawdę tego chciałeś, możesz nawet zaimplementować dopasowanie bez rozróżniania wielkości liter przez kodowanie base64 zarówno małej, jak i wielkiej litery słowa kluczowego i łącząc je w wyrażenie regularne pasujące do dowolnej ich kombinacji. Na przykład kodowanie base64 quanzhoucooway
jest, cXVhbnpob3Vjb293YXk=
podczas gdy QUANZHOUCOOWAY
jest UVVBTlpIT1VDT09XQVk=
, więc reguła:
/[cU][XV]V[hB]\s*[bT][nl]p[oI]\s*[bT][31]V[jD]\s*[bT][20]9[3X]\s*[YQ][XV]/ DISCARD
w każdym przypadku będzie pasować do słowa „Quanzhoucooway” zakodowanego w standardzie base64, pod warunkiem, że zaczyna się na granicy trojaczki. Generowanie pozostałych dwóch odpowiednich wyrażeń regularnych dla wersji przesuniętych pozostawia się jako ćwiczenie. ;)
Niestety, robienie czegokolwiek bardziej skomplikowanego niż proste dopasowywanie podciągów, takie jak to, szybko staje się niepraktyczne. Ale przynajmniej jest to fajna sztuczka. Zasadniczo może być nawet przydatne, jeśli z jakiegoś powodu nie można użyć SpamAssassin lub innego filtru, który może dekodować kodowanie base64 przed filtrowaniem. Ale jeśli możesz to zrobić, zamiast używać takich hacków, na pewno powinieneś.