Zine.net online

Witaj na Zine.net online Zaloguj się | Rejestracja | Pomoc
w Szukaj

mgrzeg.net - Admin on Rails :)

$EFS, cz 3. Wielki Finał

Odszyfrowanie wszystkich parametrów RSA klucza zbliża nas nieuchronnie do kresu wędrówki. Jesteśmy już tylko kilka kroków od rozwiązania wszystkich zagadek i odzyskania oryginalnej zawartości pliku. Zapraszam do ostatniego już odcinka mini serii poświęconej internalsom EFS i DPAPI.

FEK ponownie

Poprzednią część zakończyliśmy zapisaniem parametrów klucza RSA w formacie XML.

<RSAKeyValue>
  <Modulus>
    n9WMraGeldyUSGqorfsmOiK4n3LgwxTWuUd0JXXJ5R+4fbZGtptbk4en1Z+pmS2w19to8u
    6x9wZNFsf7ow+TMStKOTINDC37wGhLyroC2kOKs1nJQucHzXpT6iWl4WrcB2MDT+4tlmFX
    sxvmstZdy2ewJZEwi7wqcZWH21fhRfSrs+oJ9iRcmHGB9ZickLbT+kt4BtefbC1sJsVmI5
    Dpb4E64p4d8k/CmRYfhR5bw6oWHVgmu7kS8XhYNQTZUfVVALdgbkFx1WqkuEpUUj0SdtKW
    UQOdTl8uYWqj/3jZcuKeaY1cNjYr0AyPLR0+FxS8exzyr749IBoVVlzGryYnDw==
  </Modulus>
  <Exponent>
    AQAB
  </Exponent>
  <P>
    2hY1mpkEhatMHAUdE9Mvb+B5VuPY46CeLvUJM1kesUoq7G5V5GXzZG8S2oWv4ZFA8xV6HW
    MMZTk2AYgi2RpzNrxvsRCZwr0jDwMmc94BatKyMPeQQwnr9eO8L/64EZaw5AUvakD3a+qz
    biZn4HqQIHK6qjpN23yDxtca4cb3Jck=
  </P>
  <Q>
    u57aHizRDbDoimfZ1BjMIW+2u3G9IoZ4mW/iSdPQ/CWx6ODg5U9XlEgbBF9368EgzCKDDM
    +VwyeOpKb8GvvJkvAaTjH0Qmw7KU+UAaDlB0Sq9G67kJ5C6lRgiNGaGZujO9fG2R4Jgv+v
    ebMod2QP1t0pswOJWgmeKOtk7EdMshc=
  </Q>
  <DP>
    N7V2qfAulIqmXX386ISI2JZJyKVZUQRFhA8583DvgzBD+LNSo45bdytccI+31vII2k+BKy
    KTFwRfRFLnO/giuDe4fE2WSYWRABO47d4nFIeP1yxWIJnXOa+b8dKqaGvK8eRVMVo5GcsR
    XLDY1iHY0UEdZ8CPBOMwskleZ5Awr+k=
  </DP>
  <DQ>
    cXBtfvsn9zg0kaKS8QuBOOI7wP/XFG3rsxIT5wF8BUihViXJtLwRPuWN+EnkzxV5SBPB2t
    gUO+fJ9kHEgmgki4RC026euh6IcsTbv1RRxeA94Qamv50A5n/X0kGxA7S3sHIZl6Lyq1L+
    /P1XBUDp1sbn9IW54UeZajJRVg8SD0c=
  </DQ>
  <InverseQ>
    Q8+QuCMDBKHs3ZtfPOhsLuo0W+TlkPIyhw9OiO3AAJhzr4e2+8/meMXEZ0s+2kAUaDCqk2
    /AYbjFNsIPOgLm4MqZnuANJOHBg1t1VY3lqi5rwIryUOl0hIYMImyB7r59RCuaQqtCRRjI
    67J5v4GTbBiexSIwtVJLWoYUv3P5d50=
  </InverseQ>
  <D>
    CEPlw3DRH5TJgjkpwd1z65uyCmTJZK0mMWyVf/5oU1Xhl3aej4DXKnjgX/aisY4gT/lDox
    Re1ZRY1i2/QH5ksS046F5DOHcERr3d9XzK+vh1KrMg6jnCOIjz3+7UdiStfiBLoo2Bg/5C
    p7twoZzeOs+A12B7ry4qz7bY0Knpt1FLuOMXQbVBSMEo5RbfnYkleGB0UMdAosb57uNS3b
    YWwTCCJC46t/EQc4MsHFmGoisIe1HKL1ilBpiUQyPRR9ZSNicmmDjuDLOTw2i+MBWRs34C
    OdEJN3PWBuLFn6mTZzk3KBQEL9TL8mBki7iEizTWoVaKu9ojlX20i8HohYFOcQ==
  </D>
</RSAKeyValue>


(Uwaga dla purystów base64: ciągi podzieliłem ręcznie ze względu na wyświetlanie na blogu, więc nie męczcie o znaki kontynuacji. W oryginale nie ma żadnego znaku podziału wiersza i linii).
Możemy zatem przystąpić do odszyfrowania FEKa, którego namierzyliśmy w pierwszej części:

>EFSAnalysis.exe encrypted_file.txt.efs

EFS Stream Header:
Len: 664, state: 0, ver: 2, crypto api ver: 0
Num of DDFs: 1, DRFs: 0

DDFs:
SID: S-1-5-21-580747136-2243477503-2994681153-1000:
Certificate:
   Thumbprint: EFF5EDAB8123D06B6EFEA7D87716B03F9C8F48CD
   Container name: 0d29406b-f9e6-4659-90e4-c407201049d2
   Provider name: Microsoft Enhanced Cryptographic Provider v1.0
   User name: Admin(Admin@VM7)
Encrypted FEK:
FE 1B 0D 07 2F 56 96 09 6C D8 DD 54 92 FF 23 2E   ..../V?.lOYT?.#.
15 93 D2 4C 5F 4D 76 F6 35 DB 75 BF 5C 24 4C D5   .?OL_Mvö5Uu¿\$LO
46 12 B7 DD C2 09 F5 DB 0E 01 CC E0 51 B0 A6 87   F.·YA.oU..IàQ°▌?
15 AB A9 FC 56 BE 3C BD 0A BA C6 D8 DF 6A DE 4B   .«cüV_<½.ºÆOßj_K
78 BB E0 CC 2F 88 86 BC 20 23 BB 86 EB 72 AC 4B   x»àI/??¼.#»?ër¬K
4F AE 05 9F 1A 99 BC BC 80 52 FB D1 8B 7B 90 B1   Or.?.?¼¼?RûÑ?{?±
8B E9 B7 A4 85 D0 FF 18 3C C9 C5 8C 9A 7A 1C 04   ?é·☼?D..<ÉÅ??z..
D6 C7 A6 0B A8 76 4E 9C 87 3E B8 DC 62 C3 ED 57   ÖÇ▌."vN??>,ÜbAíW
CB FE 01 B8 20 91 87 EB 96 18 14 0B DF 2E E4 F8   E..,.??ë?...ß.äo
7A 5D C8 1D 77 0F E6 9A 7F 89 B9 C0 E5 8E DC 4D   z]E.w.æ?.?1Aå?ÜM
5A C5 9C 3E 05 24 89 21 C9 79 73 9F 42 FE 64 AC   ZÅ?>.$?!Éys?B.d¬
4E 28 B6 25 1A 58 0E A0 D0 68 4B 38 6B 78 6D F6   N(¶%.X. DhK8kxmö
41 6A 8A 70 24 CB 45 48 11 81 C9 06 9B 75 18 A1   Aj?p$EEH.?É.?u.¡
10 33 46 9B 63 D9 4E CF 44 C5 4E 4A 58 F6 F8 15   .3F?cUNIDÅNJXöo.
BF FD 43 98 74 2B E5 55 9A 9E FF 77 55 5B CD F9   ¿yC?t+åU??.wU[Iù
CC 48 31 BC 51 17 67 F5 61 BB A2 C4 88 2A 42 83   IH1¼Q.goa»¢Ä?*B?


Posługujemy się zatem algorytmem RSA z wyliczonym w drugiej części 2048-bitowym kluczem i w pierwszym podejściu otrzymujemy - niezwykle wredny skądinąd - komunikat ‘Złe dane’. Wrr!!! Odwracamy zaszyfrowany FEK, zapuszczamy ponownie algorytm i w wyniku otrzymujemy 48 bajtów (Rys 1).

 
Rys 1. Odszyfrowany FEK

Oczywiście najważniejszą składową jest 256-bitowy klucz deszyfrujący (zaznaczony na Rys 1 na czerwono). Druga istotna informacja oznaczona jest na niebiesko - jest to ALG_ID algorytmu symetrycznego (AES-256), który mamy zastosować podczas odszyfrowywania zawartości pliku. Mamy wszystko!

AES-256

Na chwilkę oddalamy się od naszego przypadku, bo potrzebujemy nieco innego spojrzenia na naszą zabawę. Swoje pierwsze próby podejmowałem dla pliku o rozmiarze 86 bajtów. Znałem oryginał, więc mogłem porównać go z odszyfrowanym plikiem, wyniki zabaw poniżej.


Rys 2. Oryginalna zawartość 86-bajtowego pliku testowego.

Strzał 1.


Rys 3. Zawartość odszyfrowanego pliku po pierwszych próbach.

Już pierwszy rzut oka zdradza, że coś jest jednak nie tak. Korzystam z implementacji .netowej AES z kluczem 256-bitowym, w trybie CBC, a jako wektor inicjalizacyjny ustawiłem ciąg 16 zer.

Strzał 2.

Jak widać na Rys 3. to nie jest takie proste - zaglądam zatem do linuxowego sterownika ntfs-3g i dosyć szybko znajduję zahardkodowany wektor iv, który generuję następująco:

private byte[] generatateEFSIV(ulong offset)
{
  ulong a = 0x5816657be9161312 + offset;
  ulong b = 0x1989adbe44918961 + offset;

  byte[] iv = new byte[16];

  Buffer.BlockCopy(BitConverter.GetBytes(a), 0, iv, 0, 8);
  Buffer.BlockCopy(BitConverter.GetBytes(b), 0, iv, 8, 8);

  return iv;
}

Puszczam test i w wyniku otrzymuję plik (Rys 4)


Rys 4. Poprawny iv i od razu lepiej :)

A zatem początek pliku jest już ok. Dalej niepokoi mnie jednak końcowe 6 bajtów - ewidentnie coś jest z nimi nie tak.

Czas wrócić do korzeni. Badany przypadek to AES z kluczem 32-bajtowym, 16 bajtowym wektorem inicjalizacyjnym, a dane podzielone są na bloki 16-bajtowe, przy czym trybem pracy algorytmu jest CBC. Momencik! Bloki są 16-bajtowe… więc co się dzieje z danymi z ostatniego bloku? Tam jest tylko 6 bajtów danych, a co z resztą?!
Pierwszy pomysł, jaki przyszedł mi do głowy - trzeba to czymś uzupełnić. Tylko czym?

W tym momencie wracamy do naszego pliku 15-bajtowego.


Rys 5. Zaszyfrowany plik 15-bajtowy

Tu sprawa jest szybka - znajdźmy ostatni bajt, dla którego plik jest poprawnie odszyfrowany i po prostu trzymajmy się tego, może to jakiś tajemniczy decrypt-padding, o którym należy pamiętać i tyle? Po kilkudziesięciu próbach znalazłem tajemniczy bajt (0xAF) i postanowiłem sprawdzić go na drugim testowym pliku, również 16-bajtowym o identycznej zawartości. Wynik? Oczywisty: nic z tego! Padding - owszem, jest, ale tylko przy szyfrowaniu. Podczas odszyfrowywania musisz mieć kompletne dane, inaczej nic z tego! Żadnych tajemniczych łańcuchów, po prostu wynik szyfrowania, tylko tyle i aż tyle.
Wracam zatem do strumienia $EFS i zaczynam szukać jakiejkolwiek wskazówki, może brakujące bajty zapisane są w którymś z ‘unknown’ pól? ctrl+f, ‘af’ -> “No occurrences of ‘af’ found”.
W tym momencie naszło mnie olśnienie. Wektor iv zmieniany jest co 512 bajtów, czyli wielkość sektora. A może w takim razie… nie, niemożliwe! (Rys 6)


Rys 6. Pierwsze 512 bajtów z klastra zawierającego strumień $DATA.

O, jest nasz 0xAF! Znalazł się :)
Sprawdźmy zatem, co otrzymamy po odszyfrowaniu danych z pierwszych 512 bajtów z klastra zawierającego strumień $DATA (Rys 7).


Rys 7. Dane po odszyfrowaniu.

Tym samym wszystkie zagadki zostały rozwiązane. EFS używa danych ze slack space, przy czym uzupełnia oryginalne dane zerami i to szyfruje. Zaskoczeni? :) Ja przyznaję - byłem mocno zaskoczony! :)

Podsumowanie

Uff, dotarliśmy do końca wędrówki! Każdy z omawianych elementów to godziny testów i prób. Poza hasłem użytkownika znajdziecie tu wszystko, a i samo hasło nie jest wielką tajemnicą - inaczej nie podawałbym na tacy skrótów SHA-1 ;) Czas na podziękowania i wskazanie głównych źródeł informacji.
Wszystkie testy przeprowadzałem na Windows 7 SP1 x64, która nie jest podłączona do domeny (co było widać w polu domainKeyLen = 0 - w której strukturze? ;)).

  1. Pierwsza poważniejsza próba zmierzenia się z EFS: [KLIK]. Źródło inspiracji odnośnie pokolorowania danych, a także wskazanie najważniejszych elementów systemu.
    Czy zdajecie sobie sprawę z tego, że Peter (autor tekstu) binaria opracowywał w edytorze WinHex, a wszystko kolorował z użyciem Paint Shop Pro? Kupił nawet specjalny font na potrzeby grafik, ponieważ domyślny w rozdzielczości 1024x768 był nieczytelny. No cóż, na szczęście jest już 010 Editor, z którego ja miałem szczęście korzystać.
  2. Najważniejsze opracowanie DPAPI to DPAPIck. Znajdziecie tam artykuł + pełen kod napisany w Pythonie [KLIK], który starałem się przepisać na C#, oczywiście stosując dostępne w .NET Framework biblioteki kryptograficzne, a nie np. M2Crypto (na czym opiera się DPAPIck). Zmiany są bardzo poważne, w zasadzie to zupełnie nowa implementacja rozwiązania - bardziej zależało mi na pełnym zrozumieniu wszystkich mechanizmów, niż po prostu przetłumaczeniu kodu. Cel udało mi się osiągnąć, czego efekt widzieliście w części drugiej :) Przy okazji wyszło trochę braków, które zapewne pojawią się w wydaniu 0.4 DPAPIck.
  3. Źródła linuxowego sterownika ntfs-3g, w tym narzędzie ntfsdecrypt. Rozwiązanie linuxowe opiera się na zastosowaniu pliku certyfikatu .pfx, zawierającego pełen zestaw kluczy, o DPAPI należy zapomnieć.
  4. EFS to doskonały materiał na laboratorium. W zasadzie modelowo pokazuje jak można przechowywać wrażliwe dane, z jakich algorytmów należy korzystać, jakich parametrów użyć. Dla mnie to też była doskonała okazja, żeby przypomnieć sobie szczegóły RSA, AES, SHA, HMAC, PBKDF2 oraz wgryźć się w rozwiązania typu TSK. Nie może zatem zabraknąć literatury:
    1. "Kryptografia i bezpieczeństwo sieci komputerowych. Matematyka szyfrów i techniki kryptologii", William Stallings [KLIK]. Podręcznik akademicki.
    2. "Security Driven .NET", Stan Drapkin [KLIK]. Wydawać się może, że na 70 stronach nie da się za wiele napisać. Nic bardziej mylnego, ta książka to po prostu esencja esencji, wymaga jednak dosyć dobrej znajomości tematu.
    3. “Cryptography in .NET Succinctly”, Stephen Haunts [KLIK]. Założenie darmowej serii Succinctly to książka 50-100 stron, w której znajdziesz najważniejsze informacje z interesującego Cię tematu. Jako wprowadzenie, ale bez zbytnich uproszczeń i na odpowiednim poziomie, żeby móc coś zrobić - doskonała. Warto zajrzeć do niej przed Drapkinem, tym bardziej, że - powtarzam - jest całkowicie za darmo!
    4. “Windows Internals, part 2”, 6th edition. Mark Russinovich, David A. Salomon, Alex Ionescu. Co tu pisać - po prostu mus.

Myślałem, żeby przygotować z tego jakąś prezentację na którejś grupie (Windowsowej? .NET?), ale jakoś nie bardzo wiem kogo ten temat mógłby zainteresować. Jeśli uważasz, że temat wart jest szerszego pokazania, albo masz jakieś uwagi - zostaw komentarz! Podobało się, albo wręcz przeciwnie - podziel się!

Opublikowane 30 marca 2015 19:11 przez mgrzeg
Filed under:

Powiadamianie o komentarzach

Jeżeli chciałbyś otrzymywać email gdy ta wypowiedź zostanie zaktualizowana, to zarejestruj się tutaj

Subskrybuj komentarze za pomocą RSS

Komentarze:

 

Michał Komorowski said:

Michał, Materiału to masz nie na jedną, ale kilka prezentacji :) Ja chętnie bym posłuchał o bezpieczeństwie i odświeżył sobie informacje na ten temat. Sądzę jednak, że wchodzenie w takie szczegóły, jak w tej serii postów, podczas prezentacji może być trudne w odbiorze. Napisałeś jednak, że EFS  doskonale pokazuje jak przechowywać wrażliwe dane. Może więc prezentacja na temat architektury EFS, best practises..., ale z wyższego poziomu.

kwietnia 1, 2015 21:57

Co o tym myślisz?

(wymagane) 
(opcjonalne)
(wymagane) 

  
Wprowadź kod: (wymagane)
Wyślij

Subskrypcje

W oparciu o Community Server (Personal Edition), Telligent Systems