Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* GNU GPL LICENSE
- *
- * MultiThread Exor Cracker
- * Copyright (C) 2013; Kóti Balázs (ShuffleSource);
- *
- * Ez a program szabad szoftver; terjeszthető illetve módosítható a
- * Free Software Foundation által kiadott GNU General Public License
- * dokumentumában leírtak; akár a licenc 2-es, akár (tetszőleges) későbbi
- * változata szerint.
- *
- * Ez a program abban a reményben kerül közreadásra, hogy hasznos lesz,
- * de minden egyéb GARANCIA NÉLKÜL, az ELADHATÓSÁGRA vagy VALAMELY CÉLRA
- * VALÓ ALKALMAZHATÓSÁGRA való származtatott garanciát is beleértve.
- * További részleteket a GNU General Public License tartalmaz.
- *
- * A felhasználónak a programmal együtt meg kell kapnia a GNU General
- * Public License egy példányát; ha mégsem kapta meg, akkor
- * ezt a Free Software Foundationnak küldött levélben jelezze
- * (cím: Free Software Foundation Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.)
- *
- */
- /* !!!Olvassel!!! (README)
- #fordítás:
- g++ exor_fejt.cpp -o exor_fejt -lncurses -fopenmp -O3
- #függőségek:
- nCurses fv. könyvtár (http://ftp.gnu.org/pub/gnu/ncurses/)
- */
- /* Version History (changelog)
- Version 0.1
- Alapverzió.
- Version 0.2
- - Feature: minimum és maximum kulcshossz bevezetése.
- - Feature: kulcstípus (charSet) bevezetése.
- Version 0.3
- - Feature: Részltes kiíratások bevezetése.
- Version 0.4
- - Feature: Időmérő bevezetése.
- Version 0.5
- - OpenMP párhuzamosítás bevezetése.
- - Optimalizáció: inline direktíva a tryWithKey
- függvénynek (~20% gyorsulás).
- - Optimalizáció: a cSeed 'critical' OMP direktívát kapott.
- - Optimalizáció: a kiíratások csak mesterszálon hajtódnak végre.
- - Optimalizáció: a cSeed változó regiszter direktívát kapott.
- - Bugfix: az óra (clock) mostantól csak a mesterszálon fut.
- Version 0.6
- - (+) Feature: nCurses alapú felhasználói felület bevezetése.
- - (-) Featire: Karakteres kiíratások kigyomlálva.
- Version 0.7
- - Otimalizáció: hatékonyabb kulcs kiválasztó algoritmus beépítve.
- - Feature: paraméterként megadható folyamat (%-ban)
- */
- #include <iostream>
- #include <fstream>
- #include <stdlib.h>
- #include <string>
- #include <vector>
- #include <cmath>
- #include <ctime>
- #include <omp.h>
- #include <ncurses.h>
- //std névtér globálisan
- using namespace std;
- //Globális rész
- //terminál méretei
- int row,col;
- //karakterkészlet
- string charSet = "";
- //ablak szövege
- char programTitle[] = "MultiThread Exor Cracker by Shuffle (v0.7)";
- //sor felülírása whitespace-el (törlés)
- char wsClear[] = " ";
- //white space érzékenység
- int wsThreshold = 30;
- //ablakok
- WINDOW *ui_header;
- WINDOW *ui_main;
- WINDOW *ui_progress;
- WINDOW *ui_details;
- WINDOW *ui_status;
- //szövegrész dekódolása kulcs alapján
- inline string tryWithKey(vector<char> stream, string key, int chkLen = -1){
- //kulcs léptető és kulcshossz
- short keyCnt = 0;
- short keyMax = key.length();
- //nem vizsgáljuk a teljes streamet csak egy kis részét
- //a chklen adja meg ezt az értéket
- //ha a teljes stream mérete kisebb mint az ellenőrizendő bájtok száma,
- //akkor a teljes streamet ellenőrizzük
- short checkLength = stream.size();
- if (chkLen != -1)
- checkLength = chkLen;
- if (checkLength > stream.size())
- checkLength = stream.size();
- //a deködolt szöveg ebben tárolódik
- string result;
- //a stream és a kulcs bájtjai
- char a,k,e;
- //white space hiány figyelése
- unsigned long noWSpace;
- //a stream olvasása
- for (int i = 0; i < stream.size(); ++i){
- // 'a' a stream egy bájltja
- a = stream[i];
- // 'k' a kulcs egy bájtja
- k = key[keyCnt];
- // 'dekódolt bájt (e = a (xor) k)'
- e = a ^ k;
- //ha a karakter nem whitespace,
- //a noWhitespace növelése, ellenkező esetben 0-zása
- if (e != ' ' && e != '\n')
- noWSpace++;
- else
- noWSpace = 0;
- //ha a whitespace hiány nagyobb mint az érzékenység,
- //akkor a kulcs eldobása és kilépés a ciklusból
- if (noWSpace > wsThreshold){
- result = '#';
- break;
- }
- //dekódolt karakter hozzáírása végeredményhez
- result += e;
- //kulcs léptetése
- keyCnt++;
- //ha túlszaladunk a kulcson, akkor visszaugrasztjuk
- if (keyCnt>=keyMax)
- keyCnt = 0;
- }
- return result;
- }
- //kulcs generálása decimális számból
- string generateKeyFromSeed(register long long prevKey){
- if(prevKey == 0) return "0";
- //a 'számrendszer' alapszáma
- int base = charSet.length();
- //ebbe lesz tárolva a generált kulcs
- string result = "";
- do{
- //átváltás 'számrendszerek' közt
- //a charSet globális
- result.push_back(charSet[prevKey%base]);
- prevKey /= base;
- }while(prevKey != 0);
- //string megfordítása
- return string(result.rbegin(), result.rend());
- }
- //Felhasználói felület inicializálása
- void initUserInterface(){
- //ncurses inicializálása
- initscr();
- //terminál méretei
- getmaxyx(stdscr,row,col);
- //ha a terminál támogatja, akkor színek bekapcsolása
- if(has_colors())
- start_color();
- //színpárok definiálása
- init_pair(1, COLOR_WHITE, COLOR_RED); //fejléc színe
- init_pair(2, COLOR_CYAN, COLOR_BLUE); //alap szín
- init_pair(3, COLOR_CYAN, COLOR_BLACK); //statusbar
- init_pair(4, COLOR_MAGENTA, COLOR_WHITE); //részletek
- //fejléc ablak rajzolása
- //új ablak
- ui_header = newwin(3, col, 0, 0);
- box(ui_header, 0 , 0);
- wbkgd(ui_header,COLOR_PAIR(1));
- //félkövér be
- attron(A_BOLD);
- //kiíratás ablakba (program neve és verziószám)
- mvwprintw(ui_header,1,(col-(sizeof(programTitle)/sizeof(char)))/2,"%s",programTitle);
- //félkövér ki
- attroff(A_BOLD);
- //kirajzolás (frissítés)
- wrefresh(ui_header);
- //háttér rajzolása
- ui_main = newwin(row-3, col, 3, 0);
- wbkgd(ui_main,COLOR_PAIR(2));
- wrefresh(ui_main);
- //progressbar ablak rajzolása
- ui_progress = newwin(3, 52, ((row)/2)-4, (col-52)/2);
- wbkgd(ui_progress,COLOR_PAIR(1));
- box(ui_progress, 0 , 0);
- mvwprintw(ui_progress,0,2,"%s","[Tores folyamatban]");
- wrefresh(ui_progress);
- //részletes információk rajzolása
- ui_details = newwin(6, 52, (row)/2, (col-52)/2);
- wbkgd(ui_details,COLOR_PAIR(4));
- box(ui_details, 0 , 0);
- //Amennyiben nincs beérkező stream
- mvwprintw(ui_details,2,2,"Varakozas a bejovo adatokra...");
- mvwprintw(ui_details,3,2,"(Nincs input)");
- wrefresh(ui_details);
- //statusbar ablak rajzolása
- ui_status = newwin(1, col, row-1, 0);
- wbkgd(ui_status,COLOR_PAIR(3));
- //GNU GPL License szöveg
- mvwprintw(ui_status,0,1,"%s","Copyright (C) 2013, SuffleSource - GNU General Public License");
- wrefresh(ui_status);
- }
- void stopUserInterface(){
- endwin();
- }
- //Használati utasítás kiírása képernyőre
- void help(){
- cout << "==Használat==" << endl;
- cout << "./exor_fejt <bemeneti fájlnév> <kapcsolók>" << endl << endl;
- cout << "==Kapcsolók==" << endl
- << "-o <fájlnév>: kimeneti fájlnév" << endl
- << "\t (alapértelmezett: output.decrypt)" << endl
- << "-l <szám>: legkisebb kulcshossz" << endl
- << "-h <szám>: legnagyobb kulcshossz" << endl
- << "-x <szám>: beolvasandó adat mennyisége" << endl
- << "-t <szám>: keresési érzékenység (a kisebb szám az érzékenyebb) [1-100]" << endl
- << "-p <szám>: kezdés megadott ponttól (százalékban) [1-100]" << endl
- << "-s <szám>: kezdés megadott pontig (százalékban) [1-100]" << endl
- << "-f <fájlnév>: összes talált kulcs kiírása fájlba" << endl
- << "-g <fájlnév>: összes talált kulcs és adat kiírása fájlba" << endl
- << "-c <szám>: eredmény kiírása standard kimenetre [1-2]" << endl
- << "\t (1: kulcs kiírása)" << endl
- << "\t (2: dekódolt szöveg kiírása)" << endl
- << "-d <szám>: vizsgálat mélysége [1-1000]" << endl
- << "\t (a nagyobb szám a részletesebb (lassabb))" << endl
- << "\t (alapértelmezett: 200)" << endl
- << "\t (-1 a maximális mélység)" << endl
- << "-k <szám>: keresendő kulcs típusa [0-7]" << endl;
- cout << "==Kulcs típusok==" << endl
- << "0: számok, betűk és speciális karakterek" << endl
- << "1: csak számok" << endl
- << "2: csak kisbetűk" << endl
- << "3: csak nagybetűk" << endl
- << "4: kis- és nagybetűk" << endl
- << "5: kis- és nagybetűk és számok" << endl
- << "6: bináris számjegyek [0-1]" << endl
- << "7: hexadecimális (nagybetű) [0-F]" << endl;
- }
- //belépési pont (main)
- int main(int argc, char const *argv[])
- {
- if (argc < 2){
- cout << "Túl kevés argumentum!" << endl;
- help();
- return -1;
- }
- //indítási paraméterek alaphelyzetbe
- //bemeneti fájl beolvasása
- string inputFileName = argv[1];
- //kimeneti fájl alapértelmezett neve
- string outputFileName = "output.decrypt";
- //argumentumok léptetése
- *++argv;
- --argc;
- //beolvasandó karakterek száma
- int charsNo = 300;
- //legkisebb és legnagyobb kulcshossz
- int minKey = 1;
- int maxKey = 8;
- //félbehagyott folyamat folytatása (%-ban)
- int startPerCent = 0;
- int stopPerCent = 101;
- //keresési mélység
- int searchDepth = 250;
- //kulcs típusa
- int keyMode = 0;
- //minden kulcs kiírása fájlba
- bool allKeysOut = false;
- //kulcshoz tartozó adat kiírása fájlba
- bool allKeysOutData = false;
- string keyOutFile = "";
- //kiírás coutra (1: kulcs, 2:szöveg)
- int isStdOut = 0;
- //paraméterek beolvasása
- char c;
- while (--argc && *(*++argv) == '-'){
- switch (c = *((*argv++) + 1)){
- case 'o':
- outputFileName = (*argv);
- break;
- case 'l':
- minKey = atoi(*argv);
- break;
- case 'h':
- maxKey = atoi(*argv);
- break;
- case 't':
- wsThreshold = atoi(*argv);
- break;
- case 'k':
- keyMode = atoi(*argv);
- break;
- case 'p':
- startPerCent = atoi(*argv);
- break;
- case 's':
- stopPerCent = atoi(*argv);
- break;
- case 'd':
- searchDepth = atoi(*argv);
- break;
- case 'f':
- allKeysOut = true;
- keyOutFile = (*argv);
- break;
- case 'g':
- allKeysOut = true;
- allKeysOutData = true;
- keyOutFile = (*argv);
- break;
- case 'c':
- isStdOut = atoi(*argv);
- break;
- case 'x':
- charsNo = atoi(*argv);
- break;
- case '?':
- //használati útmutató kiírása
- help();
- return -1;
- default:
- cout << "ismeretlen opció! " << c << endl;
- help();
- return -1;
- }
- --argc;
- }
- //feladat elnevezése
- string job;
- //kulcsmód alapján karakterkészlet beállítása
- /* keyMode: kulcs típusa
- * 0: számok, betűk és speciális karakterek
- * 1: csak számok
- * 2: csak kisbetűk
- * 3: csak nagybetűk
- * 4: kis- és nagybetűk
- * 5: kis- és nagybetűk és számok
- * 6: bináris
- * 7: hexadecimális (nagybetű)
- */
- switch(keyMode){
- case 0:
- charSet += "0123456789";
- charSet += "abcdefghijklmnopqrstuvwxyz";
- charSet += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- charSet += "!@#$%^&*/";
- job = "teljes";
- break;
- case 1:
- charSet += "0123456789";
- job = "decimális";
- break;
- case 2:
- charSet += "abcdefghijklmnopqrstuvwxyz";
- job = "kisbetűk";
- break;
- case 3:
- charSet += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- job = "nagybetűk";
- break;
- case 4:
- charSet += "abcdefghijklmnopqrstuvwxyz";
- charSet += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- job = "betűk";
- break;
- case 5:
- charSet += "0123456789";
- charSet += "abcdefghijklmnopqrstuvwxyz";
- charSet += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
- job = "számok és betűk";
- break;
- case 6:
- charSet += "01";
- job = "bináris";
- break;
- case 7:
- charSet += "0123456789ABCDEF";
- job = "hexadecimális";
- break;
- default:
- cout << "Hibás kulcs típus: " << keyMode << endl;
- help();
- return 1;//hibás érték
- }
- //kezdő idő megadása
- time_t startTime = time(0);
- //felhasználói felület indítása
- initUserInterface();
- //aktuális feladat kiírása
- mvwprintw(ui_details,1,2,"Feladat: %d-%d karakter (%s) (t%d)",minKey,maxKey,job.data(),wsThreshold);
- mvwprintw(ui_main,row-6,2,"Fajl: %s >> %s",inputFileName.data(),outputFileName.data());
- wrefresh(ui_main);
- //beolvasás kiírása részletek ablakohoz
- //a sok whitespace az előző szöveg felülírásához kell
- mvwprintw(ui_details,2,2,"Beolvasas...%s",wsClear);
- /*
- * Törés kezdete
- */
- //stream, a beérkező karakterek vektorba rendezve
- vector<char> stream;
- //a stream egy karaktere
- char input;
- //fájl megnyitása
- ifstream inputFile;
- inputFile.open(inputFileName.data(), ios::binary);
- //ha a fájl nem létezik
- if (!inputFile.is_open()){
- stopUserInterface();
- cout << "Érvénytelen fájl: " << inputFileName << "!" << endl;
- return 2;
- }
- //fájl olvasása
- if (charsNo == -1){
- while(!inputFile.eof()){
- inputFile.get(input);
- stream.push_back(input);
- }
- }else{
- for (int l = 0; l < charsNo; ++l)
- {
- inputFile.get(input);
- stream.push_back(input);
- }
- }
- inputFile.close();
- //kimeneti fájl megnyitása
- ofstream outputFile;
- outputFile.open (outputFileName.data(),ios::binary);
- //lehetséges kulcsok gyűjtése vektorba
- vector<string> possibleKeys;
- //ebben tárolódik az éppen aktuális kulcs
- string cKey = "";
- //ebben tárolódik az aktuálisan dekódolt szöveg
- string actual;
- //talált lehetséges kulcsok száma
- int foundKeys = 0;
- //folyamatjelzők
- float progress = 0.0;
- float prevProgress = 0.0;
- //ha a kezdőpont nagyobb mint a végpont
- if (startPerCent > stopPerCent){
- stopUserInterface();
- cout << "Hibás kezdő- és végpont (%)! Adjon meg pozitív tartományt!" << endl;
- return 4;
- }
- //a lehető legnagyobb mag értéke az adott paraméterekkel - folyamatszámításhoz szükséges
- long long maxProgress = pow(charSet.length(),maxKey) - pow(charSet.length(),minKey-1);
- //ha hibás a keresési tartomány
- if (maxProgress < 0){
- stopUserInterface();
- cout << "Hibás karakterszám! Adjon meg pozitív tartományt!" << endl;
- return 4;
- }
- //kezdő 'mag' a kulcsgenerátornak
- register unsigned long long cSeed = 1 + pow(charSet.length(),minKey-1) + ((startPerCent*maxProgress)/100);
- //Időszámítással kapcsolatos változók
- clock_t timer, prevTimer;
- //kezdőidő beállítása
- timer = clock();
- //hátralévő idő
- double timeLeft;
- //szálak száma
- int threads = 1;
- //számláló, mely a néhai kiíratást segíti elő, szándékos túlcsordulással
- short x;
- /*
- * OpenMP Blokk (!!!)
- * Parallel blokk kezdete - párhuzamosított rész
- */
- #pragma omp parallel shared(cSeed,x,possibleKeys) private(cKey,actual) firstprivate(timer,prevTimer)
- {
- //szálak száma
- threads = omp_get_num_threads();
- //szálak számának kiírása (csak mesterszálon)
- #pragma omp master
- mvwprintw(ui_details,0,44,"%d szal",threads);
- //ciklus kezdete - végtelen ciklus
- //a számláló a kiíratáshoz kell
- for (x = 0;;x++){
- //kulcs generálás
- cKey = generateKeyFromSeed(cSeed);
- //a kulcs léptetése kritikus művelet, ezért csak egy szálon inkrementálódik!
- #pragma omp critical
- cSeed++;
- //minden lehetséges kombináció meg volt vizsgálva (túlcsordulás)
- if (cKey == "0")
- break;
- if (cKey.length() > maxKey)
- break;
- //aktuális vizsgálat - visszatérési érték a dekódolt szöveg vagy egy '#' karakter
- actual = tryWithKey(stream, cKey, searchDepth);
- if (actual != "#"){
- //talált kulcsok számának növelése
- foundKeys++;
- //kulcs hozzáadása lehetséges kulcsokhoz
- #pragma omp critical
- possibleKeys.push_back(cKey);
- }
- //aktuális folyamat kiszámítása (százalékban)
- progress = (cSeed*100/maxProgress);
- //folyamatjelző változásakor futó blokk
- #pragma omp master
- {
- if (progress != prevProgress){
- //ha túlléptük a végpontot, kilépés
- if (progress > stopPerCent)
- maxKey = 0;
- //időzítő mentése
- prevTimer = timer;
- //jelenlegi idő mérése
- timer = clock();
- //hátralevő idő számítása
- timeLeft = (((100-progress) * (timer - prevTimer)/CLOCKS_PER_SEC)/threads)+1;
- //kiíratások
- //aktuális százalék kiírása
- mvwprintw(ui_progress,2,47,"%.f%s",progress,"%");
- //progressbar feltöltése
- mvwhline(ui_progress,1,1,ACS_VLINE,progress/2);
- //ablak frissítése
- wrefresh(ui_progress);
- //idő kiírása
- mvwprintw(ui_details,4,2,"Hatralevo ido:\t%.f mp ( %.f perc ) ",timeLeft, timeLeft/60,wsClear);
- }
- }
- //folyamatjelző változásakor és megadott ciklusszám után végrehajtódó blokk
- #pragma omp master //csak a mesterszálon
- if (progress != prevProgress || x==0){
- //progress mentése
- prevProgress = progress;
- //Kiíratások
- //éppen vizsgált kulcs
- mvwprintw(ui_details,2,2,"Aktualis kulcs: \t%s%s", cKey.data(),wsClear);
- //eddig megtalált kulcsok
- mvwprintw(ui_details,3,2,"Talalt kulcsok: \t%d\t ",foundKeys);
- //ablak frissítése
- wrefresh(ui_details);
- }
- }
- }
- //Parallel blokk vége
- #pragma omp end parallel
- //ha nem talált kulcsot, kilépés hibával!
- if (foundKeys == 0){
- //kilépés felhasználói felületből
- stopUserInterface();
- //eredmény kiírása
- cout << "===" << programTitle << "===" << endl;
- cout << "\033[1;31mNem találtam kulcsot!\033[0;0m" << endl;
- cout << "Próbáld újra más paraméterekkel!" << endl;
- return 3;
- }
- //találati lista szűkítése
- //ablak átrajzolása
- ui_details = newwin(3, 52, (row)/2, (col-52)/2);
- wbkgd(ui_details,COLOR_PAIR(4));
- box(ui_details, 0 , 0);
- mvwprintw(ui_details,1,2,"Talalati lista csokkentese...");
- refresh();
- //legnagyobb betű arány
- double maxAlphabetRatio = 0;
- //legnagyobb betű arányú kulcs
- string idealKey = "";
- string solution;
- //kimeneti fájl kulcsok kiírásához
- ofstream allKeysFile;
- //fájl nyitása
- if (allKeysOut){
- allKeysFile.open (keyOutFile.data(),ios::binary);
- allKeysFile << "=========" << programTitle << "=========" << endl;
- }
- //whitespace treshold kikapcsolása
- wsThreshold = stream.size();
- //talált kulcsok további ellenőrzése
- for (int i = 0; i < possibleKeys.size()-1; ++i){
- //teljes szöveg dekódolása
- actual = tryWithKey(stream, possibleKeys[i],-1);
- //kulcs fájlba írása ha szükséges
- if (allKeysOut){
- allKeysFile << "Kulcs: " << possibleKeys[i] << endl;
- if (allKeysOutData){
- allKeysFile << actual << endl;
- }
- }
- //betűk és egyéb karakterek arányának vizsgálata
- long long fullLength = actual.length();
- int alphabet = 0;
- //betűnkénti léptetés
- for (int j = 0; j < actual.length(); ++j){
- if ( (actual[j] > 'A' && actual[j] < 'Z')
- || (actual[j] > 'a' && actual[j] < 'z')
- || actual[j] == ' ' || actual[j] == '\n')
- alphabet++;
- }
- //betű arány
- double alphabetRatio = (double) alphabet/fullLength;
- if (alphabetRatio > maxAlphabetRatio){
- maxAlphabetRatio = alphabetRatio;
- idealKey = possibleKeys[i];
- solution = actual;
- }
- }
- //kulcsokat tartalmazó fájl bezárása
- allKeysFile.close();
- //találat kíirása
- vector<char> fullStream;
- if (maxAlphabetRatio > 0){
- //ablak frissítése
- mvwprintw(ui_details,1,2,"Eredmeny irasa fajlba... ");
- wrefresh(ui_details);
- //stream beolvasása, ezúttal végig
- //fájl megnyitása
- inputFile.open(inputFileName.data(), ios::binary);
- //beolvasás
- while(!inputFile.eof()){
- inputFile.get(input);
- fullStream.push_back(input);
- }
- }
- //felhasználói felület megállítása
- stopUserInterface();
- //találat kiírása, ha van
- if (maxAlphabetRatio > 0){
- solution = tryWithKey(fullStream, idealKey, -1);
- outputFile << "=========" << programTitle << "=========" << endl;
- outputFile << "Kulcs: " << idealKey << endl;
- outputFile << solution << endl;
- }else{
- outputFile << "HIBA! Nem találtam megfelelő kulcsot!";
- }
- //fájl bezárása
- outputFile.close();
- switch (isStdOut){
- case 0:
- cout << "===" << programTitle << "===" << endl;
- cout << "Megvizsgált kulcsok: \t" << cSeed << endl;
- cout << "Talált kulcsok: \t" << foundKeys << endl;
- cout << "Lehetséges kulcs: \t" << idealKey << endl;
- cout << "\033[1;31mFutási idő: " << difftime(time(0),startTime) << "mp\033[0;0m"<< endl;
- break;
- case 1:
- cout << idealKey;
- break;
- case 2:
- cout << solution;
- break;
- default:
- cout << "HIBA! c kapcsoló argumentuma hibás!" << endl;
- }
- //eredmények kiírása
- //kilépés
- return 0;
- }
Add Comment
Please, Sign In to add comment