StringEncrypt – polimorficzne szyfrowanie

Zachęcony pozytywnymi komentarzami dotyczącymi mojego projektu StringEncrypt, postanowiłem zaktualizować wszystko, co się dało i spełnić marzenia fanów tego niezwykłego rozwiązania.

Co to jest StringEncrypt?

To aplikacja do szyfrowania stringów i plików, generująca polimorficzny kod dekryptora. Ze stroną, WebAPI, dedykowanym rozszerzeniem do VSCode (ponad 4k instalacji) i aplikacją okienkową. Coś dla prawdziwych hakerów!

Silnik projektu jest wykorzystany w moich pozostałych narzędziach do masowego, polimorficznego szyfrowania stringów (w AutoIt Obfuscator i JObfuscator).

Szyfrować i generować kod można w następujących językach programowania:

Nowa wersja przynosi ogrom zmian, w tym najważniejsze – wsparcie dla wielu nowych języków programowania, tony bugfixów i najważniejsze – zagnieżdżone pętle polimorficzne.

Zagnieżdżone pętle polimorficzne

Jednym z zarzutów i wektorów ataku na StringEncrypt (w przypadku generatorów np. C/C++) było wykorzystanie narzędzi do ekstrakcji stringów, takich jak flare-floss. Narzędzie to potrafi przeskanować gotowy plik EXE, przeanalizować kod i wyciągnąć nawet zaszyfrowane stringi.

Zgłębiłem temat i cała filozofia tego rozwiązania bazuje na detekcji tzw. tight-loops, czyli ciasnych pętli. flare-floss potrafi rozpoznać krótkie pętle deszyfrujące i poprzez ich emulację wyciągnąć zaszyfrowane stringi, jeśli takie pętle zostały wykorzystane do ich odszyfrowania.

Rozwiązaniem tego problemu było wygenerowanie wielopoziomowo zagnieżdżonych pętli z polimorficznym kodem deszyfrującym co nie wpisuje się już w detekcję prostych pętli.

Przykładowy kod C

// encrypted with https://www.stringencrypt.com (v1.5.0) [C/C++]
// nie_do_wyciagniecia = "Nie tak prosto kolego!"
wchar_t nie_do_wyciagniecia[23] = { 0x0052, 0x71A4, 0x0690, 0x0900, 0x6830, 0x25B1, 0xF185, 0x0009,
                                    0x0074, 0x01D8, 0x82B4, 0x1FC7, 0x5830, 0xFD51, 0x4002, 0xD71F,
                                    0x0073, 0x01C0, 0x0690, 0x18C3, 0xA2D0, 0xD4DE, 0x4000 };

for (volatile unsigned int UCSag = 0, JkERu = 0; UCSag < 23; UCSag++)
{
	JkERu = nie_do_wyciagniecia[UCSag];
	for (unsigned int XptZj = 0; XptZj < 2; XptZj++)
	{
		JkERu = (((JkERu & 0xFFFF) >> (UCSag % 16)) | ((JkERu & 0xFFFF) << (16 - (UCSag % 16)))) & 0xFFFF;
		for (unsigned int HBXqW = 0; HBXqW < 2; HBXqW++)
		{
			JkERu = (((JkERu & 0xFFFF) >> 8) | ((JkERu & 0xFFFF) << 8)) & 0xFFFF;
			JkERu = ((JkERu ^ 0xFFFF) & 0xFFFF);
		}
	}
	for (unsigned int WAUOq = 0; WAUOq < 4; WAUOq++)
	{
		JkERu = ((JkERu & 0xFFFF) - 1) & 0xFFFF;
	}
	for (unsigned int HIbTj = 0; HIbTj < 2; HIbTj++)
	{
		JkERu = (((JkERu & 0xFFFF) << 8) | ((JkERu & 0xFFFF) >> 8)) & 0xFFFF;
		for (unsigned int Dswmt = 0; Dswmt < 2; Dswmt++)
		{
			JkERu = ((JkERu & 0xFFFF) + UCSag) & 0xFFFF;
			JkERu = (JkERu ^ (((JkERu & 0xFFFF) << 9) & 0xFFFF)) & 0xFFFF;
			JkERu = (JkERu ^ UCSag) & 0xFFFF;
		}
	}
	nie_do_wyciagniecia[UCSag] = JkERu;
}

I efekt pracy flare-floss, czyli brak znalezionych stringów metodą skanowania tight-loops:

Poprawki błędów

  • Poprawiłem formatowanie kodu Pythona, żeby było zgodne z regułami PEP.
  • Naprawiłem generator Ruby i sposób zapisywania zaszyfrowanych znaków.
  • Poprawki dotknęły też generatora AutoIt.

6 nowych instrukcji szyfrujących VM:

  • neg — klasyczna negacja (nie not)
  • swap — zamiana bitów w szyfrowanych 8 bitowych bajtach oraz 16 bitowych wartościach dla unicode
  • c_rol / c_ror — rotacje bitowe z użyciem klucza, którym jest licznik pętli
  • xor_shr / xor_shl — szyfrowanie z miksowaniem XOR, tak jak w algorytmach MurmurHash i SplitMix

Kompletna liczba instrukcji VM wykorzystanych do szyfrowania obecnie wynosi 17 (z 11), co jeszcze bardziej urozmaica wygenerowany kod wyjściowy.

Nowe podświetlanie składni

Strona zyskała nowe podświetlanie składni wygenerowanego kodu, porzucony został stary highlighter Syntax Highlighter na rzecz biblioteki Prism.

Pakiety SDK

Przykłady automatyzacji z poziomu Pythona

#!/usr/bin/env python

###############################################################################
#
# String Encrypt WebApi interface usage example.
#
# In this example we will encrypt sample string with default options.
#
# Version        : v1.0.1
# Language       : Python
# Author         : Bartosz Wójcik
# Project page   : https://www.stringencrypt.com
# Web page       : https://www.pelock.com
#
###############################################################################

#
# include StringEncrypt module
#
from stringencrypt import StringEncrypt

#
# if you don't want to use Python module, you can import it directly from the file
#
#from stringencrypt.stringencrypt import StringEncrypt

#
# create StringEncrypt class instance (we are using our activation code)
#
myStringEncrypt = StringEncrypt("YOUR-API-KEY-HERE") # leave empty for demo mode

#
# encrypt a string using all the default options
#
result = myStringEncrypt.encrypt_string("Hello, world!", "label_encrypted")

#
# result[] array holds the encryption results as well as other information
#
# result["error"] (int) - error code
# result["source"] (string) - decryptor source code
# result["expired"] (boolean) - expiration flag
# result["credits_left"] (int) - number of credits left
# result["credits_total"] (int) - initial number of credits

if result and "error" in result:

    # display source code of the decryption code
    if result["error"] == StringEncrypt.ErrorCodes.ERROR_SUCCESS:
        print(result["source"])
    else:
        print(f'An error occurred, error code: {result["error"]} ({result["error_string"]})')

else:
    print("Something unexpected happen while trying to encrypt the string.")

Pełna wersja

Klucz można zakupić za śmieszne pieniądze lub za darmo go zdobyć, pisząc o tym rozwiązaniu na social mediach, artykułach, na forach czy gdziekolwiek się da z linkiem do strony projektu i krótkim opisem oraz screenshotem. Niewiele, prawda?

Na koniec chciałbym jeszcze raz podziękować wszystkim fanom, którzy w dobie AI zmotywowali mnie do tak dużych aktualizacji – bez waszych słów wsparcia by mi się nie chciało aż tak 🙂

Szyfrowanie w Pythonie

Opublikowałem właśnie pomocniczy moduł usługi szyfrującej StringEncrypt dla Pythona 3.

Moduł znajdziecie w Pythonowym repozytorium PyPI:

https://pypi.org/project/stringencrypt/

Jego kody źródłowe opublikowałem również na GitHubie:

https://github.com/PELock/StringEncrypt-Python

Instalacja dla Pythona z wykorzystaniem menedżera paczek pip:

pip install stringencrypt

Jak to działa i co to właściwie robi?

W skrócie bierze dowolny string lub zawartość binarnego pliku, szyfruje to silnik polimorficzny i generuje kod w wybranym języku programowania (w tym wypadku w Pythonie) z kodem zawierającym zaszyfrowany string oraz kodem samego dekryptora:

Szyfrowanie stringów i plików z poziomu Visual Studio Code

Przez ostatni tydzień pisałem rozszerzenie dla darmowego środowiska programistycznego Visual Studio Code, które pozwala na bezpośrednie szyfrowanie stringów i plików w edytorze IDE wykorzystując mój projekt StringEncrypt.

Rozszerzenie pozwala w prosty sposób wstawiać zaszyfrowane ciągi tekstowe lub zaszyfrowaną zawartość wybranego pliku (czy to tekstowego, czy binarnego) w edytorze środowiska programowania.

Nie trzeba ręcznie szyfrować stringów wykorzystując jakieś proste xorowanie, albo męczyć się z importowaniem różnych dziwnych bibliotek kryptograficznych (i modlić się, żeby się wszystko poprawnie skompilowało), żeby zaszyfrować mały string lub jakiś plik.

1. Wstawianie nowego zaszyfrowanego tekstu

  1. Wystarczy otworzyć menu kontekstowe
  2. Wybrać Insert Encrypted String
  3. Wpisać label dla zaszyfrowanego stringa
  4. Wpisać zawartość stringa
Wstawianie zaszyfrowanego tekstu

2. Szyfrowanie zaznaczonego tekstu

  1. Należy zaznaczyć dowolny tekst
  2. Z menu kontekstowego wybrać Encrypt Selected Text
  3. Wpisać label dla zaszyfrowanego string
Szyfrowanie zaznaczonego tekstu

3. Wstawianie zaszyfrowanego pliku

  1. Z menu kontekstowego należy wybrać Insert Encrypted File
  2. Należy wskazać plik do zaszyfrowania (4 MB max.)
  3. Wpisać label dla zaszyfrowanego pliku
Wstawianie zaszyfrowanego pliku

Jak to działa?

Całość opiera się na polimorficznym silniku projektu StringEncrypt, generującym każdorazowo losowy kod deszyfrujący w wybranym języku programowania (których jest całkiem sporo).

Jak zainstalować?

Rozszerzenie można zainstalować bezpośrednio z marketu Visual Studio Code:

https://marketplace.visualstudio.com/items?itemName=PELock.stringencrypt

Darmowy kod aktywacyjny

Dla czytelników SecNews z okazji wydania wtyczki przygotowałem darmowy kod aktywacyjny:

4CD3-B06E-0CE5-ECD8

Korzystajcie póki nie wygaśnie 😉

Steganografia Ukrywanie Wiadomości w Obrazkach

Steganografia to sztuka i nauka ukrywania informacji poprzez osadzanie ukrytych informacji w innych, pozornie niewinnych plikach, np. w obrazkach.

Z poniższym kodekiem steganograficznym będziesz w stanie ukryć w obrazku dowolną wiadomość tekstową w bezpiecznych sposób oraz przesłać ją bez wzbudzania jakichkolwiek podejrzeń. Odczytanie wiadomości będzie możliwe jedynie po podaniu hasła deszyfrującego.

https://www.pelock.com/pl/produkty/steganografia-kodek-online

Jak to działa?

W tym przypadku poszczególne bity zaszyfrowanej wiadomości ukryte są jako najmniej znaczące bity w składowych kolorach RGB w pikselach wybranego obrazu. Naniesione zmiany nie są widoczne gołym okiem.

Steganografia sztuka ukrywania informacji w obrazkach

W jaki sposób ukrywane są dane w obrazku?

  1. Wiadomość tekstowa jest kompresowana algorytmem DEFLATE w celu zmniejszenia jej rozmiaru
  2. Generowany jest silny kryptograficzny klucz szyfrujący na podstawie podanego hasła, wykorzystując algorytm PBKDF2 z 20000 iteracjami
  3. Skompresowane dane są szyfrowane poprzednio wygenerowanym kluczem w trybie CBC używając 256 bitowego szyfrowania AES
  4. Zaszyfrowane bity danych są zapisywane na pozycjach najmniej znaczących bitów składowych kolorów RGB poszczególnych pikseli wybranego obrazu

Jakie są praktyczne zastosowania steganografii?

Kilka przykładów:

  • Możesz przechowywać ukryte i zaszyfrowane wiadomości i informacje w obrębie obrazów i przesyłać je do dowolnej osoby za pośrednictwem poczty elektronicznej bez wzbudzania żadnych podejrzeń
  • Whistleblowing i tajne dziennikarstwo
  • Wysyłanie tajnych wiadomości w wysoce monitorowanym lub wrogim środowisku (np. monitorowany przez państwo Internet, strefy działań militarnych)
  • Obrazy z ukrytymi wiadomościami można osadzać na stronach internetowych

Simple Polymorphic Engine – SPE32

Simple Polymorphic Engine SPE32 to prosty silnik polimorficzny napisany w assemblerze dla MASM32, dzięki któremu można się dowiedzieć jak w ogóle zbudowane są silniki polimorficzne oraz jak funkcjonują.

Kod polimorficzny w oknie debuggera x86dbg
Inna generacja kodu polimorficznego, tym razem z tzw. junkami

Kod źródłowy i przykład użycia:

https://github.com/PELock/Simple-Polymorphic-Engine-SPE32

Jak zaszyfrować stringi i pliki w AutoIt?

logo_autoitDzisiaj usługa StringEncrypt została poszerzona o moduł pozwalający zaszyfrować dowolny string lub zawartość pliku i wygenerować kod deszyfrujący w języku skryptowym AutoIt.

https://www.stringencrypt.com/autoit-encryption/

AutoIt jest popularnym językiem skryptowym, pozwalającym na automatyzację wielu zadań w systemie Windows. Obecnie jest tak zaawansowany, że pozwala na tworzenie samodzielnych aplikacji, jednak łatwość jego dekompilacji wymusza na autorach metody ochrony kodu np. przez obfuskację lub jak tutaj szyfrowanie.

Przykład szyfrowania prostego tekstu i wygenerowany kod:

; encrypted with https://www.stringencrypt.com (v1.1.0) [AutoIt]
#include <Array.au3>

; $Label = "Szyfrowanie stringów w AutoIt!"
Global $Label[31] = [ 0x9C5A, 0x54A5, 0xECA5, 0x24A6, 0x7CA3, 0xB4A7, 0x4CA2, 0xC4A7, _
                    0x1CA8, 0xD4A9, 0x2CA7, 0xE4B7, 0x7CA3, 0xB4A2, 0x4CA3, 0x04AA, _
                    0xDCA9, 0x14A6, 0xEC44, 0xE4A3, 0x7CB7, 0x34A2, 0x0CB7, 0x449F, _
                    0x5CA2, 0x14A2, 0x2CA9, 0xA4A2, 0x3CA2, 0x74B7, 0x4CAF ];

For $zJTHh = 0 to 30
    $ihRBt = $Label[$zJTHh];
    $ihRBt = $ihRBt + 1;
    $ihRBt = BitXOR($ihRBt, 0x7A20);
    $ihRBt = BitNOT($ihRBt);
    $ihRBt = BitRotate($ihRBt, -11, "W");
    $ihRBt = BitXOR($ihRBt, $zJTHh);
    $ihRBt += 0xFB57;
    $ihRBt += $zJTHh;
    $ihRBt = BitXOR($ihRBt, 0xD6BD);
    $ihRBt = BitXOR($ihRBt, $zJTHh);
    $ihRBt = BitRotate($ihRBt, 13, "W");
    $ihRBt = BitNOT($ihRBt);
    $Label[$zJTHh] = ChrW(BitAND($ihRBt, 0xFFFF));
Next

$Label = _ArrayToString($Label, "")

ConsoleWrite($Label);

Dla czytelników SecNews darmowy kod aktywacyjny do usługi (korzystajcie póki jest aktywny):

9071-FA5F-A482-96AE