Cóż, nieco rozwinąłem to co z quetzalcoatlem opracowaliśmy ale nie starczyło mi sił na zrobienie decryptera pliku /w sumie to jest ale rozgrzebany/.
Jak to zrobiliśmy? Cóż, program tak jak od początku sądziłem aby wyświetlić miniaturę odtwarza hasło przy pomocy którego odkodowuje plik. Przy odrobinie szczęścia wystarczy przeszukać stertę - hasło nawet po użyciu pozostaje jako śmieć w pamięci, jest zapisane jawnie... Generalnie szyfrowanie jest daremne... całość sprowadza się do odczytywania kolejnych znaków i sprawdzania czy ich pozycja spełnia odpowiednią zależność:
(nr_znaku/10)*10+marker == nr_znaku
Mnożenie z dzieleniem na na celu wyzerowanie cyfry jedności /przypominam iż operujemy na liczbach całkowitych/. Następnie zależnie od danych w nagłówku wykonywana jest korekta w górę lub w dół. Samo w sobie jest to prymitywne... ale można tą zależność ładnie przekształcić:
bufor[nr_znaku_hasla*10+marker-1] // zakładając iż bufor jest zero based
Cóż, odczyt fragmentów pliku bajt po bajcie rewelacyjnym pomysłem nie jest... Zrekonstruowaliśmy też nagłówek pliku... nie było to trudne mimo iż program pisany jest w Delphi 3, efekty pracy tego kompilatora są dosyć paskudne w analizie... ciekawym 'bajerem' jest pole bLockFile - umożliwia zablokowanie dostępu do pliku /odczytu nawet przeznaczonym do tego programem/.
Hm... jak to zabezpieczyć? Pomysł z miniaturami jest niezbyt rewelacyjny - są tylko 2 wyjścia:
- przeskalowaną bitmapę dołączać do pliku
- potraktować program jakimś protectorem /np. świetnym polskim PELock'iem/
Użyj jakiegoś normalnego kryptosystemu bo ten... ekhm... nie spełnia maksymy Shannona - 'wróg zna system jakiego używamy', system mimo wszystko musi pozostać bezpieczny przez określony okres czasu. Zapis hasła w pliku jest prostą drogą do katastrofy niezależnie od sposobu jego zaszyfrowania. Zawsze znajdzie się reverse engineer, który wydobędzie algorytm jego odtwarzania.
Pozwilisz, że skończę na teraz, może wieczorem coś napiszę, teraz muszę odpocząć... polecamy się na przyszłość :-)
Odczytywajka haseł jaką na szybko napisalem w C++: /zakłada poprawność formatu pliku, używa zoptymalizowanego przeze mnie algorytmu... miało być w asm, ale z quetzalcoatlem doszliśmy do wniosku, że w C++ więcej osób ten kod zrozumie/
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
typedef unsigned long DWORD;
typedef unsigned char BYTE;
typedef struct _JMXHEADER
{
BYTE bMagic[8];
DWORD dwFileSize;
DWORD dwPassOffset;
DWORD dwOrgFileSize;
BYTE bPassLen;
BYTE bTrigger;
BYTE bDisp;
BYTE bMarker;
BYTE bLockFile;
BYTE bRest[3];
} JMXHEADER, *PJMXHEADER;
int main (int argc, char* argv[])
{
JMXHEADER fHeader;
char cCrypted [100], cFilePassword [11];
cout << "JMX Password Reader by deus & quetzalcoatl" << endl << endl;
if (argc != 2)
{
cout << "usage: " << *argv << " filename.jmx" << endl;
return -1;
}
ifstream iFile (argv[1], ios::binary);
if (!iFile)
{
cout << "File not found: " << argv[1] << endl;
return -1;
}
iFile.read (reinterpret_cast<char*>(&fHeader), sizeof (JMXHEADER));
iFile.seekg (fHeader.dwFileSize + fHeader.dwPassOffset + sizeof (JMXHEADER));
iFile.read (cCrypted, fHeader.bPassLen * 10);
for (unsigned uCurrent = 0; uCurrent < fHeader.bPassLen; uCurrent++)
cFilePassword[uCurrent] = (cCrypted [uCurrent*10+fHeader.bMarker-1]
+ (fHeader.bTrigger == 1 ? -fHeader.bDisp : fHeader.bDisp));
cFilePassword[fHeader.bPassLen] = 0;
cout << "Password: " << cFilePassword << endl;
iFile.close();
}
Przepraszam, że formatowanie nie jest idealne ale... nie chce mi się juz tego poprawiać... a, zrób cywilizowany interface - to pierwszy program, do którego musiałem manuala czytać aby go w ogóle zacząć używać.
[Dodane] Otworzoną fotkę chciałeś: http://wrzuc.net/get.php?what=nvgj86qdcrack_me.jpg
p. s. chyba powstał nowy zabójczy duet na 4p - d&q ;-P
[browar] @quetzalcoatl, za współpracę :-)