├── README.md ├── chimera_decrypt ├── README.md ├── chimera-leak.txt ├── polarsslwrapper.dll ├── src │ ├── CMakeLists.txt │ ├── main.cpp │ └── wrapper.h └── test_cases │ ├── case1 │ ├── dumped_key.txt │ ├── encrypted │ │ ├── msg_01.txt.crypt │ │ ├── msg_02.txt.crypt │ │ ├── msg_03.txt.crypt │ │ ├── msg_04.txt.crypt │ │ ├── msg_05.txt.crypt │ │ ├── msg_06.txt.crypt │ │ ├── msg_07.txt.crypt │ │ ├── msg_08.txt.crypt │ │ ├── msg_09.txt.crypt │ │ ├── msg_10.txt.crypt │ │ ├── msg_11.txt.crypt │ │ └── msg_12.txt.crypt │ └── run.bat │ ├── case2 │ ├── dumped_key.txt │ ├── readme.txt.crypt │ └── run.bat │ ├── case3 │ ├── README.md │ ├── redist.txt.crypt │ └── run.bat │ ├── chimera_private.txt │ └── run.bat ├── dma_unlocker ├── CMakeLists.txt ├── LICENSE ├── Params.cpp ├── Params.h ├── README.md ├── cracking_crawler │ ├── CMakeLists.txt │ ├── CrackedSet.cpp │ ├── CrackedSet.h │ └── main.cpp ├── decryptor │ ├── CMakeLists.txt │ ├── aes256.cpp │ ├── aes256.h │ ├── decryptor.cpp │ ├── decryptor.h │ └── main.cpp ├── dma_crack.cpp ├── dma_crack.h ├── filetypes │ ├── CMakeLists.txt │ ├── FileTypes.cpp │ ├── FileTypes.h │ ├── TypeValidator.cpp │ ├── TypeValidator.h │ └── main.cpp ├── keygen │ ├── CMakeLists.txt │ ├── DmaKeygen.cpp │ ├── DmaKeygen.h │ ├── keygen.cpp │ ├── keygen.h │ └── main.cpp ├── main.cpp ├── main.h ├── recon │ ├── CMakeLists.txt │ ├── FileSet.cpp │ ├── FileSet.h │ ├── PathCrawler.cpp │ ├── PathCrawler.h │ └── main.cpp ├── timeconv.cpp ├── timeconv.h ├── types.h ├── unlocker │ ├── CMakeLists.txt │ ├── Unlocker.cpp │ ├── Unlocker.h │ └── main.cpp └── util.h └── princesslocker_decrypt ├── README.md ├── decryptor ├── CMakeLists.txt ├── PathCrawler.cpp ├── PathCrawler.h ├── README.md ├── decryptor.cpp ├── decryptor.h └── main.cpp └── keygen ├── CMakeLists.txt ├── README.md ├── aes_crypt.cpp ├── aes_crypt.h └── main.cpp /README.md: -------------------------------------------------------------------------------- 1 | # decryptors_archive 2 | Archive of ransomware decryptors.
3 | Warning: those decryptors are obsolete. They are available only for a case study for other researchers. 4 | -------------------------------------------------------------------------------- /chimera_decrypt/README.md: -------------------------------------------------------------------------------- 1 | Tool for checking whether your files can be decrypted using leaked Chimera keys.
2 | Read more: https://blog.malwarebytes.com/cybercrime/2016/08/decrypting-chimera-ransomware/
3 | -------------------------------------------------------------------------------- /chimera_decrypt/polarsslwrapper.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/polarsslwrapper.dll -------------------------------------------------------------------------------- /chimera_decrypt/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (chimera_dec) 3 | 4 | set (srcs 5 | main.cpp 6 | ) 7 | 8 | set (hdrs 9 | wrapper.h 10 | ) 11 | 12 | add_executable (chimera_dec ${hdrs} ${srcs}) 13 | -------------------------------------------------------------------------------- /chimera_decrypt/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "wrapper.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define KEYS_SET_FILE "chimera-leak.txt" 8 | #define OUT_KEY_FILE "found.key" 9 | #define DEFAULT_KEY_LEN 0x483 10 | 11 | using namespace std; 12 | 13 | BYTE *g_privKey = new BYTE [DEFAULT_KEY_LEN + 1]; 14 | size_t g_keyLen = 0; 15 | 16 | BYTE* HexToBytes(const std::string& hex) { 17 | size_t hex_len = hex.length(); 18 | size_t key_len = hex_len/2 + 1; 19 | 20 | memset(g_privKey, 0, key_len); 21 | 22 | const char* hex_str = hex.c_str(); 23 | char chunk[3]; 24 | memset(chunk, 0, 3); 25 | BYTE mByte = 0; 26 | g_keyLen = 0; 27 | 28 | for (size_t i = 0, j = 0; i < hex_len; i += 2, j++) { 29 | chunk[0] = hex_str[i]; 30 | chunk[1] = hex_str[i + 1]; 31 | 32 | g_privKey[g_keyLen] = static_cast(std::stoul(chunk, nullptr, 16)); 33 | g_keyLen++; 34 | } 35 | return g_privKey; 36 | } 37 | 38 | bool save_to_file(const char* path, std::string line) 39 | { 40 | std::ofstream outfile(path); 41 | if (outfile.is_open() == false) { 42 | return false; 43 | } 44 | outfile << line << endl; 45 | outfile.close(); 46 | return true; 47 | } 48 | 49 | bool file_exist(const char* path) 50 | { 51 | std::ifstream infile(path); 52 | if (infile.is_open() == false) { 53 | return false; 54 | } 55 | infile.close(); 56 | return true; 57 | } 58 | 59 | bool search_priv_key(std::ifstream &infile, const char* file_path) 60 | { 61 | t_DecryptFileWrapper func1 = loadDecryptFunc(); 62 | if (func1 == NULL) { 63 | system("pause"); 64 | return false; 65 | } 66 | 67 | std::string line; 68 | size_t key_len = 0; 69 | size_t counter = 0; 70 | while (std::getline(infile, line)) 71 | { 72 | std::istringstream iss(line); 73 | key_len = line.length() / 2; 74 | printf("key num: %d len = %#x = %d\n", counter++, key_len, key_len); 75 | 76 | BYTE *priv_key = HexToBytes(line); 77 | 78 | if (func1(file_path, priv_key, DEFAULT_KEY_LEN)) { 79 | printf("Success!\n"); 80 | if (save_to_file(OUT_KEY_FILE, line)) { 81 | printf("Found key saved to the file: %s\n", OUT_KEY_FILE); 82 | } else { 83 | printf("[ERROR] Cannot save to the file: %s\n", file_path); 84 | } 85 | return true; 86 | } 87 | } 88 | return false; 89 | } 90 | 91 | bool rename_file(std::string filename) 92 | { 93 | std::size_t found = filename.find_last_of("."); 94 | std::string newname = filename.substr(0, found); 95 | std::string ext = filename.substr(found+1); 96 | if (ext == "crypt") { 97 | MoveFileA(filename.c_str(), newname.c_str()); 98 | printf("Renamed decrypted file to: %s\n", newname.c_str()); 99 | return true; 100 | } 101 | return false; 102 | } 103 | 104 | int main(int argc, char *argv[]) 105 | { 106 | if (argc < 3) { 107 | printf("USAGE:\nchimera_dec.exe \nEXAMPLE:\nchimera_dec.exe myFile.docx.crypt chimera-leak.txt\n"); 108 | system("pause"); 109 | return -1; 110 | } 111 | 112 | const char *path = path = argv[1]; 113 | const char *key_leak_file = argv[2]; 114 | 115 | std::ifstream infile(key_leak_file); 116 | if (infile.is_open() == false) { 117 | printf("[ERROR] Cannot open the file with keys: %s\n", key_leak_file); 118 | system("pause"); 119 | return -1; 120 | } 121 | 122 | if (file_exist(path) == false) { 123 | printf("[ERROR] Cannot open encrypted file: %s\n", path); 124 | system("pause"); 125 | return -1; 126 | } 127 | 128 | if (search_priv_key(infile, path)) { 129 | rename_file(path); 130 | printf("Hurray! The set contains your key!\n"); 131 | } else { 132 | printf("Sorry! None of the keys fit to your file!\n"); 133 | } 134 | 135 | system("pause"); 136 | return 0; 137 | } 138 | -------------------------------------------------------------------------------- /chimera_decrypt/src/wrapper.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define DLL_PATH "polarsslwrapper" 5 | #define DECRYPT_FUNC "DecryptFileWrapper" 6 | #define ID_FUNC "GetHardwareIdWrapper" 7 | 8 | typedef bool (__cdecl *t_DecryptFileWrapper)(const char *filePath, BYTE *privateKey, size_t privateKeyLen); 9 | 10 | t_DecryptFileWrapper loadDecryptFunc() 11 | { 12 | HMODULE hLib = LoadLibraryA(DLL_PATH); 13 | if (hLib == NULL) { 14 | printf("Could not load the DLL!\n"); 15 | return NULL; 16 | } else { 17 | printf("DLL loaded\n"); 18 | } 19 | 20 | t_DecryptFileWrapper func = (t_DecryptFileWrapper) GetProcAddress(hLib, DECRYPT_FUNC); 21 | if (func == NULL) { 22 | printf("Could not get the %s\n", DECRYPT_FUNC); 23 | return NULL; 24 | } 25 | printf("Got the %s\n", DECRYPT_FUNC); 26 | return func; 27 | } 28 | -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/dumped_key.txt: -------------------------------------------------------------------------------- 1 | A4638D07923CE31933D75104B6C10687DFD9FEB5350CFB356858E06E909E1F7A4935838FDDF5CBF73141F9B82877FA5F83B1809099126620944B48BE067BE36761B02673FFB0A28EAAC37793B50500E9267D88DCFEAEB6AEDD3F1A0D2C741FDA5210625C5F3EE556642598ACE44642A7688985E6C4B1C0F154A4B95003310283A95915492E80E2100AD1FED14F3BA78A501E32C91E16B82132E74BC53804AE0A61FA8F9E6ECF0137FC3E37DA1318E0492D66680B42AEA933ABCB2FE519830AF12AE9AC2940C9F9F5913DB57051E14817EC40B1F418A328D42803492603F136E4BAF052A536CA2725C117AF3E1E1F58BCD38EA0C61C544C11392D9A343ED96F670100016C211F4EEF9E25331AAA729C4B29C485F3748CD9DCBF612DCC2949D6F041522B39A47D995042B19B3347565F101F7B0D00AEED062FE9AE4B97BFBD656116748A37F38A179B0430A8EF220BB198CC65C0F694744609301AF2028DD330FF20932323FFAAF35FA31B6F2C089ED87A7ECCB1194DFC49C2EFB91E04B32541C017A8B2A8CAC8EFF65FD00C0A0B643DBC6016DA3B2BE43AEB0C54FC8BA1493A98F7410DD2C8FA85F21E877F238107DBA0608CAA8103E5F86E286987679DFE46226BFA495214CDBACE4ECFEC122A2119321E7D1E2C61B5FAE985F8CD7BA4C464E0303BD1A6C1E9EB0FA900E4C31585D08FA6928862C3D99F1EC4F3384652DB68EFD70041EF40F86AF2BE3C0C14CD0C7E78DF91E47AA632B48A6FF030584C1B01173337A14D644FB20D618AABBC98B7CBA8C1428DB6235E50E3C923230FF671CFA2638BDA5E5666E04CA78F7EDDFB04EE95CB5376CB811FE6A303A5AC1224540EC242CC66B9841A4BD6E0963D3EDF5C5FB191591ACFC405C3BAED5B149BF159B52C2E3C9FAFE520337DDEB01CA72EA5420A15F1566332B0582364A61C091B328039B3A38F9C5FA17D1680F4AC58BAE203DDFA2305F307FDA8AC4876511E5A411072F417D85EE39BD9121A4D6B36EADFCE3A69B7BE43FA040BB4606E4DB5A7164A228253F6421BB67A86B9FBA03363C3D4F60CB6F98495F6B4FC96A6E3CE38CC1A00BC10398369BF49170DD0739E5546408D69D77B94B686F14D7CD083ED6BD8055055EC7F67BFEA5A5529377EBEF76F34A8FB85EFCA9440B0D37CDE14DB26B53AA3EA639DCCE54E5A7320321C3017398D46AFC8A75E7E0D24A4735363610F9D300219A8A5DFCE2497756E24777D7A3805C3C59F18AFF7EE66A4DCCC8354684BAACC9A94E7A9EBAFDAEE7AC52938FC5FDB5740F15EE1FFA2C9D28F35C519AAF37359CAC77441BD449541BB1C22AEA90314774960B22BA089947BB298D22E7F4421AEDB4D79D1D911C276B1801ED5F3BA775088B65F90EDA320E784CCAA37950D7C5AB00A8A783CAB60DC6C28C00F450E76D9A758CFDD1CBE33035C4A27021E6E55A4660949594FAA540D7482407C0AB53E1F22F206C73300A2E6FE1779EA49068813A4FB8BE223A9F6093AB828364ADB8B8F569EBD59F52058423DD84CB4D23C8E99CA7E6E13343BD464ADD931180FA8B4BC9380750A07FD60516CEB9C991E15B6259F9F5B9AA3E7F37487EE5B2F3CA03FF2704BCEF0FEDF06C641080D4840F212E6B406380 -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_01.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_01.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_02.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_02.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_03.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_03.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_04.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_04.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_05.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_05.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_06.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_06.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_07.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_07.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_08.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_08.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_09.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_09.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_10.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_10.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_11.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_11.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/encrypted/msg_12.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case1/encrypted/msg_12.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case1/run.bat: -------------------------------------------------------------------------------- 1 | chimera_dec.exe encrypted\msg_01.txt.crypt dumped_key.txt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case2/dumped_key.txt: -------------------------------------------------------------------------------- 1 | AF76197D882C7FF4D7DEB7418FB2C656ECDD7330B022C4351EDD82808002885E7B8FD76E48B6E9994125526DFAC891DEDD75DAB92408F91F506379E278D07092958C303F97C87D3F6BCEF786862BF89B7236CCD6FDDFE91005171DBA567E6CACA137CCEDE9D5DCF7B9E38305B654ABFAB3AD1465FA007AA17C60DC02CBAA89C944DB80AC45B2C4AEA67471AE90C49B78F88F90281518565F4BE1ED59E153945A62005C040EBCE02ED8C80F24D518CE2E05BB26456BE202FB9800E458C0E03E5AB472BDE32327B8348173B17E6765F5AE390191A5E13EB69979E8B2B795FD4B7F027CB5FB9B77E448751C69D7A0E35B6B73AE06EAA2461299AB2E7719AF8CD7850100019C357E581E25CFFD413A8CD81780C7C797B547DA2ED5A4ECCDFFD33167C5D9769476E90ACC3DDC168EC31571C8754C38A7DD46CED16013BA672D48D3F14F51098F8E715E0C5977F84098D011B9DDE7C52C97D1220E7F8BD4B1537529F1DB381130AEA709A0C6BFA4E49FC2841161AC82D3F7E1533091C09B884A0B5589D0D83D1835F1824135228151B9881463CD4CDDFA93683426693FAC2AC08E20C6962F491C5D123FF78A1BBFE722932D18DF76DE6888833E7C7995D156AF2063BB32CEF0681C2124BA791F58D676607A7C0708493B3D19541E789452C857E3A646B7F7DA28DE732F04B914AD9CC85A3B21B66ED4444C57B6DF0065A064429391D7D63441DB10837D1E915A6F84133FDEB0DF45D2D6389B06DA782EC072133C7E3A01CD79CCF8801EC96C384AAA5B149A5600A6AD5316DCF01027504452CE216BD121F344FB6D6A6C2F3AEF83380667237C0F506F068DD345D2B7E1392960475815DDEF7C342AC92182F967D6DE4B37BDAD236284DFCE36A0D7D284BC8C0DFF7CD4B291ADCD0B8A76F2DE2E2FD8C96B3F0C70B7AE283B05C504200FF04F39C56E1BF2687C31E9E14BECA654E2E572DFD02532C78E09EF0B2ECD18A4FF03B2A7E2A09D59B7745C6A2E137FB7A23638AB85030AE0F3D1E3517C9A7D1928B1B737C1A1E1382E5CF0F7A5D6ECD1DE1B281C28221805478C3EF466DC2BFB06352EFB7335D108393A720C72BC4E116FC130159147653A4EC702B131C1E5E0AB4D841E569B095215D5FED2C7E3FB708553301BAE1595F4E23751D93E5F40EDE45CA74C3964C18712F775B8B8065DD5FB0F5E7DF3F4AC6D4C41D662F0B508841969159BD33F7A47E3BE534FF815E68EB2BFFA17740E966B3982309558925C4337BEB21960E7AA80BD1E1AB1ABA120C9BB30A2F1E201DB92BC391FE14AF9BE1358FEE8C679D214970E94ED77AC84042FB65865B34286139C84D8248689CA86F1C2973265BFBA411FE8F56694184BB896A7743A81C4379C2346E8EBED0CD449C5A5D9E1C287E55281C31CD62C25E7164201D00EE58366EE0BE86348E2ED2F2A2DE2CD70266ED5D9E8D1CF746A52DF5E15648D423FEF89FB1C10406F8B69357826A863A9CE78E7C5FCF246E90EB4FDC692753AE9B834CAB6E9D80DF68F82567EF4AF3F30937C4519E7326E9212DB2A2D2BA082D2A2F45E8B6643C78137978B7CEDD4C8AFD032FEB652BB5522427A0C3F2E23DB05DC7823F250D60246558CF1A755356A554C071E101780BA -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case2/readme.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case2/readme.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case2/run.bat: -------------------------------------------------------------------------------- 1 | chimera_dec.exe readme.txt.crypt dumped_key.txt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case3/README.md: -------------------------------------------------------------------------------- 1 | This sample file (redist.txt.crypt) has been encrypted with the help of public key from the leaked set. -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case3/redist.txt.crypt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/chimera_decrypt/test_cases/case3/redist.txt.crypt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/case3/run.bat: -------------------------------------------------------------------------------- 1 | chimera_dec.exe redist.txt.crypt chimera-leak.txt -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/chimera_private.txt: -------------------------------------------------------------------------------- 1 | A4638D07923CE31933D75104B6C10687DFD9FEB5350CFB356858E06E909E1F7A4935838FDDF5CBF73141F9B82877FA5F83B1809099126620944B48BE067BE36761B02673FFB0A28EAAC37793B50500E9267D88DCFEAEB6AEDD3F1A0D2C741FDA5210625C5F3EE556642598ACE44642A7688985E6C4B1C0F154A4B95003310283A95915492E80E2100AD1FED14F3BA78A501E32C91E16B82132E74BC53804AE0A61FA8F9E6ECF0137FC3E37DA1318E0492D66680B42AEA933ABCB2FE519830AF12AE9AC2940C9F9F5913DB57051E14817EC40B1F418A328D42803492603F136E4BAF052A536CA2725C117AF3E1E1F58BCD38EA0C61C544C11392D9A343ED96F670100016C211F4EEF9E25331AAA729C4B29C485F3748CD9DCBF612DCC2949D6F041522B39A47D995042B19B3347565F101F7B0D00AEED062FE9AE4B97BFBD656116748A37F38A179B0430A8EF220BB198CC65C0F694744609301AF2028DD330FF20932323FFAAF35FA31B6F2C089ED87A7ECCB1194DFC49C2EFB91E04B32541C017A8B2A8CAC8EFF65FD00C0A0B643DBC6016DA3B2BE43AEB0C54FC8BA1493A98F7410DD2C8FA85F21E877F238107DBA0608CAA8103E5F86E286987679DFE46226BFA495214CDBACE4ECFEC122A2119321E7D1E2C61B5FAE985F8CD7BA4C464E0303BD1A6C1E9EB0FA900E4C31585D08FA6928862C3D99F1EC4F3384652DB68EFD70041EF40F86AF2BE3C0C14CD0C7E78DF91E47AA632B48A6FF030584C1B01173337A14D644FB20D618AABBC98B7CBA8C1428DB6235E50E3C923230FF671CFA2638BDA5E5666E04CA78F7EDDFB04EE95CB5376CB811FE6A303A5AC1224540EC242CC66B9841A4BD6E0963D3EDF5C5FB191591ACFC405C3BAED5B149BF159B52C2E3C9FAFE520337DDEB01CA72EA5420A15F1566332B0582364A61C091B328039B3A38F9C5FA17D1680F4AC58BAE203DDFA2305F307FDA8AC4876511E5A411072F417D85EE39BD9121A4D6B36EADFCE3A69B7BE43FA040BB4606E4DB5A7164A228253F6421BB67A86B9FBA03363C3D4F60CB6F98495F6B4FC96A6E3CE38CC1A00BC10398369BF49170DD0739E5546408D69D77B94B686F14D7CD083ED6BD8055055EC7F67BFEA5A5529377EBEF76F34A8FB85EFCA9440B0D37CDE14DB26B53AA3EA639DCCE54E5A7320321C3017398D46AFC8A75E7E0D24A4735363610F9D300219A8A5DFCE2497756E24777D7A3805C3C59F18AFF7EE66A4DCCC8354684BAACC9A94E7A9EBAFDAEE7AC52938FC5FDB5740F15EE1FFA2C9D28F35C519AAF37359CAC77441BD449541BB1C22AEA90314774960B22BA089947BB298D22E7F4421AEDB4D79D1D911C276B1801ED5F3BA775088B65F90EDA320E784CCAA37950D7C5AB00A8A783CAB60DC6C28C00F450E76D9A758CFDD1CBE33035C4A27021E6E55A4660949594FAA540D7482407C0AB53E1F22F206C73300A2E6FE1779EA49068813A4FB8BE223A9F6093AB828364ADB8B8F569EBD59F52058423DD84CB4D23C8E99CA7E6E13343BD464ADD931180FA8B4BC9380750A07FD60516CEB9C991E15B6259F9F5B9AA3E7F37487EE5B2F3CA03FF2704BCEF0FEDF06C641080D4840F212E6B406380 -------------------------------------------------------------------------------- /chimera_decrypt/test_cases/run.bat: -------------------------------------------------------------------------------- 1 | chimera_dec.exe encrypted\msg_01.txt.crypt chimera_private.txt -------------------------------------------------------------------------------- /dma_unlocker/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (DMA_Unlocker) 3 | 4 | set (recon_srcs 5 | recon/PathCrawler.cpp 6 | recon/FileSet.cpp 7 | ) 8 | 9 | set (srcs 10 | decryptor/decryptor.cpp 11 | decryptor/aes256.cpp 12 | keygen/keygen.cpp 13 | keygen/DmaKeygen.cpp 14 | filetypes/filetypes.cpp 15 | filetypes/TypeValidator.cpp 16 | cracking_crawler/CrackedSet.cpp 17 | main.cpp 18 | dma_crack.cpp 19 | timeconv.cpp 20 | Params.cpp 21 | ) 22 | 23 | set (recon_hdrs 24 | recon/PathCrawler.h 25 | recon/FileSet.h 26 | ) 27 | 28 | set (hdrs 29 | main.h 30 | util.h 31 | decryptor/decryptor.h 32 | decryptor/aes256.h 33 | keygen/keygen.h 34 | keygen/DmaKeygen.h 35 | filetypes/filetypes.h 36 | filetypes/TypeValidator.h 37 | cracking_crawler/CrackedSet.h 38 | dma_crack.h 39 | types.h 40 | timeconv.h 41 | Params.h 42 | ) 43 | 44 | SOURCE_GROUP("Header Files\\recon" FILES ${recon_hdrs} ) 45 | SOURCE_GROUP("Source Files\\recon" FILES ${recon_srcs} ) 46 | 47 | add_executable (DMA_Unlocker ${hdrs} ${srcs} ${recon_hdrs} ${recon_srcs}) 48 | -------------------------------------------------------------------------------- /dma_unlocker/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, hasherezade , https://keybase.io/hasherezade 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | 25 | -------------------------------------------------------------------------------- /dma_unlocker/Params.cpp: -------------------------------------------------------------------------------- 1 | #include "Params.h" 2 | 3 | const char Params::id_hash[] = "qWyYGuCxIkhne4XjTyli7ApK761u0xfG9exLhPteuj/bwJxWQzcmh9Zn56dcqnLX"; 4 | 5 | //when it all started? 6 | uint32_t Params::encryptionStartTime() 7 | { 8 | time_t start = get_file_creation("C:\\ProgramData\\start.txt"); 9 | if (start == 0) { 10 | start = get_file_creation("C:\\ProgramData\\cryptinfo.txt"); 11 | } 12 | //--- 13 | if (start > 0) { 14 | printf("Infections start time:\n"); 15 | print_time_str(start); 16 | } else { 17 | printf("Infections start time: UNKNOWN\n"); 18 | } 19 | return static_cast(start); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /dma_unlocker/Params.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #include 6 | #include /* printf, scanf, puts, NULL */ 7 | #include 8 | #include "types.h" 9 | #include "timeconv.h" 10 | 11 | //#define DEBUG 1 12 | 13 | class Params { 14 | 15 | public: 16 | static uint32_t encryptionStartTime(); 17 | 18 | Params() 19 | { 20 | this->timeNow = static_cast (time(NULL)); 21 | this->startTime = encryptionStartTime(); 22 | this->seed = timeNow; 23 | incrementalMode = false; 24 | filename = ""; //not known yet 25 | fileEncryptionTime = 0; 26 | key_num = 0; 27 | } 28 | 29 | void init(std::string enc_filename, uint32_t encryptionTime) 30 | { 31 | if (enc_filename.length() == 0) return; 32 | this->filename = enc_filename; 33 | this->fileEncryptionTime = encryptionTime; 34 | if (seed == 0 || seed > fileEncryptionTime) { 35 | seed = encryptionTime; 36 | } 37 | autosetMode(); 38 | } 39 | 40 | void autosetMode() { 41 | this->incrementalMode = (seed < this->fileEncryptionTime); 42 | } 43 | 44 | //---- 45 | std::string filename; 46 | uint32_t startTime; //optional 47 | uint32_t fileEncryptionTime; //optional 48 | 49 | uint32_t timeNow; 50 | uint32_t seed; 51 | size_t key_num; 52 | bool incrementalMode; 53 | size_t series_min, series_max; 54 | static const char id_hash[]; 55 | 56 | protected: 57 | void setIncrementalMode(bool val); 58 | }; -------------------------------------------------------------------------------- /dma_unlocker/README.md: -------------------------------------------------------------------------------- 1 | Unlocker for DMA Locker ransomware 2 | 3 | # DMA Unlocker 4 | (plus some tiny helper tools) 5 | - 6 | Read more: https://hshrzd.wordpress.com/dma-unlocker/ 7 |
8 | DISCLAIMER: this code is not polished or so, it is just a raw snapshot from the middle of the battle with this ransomware ;) 9 | -------------------------------------------------------------------------------- /dma_unlocker/cracking_crawler/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (DMA_crawler) 3 | 4 | set (recon_srcs 5 | ../recon/PathCrawler.cpp 6 | ../recon/FileSet.cpp 7 | ) 8 | 9 | set (srcs 10 | main.cpp 11 | CrackedSet.cpp 12 | ../decryptor/decryptor.cpp 13 | ../decryptor/aes256.cpp 14 | ../keygen/keygen.cpp 15 | ../filetypes/filetypes.cpp 16 | ../filetypes/TypeValidator.cpp 17 | ../dma_crack.cpp 18 | ../timeconv.cpp 19 | ../Params.cpp 20 | ) 21 | 22 | set (recon_hdrs 23 | ../recon/PathCrawler.h 24 | ../recon/FileSet.h 25 | ) 26 | 27 | set (hdrs 28 | CrackedSet.h 29 | ../decryptor/decryptor.h 30 | ../decryptor/aes256.h 31 | ../keygen/keygen.h 32 | ../filetypes/filetypes.h 33 | ../filetypes/TypeValidator.h 34 | ../dma_crack.h 35 | ../types.h 36 | ../timeconv.h 37 | ../Params.h 38 | ) 39 | 40 | SOURCE_GROUP("Header Files\\recon" FILES ${recon_hdrs} ) 41 | SOURCE_GROUP("Source Files\\recon" FILES ${recon_srcs} ) 42 | 43 | add_executable (DMA_crawler ${hdrs} ${srcs} ${recon_hdrs} ${recon_srcs}) 44 | -------------------------------------------------------------------------------- /dma_unlocker/cracking_crawler/CrackedSet.cpp: -------------------------------------------------------------------------------- 1 | #include "CrackedSet.h" 2 | #define INFECTED_PER_MS 50 3 | #define UPPER_SERIES_BOUND 2000000 4 | 5 | #include "../timeconv.h" 6 | 7 | 8 | //virtual 9 | bool CrackedSet::processFile(std::string path, std::string ext, uint32_t writeTime) 10 | { 11 | if (params.fileEncryptionTime == 0) { 12 | params.fileEncryptionTime = writeTime; 13 | params.init(path, writeTime); 14 | } 15 | long dif = 0; 16 | if (this->lastDecryptedTimestamp != 0) { 17 | dif = abs(long(writeTime - lastDecryptedTimestamp)); 18 | } 19 | 20 | if (params.seed == 0 || writeTime < params.seed || dif > HOUR_LEN) { 21 | #ifdef DEBUG 22 | printf ("Setting seed to the file encryption time!\n"); 23 | #endif 24 | params.init(path, writeTime); 25 | params.seed = params.fileEncryptionTime; 26 | params.autosetMode(); 27 | } 28 | 29 | if (params.fileEncryptionTime == params.seed) { 30 | #ifdef DEBUG 31 | printf("Smart timestamp enabled!\n"); 32 | #endif 33 | params.series_min = INFECTED_PER_MS; //start from small series 34 | params.series_max = UPPER_SERIES_BOUND; 35 | } else { 36 | params.series_min = params.series_max; 37 | } 38 | 39 | params.filename = path; 40 | if (decrypt_file(fileTypes, params, path)) { 41 | printf("[SUCCESS]\n"); 42 | this->lastDecryptedTimestamp = writeTime; 43 | logToFile(path, writeTime); 44 | return true; 45 | } 46 | return false; 47 | } 48 | -------------------------------------------------------------------------------- /dma_unlocker/cracking_crawler/CrackedSet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../recon/FileSet.h" 4 | #include "../dma_crack.h" 5 | 6 | class CrackedSet : public FileSet 7 | { 8 | public: 9 | 10 | CrackedSet(FileTypesSet &fTypes, Params &p) 11 | : fileTypes(fTypes), params(p) { lastDecryptedTimestamp = 0; } 12 | 13 | virtual void init() 14 | { 15 | logFilename = "cracked_log.txt"; 16 | FILE *logFile = fopen(logFilename.c_str(), "w"); 17 | if (!logFile) { 18 | printf ("Open log file failed\n"); 19 | return; 20 | } 21 | fclose(logFile); 22 | } 23 | 24 | protected: 25 | virtual bool processFile(std::string path, std::string ext, uint32_t writeTime); 26 | void autoinitParams(std::string path, std::string ext, uint32_t writeTime); 27 | 28 | FileTypesSet &fileTypes; 29 | Params ¶ms; 30 | uint32_t lastDecryptedTimestamp; 31 | }; -------------------------------------------------------------------------------- /dma_unlocker/cracking_crawler/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../types.h" 2 | #include 3 | 4 | #include /* printf, scanf, puts, NULL */ 5 | #include 6 | #include 7 | 8 | #include "../Params.h" 9 | #include "../recon/PathCrawler.h" 10 | #include "../decryptor/decryptor.h" 11 | #include "../filetypes/FileTypes.h" 12 | 13 | #include "CrackedSet.h" 14 | #define MIN_ARG 2 15 | //---- 16 | 17 | int main (int argc, char *argv[]) 18 | { 19 | printf("---------------------------\n"); 20 | printf("DMA CRAWLER v0.2, by hasherezade\n"); 21 | printf("---------------------------\n"); 22 | 23 | printf("Params:\n \n optional:[start_time] [increment_mode] [series][file_mod_time]\n\n"); 24 | printf(" start_time (optional) : timestamp from which the search should start\n"); 25 | printf(" increment_mode (optional) : 1 - increment start_time ; 0 - decrement start_time\n"); 26 | printf(" series : how many keys to generate per single timestamp (max)\n"); 27 | printf(" file_mod_time (optional) : file modification timestamp (in case if the saved one is invalid)\n"); 28 | printf("---------------------------\n"); 29 | 30 | bool isIncrementalMode = false; 31 | int seed = 0; 32 | uint32_t mod_timestamp = 0; 33 | size_t max_series = 2000000; //TODO: calculate dynamically 34 | 35 | FileTypesSet fileTypes; 36 | if (fileTypes.listDir(HDRS_DIR) == 0) { 37 | printf("[ERROR] Cannot load supported extensions!\n"); 38 | } 39 | 40 | size_t arg_num = MIN_ARG; 41 | if (argc >= arg_num) { 42 | sscanf(argv[arg_num - 1],"%d", &seed); 43 | printf("SEED = %d = %#x\n", seed, seed); 44 | } 45 | arg_num++; 46 | 47 | if (argc >= arg_num) { 48 | int mode = 0; 49 | sscanf(argv[arg_num - 1],"%d", &mode); 50 | isIncrementalMode = (mode >= 1); 51 | printf("is INC MODE_ = %d\n", isIncrementalMode); 52 | } 53 | arg_num++; 54 | 55 | if (argc >= arg_num) { 56 | sscanf(argv[arg_num - 1],"%d", &max_series); 57 | printf("MAX_SERIES = %d\n", max_series); 58 | } 59 | 60 | arg_num++; 61 | if (argc >= arg_num) { 62 | sscanf(argv[arg_num - 1],"%d", &mod_timestamp); 63 | printf("overwriting FILEMODTIME = %d\n", mod_timestamp); 64 | } 65 | 66 | //max number of encrypted files per milisecons 67 | int infected_per_ms = 50; //todo: calculate this! 68 | int upper_search_bound = max_series; 69 | 70 | Params params; 71 | params.seed = seed; 72 | params.series_max = max_series; 73 | params.series_min = infected_per_ms; 74 | params.fileEncryptionTime = mod_timestamp; //if there is a need to overwrite 75 | params.incrementalMode = isIncrementalMode; 76 | 77 | CrackedSet fileSet(fileTypes, params); 78 | fileSet.init(); 79 | PathCrawler crawler; 80 | std::string start_path = PathCrawler::getLocalDir(); 81 | printf("Start path: %s\n", start_path.c_str()); 82 | crawler.listDir(start_path, &fileSet, true); 83 | printf("Summary:\n"); 84 | fileSet.printSummary(); 85 | printf("FINISHED!\n"); 86 | 87 | system("pause"); 88 | return 0; 89 | } -------------------------------------------------------------------------------- /dma_unlocker/decryptor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (DMA_decryptor) 3 | 4 | set (srcs 5 | main.cpp 6 | decryptor.cpp 7 | aes256.cpp 8 | ) 9 | 10 | set (hdrs 11 | decryptor.h 12 | aes256.h 13 | ../types.h 14 | ) 15 | 16 | add_executable (DMA_decryptor ${hdrs} ${srcs} ) 17 | -------------------------------------------------------------------------------- /dma_unlocker/decryptor/aes256.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Byte-oriented AES-256 implementation. 3 | * All lookup tables replaced with 'on the fly' calculations. 4 | * 5 | * Copyright (c) 2007-2011 Ilya O. Levin, http://www.literatecode.com 6 | * Other contributors: Hal Finney 7 | * 8 | * Permission to use, copy, modify, and distribute this software for any 9 | * purpose with or without fee is hereby granted, provided that the above 10 | * copyright notice and this permission notice appear in all copies. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 | */ 20 | #include "aes256.h" 21 | 22 | #define FD(x) (((x) >> 1) ^ (((x) & 1) ? 0x8d : 0)) 23 | 24 | #define BACK_TO_TABLES 25 | 26 | static uint8_t rj_xtime(uint8_t); 27 | static void aes_subBytes(uint8_t *); 28 | static void aes_subBytes_inv(uint8_t *); 29 | static void aes_addRoundKey(uint8_t *, uint8_t *); 30 | static void aes_addRoundKey_cpy(uint8_t *, uint8_t *, uint8_t *); 31 | static void aes_shiftRows(uint8_t *); 32 | static void aes_shiftRows_inv(uint8_t *); 33 | static void aes_mixColumns(uint8_t *); 34 | static void aes_mixColumns_inv(uint8_t *); 35 | static void aes_expandEncKey(uint8_t *, uint8_t *); 36 | static void aes_expandDecKey(uint8_t *, uint8_t *); 37 | #ifndef BACK_TO_TABLES 38 | static uint8_t gf_alog(uint8_t); 39 | static uint8_t gf_log(uint8_t); 40 | static uint8_t gf_mulinv(uint8_t); 41 | static uint8_t rj_sbox(uint8_t); 42 | static uint8_t rj_sbox_inv(uint8_t); 43 | #endif 44 | 45 | #ifdef BACK_TO_TABLES 46 | 47 | static const uint8_t sbox[256] = 48 | { 49 | 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 50 | 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 51 | 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 52 | 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 53 | 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 54 | 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 55 | 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 56 | 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 57 | 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 58 | 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 59 | 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 60 | 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 61 | 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 62 | 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 63 | 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 64 | 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 65 | 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 66 | 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 67 | 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 68 | 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 69 | 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 70 | 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 71 | 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 72 | 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 73 | 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 74 | 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 75 | 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 76 | 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 77 | 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 78 | 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 79 | 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 80 | 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 81 | }; 82 | static const uint8_t sboxinv[256] = 83 | { 84 | 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 85 | 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 86 | 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 87 | 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 88 | 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 89 | 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 90 | 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 91 | 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 92 | 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 93 | 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 94 | 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 95 | 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 96 | 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 97 | 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 98 | 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 99 | 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 100 | 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 101 | 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 102 | 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 103 | 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 104 | 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 105 | 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 106 | 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 107 | 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 108 | 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 109 | 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 110 | 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 111 | 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 112 | 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 113 | 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 114 | 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 115 | 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d 116 | }; 117 | 118 | #define rj_sbox(x) sbox[(x)] 119 | #define rj_sbox_inv(x) sboxinv[(x)] 120 | 121 | #else /* tableless subroutines */ 122 | 123 | /* -------------------------------------------------------------------------- */ 124 | static uint8_t gf_alog(uint8_t x) // calculate anti-logarithm gen 3 125 | { 126 | uint8_t y = 1, i; 127 | 128 | for (i = 0; i < x; i++) y ^= rj_xtime(y); 129 | 130 | return y; 131 | } /* gf_alog */ 132 | 133 | /* -------------------------------------------------------------------------- */ 134 | static uint8_t gf_log(uint8_t x) // calculate logarithm gen 3 135 | { 136 | uint8_t y, i = 0; 137 | 138 | if (x) 139 | for (i = 1, y = 1; i > 0; i++ ) 140 | { 141 | y ^= rj_xtime(y); 142 | if (y == x) break; 143 | } 144 | 145 | return i; 146 | } /* gf_log */ 147 | 148 | 149 | /* -------------------------------------------------------------------------- */ 150 | static uint8_t gf_mulinv(uint8_t x) // calculate multiplicative inverse 151 | { 152 | return (x) ? gf_alog(255 - gf_log(x)) : 0; 153 | } /* gf_mulinv */ 154 | 155 | /* -------------------------------------------------------------------------- */ 156 | static uint8_t rj_sbox(uint8_t x) 157 | { 158 | uint8_t y, sb; 159 | 160 | sb = y = gf_mulinv(x); 161 | y = (uint8_t)(y << 1) | (y >> 7), sb ^= y; 162 | y = (uint8_t)(y << 1) | (y >> 7), sb ^= y; 163 | y = (uint8_t)(y << 1) | (y >> 7), sb ^= y; 164 | y = (uint8_t)(y << 1) | (y >> 7), sb ^= y; 165 | 166 | return (sb ^ 0x63); 167 | } /* rj_sbox */ 168 | 169 | /* -------------------------------------------------------------------------- */ 170 | static uint8_t rj_sbox_inv(uint8_t x) 171 | { 172 | uint8_t y, sb; 173 | 174 | y = x ^ 0x63; 175 | sb = y = (uint8_t)(y << 1) | (y >> 7); 176 | y = (uint8_t)(y << 2) | (y >> 6); 177 | sb ^= y; 178 | y = (uint8_t)(y << 3) | (y >> 5); 179 | sb ^= y; 180 | 181 | return gf_mulinv(sb); 182 | } /* rj_sbox_inv */ 183 | 184 | #endif 185 | 186 | /* -------------------------------------------------------------------------- */ 187 | static uint8_t rj_xtime(uint8_t x) 188 | { 189 | uint8_t y = (uint8_t)(x << 1); 190 | return (x & 0x80) ? (y ^ 0x1b) : y; 191 | } /* rj_xtime */ 192 | 193 | /* -------------------------------------------------------------------------- */ 194 | static void aes_subBytes(uint8_t *buf) 195 | { 196 | register uint8_t i = 16; 197 | 198 | while (i--) buf[i] = rj_sbox(buf[i]); 199 | } /* aes_subBytes */ 200 | 201 | /* -------------------------------------------------------------------------- */ 202 | static void aes_subBytes_inv(uint8_t *buf) 203 | { 204 | register uint8_t i = 16; 205 | 206 | while (i--) buf[i] = rj_sbox_inv(buf[i]); 207 | } /* aes_subBytes_inv */ 208 | 209 | /* -------------------------------------------------------------------------- */ 210 | static void aes_addRoundKey(uint8_t *buf, uint8_t *key) 211 | { 212 | register uint8_t i = 16; 213 | 214 | while (i--) buf[i] ^= key[i]; 215 | } /* aes_addRoundKey */ 216 | 217 | /* -------------------------------------------------------------------------- */ 218 | static void aes_addRoundKey_cpy(uint8_t *buf, uint8_t *key, uint8_t *cpk) 219 | { 220 | register uint8_t i = 16; 221 | 222 | while (i--) buf[i] ^= (cpk[i] = key[i]), cpk[16 + i] = key[16 + i]; 223 | } /* aes_addRoundKey_cpy */ 224 | 225 | 226 | /* -------------------------------------------------------------------------- */ 227 | static void aes_shiftRows(uint8_t *buf) 228 | { 229 | register uint8_t i, j; /* to make it potentially parallelable :) */ 230 | 231 | i = buf[1], buf[1] = buf[5], buf[5] = buf[9], buf[9] = buf[13], buf[13] = i; 232 | i = buf[10], buf[10] = buf[2], buf[2] = i; 233 | j = buf[3], buf[3] = buf[15], buf[15] = buf[11], buf[11] = buf[7], buf[7] = j; 234 | j = buf[14], buf[14] = buf[6], buf[6] = j; 235 | 236 | } /* aes_shiftRows */ 237 | 238 | /* -------------------------------------------------------------------------- */ 239 | static void aes_shiftRows_inv(uint8_t *buf) 240 | { 241 | register uint8_t i, j; /* same as above :) */ 242 | 243 | i = buf[1], buf[1] = buf[13], buf[13] = buf[9], buf[9] = buf[5], buf[5] = i; 244 | i = buf[2], buf[2] = buf[10], buf[10] = i; 245 | j = buf[3], buf[3] = buf[7], buf[7] = buf[11], buf[11] = buf[15], buf[15] = j; 246 | j = buf[6], buf[6] = buf[14], buf[14] = j; 247 | 248 | } /* aes_shiftRows_inv */ 249 | 250 | /* -------------------------------------------------------------------------- */ 251 | static void aes_mixColumns(uint8_t *buf) 252 | { 253 | register uint8_t i, a, b, c, d, e; 254 | 255 | for (i = 0; i < 16; i += 4) 256 | { 257 | a = buf[i]; 258 | b = buf[i + 1]; 259 | c = buf[i + 2]; 260 | d = buf[i + 3]; 261 | e = a ^ b ^ c ^ d; 262 | buf[i] ^= e ^ rj_xtime(a ^ b); 263 | buf[i + 1] ^= e ^ rj_xtime(b ^ c); 264 | buf[i + 2] ^= e ^ rj_xtime(c ^ d); 265 | buf[i + 3] ^= e ^ rj_xtime(d ^ a); 266 | } 267 | } /* aes_mixColumns */ 268 | 269 | /* -------------------------------------------------------------------------- */ 270 | void aes_mixColumns_inv(uint8_t *buf) 271 | { 272 | register uint8_t i, a, b, c, d, e, x, y, z; 273 | 274 | for (i = 0; i < 16; i += 4) 275 | { 276 | a = buf[i]; 277 | b = buf[i + 1]; 278 | c = buf[i + 2]; 279 | d = buf[i + 3]; 280 | e = a ^ b ^ c ^ d; 281 | z = rj_xtime(e); 282 | x = e ^ rj_xtime(rj_xtime(z ^ a ^ c)); 283 | y = e ^ rj_xtime(rj_xtime(z ^ b ^ d)); 284 | buf[i] ^= x ^ rj_xtime(a ^ b); 285 | buf[i + 1] ^= y ^ rj_xtime(b ^ c); 286 | buf[i + 2] ^= x ^ rj_xtime(c ^ d); 287 | buf[i + 3] ^= y ^ rj_xtime(d ^ a); 288 | } 289 | } /* aes_mixColumns_inv */ 290 | 291 | /* -------------------------------------------------------------------------- */ 292 | static void aes_expandEncKey(uint8_t *k, uint8_t *rc) 293 | { 294 | register uint8_t i; 295 | 296 | k[0] ^= rj_sbox(k[29]) ^ (*rc); 297 | k[1] ^= rj_sbox(k[30]); 298 | k[2] ^= rj_sbox(k[31]); 299 | k[3] ^= rj_sbox(k[28]); 300 | *rc = rj_xtime( *rc); 301 | 302 | for(i = 4; i < 16; i += 4) k[i] ^= k[i - 4], k[i + 1] ^= k[i - 3], 303 | k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1]; 304 | k[16] ^= rj_sbox(k[12]); 305 | k[17] ^= rj_sbox(k[13]); 306 | k[18] ^= rj_sbox(k[14]); 307 | k[19] ^= rj_sbox(k[15]); 308 | 309 | for(i = 20; i < 32; i += 4) k[i] ^= k[i - 4], k[i + 1] ^= k[i - 3], 310 | k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1]; 311 | 312 | } /* aes_expandEncKey */ 313 | 314 | /* -------------------------------------------------------------------------- */ 315 | void aes_expandDecKey(uint8_t *k, uint8_t *rc) 316 | { 317 | uint8_t i; 318 | 319 | for(i = 28; i > 16; i -= 4) k[i + 0] ^= k[i - 4], k[i + 1] ^= k[i - 3], 320 | k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1]; 321 | 322 | k[16] ^= rj_sbox(k[12]); 323 | k[17] ^= rj_sbox(k[13]); 324 | k[18] ^= rj_sbox(k[14]); 325 | k[19] ^= rj_sbox(k[15]); 326 | 327 | for(i = 12; i > 0; i -= 4) k[i + 0] ^= k[i - 4], k[i + 1] ^= k[i - 3], 328 | k[i + 2] ^= k[i - 2], k[i + 3] ^= k[i - 1]; 329 | 330 | *rc = FD(*rc); 331 | k[0] ^= rj_sbox(k[29]) ^ (*rc); 332 | k[1] ^= rj_sbox(k[30]); 333 | k[2] ^= rj_sbox(k[31]); 334 | k[3] ^= rj_sbox(k[28]); 335 | } /* aes_expandDecKey */ 336 | 337 | 338 | /* -------------------------------------------------------------------------- */ 339 | void aes256_init(aes256_context *ctx, uint8_t *k) 340 | { 341 | uint8_t rcon = 1; 342 | register uint8_t i; 343 | 344 | for (i = 0; i < sizeof(ctx->key); i++) ctx->enckey[i] = ctx->deckey[i] = k[i]; 345 | for (i = 8; --i;) aes_expandEncKey(ctx->deckey, &rcon); 346 | } /* aes256_init */ 347 | 348 | /* -------------------------------------------------------------------------- */ 349 | void aes256_done(aes256_context *ctx) 350 | { 351 | register uint8_t i; 352 | 353 | for (i = 0; i < sizeof(ctx->key); i++) 354 | ctx->key[i] = ctx->enckey[i] = ctx->deckey[i] = 0; 355 | } /* aes256_done */ 356 | 357 | /* -------------------------------------------------------------------------- */ 358 | void aes256_encrypt_ecb(aes256_context *ctx, uint8_t *buf) 359 | { 360 | uint8_t i, rcon; 361 | 362 | aes_addRoundKey_cpy(buf, ctx->enckey, ctx->key); 363 | for(i = 1, rcon = 1; i < 14; ++i) 364 | { 365 | aes_subBytes(buf); 366 | aes_shiftRows(buf); 367 | aes_mixColumns(buf); 368 | if( i & 1 ) aes_addRoundKey( buf, &ctx->key[16]); 369 | else aes_expandEncKey(ctx->key, &rcon), aes_addRoundKey(buf, ctx->key); 370 | } 371 | aes_subBytes(buf); 372 | aes_shiftRows(buf); 373 | aes_expandEncKey(ctx->key, &rcon); 374 | aes_addRoundKey(buf, ctx->key); 375 | } /* aes256_encrypt */ 376 | 377 | /* -------------------------------------------------------------------------- */ 378 | void aes256_decrypt_ecb(aes256_context *ctx, uint8_t *buf) 379 | { 380 | uint8_t i, rcon; 381 | 382 | aes_addRoundKey_cpy(buf, ctx->deckey, ctx->key); 383 | aes_shiftRows_inv(buf); 384 | aes_subBytes_inv(buf); 385 | 386 | for (i = 14, rcon = 0x80; --i;) 387 | { 388 | if( ( i & 1 ) ) 389 | { 390 | aes_expandDecKey(ctx->key, &rcon); 391 | aes_addRoundKey(buf, &ctx->key[16]); 392 | } 393 | else aes_addRoundKey(buf, ctx->key); 394 | aes_mixColumns_inv(buf); 395 | aes_shiftRows_inv(buf); 396 | aes_subBytes_inv(buf); 397 | } 398 | aes_addRoundKey( buf, ctx->key); 399 | } /* aes256_decrypt */ 400 | -------------------------------------------------------------------------------- /dma_unlocker/decryptor/aes256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Byte-oriented AES-256 implementation. 3 | * All lookup tables replaced with 'on the fly' calculations. 4 | * 5 | * Copyright (c) 2007-2009 Ilya O. Levin, http://www.literatecode.com 6 | * Other contributors: Hal Finney 7 | * 8 | * Permission to use, copy, modify, and distribute this software for any 9 | * purpose with or without fee is hereby granted, provided that the above 10 | * copyright notice and this permission notice appear in all copies. 11 | * 12 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 | */ 20 | #pragma once 21 | 22 | #ifndef uint8_t 23 | #define uint8_t unsigned char 24 | #endif 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif 29 | 30 | typedef struct { 31 | uint8_t key[32]; 32 | uint8_t enckey[32]; 33 | uint8_t deckey[32]; 34 | } aes256_context; 35 | 36 | 37 | void aes256_init(aes256_context *, uint8_t * /* key */); 38 | void aes256_done(aes256_context *); 39 | void aes256_encrypt_ecb(aes256_context *, uint8_t * /* plaintext */); 40 | void aes256_decrypt_ecb(aes256_context *, uint8_t * /* cipertext */); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif 45 | -------------------------------------------------------------------------------- /dma_unlocker/decryptor/decryptor.cpp: -------------------------------------------------------------------------------- 1 | #include "decryptor.h" 2 | 3 | #define CHUNK_NUM 45 4 | #define MAX_ENCRYPTED 1000000000 5 | 6 | void DmaDecryptor::decryptChunk(unsigned char enc_buf[], unsigned char key[]) 7 | { 8 | aes256_context ctx; 9 | memset(&ctx, 0, sizeof(ctx)); 10 | 11 | aes256_init(&ctx, key); 12 | aes256_decrypt_ecb(&ctx, enc_buf); 13 | aes256_done(&ctx); 14 | } 15 | 16 | bool DmaDecryptor::_decrypt(unsigned char buf[], size_t bufSize, unsigned char key[]) 17 | { 18 | aes256_context ctx; 19 | memset(&ctx,0,sizeof(ctx)); 20 | aes256_init(&ctx, key); 21 | 22 | size_t iters = bufSize / UNIT_LEN; 23 | size_t i = 0; 24 | 25 | unsigned char* buf_ptr = this->buffer; 26 | 27 | for (i = 0 ; i < bufSize / UNIT_LEN ; i++) { 28 | aes256_decrypt_ecb(&ctx, buf_ptr); 29 | buf_ptr += UNIT_LEN; 30 | } 31 | size_t rem = (buffer + bufSize) - buf_ptr; 32 | 33 | aes256_done(&ctx); 34 | return true; 35 | } 36 | 37 | //------- 38 | 39 | bool DmaDecryptor::init() 40 | { 41 | FILE *pFile = fopen(this->filename.c_str(), "rb"); 42 | if (!pFile) return false; 43 | 44 | if (DmaDecryptor::isInfected(pFile) == false) { 45 | printf("It is not infected file!\n"); 46 | fclose(pFile); 47 | return false; 48 | } 49 | 50 | fseek(pFile, 0, SEEK_END); 51 | this->fileSize = ftell(pFile); 52 | fclose(pFile); 53 | 54 | if (this->fileSize <= OFFSET) { 55 | printf("Invalid File Size\n"); 56 | return false; 57 | } 58 | this->fileSize -= OFFSET; 59 | this->encryptedSize = (this->fileSize > MAX_ENCRYPTED) ? MAX_ENCRYPTED : this->fileSize; 60 | 61 | this->chunkSize = (this->encryptedSize / CHUNK_NUM); 62 | this->lastChunkSize = this->encryptedSize - (chunkSize * CHUNK_NUM); 63 | this->chunkNum = (chunkSize == 0) ? 0 : CHUNK_NUM; 64 | 65 | this->buffer = static_cast (calloc(this->chunkSize, 1)); 66 | 67 | memcpy(aesKey,this->key.c_str(), KEY_LEN); 68 | aesKey[KEY_LEN] ='\0'; 69 | 70 | return true; 71 | } 72 | 73 | bool DmaDecryptor::isInfected(FILE *fp) 74 | { 75 | char buf[10]; 76 | fread(buf, 1, 8, fp); 77 | 78 | if (memcmp(buf, "!DMALOCK", 8) == 0) { 79 | return true; 80 | } 81 | return false; 82 | } 83 | 84 | std::string DmaDecryptor::makeOutName(const char *inFile) 85 | { 86 | std::string ext = ""; 87 | char *pos = strrchr(const_cast(inFile), '.'); 88 | if (pos) { 89 | ext = pos; 90 | *(pos) = 0; 91 | } 92 | return std::string(inFile) + "_decrypted" + ext; 93 | } 94 | 95 | bool DmaDecryptor::decrypt(std::string outFilename) 96 | { 97 | FILE *inFile = fopen(this->filename.c_str(), "rb"); 98 | if (!inFile) { 99 | printf("Cannot open IN file: %s\n", filename.c_str()); 100 | return false; 101 | } 102 | 103 | fseek(inFile, OFFSET, SEEK_SET); 104 | 105 | FILE *outFile = fopen(outFilename.c_str(), "wb"); 106 | if (!outFile) { 107 | printf("Cannot open OUT file\n"); 108 | fclose(inFile); 109 | return false; 110 | } 111 | 112 | for (size_t i = 0; i < chunkNum; i++) { 113 | 114 | if (fread(this->buffer, 1, this->chunkSize, inFile) == 0) { 115 | return false; 116 | } 117 | if (_decrypt(this->buffer, this->chunkSize, this->aesKey) == false) { 118 | return false; 119 | } 120 | fwrite(this->buffer, 1, this->chunkSize, outFile); 121 | fflush(outFile); 122 | } 123 | 124 | if (this->lastChunkSize > 0) { 125 | if (fread(this->buffer, 1, this->lastChunkSize, inFile) == 0) { 126 | return false; 127 | } 128 | if (_decrypt(this->buffer, this->lastChunkSize, this->aesKey) == false) { 129 | return false; 130 | } 131 | fwrite(this->buffer, 1, this->lastChunkSize, outFile); 132 | fflush(outFile); 133 | } 134 | //copy the remaining, unencrypted content: 135 | int dif = this->fileSize - this->encryptedSize; 136 | while (dif > 0) { 137 | size_t count = fread(this->buffer, 1, this->chunkSize, inFile); 138 | if (count == 0) break; 139 | fwrite(this->buffer, 1, count, outFile); 140 | fflush(outFile); 141 | dif -= count; 142 | } 143 | 144 | fclose(inFile); 145 | fclose(outFile); 146 | 147 | printf("Saved to file: %s\n", outFilename.c_str()); 148 | return true; 149 | } 150 | -------------------------------------------------------------------------------- /dma_unlocker/decryptor/decryptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include /* printf, scanf, puts, NULL */ 4 | #include 5 | #include 6 | #include 7 | 8 | #include "aes256.h" 9 | 10 | class DmaDecryptor { 11 | 12 | public: 13 | static const size_t OFFSET = 0x88; 14 | static const size_t KEY_LEN = 32; 15 | static const size_t UNIT_LEN = 16; 16 | 17 | static bool isInfected(FILE *f); 18 | static std::string makeOutName(const char *inFile); 19 | 20 | static void decryptChunk(unsigned char enc_buf[], unsigned char key[]); 21 | 22 | //--- 23 | DmaDecryptor(std::string filename, std::string key) 24 | { 25 | this->filename = filename; 26 | this->key = key; 27 | 28 | this->encryptedSize = this->fileSize = 0; 29 | this->buffer = NULL; 30 | this->chunkNum = 0; 31 | this->lastChunkSize = 0; 32 | } 33 | 34 | ~DmaDecryptor() 35 | { 36 | if (buffer) free(buffer); 37 | } 38 | 39 | bool init(); 40 | bool decrypt(std::string outFilename); 41 | 42 | protected: 43 | bool _decrypt(unsigned char buf[], size_t bufSize, unsigned char key[]); 44 | 45 | size_t chunkSize; 46 | size_t chunkNum; 47 | size_t lastChunkSize; 48 | 49 | size_t encryptedSize, fileSize; 50 | std::string filename; 51 | std::string key; 52 | 53 | aes256_context ctx; 54 | 55 | unsigned char aesKey[KEY_LEN + 1]; 56 | unsigned char *buffer; 57 | }; -------------------------------------------------------------------------------- /dma_unlocker/decryptor/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include /* printf, scanf, puts, NULL */ 4 | #include 5 | #include 6 | 7 | #include "decryptor.h" 8 | //---- 9 | 10 | bool decryptChunk(unsigned char *key, unsigned char *enc_buf) 11 | { 12 | size_t chunk_len = 16; 13 | size_t key_len = 32; 14 | aes256_context ctx; 15 | memset(&ctx,0,sizeof(ctx)); 16 | 17 | aes256_init(&ctx, key); 18 | aes256_decrypt_ecb(&ctx, enc_buf); 19 | aes256_done(&ctx); 20 | 21 | return false; 22 | } 23 | 24 | bool read_header(char *filename, unsigned char buf[], size_t offset) 25 | { 26 | FILE *fp = fopen(filename,"rb"); 27 | if (!fp) { 28 | printf("Cannot open"); 29 | return false; 30 | } 31 | fseek(fp, offset, SEEK_SET); 32 | fread(buf, 1, 16, fp); 33 | fclose(fp); 34 | 35 | printf("File:\t%s\n", filename); 36 | 37 | return true; 38 | } 39 | 40 | #define DAY_LEN 86400 41 | 42 | int main (int argc, char *argv[]) 43 | { 44 | printf("---------------------------\n"); 45 | printf("DMA cracker v0.1\n"); 46 | printf("---------------------------\n"); 47 | if (argc < 3) { 48 | printf ("Expected: \n"); 49 | system("pause"); 50 | return -1; 51 | } 52 | printf("%s\n", argv[1]); 53 | printf("%s\n", argv[2]); 54 | DmaDecryptor decr(argv[1], argv[2]); 55 | printf ("Init...\n"); 56 | if (decr.init() == false) { 57 | printf ("Init failed\n"); 58 | system("pause"); 59 | return -1; 60 | } 61 | 62 | std::string ext = ""; 63 | char *pos = strrchr(argv[1], '.'); 64 | if (pos) { 65 | ext = pos; 66 | *(pos) = 0; 67 | } 68 | 69 | std::string outName = std::string(argv[1]) + "_dec" + ext; 70 | printf ("Decrypting...\n"); 71 | if (decr.decrypt(outName) == false) { 72 | printf ("Init failed\n"); 73 | system("pause"); 74 | return -1; 75 | } 76 | printf ("Decrypted\n"); 77 | printf ("ok!\n"); 78 | system("pause"); 79 | return 0; 80 | } -------------------------------------------------------------------------------- /dma_unlocker/dma_crack.cpp: -------------------------------------------------------------------------------- 1 | #include "dma_crack.h" 2 | #include "keygen/keygen.h" 3 | #include "decryptor/aes256.h" 4 | #include "decryptor/decryptor.h" 5 | #include "util.h" 6 | #include "filetypes/TypeValidator.h" 7 | 8 | //#define DEBUG 0 9 | 10 | void log_key(uint32_t seed, char *key, int key_num, std::string filename) 11 | { 12 | FILE* f_out = fopen("key_out.txt", "a"); 13 | if (!f_out) return; 14 | fprintf (f_out, "File: %s\n", filename.c_str()); 15 | fprintf (f_out, "KEY: %s\n", key); 16 | fprintf (f_out, "INIT %x = %d (num: %d)\n", seed, seed, key_num); 17 | fprintf (f_out, "---\n"); 18 | fflush(f_out); 19 | fclose(f_out); 20 | } 21 | 22 | std::string search_key(Params ¶ms, 23 | TypeValidator *validator, 24 | size_t series_min, 25 | size_t series_max 26 | ) 27 | { 28 | if (validator == NULL) { 29 | printf("Validator not found!\n"); 30 | return ""; 31 | } 32 | 33 | size_t days = 0; 34 | int day_start = params.seed; 35 | int deadline = 2; //2 days max 36 | //--- 37 | int seed = params.seed; 38 | char key[0x100]; 39 | 40 | printf("Searching key started...\n"); 41 | #ifdef DEBUG 42 | printf("Start seed: %d = %#x\n----------\n", seed, seed); 43 | print_time_str(seed); 44 | #endif 45 | 46 | if (series_min != series_max) { 47 | #ifdef DEBUG 48 | printf("Smart search mode: ON!\nWarning: it works only if the file have a valid modification timestamp!\n"); 49 | printf("Series min = %d , max = %d\n----------\n", series_min, series_max); 50 | #endif 51 | } else { 52 | #ifdef DEBUG 53 | printf("Smart search mode: OFF!\n"); 54 | printf("Series min = %d , max = %d\n----------\n", series_min, series_max); 55 | #endif 56 | } 57 | size_t series = series_min; 58 | 59 | while (deadline > 0) { 60 | srand (seed); 61 | for (size_t key_num = 0; key_num < series; key_num++) { 62 | make_random_key(key, sizeof(key)); 63 | if (validator->testKey(key)) { 64 | if (validator->getAccuracy() >= PIVOT_MIN) { 65 | #ifdef DEBUG 66 | printf("Adjusting seed to to found one!\n"); 67 | #endif 68 | params.seed = seed; 69 | params.key_num = key_num; 70 | } 71 | printf(">> KEY FOUND: %s\n", key); 72 | printf("[SUCCESS]\n"); 73 | #ifdef DEBUG 74 | printf ("KEY: %s\nSEED %x = %d\nkey number in series: %d\n", key, seed, seed, key_num); 75 | #endif 76 | log_key(seed, key, key_num, params.filename); 77 | return key; 78 | } 79 | } 80 | if (params.incrementalMode) { 81 | seed++; 82 | } else { 83 | seed--; 84 | if (series < series_max) { 85 | //max number of encrypted files per milisecons 86 | series += series_min; 87 | } 88 | } 89 | if (abs(day_start - seed) > DAY_LEN) { 90 | day_start = seed; 91 | days++; 92 | deadline--; 93 | printf("%d day passed!\n", days); 94 | } 95 | } 96 | return ""; 97 | } 98 | 99 | std::string search_key_in_series(uint32_t seed, TypeValidator *validator, unsigned char *enc_buf) 100 | { 101 | if (validator == NULL) { 102 | printf("Validator not found!\n"); 103 | return ""; 104 | } 105 | //single series without incrementing seed 106 | char key[0x100]; 107 | 108 | printf("Searching key started...\n"); 109 | #ifdef DEBUG 110 | printf("Start seed: %d = %#x\n----------\n", seed, seed); 111 | print_time_str(seed); 112 | #endif 113 | srand (seed); 114 | 115 | for (size_t key_num = 0; key_num < 10000000; key_num++) { 116 | make_random_key(key, sizeof(key)); 117 | 118 | if (validator->testKey(key)) { 119 | printf("> KEY FOUND: %s\n", key); 120 | printf("[SUCCESS]\n"); 121 | #ifdef DEBUG 122 | printf ("KEY: %s\nSEED %x = %d\nkey number in series: %d\n", key, seed, seed, key_num); 123 | #endif 124 | //log_key(seed, key, key_num, params.filename); 125 | return key; 126 | } 127 | } 128 | return ""; 129 | } 130 | 131 | TypeValidator* makeValidator(FileType *my_type) 132 | { 133 | if (my_type == NULL) return NULL; 134 | 135 | if (my_type->group == T_GROUP::HEADER) { 136 | #ifdef DEBUG 137 | printf("Making Header validator\n"); 138 | #endif 139 | return new HeaderValidator(); 140 | } 141 | 142 | if (my_type->group == T_GROUP::MULTI) { 143 | #ifdef DEBUG 144 | printf("Making MULTI validator\n"); 145 | #endif 146 | return new MultiValidator(); 147 | } 148 | 149 | if (my_type->extension == ".bmp") { 150 | #ifdef DEBUG 151 | printf ("BMP: Special validator required!\n"); 152 | #endif 153 | return new BMPValidator(); 154 | } 155 | return NULL; 156 | } 157 | 158 | bool decrypt_file(FileTypesSet &fileTypes, Params ¶ms, std::string enc_filename) 159 | { 160 | //get extension: 161 | std::string extension = get_extension(enc_filename); 162 | FileType *my_type = fileTypes.getType(extension); 163 | 164 | if (my_type == NULL) { 165 | printf("[ERROR] Not supported file type! Add a header for %s into '%s' folder!\n", extension.c_str(), HDRS_DIR); 166 | return false; 167 | } 168 | TypeValidator *validator = makeValidator(my_type); 169 | if (validator == NULL) { 170 | printf("[ERROR] Not suppeoted File Type: %s\n", extension.c_str()); 171 | return false; 172 | } 173 | validator->init(enc_filename, my_type); 174 | 175 | printf("Extension: %s\n", extension.c_str()); 176 | //crack it! 177 | bool isDecrypted = false; 178 | std::string key = search_key(params, validator, params.series_min, params.series_max); 179 | if (key.length() == DmaDecryptor::KEY_LEN ) { 180 | DmaDecryptor decr(enc_filename, key); 181 | decr.init(); 182 | isDecrypted = decr.decrypt(DmaDecryptor::makeOutName(enc_filename.c_str())); 183 | } 184 | delete validator; 185 | return isDecrypted; 186 | } 187 | 188 | bool decrypt_file(FileTypesSet &fileTypes, Params ¶ms, std::string enc_filename, std::string &key) 189 | { 190 | //get extension: 191 | std::string extension = get_extension(enc_filename); 192 | FileType *my_type = fileTypes.getType(extension); 193 | if (my_type == NULL) { 194 | printf("[ERROR] Not supported file type! Add a header for %s into '%s' folder!\n", extension.c_str(), HDRS_DIR); 195 | return false; 196 | } 197 | TypeValidator *validator = makeValidator(my_type); 198 | if (validator == NULL) { 199 | printf("[ERROR] Not suppeoted File Type\n"); 200 | return false; 201 | } 202 | validator->init(enc_filename, my_type); 203 | 204 | //crack it! 205 | bool isDecrypted = false; 206 | if (validator->testKey(key)) { 207 | DmaDecryptor decr(enc_filename, key); 208 | decr.init(); 209 | isDecrypted = decr.decrypt(DmaDecryptor::makeOutName(enc_filename.c_str())); 210 | } 211 | return isDecrypted; 212 | } 213 | -------------------------------------------------------------------------------- /dma_unlocker/dma_crack.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include /* printf, scanf, puts, NULL */ 4 | #include 5 | #include "filetypes/FileTypes.h" 6 | #include "filetypes/TypeValidator.h" 7 | #include "Params.h" 8 | 9 | std::string search_key(Params ¶ms, 10 | TypeValidator *validator, 11 | size_t series_min, 12 | size_t series_max 13 | ); 14 | 15 | std::string search_key_in_series(uint32_t seed, 16 | TypeValidator *validator, 17 | unsigned char *enc_buf 18 | ); 19 | 20 | 21 | std::string get_extension(std::string filename); 22 | bool read_header(std::string filename, unsigned char buf[], size_t offset); 23 | 24 | bool decrypt_file(FileTypesSet &fileTypes, Params ¶ms, 25 | std::string enc_filename); 26 | 27 | bool decrypt_file(FileTypesSet &fileTypes, Params ¶ms, 28 | std::string enc_filename, std::string &key); -------------------------------------------------------------------------------- /dma_unlocker/filetypes/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (DMA_filetypes) 3 | 4 | set (srcs 5 | main.cpp 6 | FileTypes.cpp 7 | ) 8 | 9 | set (hdrs 10 | FileTypes.h 11 | ../types.h 12 | ) 13 | 14 | add_executable (DMA_filetypes ${hdrs} ${srcs} ) 15 | -------------------------------------------------------------------------------- /dma_unlocker/filetypes/FileTypes.cpp: -------------------------------------------------------------------------------- 1 | #include "FileTypes.h" 2 | #include 3 | #include "../util.h" 4 | 5 | bool FileType::parseName(std::string fname) 6 | { 7 | char *filename = const_cast(fname.c_str()); 8 | char* ext = strrchr(filename, '.'); 9 | if (ext == NULL) return false; 10 | 11 | char* separator = strrchr(filename, '//'); 12 | if (separator == NULL) return false; 13 | 14 | separator++; 15 | sscanf(separator, "%d", &accuracy); 16 | 17 | char* separator2 = strrchr(filename, '_'); 18 | if (separator2 != NULL) { 19 | separator2++; 20 | sscanf(separator2, "%d", &offset); 21 | } 22 | if (accuracy < MIN_ACCURACY) { 23 | printf("[ERROR] Cannot register filetype %s! Minimal accuracy for match is %d\n", ext, MIN_ACCURACY); 24 | return false; 25 | } 26 | init_params(offset, accuracy); 27 | return true; 28 | } 29 | 30 | bool FileType::readHeader(std::string fname, size_t offset) 31 | { 32 | char *filename = const_cast(fname.c_str()); 33 | FILE *fp = fopen(filename,"rb"); 34 | if (fp == NULL) { 35 | printf("Cannot open: %s\n", filename); 36 | return false; 37 | } 38 | memset(this->buffer, 0, sizeof(buffer)); 39 | fseek(fp, offset, SEEK_SET); 40 | fread(this->buffer, 1, FileType::CHUNK_SIZE, fp); 41 | fclose(fp); 42 | buffer[FileType::CHUNK_SIZE] = '\0'; 43 | return true; 44 | } 45 | 46 | FileType* FileTypesSet::getType(std::string ext) 47 | { 48 | std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); 49 | 50 | std::map::iterator found = types.find(ext); 51 | if (found == types.end()) return NULL; 52 | return found->second; 53 | } 54 | 55 | size_t FileTypesSet::listDir(std::string path) 56 | { 57 | const std::string fileName = path + "\\*.*"; 58 | WIN32_FIND_DATA foundFileData; 59 | HANDLE hFind = FindFirstFile(fileName.c_str(), &foundFileData); 60 | if (hFind == INVALID_HANDLE_VALUE) { 61 | printf("No such dir: %s\n", path.c_str()); 62 | return 0; 63 | } 64 | 65 | while (FindNextFile(hFind, &foundFileData)) { 66 | if (foundFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) { 67 | if (strcmp(foundFileData.cFileName, ".") == 0) continue; 68 | if (strcmp(foundFileData.cFileName, "..") == 0) continue; 69 | 70 | std::string ext = get_extension(foundFileData.cFileName); 71 | if (ext == "") continue; // skip 72 | 73 | std::string fullPath = path + "//" + foundFileData.cFileName; 74 | 75 | MultiFileType *multiType = new MultiFileType(); 76 | if (multiType->init(fullPath, ext) == false) { 77 | delete multiType; 78 | continue; 79 | } 80 | this->types[ext] = multiType; 81 | continue; 82 | } 83 | 84 | std::string ext = get_extension(foundFileData.cFileName); 85 | if (ext == "") { 86 | printf("skipping file without extension!\n"); 87 | continue; //skipping file 88 | } 89 | 90 | std::string full_path = path + "//" + foundFileData.cFileName; 91 | FileType* type = NULL; 92 | 93 | if (strstr(foundFileData.cFileName, SPECIAL_TITLE)) { 94 | printf("Special type: %s\n", ext.c_str()); 95 | type = new SpecialFileType(); 96 | } else { 97 | //normal, header type 98 | type = new FileType(); 99 | } 100 | 101 | if (type->init(full_path, ext) == false) { 102 | delete type; 103 | type = NULL; 104 | continue; 105 | } 106 | this->types[ext] = type; 107 | } 108 | FindClose(hFind); 109 | return types.size(); 110 | } 111 | 112 | size_t MultiFileType::listDir(std::string path, std::string dir_extension) 113 | { 114 | const std::string fileName = path + "\\*.*"; 115 | WIN32_FIND_DATA foundFileData; 116 | 117 | HANDLE hFind = FindFirstFile(fileName.c_str(), &foundFileData); 118 | if (hFind == INVALID_HANDLE_VALUE) { 119 | printf("No such dir: %s\n", path.c_str()); 120 | return 0; 121 | } 122 | 123 | FileType* type = NULL; 124 | 125 | while (FindNextFile(hFind, &foundFileData)) { 126 | if (foundFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) { 127 | continue; //skip nested dir 128 | } 129 | std::string ext = get_extension(foundFileData.cFileName); 130 | if (ext != dir_extension) { 131 | printf("Wrong extension: %s dir: %s\n", ext.c_str(), dir_extension.c_str()); 132 | continue; 133 | } 134 | 135 | std::string fullPath = path + "//" + foundFileData.cFileName; 136 | FileType* type = new FileType(); 137 | #ifdef DEBUG 138 | printf("Adding to MULTI: %s\n", foundFileData.cFileName); 139 | #endif 140 | if (type->init(fullPath, ext, this->offset, this->accuracy) == false) { 141 | delete type; 142 | type = NULL; 143 | continue; 144 | } 145 | this->defs.insert(type); 146 | } 147 | 148 | FindClose(hFind); 149 | return defs.size(); 150 | } 151 | -------------------------------------------------------------------------------- /dma_unlocker/filetypes/FileTypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../types.h" 4 | 5 | #include /* printf, scanf, puts, NULL */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define HDRS_DIR "headers" 14 | #define SPECIAL_TITLE "special" 15 | 16 | #define MIN_ACCURACY 4 17 | #define PIVOT_MIN 5 18 | 19 | enum type_group { 20 | HEADER = 0, 21 | MULTI = 1, 22 | SPECIAL 23 | }; 24 | typedef type_group T_GROUP; 25 | 26 | class FileType { 27 | public: 28 | FileType() 29 | { 30 | this->offset = this->r_offset = this->m_offset = 0; 31 | this->accuracy = this->c_accuracy = CHUNK_SIZE; 32 | this->group = HEADER; 33 | } 34 | 35 | virtual bool init(std::string filename, std::string extension) 36 | { 37 | if (parseName(filename) == false) return false; 38 | setExtension(extension); 39 | 40 | if (readHeader(filename, offset) == false) return false; 41 | return true; 42 | } 43 | 44 | virtual bool init(std::string filename, std::string extension, size_t offset, size_t accuracy) 45 | { 46 | setExtension(extension); 47 | init_params(offset, accuracy); 48 | 49 | if (readHeader(filename, offset) == false) return false; 50 | return true; 51 | } 52 | 53 | void setExtension(std::string extension) 54 | { 55 | std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower); 56 | this->extension = extension; 57 | } 58 | 59 | static const size_t CHUNK_SIZE = 16; 60 | unsigned char buffer[CHUNK_SIZE + 1]; 61 | 62 | std::string extension; 63 | T_GROUP group; 64 | 65 | size_t getReadOffset() { return r_offset; } 66 | size_t getMatchOffset() { return m_offset; } 67 | size_t getAccuracy() { return c_accuracy; } 68 | 69 | //calculated 70 | size_t r_offset; //read offset - offset of chunk including header 71 | size_t m_offset; //match offset - where the matching should start 72 | size_t c_accuracy; //how long should match 73 | 74 | //raw: 75 | size_t offset; //where the header starts 76 | size_t accuracy; //how long should match 77 | 78 | protected: 79 | 80 | void init_params(size_t offset, size_t accuracy) 81 | { 82 | this->offset = offset; 83 | this->accuracy = accuracy; 84 | 85 | r_offset = offset / FileType::CHUNK_SIZE; 86 | m_offset = offset - r_offset; 87 | 88 | size_t dif = FileType::CHUNK_SIZE - m_offset; 89 | c_accuracy = accuracy > dif ? dif : accuracy; 90 | #ifdef DEBUG 91 | if (offset != 0) { 92 | printf("Raw offset: %d\n", offset); 93 | printf("Chunk read offset: %d\n", r_offset); 94 | printf("Chunk match offset: %d\n", m_offset); 95 | printf("Check accuracy: %d\n", c_accuracy); 96 | } 97 | #endif 98 | } 99 | 100 | virtual bool parseName(std::string filename); 101 | virtual bool readHeader(std::string filename, size_t offset); 102 | }; 103 | 104 | class FileTypesSet 105 | { 106 | public: 107 | //destroy all FileType objects 108 | ~FileTypesSet() { deleteTypes(); } 109 | 110 | size_t listDir(std::string dirName); 111 | 112 | void deleteTypes() 113 | { 114 | if (types.size() == 0) return; 115 | std::map::iterator itr; 116 | for (itr = types.begin(); itr != types.end(); itr++) { 117 | FileType *type = itr->second; 118 | delete type; 119 | } 120 | types.clear(); 121 | } 122 | 123 | FileType* getType(std::string extension); 124 | size_t countTypes() { return types.size(); } 125 | 126 | protected: 127 | std::map types; 128 | }; 129 | 130 | class SpecialFileType : public FileType 131 | { 132 | public: 133 | SpecialFileType() 134 | { 135 | this->offset = this->r_offset = this->m_offset = 0; 136 | this->accuracy = 1; 137 | this->group = SPECIAL; 138 | } 139 | 140 | virtual bool init(std::string filename, std::string extension) 141 | { 142 | setExtension(extension); 143 | //init_params(); 144 | return true; 145 | } 146 | }; 147 | 148 | 149 | //type with multiple alternative headers: 150 | class MultiFileType : public FileType 151 | { 152 | public: 153 | 154 | MultiFileType() 155 | { 156 | this->offset = this->r_offset = this->m_offset = 0; 157 | this->accuracy = 1; 158 | this->group = MULTI; 159 | } 160 | ~MultiFileType() { deleteTypes(); } 161 | 162 | virtual bool init(std::string dirName, std::string extension) 163 | { 164 | setExtension(extension); 165 | parseName(dirName); 166 | if (listDir(dirName, extension) == 0) return false; 167 | return true; 168 | } 169 | 170 | size_t listDir(std::string dirName, std::string extension); 171 | 172 | void deleteTypes() 173 | { 174 | if (defs.size() == 0) return; 175 | std::set::iterator itr; 176 | for (itr = defs.begin(); itr != defs.end(); itr++) { 177 | FileType *type = *itr; 178 | delete type; 179 | } 180 | defs.clear(); 181 | } 182 | 183 | std::set defs; 184 | }; -------------------------------------------------------------------------------- /dma_unlocker/filetypes/TypeValidator.cpp: -------------------------------------------------------------------------------- 1 | #include "TypeValidator.h" 2 | 3 | 4 | bool TypeValidator::read_header(std::string filename, unsigned char buf[], size_t offset) 5 | { 6 | FILE *fp = fopen(filename.c_str(),"rb"); 7 | if (!fp) { 8 | printf("Cannot open"); 9 | return false; 10 | } 11 | fseek(fp, offset, SEEK_SET); 12 | fread(buf, 1, DmaDecryptor::UNIT_LEN, fp); 13 | fclose(fp); 14 | #ifdef DEBUG 15 | printf("File:\t%s\n", filename); 16 | #endif 17 | return true; 18 | } 19 | 20 | size_t TypeValidator::get_original_file_size(std::string filename, size_t offset) 21 | { 22 | FILE *fp = fopen(filename.c_str(),"rb"); 23 | if (!fp) { 24 | printf("Cannot open"); 25 | return 0; 26 | } 27 | fseek(fp, 0, SEEK_END); 28 | size_t size = ftell(fp); 29 | fclose(fp); 30 | if (size < offset) return 0; 31 | return size - offset; 32 | } 33 | //--- 34 | bool TypeValidator::init(std::string enc_filename, FileType* my_type) 35 | { 36 | if (my_type == NULL) return false; 37 | this->my_type = my_type; 38 | 39 | memset(enc_buf, 0, sizeof(enc_buf)); 40 | //read header: 41 | 42 | size_t read_offset = my_type->offset / FileType::CHUNK_SIZE; 43 | const size_t total_offset = DmaDecryptor::OFFSET + read_offset; 44 | 45 | if (read_header(enc_filename, enc_buf, total_offset) == false) { 46 | printf("Opening encrypted file failed!\n"); 47 | return false; 48 | } 49 | enc_buf[DmaDecryptor::UNIT_LEN] = '\0'; 50 | isInit = true; 51 | return true; 52 | } 53 | 54 | bool TypeValidator::testKey(std::string key) 55 | { 56 | if (!isInit) return false; 57 | if (key == "" || enc_buf == NULL || my_type == NULL) { 58 | printf("[ERROR] NULL buffer supplied to test_key!!!\n"); 59 | return false; 60 | } 61 | 62 | unsigned char aesKey[DmaDecryptor::KEY_LEN + 1]; 63 | memcpy(aesKey, key.c_str(), DmaDecryptor::KEY_LEN); 64 | aesKey[DmaDecryptor::KEY_LEN] ='\0'; 65 | 66 | memcpy(buf, enc_buf, DmaDecryptor::UNIT_LEN); 67 | DmaDecryptor::decryptChunk(buf, aesKey); 68 | return isDecodedValid(buf); 69 | } 70 | 71 | ///----- 72 | 73 | bool HeaderValidator::isDecodedValid(unsigned char *enc_buf) 74 | { 75 | return isDecodedValid(enc_buf, this->my_type); 76 | } 77 | 78 | bool HeaderValidator::isDecodedValid(unsigned char *enc_buf, FileType *my_type) 79 | { 80 | if (enc_buf == NULL) { 81 | printf("[ERROR] NULL buffer supplied to test_key!!!\n"); 82 | return false; 83 | } 84 | size_t accuracy = my_type->getAccuracy(); 85 | size_t match_offset = my_type->getMatchOffset(); 86 | if (accuracy == 0 || accuracy > FileType::CHUNK_SIZE) { 87 | accuracy = FileType::CHUNK_SIZE; 88 | } 89 | if (memcmp(enc_buf + match_offset, my_type->buffer, accuracy) == 0) { 90 | return true; 91 | } 92 | return false; 93 | } 94 | 95 | //---- 96 | bool BMPValidator::init(std::string enc_filename, FileType* my_type) 97 | { 98 | if (!TypeValidator::init(enc_filename, my_type)) return false; 99 | this->original_size = get_original_file_size(enc_filename, DmaDecryptor::OFFSET); 100 | printf("\nBMP: original file size: %x = %d\n", original_size, original_size); 101 | return true; 102 | } 103 | 104 | bool BMPValidator::isDecodedValid(unsigned char *enc_buf) 105 | { 106 | if (enc_buf == NULL) { 107 | printf("[ERROR] NULL buffer supplied to test_key!!!\n"); 108 | return false; 109 | } 110 | size_t size_offset = 2; 111 | if (memcmp(enc_buf, "BM", size_offset) != 0) { 112 | return false; 113 | } 114 | uint32_t size; 115 | memcpy(&size, enc_buf + size_offset, sizeof(uint32_t)); 116 | if (size == this->original_size) return true; 117 | 118 | return false; 119 | } 120 | 121 | bool MultiValidator::isDecodedValid(unsigned char *enc_buf) 122 | { 123 | if (my_type == NULL) { 124 | printf("Wrong type definition!\n"); 125 | return false; 126 | } 127 | std::set::iterator itr; 128 | for (itr = my_type->defs.begin(); itr != my_type->defs.end(); itr++) { 129 | FileType* def = *itr; 130 | 131 | if (HeaderValidator::isDecodedValid(enc_buf, def)) return true; 132 | } 133 | return false; 134 | } -------------------------------------------------------------------------------- /dma_unlocker/filetypes/TypeValidator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../types.h" 4 | #include "../util.h" 5 | 6 | #include /* printf, scanf, puts, NULL */ 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "FileTypes.h" 14 | #include "../decryptor/decryptor.h" 15 | 16 | class TypeValidator 17 | { 18 | public: 19 | 20 | static bool read_header(std::string filename, unsigned char buf[], size_t offset); 21 | static size_t get_original_file_size(std::string filename, size_t offset); 22 | //------------------ 23 | TypeValidator() 24 | { 25 | isInit = false; 26 | my_type = NULL; 27 | } 28 | 29 | virtual size_t getAccuracy() 30 | { 31 | if (my_type == NULL) return 0; 32 | return my_type->getAccuracy(); 33 | } 34 | 35 | virtual bool init(std::string enc_filename, FileType* my_type); 36 | virtual bool testKey(std::string key); 37 | 38 | protected: 39 | virtual bool isDecodedValid(unsigned char *buf) = 0; 40 | //------ 41 | FileType *my_type; 42 | //base, copied from the file: 43 | unsigned char enc_buf[DmaDecryptor::UNIT_LEN + 1]; 44 | 45 | //verification buffer 46 | unsigned char buf[DmaDecryptor::UNIT_LEN + 1]; 47 | 48 | bool isInit; 49 | }; 50 | 51 | class HeaderValidator : public TypeValidator 52 | { 53 | public: 54 | static bool isDecodedValid(unsigned char *buf, FileType *my_type); 55 | protected: 56 | virtual bool isDecodedValid(unsigned char *buf); 57 | 58 | }; 59 | 60 | class BMPValidator : public TypeValidator 61 | { 62 | public: 63 | virtual bool init(std::string enc_filename, FileType* my_type); 64 | virtual size_t getAccuracy() { return 6; } // 2 for header + 4 for size 65 | 66 | protected: 67 | virtual bool isDecodedValid(unsigned char *buf); 68 | uint32_t original_size; 69 | }; 70 | 71 | class MultiValidator : public TypeValidator 72 | { 73 | public: 74 | MultiValidator() { my_type = NULL; } 75 | 76 | virtual bool init(std::string enc_filename, FileType* type) 77 | { 78 | this->my_type = dynamic_cast (type); 79 | if (my_type == NULL) return false; 80 | return TypeValidator::init(enc_filename, my_type); 81 | } 82 | 83 | virtual size_t getAccuracy() { return 4; } 84 | 85 | protected: 86 | virtual bool isDecodedValid(unsigned char *buf); 87 | MultiFileType *my_type; 88 | }; -------------------------------------------------------------------------------- /dma_unlocker/filetypes/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include /* printf, scanf, puts, NULL */ 4 | #include 5 | #include 6 | 7 | #include "FileTypes.h" 8 | 9 | //---- 10 | 11 | int main (int argc, char *argv[]) 12 | { 13 | printf("---------------------------\n"); 14 | printf("DMA filetypes v0.1\n"); 15 | printf ("params: [hdrs_dir] - default: '%s'\n", HDRS_DIR); 16 | printf("---------------------------\n"); 17 | 18 | FileTypesSet typesSet; 19 | typesSet.listDir(HDRS_DIR); 20 | printf("Registered %d filetypes!\n", typesSet.countTypes()); 21 | printf ("ok!\n"); 22 | system("pause"); 23 | return 0; 24 | } -------------------------------------------------------------------------------- /dma_unlocker/keygen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (DMA_keygen) 3 | 4 | set (srcs 5 | main.cpp 6 | DmaKeygen.cpp 7 | keygen.cpp 8 | ) 9 | 10 | set (hdrs 11 | DmaKeygen.h 12 | keygen.h 13 | ../types.h 14 | ) 15 | 16 | add_executable (DMA_keygen ${hdrs} ${srcs} ) 17 | -------------------------------------------------------------------------------- /dma_unlocker/keygen/DmaKeygen.cpp: -------------------------------------------------------------------------------- 1 | #include "DmaKeygen.h" 2 | #include "keygen.h" 3 | 4 | std::string DmaKeygen::makeNextKey() 5 | { 6 | char buffer[KEY_SIZE + 1]; 7 | make_random_key(buffer, KEY_SIZE); 8 | buffer[KEY_SIZE] = '\0'; 9 | 10 | this->key = buffer; 11 | this->keyNumber++; 12 | return this->key; 13 | } -------------------------------------------------------------------------------- /dma_unlocker/keygen/DmaKeygen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../types.h" 4 | #include 5 | #include 6 | 7 | #define KEY_SIZE 32 8 | 9 | class DmaKeygen 10 | { 11 | public: 12 | DmaKeygen(uint32_t seed) 13 | { 14 | reset(seed); 15 | } 16 | 17 | void reset(uint32_t seed) 18 | { 19 | this->seed = seed; 20 | reset(); 21 | } 22 | 23 | void reset() 24 | { 25 | srand(seed); 26 | this->keyNumber = 0; 27 | this->key = ""; 28 | } 29 | 30 | std::string makeNextKey(); 31 | 32 | //make and store: 33 | std::vector makeKeys(size_t key_number) 34 | { 35 | std::vector keys; 36 | for (size_t i = 0; i < key_number; i++) { 37 | keys.push_back(makeNextKey()); 38 | } 39 | return keys; 40 | } 41 | 42 | //make but not store 43 | std::string makeKeyNumber(size_t key_number) 44 | { 45 | std::vector keys; 46 | for (size_t i = 0; i < key_number; i++) { 47 | makeNextKey(); 48 | } 49 | return makeNextKey(); 50 | } 51 | 52 | size_t searchNumberOfKey(std::string searched_key, size_t max_search) 53 | { 54 | std::vector keys; 55 | for (size_t i = 0; i < max_search; i++) { 56 | makeNextKey(); 57 | if (searched_key == this->key) { 58 | return i; 59 | } 60 | } 61 | return -1; 62 | } 63 | 64 | uint32_t seed; 65 | std::string key; 66 | size_t keyNumber; 67 | }; 68 | 69 | -------------------------------------------------------------------------------- /dma_unlocker/keygen/keygen.cpp: -------------------------------------------------------------------------------- 1 | #include "keygen.h" 2 | 3 | #include "../types.h" 4 | #include "../Params.h" 5 | 6 | #include /* printf, scanf, puts, NULL */ 7 | #include /* srand, rand */ 8 | #include /* time */ 9 | #include /* memset */ 10 | 11 | const int KEY_LEN = 32; 12 | 13 | inline unsigned int random_chunk(int div, int add, char* buf) 14 | { 15 | int r = rand(); 16 | int b = r; 17 | int result = r / div; 18 | (*buf) = (b % div) + add; 19 | return result; 20 | } 21 | 22 | int make_random_key_v1(char *buffer, size_t buffer_size) 23 | { 24 | signed int index = 0; 25 | int v2, v3, result; 26 | v2 = v3 = result = 0; 27 | 28 | memset(buffer, 0, sizeof(buffer_size)); 29 | char *pBuf = &buffer[0]; 30 | 31 | do { 32 | v2 = rand(); 33 | v3 = v2 % 100 + 1; 34 | if ((unsigned int) (v2 % 100 - 25) <= 0x17) { 35 | result = random_chunk(10, 0x30, pBuf++); 36 | continue; 37 | } 38 | if (v3 < 25) { 39 | result = random_chunk(25, 0x61, pBuf++); 40 | continue; 41 | } 42 | if (v3 <= 50) { 43 | result = random_chunk(10, 0x30, pBuf++); 44 | } else { 45 | result = random_chunk(25, 0x41, pBuf++); 46 | } 47 | } while (++index < KEY_LEN); 48 | 49 | buffer[KEY_LEN] = '\0'; 50 | return result; 51 | } 52 | 53 | int make_random_key_v2(char *buffer, size_t buffer_size) 54 | { 55 | if (buffer_size < KEY_LEN) { 56 | printf("Wrong key buffer size!\n"); 57 | return 0; 58 | } 59 | int index = 0; 60 | for (index = 0; index < KEY_LEN; index++) { 61 | uint8_t key_char = static_cast((rand() % 254) + 1); 62 | buffer[index] = key_char; 63 | } 64 | buffer[KEY_LEN] = '\0'; 65 | return 1; 66 | } 67 | 68 | int make_random_key(char *buffer, size_t buffer_size) 69 | { 70 | #ifdef VARIANT_2 71 | return make_random_key_v2(buffer, buffer_size); 72 | #else 73 | return make_random_key_v1(buffer, buffer_size); 74 | #endif 75 | } -------------------------------------------------------------------------------- /dma_unlocker/keygen/keygen.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../types.h" 4 | #include /* printf, scanf, puts, NULL */ 5 | #include /* srand, rand */ 6 | #include /* time */ 7 | #include /* memset */ 8 | 9 | //inline unsigned int random_chunk(int div, int add, char* buf); 10 | int make_random_key(char *buffer, size_t buffer_size); -------------------------------------------------------------------------------- /dma_unlocker/keygen/main.cpp: -------------------------------------------------------------------------------- 1 | #include "DmaKeygen.h" 2 | #define MIN_ARG 3 3 | 4 | int main (int argc, char *argv[]) 5 | { 6 | if (argc < MIN_ARG) { 7 | printf("Usage: "); 8 | } 9 | size_t arg_num = 2; 10 | 11 | uint32_t seed = 0; 12 | if (argc >= arg_num) { 13 | sscanf(argv[arg_num - 1],"%d", &seed); 14 | printf("SEED = %d = %#x\n", seed, seed); 15 | } 16 | arg_num++; 17 | 18 | uint32_t key_number = 0; 19 | if (argc >= arg_num) { 20 | sscanf(argv[arg_num - 1],"%d", &key_number); 21 | printf("KEY_NUMBER = %d = %#x\n", key_number, key_number); 22 | } 23 | arg_num++; 24 | 25 | DmaKeygen keygen(seed); 26 | std::string key = keygen.makeKeyNumber(key_number); 27 | printf("%s\n", key.c_str()); 28 | 29 | key = keygen.makeKeyNumber(key_number + 1); 30 | printf("%s\n", key.c_str()); 31 | 32 | system("pause"); 33 | return 0; 34 | } -------------------------------------------------------------------------------- /dma_unlocker/main.cpp: -------------------------------------------------------------------------------- 1 | #include "types.h" 2 | #include 3 | 4 | #include /* printf, scanf, puts, NULL */ 5 | #include 6 | #include 7 | 8 | #include "main.h" 9 | 10 | #define ARG_MIN 2 11 | #define SERIES_MAX 1000000 12 | #define INFECTED_PER_MS 65 13 | 14 | #define VERSION "0.0.7.1" 15 | //---- 16 | void version_banner() 17 | { 18 | printf("---------------------------\n"); 19 | printf("DMA UNLOCKER v%s - alpha, by hasherezade\n", VERSION); 20 | #ifdef VARIANT_2 21 | printf("for VARIANT 2, i.e:\nDMALOCK 41:11:11:84:32:13:64:68\n\n"); 22 | #endif 23 | printf("This is experimental version, in case of any problems please contact:\n"); 24 | printf("hasherezade@gmail.com\n"); 25 | printf("---------------------------\n"); 26 | } 27 | 28 | void banner() 29 | { 30 | printf("-----------------------------------------------------------------\n"); 31 | printf("!!!!DISCLAIMER!!!!\n\ 32 | This tool is an experiment in unlocking a particular kind of Ransomware,\n\ 33 | neither Malwarebytes or Hasherezade promise this tool will unlock or decrypt\n\ 34 | your files.\n\ 35 | This tool should not be considered an official solution to the DMA Locker \nproblem.\n\ 36 | Any files destroyed, further encrypted or otherwise tampered with against\n\ 37 | the desire of the user are not the responsibility of the developers.\n\ 38 | Please use at your own risk.\n\n"); 39 | printf("If you cannot accept this, please exit the program now.\n"); 40 | printf("If you accept the above, press any button to start the program\n"); 41 | printf("-----------------------------------------------------------------\n"); 42 | system("pause"); 43 | } 44 | 45 | void print_infected_info(FileSet &fileSet) 46 | { 47 | FILE *logFile = fopen("infected_summary.txt", "w"); 48 | fileSet.printSummary(logFile); 49 | fclose(logFile); 50 | 51 | printf("Infected files: %d\n", fileSet.countFiles()); 52 | printf("\nDETECTED PIVOT FILE:\n [%s]\n", fileSet.minTimestampFile.c_str()); 53 | } 54 | 55 | int main (int argc, char *argv[]) 56 | { 57 | version_banner(); 58 | if (argc < ARG_MIN) { 59 | printf("Params: [start_dir] [skip_decrypted?]\n"); 60 | printf(" start_dir (optional) : directory with infected files (default is current)\n"); 61 | printf(" overwrite_decrypted? (optional) : 1 - yes, 0 - no; (default=0)\n"); 62 | } 63 | banner(); 64 | 65 | std::string start_dir = ""; 66 | 67 | FileTypesSet fileTypes; 68 | if (fileTypes.listDir(HDRS_DIR) == 0) { 69 | printf("[ERROR] Cannot load supported extensions!\n"); 70 | } 71 | 72 | size_t arg_num = ARG_MIN; 73 | if (argc >= arg_num) { 74 | start_dir = argv[arg_num - 1]; 75 | } else { 76 | start_dir = PathCrawler::getLocalDir(); 77 | } 78 | arg_num++; 79 | 80 | 81 | FileSet fileSet; 82 | PathCrawler crawler; 83 | fileSet.init(); 84 | 85 | bool skip_decrypted = true; 86 | if (argc >= arg_num) { 87 | int overwrite = 0; 88 | sscanf(argv[arg_num - 1],"%d", &overwrite); 89 | if (overwrite > 0) { 90 | skip_decrypted = false; 91 | printf("MODE: Overwrite decrypted!\n"); 92 | } 93 | } 94 | 95 | printf("\n>>Start path:\n%s\n", start_dir.c_str()); 96 | 97 | Params::encryptionStartTime(); 98 | fileSet.setKnownTypes(&fileTypes); 99 | crawler.listDir(start_dir, &fileSet, skip_decrypted); 100 | 101 | if (fileSet.countFiles() == 0) { 102 | printf("No files with recognized headers!\n"); 103 | system("pause"); 104 | return -1; 105 | } 106 | print_infected_info(fileSet); 107 | 108 | std::string pivot_file = fileSet.getPivotFile(); 109 | uint32_t fileModTime = static_cast(get_file_modification(pivot_file)); 110 | if (fileModTime == 0) { 111 | system("pause"); 112 | return -1; 113 | } 114 | 115 | Params params; 116 | params.init(pivot_file, fileModTime); 117 | params.seed = fileModTime; 118 | #ifdef DEBUG 119 | printf("MOD TIME = %d\n", params.fileEncryptionTime, params.fileEncryptionTime); 120 | printf("SEED = %d = %#x\n", params.seed, params.seed); 121 | #endif 122 | printf("Days ago:\t%d\n", (params.timeNow - params.seed) / DAY_LEN); 123 | 124 | //max number of encrypted files per milisecons 125 | int infected_per_ms = INFECTED_PER_MS; 126 | params.series_min = params.series_max = SERIES_MAX; 127 | 128 | if (params.fileEncryptionTime == params.seed) { 129 | params.series_min = infected_per_ms; //start from small series 130 | params.series_max = SERIES_MAX; 131 | } 132 | 133 | if (decrypt_file(fileTypes, params, pivot_file) == false) { 134 | printf("Could not crack the pivot file!\n%s\n", pivot_file.c_str()); 135 | system("pause"); 136 | return -1; 137 | } 138 | printf("[SUCCESS]\n"); 139 | 140 | //added part from the crawler: 141 | CrackedSet crackedSet(fileTypes, params); 142 | crackedSet.init(); 143 | PathCrawler crackingCrawler; 144 | 145 | crackingCrawler.listDir(start_dir, &crackedSet, skip_decrypted); 146 | crackedSet.printSummary(); 147 | printf("FINISHED!\n"); 148 | 149 | system("pause"); 150 | return 0; 151 | } 152 | -------------------------------------------------------------------------------- /dma_unlocker/main.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "dma_crack.h" 4 | 5 | #include "Params.h" 6 | #include "recon/PathCrawler.h" 7 | #include "decryptor/decryptor.h" 8 | #include "filetypes/FileTypes.h" 9 | #include "cracking_crawler/CrackedSet.h" -------------------------------------------------------------------------------- /dma_unlocker/recon/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (DMA_recon) 3 | 4 | set (srcs 5 | main.cpp 6 | PathCrawler.cpp 7 | FileSet.cpp 8 | ../filetypes/FileTypes.cpp 9 | ../decryptor/decryptor.cpp 10 | ../decryptor/aes256.cpp 11 | ../timeconv.cpp 12 | ../Params.cpp 13 | ) 14 | 15 | set (hdrs 16 | PathCrawler.h 17 | FileSet.h 18 | ../filetypes/FileTypes.h 19 | ../decryptor/decryptor.h 20 | ../decryptor/aes256.h 21 | ../types.h 22 | ../timeconv.h 23 | ../Params.h 24 | ) 25 | 26 | add_executable (DMA_recon ${hdrs} ${srcs} ) 27 | -------------------------------------------------------------------------------- /dma_unlocker/recon/FileSet.cpp: -------------------------------------------------------------------------------- 1 | #include "FileSet.h" 2 | 3 | //virtual 4 | bool FileSet::processFile(std::string path, std::string ext, uint32_t writeTime) 5 | { 6 | return logToFile(path, writeTime); 7 | } 8 | 9 | bool FileSet::logToFile(std::string path, uint32_t writeTime) 10 | { 11 | if (logFile) { 12 | fprintf(logFile, "%d,%s\n", writeTime, path.c_str()); 13 | fflush(logFile); 14 | } 15 | return true; 16 | } 17 | 18 | void FileSet::addPivot(std::string path, std::string ext, uint32_t writeTime) 19 | { 20 | if (this->knownTypes == NULL) return; 21 | FileType *type = this->knownTypes->getType(ext); 22 | if (type != NULL && type->accuracy >= PIVOT_MIN) { 23 | this->pivotFile = path; 24 | } 25 | } 26 | 27 | void FileSet::addFile(std::string path, std::string ext, uint32_t writeTime) 28 | { 29 | if (path.length() == 0) return; 30 | if (this->knownTypes != NULL && knownTypes->getType(ext) == NULL) { 31 | return; //skip unknown extension 32 | } 33 | 34 | if (processFile(path, ext, writeTime) == false) { 35 | return; 36 | } 37 | 38 | filesCounter++; 39 | extensions.insert(ext); 40 | 41 | if (this->minTimestamp == 0) { 42 | minTimestamp = maxTimestamp = writeTime; 43 | minTimestampFile = maxTimestampFile = pivotFile = path; 44 | return; 45 | } 46 | 47 | if (writeTime < minTimestamp) { 48 | writeTime = writeTime; 49 | minTimestampFile = path; 50 | addPivot(path, ext, writeTime); 51 | } 52 | 53 | if (writeTime > maxTimestamp) { 54 | maxTimestamp = writeTime; 55 | maxTimestampFile = path; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /dma_unlocker/recon/FileSet.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../types.h" 12 | #include "../filetypes/FileTypes.h" 13 | 14 | class FileSet { 15 | 16 | public: 17 | FileSet() 18 | { 19 | minTimestamp = maxTimestamp = 0; 20 | filesCounter = 0; 21 | knownTypes = NULL; 22 | this->logFile = NULL; 23 | } 24 | 25 | ~FileSet() 26 | { 27 | if (!logFile) return; 28 | fclose(logFile); 29 | } 30 | 31 | virtual void init() 32 | { 33 | logFilename = "infected_log.txt"; 34 | this->logFile = fopen(logFilename.c_str(), "w"); 35 | if (!logFile) { 36 | printf ("Open log file failed\n"); 37 | return; 38 | } 39 | } 40 | 41 | void setKnownTypes(FileTypesSet *types) 42 | { 43 | knownTypes = types; 44 | } 45 | 46 | virtual std::string getPivotFile() 47 | { 48 | return this->minTimestampFile; 49 | } 50 | 51 | void addFile(std::string path, std::string ext, uint32_t writeTime); 52 | 53 | 54 | size_t countFiles() 55 | { 56 | return filesCounter; 57 | } 58 | 59 | void printSummary() 60 | { 61 | printf("INFECTED: %ld\n", countFiles()); 62 | if (countFiles() == 0) return; 63 | 64 | printf("Files:\n"); 65 | printf("1) %s\n", minTimestampFile.c_str()); 66 | printf("2) %s\n", maxTimestampFile.c_str()); 67 | } 68 | 69 | void printSummary(FILE* logFile) 70 | { 71 | if (!logFile) return; 72 | if (countFiles() == 0) return; 73 | 74 | uint32_t dif = maxTimestamp - minTimestamp; 75 | fprintf(logFile, "TIMESTAMPS:\nMin: %d\nMax: %d\nDif: %d\n", minTimestamp, maxTimestamp, dif); 76 | fprintf(logFile, "1) %s\n", minTimestampFile.c_str()); 77 | fprintf(logFile, "2) %s\n", maxTimestampFile.c_str()); 78 | 79 | fprintf(logFile, "INFECTED: %ld\n", countFiles()); 80 | fprintf(logFile, "EXTENSIONS:\n"); 81 | std::set::iterator itr; 82 | for (itr = extensions.begin(); itr != extensions.end(); itr++) { 83 | fprintf(logFile, "%s\n", itr->c_str()); 84 | } 85 | } 86 | 87 | std::string minTimestampFile, maxTimestampFile, pivotFile; 88 | uint32_t minTimestamp, maxTimestamp; 89 | 90 | protected: 91 | virtual void addPivot(std::string path, std::string ext, uint32_t writeTime); 92 | virtual bool processFile(std::string path, std::string ext, uint32_t writeTime); 93 | 94 | bool logToFile(std::string path, uint32_t writeTime); 95 | std::string logFilename; 96 | size_t filesCounter; 97 | std::set extensions; 98 | 99 | FileTypesSet* knownTypes; 100 | FILE *logFile; 101 | }; 102 | 103 | class FileStoringSet : public FileSet 104 | { 105 | public: 106 | FileStoringSet() 107 | { 108 | lastWriteTime = 0; 109 | } 110 | //--- 111 | 112 | std::map > filesMap; 113 | std::map pivotsMap; 114 | 115 | protected: 116 | virtual bool processFile(std::string path, std::string ext, uint32_t writeTime) 117 | { 118 | FileType *type = this->knownTypes->getType(ext); 119 | if (type != NULL && type->accuracy >= PIVOT_MIN) { 120 | if (abs(long(lastWriteTime - writeTime)) > 3) { 121 | pivotsMap[writeTime] = path; 122 | } 123 | } 124 | lastWriteTime = writeTime; 125 | 126 | insertFile(path, writeTime); 127 | logToFile(path, writeTime); 128 | return true; 129 | } 130 | 131 | void insertFile(std::string path, uint32_t writeTime) 132 | { 133 | filesMap[writeTime].push_back(path); 134 | } 135 | //--- 136 | 137 | uint32_t lastWriteTime; 138 | }; -------------------------------------------------------------------------------- /dma_unlocker/recon/PathCrawler.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hasherezade/decryptors_archive/0bd5384d47164035c28af4188d5700708c8e4244/dma_unlocker/recon/PathCrawler.cpp -------------------------------------------------------------------------------- /dma_unlocker/recon/PathCrawler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../types.h" 4 | #include 5 | #include 6 | #include 7 | #include "FileSet.h" 8 | 9 | class PathCrawler 10 | { 11 | public: 12 | static std::string getLocalDir(); 13 | 14 | void listDir(std::string path, FileSet *fileSet, bool skip_decrypted); 15 | bool isExtensionAttacked(char *filename); 16 | bool isInfected(std::string filename); 17 | bool isDecrypted(std::string filename); 18 | }; -------------------------------------------------------------------------------- /dma_unlocker/recon/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include /* printf, scanf, puts, NULL */ 4 | #include 5 | #include 6 | 7 | #include "../Params.h" 8 | #include "PathCrawler.h" 9 | #include "FileSet.h" 10 | #include "../filetypes/FileTypes.h" 11 | //---- 12 | 13 | #define DAY_LEN 86400 14 | 15 | int main (int argc, char *argv[]) 16 | { 17 | bool skip_decrypted = false; 18 | 19 | FileSet fileSet; 20 | PathCrawler crawler(&fileSet); 21 | 22 | printf("---------------------------\n"); 23 | printf("DMA recon v1.4\n"); 24 | printf("---------------------------\n"); 25 | if (argc >= 2 && argv[1][0] == '1') { 26 | skip_decrypted = true; 27 | printf("Skipping decrypted!\n"); 28 | } 29 | 30 | crawler.listDir(crawler.startPath, skip_decrypted); 31 | printf("listing finished...\n"); 32 | fileSet.printSummary(); 33 | 34 | system("pause"); 35 | return 0; 36 | 37 | } -------------------------------------------------------------------------------- /dma_unlocker/timeconv.cpp: -------------------------------------------------------------------------------- 1 | #include "timeconv.h" 2 | //#define DEBUG 1 3 | //---- 4 | 5 | time_t FileTime_to_POSIX(FILETIME ft) 6 | { 7 | // takes the last modified date 8 | LARGE_INTEGER date, adjust; 9 | date.HighPart = ft.dwHighDateTime; 10 | date.LowPart = ft.dwLowDateTime; 11 | // 100-nanoseconds = milliseconds * 10000 12 | adjust.QuadPart = 11644473600000 * 10000; 13 | // removes the diff between 1970 and 1601 14 | date.QuadPart -= adjust.QuadPart; 15 | // converts back from 100-nanoseconds to seconds 16 | return date.QuadPart / 10000000; 17 | } 18 | 19 | void print_time_str(time_t rawtime) 20 | { 21 | struct tm* timeinfo = localtime (&rawtime); 22 | char s[100]; /* strlen("2009-08-10 18:17:54") + 1 */ 23 | strftime (s, 100, "%Y-%m-%d %H:%M:%S", timeinfo); 24 | printf("%s\n", s); 25 | } 26 | 27 | time_t get_file_modification(std::string filename) 28 | { 29 | HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, 0); 30 | if (hFile == NULL) { 31 | printf("Cannot open file: %s\n", filename.c_str()); 32 | return 0; 33 | } 34 | FILETIME lastWriteTime; 35 | BOOL isOk = GetFileTime(hFile, NULL, NULL, &lastWriteTime); 36 | 37 | CloseHandle(hFile); 38 | 39 | return FileTime_to_POSIX(lastWriteTime); 40 | } 41 | 42 | time_t get_file_creation(std::string filename) 43 | { 44 | 45 | HANDLE hFile = CreateFile(filename.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, 0); 46 | if (!hFile) { 47 | printf("Cannot open file: %s\n", filename.c_str()); 48 | return 0; 49 | } 50 | FILETIME creationTime; 51 | BOOL isOk = GetFileTime(hFile, &creationTime, NULL, NULL); 52 | CloseHandle(hFile); 53 | 54 | if (isOk == FALSE) { 55 | #ifdef DEBUG 56 | printf("Cannot get creation of file: %s\n", filename); 57 | #endif 58 | return 0; 59 | } 60 | return FileTime_to_POSIX(creationTime); 61 | } 62 | 63 | uint32_t print_time_info(std::string path, uint32_t fileModTime) 64 | { 65 | #ifdef DEBUG 66 | printf("***\n"); 67 | printf("Detected encryption time for the file:\n[%s]\n", path); 68 | printf("TIMESTAMP: %d = %x\n", fileModTime, fileModTime); 69 | print_time_str(fileModTime); 70 | printf("Days ago:\t%d\n", (time(NULL) - fileModTime) / DAY_LEN); 71 | printf("***\n"); 72 | #endif 73 | return fileModTime; 74 | } 75 | -------------------------------------------------------------------------------- /dma_unlocker/timeconv.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "types.h" 4 | 5 | #include 6 | #include /* printf, scanf, puts, NULL */ 7 | #include 8 | #include /* time */ 9 | #include 10 | 11 | #define DAY_LEN 86400 12 | #define HOUR_LEN 3600 13 | 14 | //---- 15 | time_t FileTime_to_POSIX(FILETIME ft); 16 | void print_time_str(time_t rawtime); 17 | time_t get_file_modification(std::string filename); 18 | time_t get_file_creation(std::string filename); 19 | 20 | uint32_t print_time_info(std::string path, uint32_t fileModTime); -------------------------------------------------------------------------------- /dma_unlocker/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef _MSC_VER 4 | #include 5 | #else 6 | #include 7 | #endif 8 | 9 | -------------------------------------------------------------------------------- /dma_unlocker/unlocker/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (DMA_unlocker) 3 | 4 | set (recon_srcs 5 | ../recon/PathCrawler.cpp 6 | ../recon/FileSet.cpp 7 | ) 8 | 9 | set (decryptor_srcs 10 | ../decryptor/decryptor.cpp 11 | ../decryptor/aes256.cpp 12 | ) 13 | 14 | set (srcs 15 | main.cpp 16 | Unlocker.cpp 17 | ../keygen/keygen.cpp 18 | ../keygen/DmaKeygen.cpp 19 | ../filetypes/filetypes.cpp 20 | ../filetypes/TypeValidator.cpp 21 | ../cracking_crawler/CrackedSet.cpp 22 | ../dma_crack.cpp 23 | ../timeconv.cpp 24 | ../Params.cpp 25 | ) 26 | 27 | set (recon_hdrs 28 | ../recon/PathCrawler.h 29 | ../recon/FileSet.h 30 | ) 31 | 32 | set (decryptor_hdrs 33 | ../decryptor/decryptor.h 34 | ../decryptor/aes256.h 35 | ) 36 | 37 | set (hdrs 38 | Unlocker.h 39 | ../keygen/keygen.h 40 | ../keygen/DmaKeygen.h 41 | ../filetypes/filetypes.h 42 | ../filetypes/TypeValidator.h 43 | ../cracking_crawler/CrackedSet.h 44 | ../dma_crack.h 45 | ../util.h 46 | ../types.h 47 | ../timeconv.h 48 | ../Params.h 49 | ) 50 | 51 | SOURCE_GROUP("Header Files\\recon" FILES ${recon_hdrs} ) 52 | SOURCE_GROUP("Source Files\\recon" FILES ${recon_srcs} ) 53 | 54 | SOURCE_GROUP("Header Files\\decryptor" FILES ${decryptor_hdrs} ) 55 | SOURCE_GROUP("Source Files\\decryptor" FILES ${decryptor_srcs} ) 56 | 57 | add_executable (DMA_unlocker ${hdrs} ${srcs} ${recon_hdrs} ${recon_srcs} ${decryptor_hdrs} ${decryptor_srcs}) 58 | -------------------------------------------------------------------------------- /dma_unlocker/unlocker/Unlocker.cpp: -------------------------------------------------------------------------------- 1 | #include "Unlocker.h" 2 | #include "../util.h" 3 | 4 | #define CHECK_MS 5 5 | 6 | bool Unlocker::tryKey(FileStoringSet& filesInput, std::string key) 7 | { 8 | std::map >::iterator itr; 9 | size_t checked_ms = 0; 10 | for (itr = filesInput.filesMap.begin(); itr != filesInput.filesMap.end() && checked_ms < CHECK_MS; itr++, checked_ms++) { 11 | std::vector&vec = itr->second; 12 | uint32_t infection_time = itr->first; 13 | 14 | std::vector::iterator paths_itr; 15 | for (paths_itr = vec.begin(); paths_itr != vec.end(); paths_itr++) { 16 | std::string &full_path = *paths_itr; 17 | 18 | if (decrypt_file(fileTypes, params, full_path, key)) { 19 | printf ("[KEY OK]\n"); 20 | return true; 21 | } 22 | } 23 | } 24 | return false; 25 | } 26 | -------------------------------------------------------------------------------- /dma_unlocker/unlocker/Unlocker.h: -------------------------------------------------------------------------------- 1 | #include "../dma_crack.h" 2 | 3 | #include "../Params.h" 4 | #include "../recon/PathCrawler.h" 5 | #include "../decryptor/decryptor.h" 6 | #include "../filetypes/FileTypes.h" 7 | #include "../cracking_crawler/CrackedSet.h" 8 | #include "../keygen/DmaKeygen.h" 9 | 10 | 11 | class Unlocker { 12 | public: 13 | Unlocker(FileTypesSet &fTypes, Params &p, DmaKeygen &k) 14 | : fileTypes(fTypes), params(p), keygen(k) {} 15 | 16 | static std::string getPivotFile(FileTypesSet &fileTypes, FileStoringSet& filesInput); 17 | 18 | bool tryKey(FileStoringSet& filesInput, std::string key); 19 | 20 | DmaKeygen &keygen; 21 | FileTypesSet &fileTypes; 22 | Params ¶ms; 23 | }; -------------------------------------------------------------------------------- /dma_unlocker/unlocker/main.cpp: -------------------------------------------------------------------------------- 1 | #include "../types.h" 2 | #include 3 | 4 | #include /* printf, scanf, puts, NULL */ 5 | #include 6 | #include 7 | 8 | #include "Unlocker.h" 9 | 10 | #define ARG_MIN 2 11 | #define SERIES_MAX 1000000 12 | #define INFECTED_PER_MS 65 13 | 14 | #define VERSION "0.0.6.5" 15 | //---- 16 | 17 | void disclaimer_banner() 18 | { 19 | printf("-----------------------------------------------------------------\n"); 20 | printf("!!!!DISCLAIMER!!!!\n\ 21 | This tool is an experiment in unlocking a particular kind of Ransomware,\n\ 22 | neither Malwarebytes or Hasherezade promise this tool will unlock or decrypt\n\ 23 | your files.\n\ 24 | This tool should not be considered an official solution to the DMA Locker \nproblem.\n\ 25 | Any files destroyed, further encrypted or otherwise tampered with against\n\ 26 | the desire of the user are not the responsibility of the developers.\n\ 27 | Please use at your own risk.\n\n"); 28 | printf("If you cannot accept this, please exit the program now.\n"); 29 | printf("If you accept the above, press any button to start the program\n"); 30 | printf("-----------------------------------------------------------------\n"); 31 | system("pause"); 32 | } 33 | 34 | void print_infected_info(FileSet &fileSet) 35 | { 36 | FILE *logFile = fopen("infected_summary.txt", "w"); 37 | fileSet.printSummary(logFile); 38 | fclose(logFile); 39 | 40 | printf("Infected files: %d\n", fileSet.countFiles()); 41 | printf("\nDETECTED PIVOT FILE:\n [%s]\n", fileSet.minTimestampFile.c_str()); 42 | } 43 | 44 | void version_banner() 45 | { 46 | printf("---------------------------\n"); 47 | printf("!DMALOCK UNLOCKER v%s - alpha\n", VERSION); 48 | printf("This is experimental version, in case of any problems please contact:\n"); 49 | printf("hasherezade@gmail.com\n"); 50 | printf("---------------------------\n\n"); 51 | } 52 | 53 | int main (size_t argc, char *argv[]) 54 | { 55 | bool skip_decrypted = true; 56 | version_banner(); 57 | if (argc < ARG_MIN) { 58 | printf("Params: [start_dir] [skip_decrypted]\n"); 59 | printf(" start_dir (optional) : directory with infected files (default is current)\n"); 60 | printf(" skip_decrypted : do not try to decrypt already decrypted files\n\n"); 61 | } 62 | disclaimer_banner(); 63 | 64 | std::string start_dir = ""; 65 | 66 | FileTypesSet fileTypes; 67 | if (fileTypes.listDir(HDRS_DIR) == 0) { 68 | printf("[ERROR] Cannot load supported extensions!\n"); 69 | system("pause"); 70 | return -1; 71 | } 72 | 73 | size_t arg_num = ARG_MIN; 74 | if (argc >= ARG_MIN) { 75 | start_dir = argv[ARG_MIN - 1]; 76 | } else { 77 | start_dir = PathCrawler::getLocalDir(); 78 | } 79 | arg_num++; 80 | 81 | if (argc >= arg_num) { 82 | int mode = 0; 83 | sscanf(argv[arg_num - 1],"%d", &mode); 84 | skip_decrypted = (mode > 0); 85 | } 86 | 87 | FileStoringSet fileSet; 88 | PathCrawler crawler; 89 | fileSet.init(); 90 | 91 | printf("\n>>Start path:\n%s\n", start_dir.c_str()); 92 | 93 | Params::encryptionStartTime(); 94 | fileSet.setKnownTypes(&fileTypes); 95 | crawler.listDir(start_dir, &fileSet, skip_decrypted); 96 | 97 | if (fileSet.countFiles() == 0) { 98 | printf("No files with recognized headers!\n"); 99 | system("pause"); 100 | return -1; 101 | } 102 | print_infected_info(fileSet); 103 | 104 | std::string pivot_file = fileSet.getPivotFile(); 105 | 106 | uint32_t fileModTime = static_cast(get_file_modification(pivot_file)); 107 | if (fileModTime == 0) { 108 | system("pause"); 109 | return -1; 110 | } 111 | 112 | Params params; 113 | params.init(pivot_file, fileModTime); 114 | params.seed = fileModTime; 115 | params.autosetMode(); 116 | 117 | printf("Days ago:\t%d\n", (params.timeNow - params.seed) / DAY_LEN); 118 | 119 | //max number of encrypted files per milisecons 120 | int infected_per_ms = INFECTED_PER_MS; 121 | 122 | if (params.fileEncryptionTime == params.seed) { 123 | params.series_min = infected_per_ms; //start from small series 124 | params.series_max = SERIES_MAX; 125 | } 126 | 127 | if (decrypt_file(fileTypes, params, pivot_file) == false) { 128 | printf("Could not crack the pivot file!\n%s", pivot_file.c_str()); 129 | system("pause"); 130 | return -1; 131 | } 132 | printf("[SUCCESS]\n"); 133 | DmaKeygen keygen(params.seed); 134 | Unlocker unlocker (fileTypes, params, keygen); 135 | std::vector keys = keygen.makeKeys(params.key_num + SERIES_MAX); 136 | std::vector::iterator key_itr; 137 | size_t unlocked = 0; 138 | size_t to_unlock = fileSet.countFiles() - 1; 139 | 140 | for (key_itr = keys.begin(); key_itr != keys.end(); key_itr++) { 141 | if (unlocker.tryKey(fileSet, *key_itr)) { 142 | unlocked++; 143 | //this key fits to no file - file could be removed? 144 | printf("Unlocked %d remaining %d\n", unlocked, to_unlock); 145 | } 146 | if (unlocked == to_unlock) break; 147 | } 148 | 149 | if (unlocked == fileSet.countFiles()) { 150 | printf("FINISHED!\n"); 151 | } else { 152 | //TODO: find another pivot and repeat... 153 | } 154 | 155 | 156 | //keygen.reset(params.seed); 157 | //added part from the crawler: 158 | /* 159 | crackedSet.init(); 160 | PathCrawler crackingCrawler; 161 | 162 | crackingCrawler.listDir(start_dir, &crackedSet, skip_decrypted); 163 | crackedSet.printSummary(); 164 | printf("FINISHED!\n");*/ 165 | 166 | system("pause"); 167 | return 0; 168 | } -------------------------------------------------------------------------------- /dma_unlocker/util.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | inline std::string get_extension(std::string filename) 6 | { 7 | char* extension = strrchr(const_cast(filename.c_str()), '.'); 8 | if (extension == NULL) return ""; 9 | std::string ext = extension; 10 | std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower); 11 | return ext; 12 | } 13 | /* 14 | void hex_dump(unsigned char buffer[], size_t buf_size) 15 | { 16 | for (size_t i = 0; i < buf_size; i++) { 17 | printf("%02x ", buffer[i]); 18 | } 19 | printf("\n"); 20 | } 21 | */ -------------------------------------------------------------------------------- /princesslocker_decrypt/README.md: -------------------------------------------------------------------------------- 1 | Read more:
2 | https://hshrzd.wordpress.com/2016/11/17/princess-locker-decryptor/ -------------------------------------------------------------------------------- /princesslocker_decrypt/decryptor/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (PrincessDecryptor) 3 | 4 | add_definitions(-DUNICODE -D_UNICODE) 5 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") 6 | 7 | set (srcs 8 | decryptor.cpp 9 | main.cpp 10 | PathCrawler.cpp 11 | ) 12 | 13 | set (hdrs 14 | decryptor.h 15 | PathCrawler.h 16 | ) 17 | add_executable (PrincessDecryptor ${rsrc} ${hdrs} ${srcs}) -------------------------------------------------------------------------------- /princesslocker_decrypt/decryptor/PathCrawler.cpp: -------------------------------------------------------------------------------- 1 | #include "PathCrawler.h" 2 | #include "decryptor.h" 3 | 4 | #include 5 | 6 | std::wstring PathCrawler::getLocalDir() 7 | { 8 | wchar_t current_dir[MAX_PATH]; 9 | GetCurrentDirectory(MAX_PATH, current_dir); 10 | return current_dir; 11 | } 12 | 13 | bool PathCrawler::isDecrypted(std::wstring filename, wchar_t *extension) 14 | { 15 | wchar_t orig_name[MAX_PATH]; 16 | wchar_t* filename_str = const_cast(filename.c_str()); 17 | get_original_name(filename_str, extension, orig_name); 18 | if (is_existing(orig_name)) { 19 | return true; 20 | } 21 | return false; 22 | } 23 | 24 | bool PathCrawler::isInfected(std::wstring filename, wchar_t* extension) 25 | { 26 | wchar_t* filename_str = const_cast(filename.c_str()); 27 | return is_infected(filename_str, extension); 28 | } 29 | 30 | void PathCrawler::listDir(std::wstring path, wchar_t* extension, wchar_t* key_str, bool skip_decrypted) 31 | { 32 | if (path.length() == 0) { 33 | path = PathCrawler::getLocalDir(); 34 | } 35 | printf("Dir: %S\n", path.c_str()); 36 | const std::wstring fileName = path + L"\\*"; 37 | WIN32_FIND_DATA foundFileData; 38 | HANDLE hFind = FindFirstFile(fileName.c_str(), &foundFileData); 39 | if (hFind == INVALID_HANDLE_VALUE) { 40 | printf("[ERROR] INVALID_HANDLE_VALUE\n"); 41 | return; 42 | } 43 | 44 | do { 45 | if (foundFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) { 46 | if (wcscmp(foundFileData.cFileName, L".") == 0) continue; 47 | if (wcscmp(foundFileData.cFileName, L"..") == 0) continue; 48 | std::wstring full_path = path + L"\\"+ foundFileData.cFileName; 49 | listDir(full_path, extension, key_str, skip_decrypted); 50 | continue; 51 | } 52 | std::wstring full_path = path + L"\\"+ foundFileData.cFileName; 53 | const wchar_t* full_path_str = full_path.c_str(); 54 | 55 | if (isInfected(full_path_str, extension) == false) { 56 | //printf("Not infected, skipping: %S\n", full_path_str); 57 | continue; 58 | } 59 | if (skip_decrypted && isDecrypted(full_path_str, extension) == true) { 60 | printf("Already decrypted, skipping: %S\n", full_path.c_str()); 61 | continue; 62 | } 63 | wchar_t orig_name[MAX_PATH]; 64 | get_original_name(full_path.c_str(), extension, orig_name); 65 | 66 | if (!aes_decrypt_file(full_path_str, orig_name, key_str)) { 67 | printf("[-] Failed to decrypt: %S\n", full_path_str); 68 | } else { 69 | printf("[+] %S\n", full_path_str); 70 | } 71 | } while (FindNextFile(hFind, &foundFileData)); 72 | 73 | FindClose(hFind); 74 | } 75 | -------------------------------------------------------------------------------- /princesslocker_decrypt/decryptor/PathCrawler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace PathCrawler 8 | { 9 | std::wstring getLocalDir(); 10 | 11 | void listDir(std::wstring path, wchar_t* extension, wchar_t* key_str, bool skip_decrypted); 12 | bool isInfected(std::wstring filename, wchar_t* extension); 13 | bool isDecrypted(std::wstring filename1, wchar_t *extension); 14 | 15 | bool decryptFile(); 16 | }; -------------------------------------------------------------------------------- /princesslocker_decrypt/decryptor/README.md: -------------------------------------------------------------------------------- 1 | # PrincessDecryptor 2 | Decryptor for Princess Locker ransomware. Requires having a key. 3 | -------------------------------------------------------------------------------- /princesslocker_decrypt/decryptor/decryptor.cpp: -------------------------------------------------------------------------------- 1 | #include "decryptor.h" 2 | 3 | wchar_t* get_extension_ptr(IN wchar_t *filename) 4 | { 5 | size_t len = lstrlenW(filename); 6 | for (int i = len - 1; i > 0; i--) { 7 | if (filename[i] == '.') { 8 | return &filename[i]; 9 | } 10 | } 11 | return NULL; 12 | } 13 | 14 | bool is_infected(wchar_t* filename, wchar_t* extension) 15 | { 16 | wchar_t* ptr = get_extension_ptr(filename); 17 | if (ptr == NULL) return false; 18 | if (*ptr == L'.') ptr++; 19 | 20 | if (wcscmp(ptr, extension) == 0) { 21 | return true; // file have the defined extension 22 | } 23 | return false; 24 | } 25 | 26 | bool is_existing(IN const wchar_t *filename) 27 | { 28 | if(INVALID_FILE_ATTRIBUTES == GetFileAttributes(filename) && GetLastError()==ERROR_FILE_NOT_FOUND) { 29 | return false; 30 | } 31 | return true; 32 | } 33 | 34 | bool is_directory(IN const wchar_t *filename) 35 | { 36 | DWORD attributes = GetFileAttributes(filename); 37 | if(INVALID_FILE_ATTRIBUTES == attributes && GetLastError()==ERROR_FILE_NOT_FOUND) { 38 | return false; 39 | } 40 | if (attributes == FILE_ATTRIBUTE_DIRECTORY) { 41 | return true; 42 | } 43 | return false; 44 | } 45 | 46 | bool get_original_name(IN const wchar_t *filename1, IN const wchar_t *extension, OUT wchar_t *out_filename) 47 | { 48 | if (filename1 == NULL || extension == NULL || out_filename == NULL) { 49 | return false; 50 | } 51 | wcscpy(out_filename, filename1); 52 | 53 | wchar_t *ptr = wcsstr(out_filename, extension); 54 | if (ptr == NULL) { 55 | return false; 56 | } 57 | ptr--; 58 | if (*(ptr) != '.') { 59 | return false; 60 | } 61 | (*ptr) = 0; 62 | return true; 63 | } 64 | 65 | BOOL aes_decrypt_file(const wchar_t* filename, const wchar_t* filename2, const wchar_t* key_str) 66 | { 67 | if (filename == NULL || filename2 == NULL || key_str == NULL) return FALSE; 68 | 69 | size_t key_len = lstrlenW(key_str); 70 | BOOL dwStatus = FALSE; 71 | 72 | wchar_t info[] = L"Microsoft Enhanced RSA and AES Cryptographic Provider"; 73 | HCRYPTPROV hProv; 74 | if (!CryptAcquireContextW(&hProv, NULL, info, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ 75 | dwStatus = GetLastError(); 76 | printf("CryptAcquireContext failed: %x\n", dwStatus); 77 | CryptReleaseContext(hProv, 0); 78 | return dwStatus; 79 | } 80 | HCRYPTHASH hHash; 81 | if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) { 82 | dwStatus = GetLastError(); 83 | printf("CryptCreateHash failed: %x\n", dwStatus); 84 | CryptReleaseContext(hProv, 0); 85 | return dwStatus; 86 | } 87 | 88 | if (!CryptHashData(hHash, (BYTE*)key_str, key_len, 0)) { 89 | DWORD err = GetLastError(); 90 | printf ("CryptHashData Failed : %#x\n", err); 91 | return dwStatus; 92 | } 93 | HCRYPTKEY hKey; 94 | if (!CryptDeriveKey(hProv, CALG_AES_128, hHash, 0,&hKey)){ 95 | dwStatus = GetLastError(); 96 | printf("CryptDeriveKey failed: %x\n", dwStatus); 97 | CryptReleaseContext(hProv, 0); 98 | return dwStatus; 99 | } 100 | 101 | const size_t chunk_size = BLOCK_LEN; 102 | BYTE chunk[chunk_size]; 103 | DWORD read = 0; 104 | DWORD written = 0; 105 | 106 | HANDLE hInpFile = CreateFileW(filename, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); 107 | HANDLE hOutFile = CreateFileW(filename2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 108 | 109 | if (hInpFile == INVALID_HANDLE_VALUE) { 110 | printf("Cannot open input file!\n"); 111 | return dwStatus; 112 | } 113 | if (hOutFile == INVALID_HANDLE_VALUE) { 114 | printf("Cannot open output file!\n"); 115 | return dwStatus; 116 | } 117 | while (ReadFile(hInpFile, chunk, chunk_size, &read, NULL)) { 118 | if (0 == read){ 119 | break; 120 | } 121 | DWORD ciphertextLen = BLOCK_LEN; 122 | if (!CryptDecrypt(hKey, NULL, FALSE, 0,chunk, &ciphertextLen)) { 123 | printf("failed!\n"); 124 | dwStatus = FALSE; 125 | break; 126 | } else { 127 | dwStatus = TRUE; 128 | } 129 | if (!WriteFile(hOutFile, chunk, ciphertextLen, &written, NULL)) { 130 | printf("writing failed!\n"); 131 | break; 132 | } 133 | memset(chunk, 0, chunk_size); 134 | } 135 | 136 | CryptReleaseContext(hProv, 0); 137 | CryptDestroyKey(hKey); 138 | CryptDestroyHash(hHash); 139 | 140 | CloseHandle(hInpFile); 141 | CloseHandle(hOutFile); 142 | return dwStatus; 143 | } 144 | -------------------------------------------------------------------------------- /princesslocker_decrypt/decryptor/decryptor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #pragma comment(lib, "crypt32.lib") 7 | 8 | #define BLOCK_LEN 128 9 | 10 | wchar_t* get_extension_ptr(IN wchar_t *filename); 11 | bool is_infected(wchar_t* filename, wchar_t* extension); 12 | bool is_existing(IN const wchar_t *filename); 13 | bool is_directory(IN const wchar_t *filename); 14 | bool get_original_name(IN const wchar_t *filename1, IN const wchar_t *extension, OUT wchar_t *out_filename); 15 | 16 | BOOL aes_decrypt_file(const wchar_t* filename, const wchar_t* filename2, const wchar_t* key_str); -------------------------------------------------------------------------------- /princesslocker_decrypt/decryptor/main.cpp: -------------------------------------------------------------------------------- 1 | #include "decryptor.h" 2 | #include "PathCrawler.h" 3 | 4 | #define VERSION "0.2.5" 5 | 6 | bool make_outfilename(IN const wchar_t *filename1, IN const wchar_t *extension, OUT wchar_t *out_filename) 7 | { 8 | if (filename1 == NULL || out_filename == NULL) { 9 | return false; 10 | } 11 | 12 | if (!get_original_name(filename1, extension, out_filename)) { 13 | return false; 14 | } 15 | if (is_existing(out_filename)) { 16 | size_t len = lstrlenW(out_filename); 17 | if (len < MAX_PATH) { 18 | out_filename[len] = '_'; 19 | out_filename[len+1] = 0; 20 | } 21 | } 22 | return true; 23 | } 24 | 25 | void banner() 26 | { 27 | printf("-------------------------------------------------------------------\n"); 28 | printf("PrincessLocker Decryptor v%s\n", VERSION); 29 | printf("Questions? Remarks? Contact the author: hasherezade@gmail.com\n"); 30 | printf("-------------------------------------------------------------------\n"); 31 | } 32 | 33 | //params: [directory/file] 34 | int wmain(int argc, wchar_t *argv[]) 35 | { 36 | wchar_t *dirname = NULL; //input file 37 | wchar_t *key_str = NULL; 38 | wchar_t *extension = NULL; 39 | 40 | banner(); 41 | 42 | if (argc < 3) { 43 | printf("Expected params: [file/directory name] \n"); 44 | system("pause"); 45 | return (-1); 46 | } else { 47 | key_str = argv[1]; 48 | extension = argv[2]; 49 | if (argc >= 4) { 50 | dirname = argv[3]; 51 | } 52 | } 53 | printf("Key: %S\n", key_str); 54 | printf("Ransom extension: %S\n", extension); 55 | printf("----\n"); 56 | 57 | if (dirname == NULL) { 58 | PathCrawler::listDir(L"", extension, key_str, true); 59 | system("pause"); 60 | return 0; 61 | } 62 | 63 | if (is_directory(dirname)) { 64 | PathCrawler::listDir(dirname, extension, key_str, true); 65 | system("pause"); 66 | return 0; 67 | } 68 | 69 | wchar_t filename2[MAX_PATH]; 70 | if (!make_outfilename(dirname, extension, filename2)) { 71 | printf("Coud not make output filename\n"); 72 | system("pause"); 73 | return -1; 74 | } 75 | printf("Input File: %S\n", dirname); 76 | printf("Output File: %S\n", filename2); 77 | printf("----\n"); 78 | 79 | if (aes_decrypt_file(dirname, filename2, key_str)) { 80 | printf("[+] Decrypted! Check the output: %S\n", filename2); 81 | } else { 82 | printf("[-] Decrypting failed!\n"); 83 | } 84 | system("pause"); 85 | return 0; 86 | } -------------------------------------------------------------------------------- /princesslocker_decrypt/keygen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8) 2 | project (PrincessKeygen) 3 | 4 | add_definitions(-DUNICODE -D_UNICODE) 5 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") 6 | 7 | set (srcs 8 | aes_crypt.cpp 9 | main.cpp 10 | ) 11 | 12 | set (hdrs 13 | aes_crypt.h 14 | ) 15 | 16 | add_executable (PrincessKeygen ${hdrs} ${srcs}) -------------------------------------------------------------------------------- /princesslocker_decrypt/keygen/README.md: -------------------------------------------------------------------------------- 1 | #PrincessKeygen 2 | 3 | Keygen for Princess Locker ransomware. -------------------------------------------------------------------------------- /princesslocker_decrypt/keygen/aes_crypt.cpp: -------------------------------------------------------------------------------- 1 | #include "aes_crypt.h" 2 | 3 | size_t read_from_file(LPWSTR filename, BYTE *buffer, size_t buffer_size) 4 | { 5 | HANDLE hInpFile = CreateFileW(filename, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); 6 | 7 | if (hInpFile == NULL) { 8 | printf("Cannot open input file!\n"); 9 | return false; 10 | } 11 | 12 | DWORD read = 0; 13 | ReadFile(hInpFile, buffer, buffer_size, &read, NULL); 14 | CloseHandle(hInpFile); 15 | return read; 16 | } 17 | 18 | BOOL aes_decrypt(BYTE *inbuf, BYTE *outbuf, size_t buf_size, LPCWSTR key_str, size_t key_len) 19 | { 20 | if (inbuf == NULL || outbuf == NULL) return FALSE; 21 | 22 | BOOL dwStatus = FALSE; 23 | 24 | BOOL bResult = FALSE; 25 | wchar_t info[] = L"Microsoft Enhanced RSA and AES Cryptographic Provider"; 26 | HCRYPTPROV hProv; 27 | if (!CryptAcquireContextW(&hProv, NULL, info, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ 28 | dwStatus = GetLastError(); 29 | printf("CryptAcquireContext failed: %x\n", dwStatus); 30 | CryptReleaseContext(hProv, 0); 31 | return dwStatus; 32 | } 33 | HCRYPTHASH hHash; 34 | if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)){ 35 | dwStatus = GetLastError(); 36 | printf("CryptCreateHash failed: %x\n", dwStatus); 37 | CryptReleaseContext(hProv, 0); 38 | return dwStatus; 39 | } 40 | 41 | if (!CryptHashData(hHash, (BYTE*)key_str, key_len, 0)) { 42 | DWORD err = GetLastError(); 43 | printf ("CryptHashData Failed : %#x\n", err); 44 | return dwStatus; 45 | } 46 | 47 | HCRYPTKEY hKey; 48 | if (!CryptDeriveKey(hProv, CALG_AES_128, hHash, 0,&hKey)){ 49 | dwStatus = GetLastError(); 50 | printf("CryptDeriveKey failed: %x\n", dwStatus); 51 | CryptReleaseContext(hProv, 0); 52 | return dwStatus; 53 | } 54 | 55 | const size_t chunk_size = BLOCK_LEN; 56 | 57 | DWORD read = 0; 58 | DWORD written = 0; 59 | 60 | DWORD ciphertextLen = BLOCK_LEN; 61 | 62 | memcpy(outbuf, inbuf, chunk_size); 63 | 64 | if (CryptDecrypt(hKey, NULL, FALSE, 0,outbuf, &ciphertextLen)) { 65 | //printf ("[+] crypt OK!\n"); 66 | dwStatus = TRUE; 67 | } 68 | 69 | CryptReleaseContext(hProv, 0); 70 | CryptDestroyKey(hKey); 71 | CryptDestroyHash(hHash); 72 | 73 | return dwStatus; 74 | } 75 | 76 | BOOL aes_decrypt_file(LPWSTR filename, LPWSTR filename2, LPCWSTR key_str, size_t key_len) 77 | { 78 | if (filename == NULL || filename2 == NULL) return FALSE; 79 | 80 | BOOL dwStatus = FALSE; 81 | printf("Key: %S\n", key_str); 82 | printf("Key len: %#x\n", key_len); 83 | printf("Input File: %S\n", filename); 84 | printf("Output File: %S\n", filename2); 85 | printf("----\n"); 86 | 87 | wchar_t info[] = L"Microsoft Enhanced RSA and AES Cryptographic Provider"; 88 | HCRYPTPROV hProv; 89 | if (!CryptAcquireContextW(&hProv, NULL, info, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)){ 90 | dwStatus = GetLastError(); 91 | printf("CryptAcquireContext failed: %x\n", dwStatus); 92 | CryptReleaseContext(hProv, 0); 93 | return dwStatus; 94 | } 95 | HCRYPTHASH hHash; 96 | if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)){ 97 | dwStatus = GetLastError(); 98 | printf("CryptCreateHash failed: %x\n", dwStatus); 99 | CryptReleaseContext(hProv, 0); 100 | return dwStatus; 101 | } 102 | 103 | if (!CryptHashData(hHash, (BYTE*)key_str, key_len, 0)) { 104 | DWORD err = GetLastError(); 105 | printf ("CryptHashData Failed : %#x\n", err); 106 | return dwStatus; 107 | } 108 | HCRYPTKEY hKey; 109 | if (!CryptDeriveKey(hProv, CALG_AES_128, hHash, 0,&hKey)){ 110 | dwStatus = GetLastError(); 111 | printf("CryptDeriveKey failed: %x\n", dwStatus); 112 | CryptReleaseContext(hProv, 0); 113 | return dwStatus; 114 | } 115 | 116 | const size_t chunk_size = BLOCK_LEN; 117 | BYTE chunk[chunk_size]; 118 | DWORD read = 0; 119 | DWORD written = 0; 120 | 121 | HANDLE hInpFile = CreateFileW(filename, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); 122 | HANDLE hOutFile = CreateFileW(filename2, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 123 | 124 | if (hInpFile == NULL) { 125 | printf("Cannot open input file!\n"); 126 | return dwStatus; 127 | } 128 | if (hOutFile == NULL) { 129 | printf("Cannot open output file!\n"); 130 | return dwStatus; 131 | } 132 | while (ReadFile(hInpFile, chunk, chunk_size, &read, NULL)) { 133 | if (0 == read){ 134 | break; 135 | } 136 | DWORD ciphertextLen = BLOCK_LEN; 137 | if (!CryptDecrypt(hKey, NULL, FALSE, 0,chunk, &ciphertextLen)) { 138 | printf("failed!\n"); 139 | dwStatus = FALSE; 140 | break; 141 | } else { 142 | dwStatus = TRUE; 143 | } 144 | if (!WriteFile(hOutFile, chunk, ciphertextLen, &written, NULL)) { 145 | printf("writing failed!\n"); 146 | break; 147 | } 148 | memset(chunk, 0, chunk_size); 149 | } 150 | 151 | CryptReleaseContext(hProv, 0); 152 | CryptDestroyKey(hKey); 153 | CryptDestroyHash(hHash); 154 | 155 | CloseHandle(hInpFile); 156 | CloseHandle(hOutFile); 157 | return dwStatus; 158 | } 159 | -------------------------------------------------------------------------------- /princesslocker_decrypt/keygen/aes_crypt.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #pragma comment(lib, "crypt32.lib") 7 | 8 | #define BLOCK_LEN 128 9 | 10 | 11 | size_t read_from_file(LPWSTR filename, BYTE *buffer, size_t buffer_size); 12 | BOOL aes_decrypt(BYTE *inbuf, BYTE *outbuf, size_t buf_size, LPCWSTR key_str, size_t key_len); 13 | BOOL aes_decrypt_file(LPWSTR filename, LPWSTR filename2, LPCWSTR key_str, size_t key_len); -------------------------------------------------------------------------------- /princesslocker_decrypt/keygen/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "aes_crypt.h" 7 | 8 | #define VERSION "0.2" 9 | 10 | #define CHARSET "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" 11 | #define MIN_KEY 0x15 12 | #define MAX_KEY 0x20 13 | 14 | wchar_t* make_key(size_t len, size_t seed, bool is_key = true) 15 | { 16 | wchar_t *key_buf = (wchar_t*) calloc(len + 1, sizeof(wchar_t)); 17 | if (key_buf == NULL) return NULL; 18 | 19 | char charset[] = CHARSET; 20 | size_t charset_len = strlen(charset); 21 | 22 | srand(seed); 23 | for (int i = 0; i < len; i++) { 24 | size_t index = rand() % charset_len; 25 | key_buf[i] = charset[index]; 26 | if (!is_key) { 27 | key_buf[i] = tolower(charset[index]); 28 | } 29 | } 30 | return key_buf; 31 | } 32 | 33 | DWORD find_seed(wchar_t* uid, DWORD start_seed, bool increment = true, bool is_key = true) 34 | { 35 | size_t uid_len = lstrlenW(uid); 36 | 37 | const char charset[] = CHARSET; 38 | const size_t charset_len = strlen(charset); 39 | DWORD seed = start_seed; 40 | 41 | size_t pos = 0; 42 | while (true) { 43 | srand(seed); 44 | 45 | for (pos = 0; pos < uid_len; pos++) { 46 | size_t index = rand() % charset_len; 47 | char rand_char = charset[index]; 48 | if (!is_key) { 49 | rand_char = tolower(rand_char); 50 | } 51 | if (rand_char != uid[pos]) { 52 | break; 53 | } 54 | } 55 | if (pos < uid_len) { 56 | pos = 0; 57 | seed = (increment) ? seed + 1 : seed - 1; 58 | } else { 59 | return seed; 60 | } 61 | } 62 | return -1; 63 | } 64 | 65 | DWORD find_key_seed(wchar_t* uid, DWORD start_seed, bool increment = true) 66 | { 67 | return find_seed(uid, start_seed, increment, true); 68 | } 69 | 70 | DWORD find_uid_seed(wchar_t* uid, DWORD start_seed, bool increment = true) 71 | { 72 | return find_seed(uid, start_seed, increment, false); 73 | } 74 | 75 | DWORD find_start_seed(wchar_t *uid, wchar_t *ext, DWORD init_seed) 76 | { 77 | DWORD seed = init_seed; 78 | DWORD uid_seed = 0; 79 | DWORD ext_seed = 0; 80 | 81 | //printf ("i: %#x\n", init_seed); 82 | if (uid) { 83 | uid_seed = find_uid_seed(uid, seed, false); 84 | //printf ("u: %#x\n", uid_seed); 85 | } 86 | if (!ext) return uid_seed; 87 | 88 | if (uid) { 89 | ext_seed = find_uid_seed(ext, uid_seed, true); 90 | } else { 91 | ext_seed = find_uid_seed(ext, seed, false); 92 | } 93 | //printf ("e: %#x\n", ext_seed); 94 | if (uid && ext_seed - uid_seed > 100) { 95 | printf("[WARNING] Inconsistency detected!\n"); 96 | } 97 | if (uid) return uid_seed; 98 | return ext_seed; //lower quality recognition! 99 | } 100 | 101 | bool check_key(BYTE* inbuf, BYTE *expbuf, size_t check_size, wchar_t* key_str, size_t key_len) 102 | { 103 | BYTE outbuf[BLOCK_LEN]; 104 | 105 | if (!aes_decrypt(inbuf, outbuf, BLOCK_LEN, key_str, key_len)) { 106 | return false; 107 | } 108 | if (memcmp(outbuf, expbuf, check_size) == 0) { 109 | return true; 110 | } 111 | return false; 112 | } 113 | 114 | size_t read_buffer(LPWSTR filename, BYTE *buffer, size_t buffer_size) 115 | { 116 | HANDLE hInpFile = CreateFileW(filename, GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); 117 | 118 | if (hInpFile == NULL) { 119 | printf("Cannot open input file!\n"); 120 | return false; 121 | } 122 | 123 | DWORD read = 0; 124 | ReadFile(hInpFile, buffer, buffer_size, &read, NULL); 125 | CloseHandle(hInpFile); 126 | return read; 127 | } 128 | 129 | bool is_existing(IN const wchar_t *filename) 130 | { 131 | if(INVALID_FILE_ATTRIBUTES == GetFileAttributes(filename) && GetLastError()==ERROR_FILE_NOT_FOUND) { 132 | return false; 133 | } 134 | return true; 135 | } 136 | 137 | wchar_t* get_extension_ptr(IN wchar_t *filename) 138 | { 139 | size_t len = lstrlenW(filename); 140 | for (int i = len - 1; i > 0; i--) { 141 | if (filename[i] == '.') { 142 | return &filename[i]; 143 | } 144 | } 145 | return NULL; 146 | } 147 | 148 | bool get_original_name(IN const wchar_t *filename1, IN const wchar_t *extension, OUT wchar_t *out_filename) 149 | { 150 | if (filename1 == NULL || extension == NULL || out_filename == NULL) { 151 | return false; 152 | } 153 | wcscpy(out_filename, filename1); 154 | 155 | wchar_t *ptr = wcsstr(out_filename, extension); 156 | if (ptr == NULL) { 157 | return false; 158 | } 159 | ptr--; 160 | if (*(ptr) != '.') { 161 | return false; 162 | } 163 | (*ptr) = 0; 164 | return true; 165 | } 166 | 167 | bool make_outfilename(IN const wchar_t *filename1, IN const wchar_t *extension, OUT wchar_t *out_filename) 168 | { 169 | if (filename1 == NULL || extension == NULL || out_filename == NULL) { 170 | return false; 171 | } 172 | if (!get_original_name(filename1, extension, out_filename)) { 173 | return false; 174 | } 175 | if (is_existing(out_filename)) { 176 | size_t len = lstrlenW(out_filename); 177 | if (len < MAX_PATH) { 178 | out_filename[len] = '_'; 179 | out_filename[len+1] = 0; 180 | } 181 | } 182 | return true; 183 | } 184 | 185 | bool dump_key(char* filename, wchar_t* key) 186 | { 187 | FILE *fp = fopen(filename, "w"); 188 | if (fp == NULL) return false; 189 | fprintf(fp,"%S\n", key); 190 | fclose(fp); 191 | return true; 192 | } 193 | 194 | size_t get_check_size(IN const wchar_t *filename1, IN const wchar_t *extension, IN const wchar_t *filename2) 195 | { 196 | wchar_t orig_name[MAX_PATH]; 197 | if (!get_original_name(filename1, extension, orig_name)) { 198 | printf("-"); 199 | return false; 200 | } 201 | wchar_t *ext = get_extension_ptr(orig_name); 202 | if (ext == NULL) return false; 203 | 204 | if (wcscmp(filename2, orig_name) == 0) { 205 | return BLOCK_LEN; 206 | } 207 | printf("File used for validation: %S\n", filename2); 208 | DWORD len = 0; 209 | swscanf(filename2, L"%d", &len); 210 | return len; 211 | } 212 | 213 | wchar_t* find_key(IN wchar_t *filename1, IN wchar_t *filename2, size_t check_size, DWORD uid_seed, DWORD limit=100) 214 | { 215 | bool increment = false; 216 | bool found = false; 217 | 218 | BYTE in_buf[BLOCK_LEN+1]; 219 | memset(in_buf, 0, BLOCK_LEN+1); 220 | 221 | BYTE expected_buf[BLOCK_LEN+1]; 222 | memset(expected_buf, 0, BLOCK_LEN+1); 223 | 224 | if (read_buffer(filename1, in_buf, BLOCK_LEN) == 0) { 225 | printf("Cannot read the file: %S\n", filename1); 226 | system("pause"); 227 | return 0; 228 | } 229 | if (read_buffer(filename2, expected_buf, BLOCK_LEN) == 0) { 230 | printf("Cannot read the file: %S\n", filename2);; 231 | system("pause"); 232 | return 0; 233 | } 234 | DWORD key_seed = uid_seed; 235 | size_t key_len = 0; 236 | wchar_t *key = NULL; 237 | printf("."); 238 | do { 239 | key = make_key(MAX_KEY, key_seed, true); 240 | for (key_len = MIN_KEY; key_len <= MAX_KEY; key_len++) { 241 | if (check_key(in_buf, expected_buf, check_size, key, key_len)) { 242 | printf("\nMatch found, accuracy %d/%d\n", check_size, BLOCK_LEN); 243 | key[key_len] = 0; 244 | found = true; 245 | break; 246 | } 247 | } 248 | if (!found) { 249 | limit--; 250 | key_seed = (increment) ? key_seed + 1 : key_seed - 1; 251 | free(key); 252 | key = NULL; 253 | } 254 | } while (!found && limit > 0); 255 | 256 | //--- 257 | if (key) { 258 | printf("---\n"); 259 | printf("%S\n", key); 260 | printf("---\n"); 261 | } 262 | return key; 263 | } 264 | 265 | void banner() 266 | { 267 | printf("-------------------------------------------------------------------\n"); 268 | printf("PrincessLocker Keygen v%s\n", VERSION); 269 | printf("Questions? Remarks? Contact the author: hasherezade@gmail.com\n"); 270 | printf("-------------------------------------------------------------------\n"); 271 | } 272 | 273 | int wmain(int argc, wchar_t *argv[]) 274 | { 275 | wchar_t *filename1 = NULL; 276 | wchar_t *extension = NULL; 277 | wchar_t *unique_id = NULL; 278 | wchar_t *filename2 = NULL; 279 | banner(); 280 | if (argc < 4) { 281 | printf("Expected params: [unique id]\n"); 282 | system("pause"); 283 | return (-1); 284 | } else { 285 | filename1 = argv[1]; 286 | filename2 = argv[2]; 287 | extension = argv[3]; 288 | if (argc < 5) { 289 | printf("[WARNING] If you have the ransom note, please supply your unique ID!\n"); 290 | } else { 291 | unique_id = argv[4]; 292 | } 293 | } 294 | 295 | wchar_t out_filename[MAX_PATH]; 296 | memset(out_filename, 0, MAX_PATH); 297 | if (!make_outfilename(filename1, extension, out_filename)) { 298 | printf("Input file not matching the extension!\n"); 299 | system("pause"); 300 | return (-1); 301 | } 302 | 303 | size_t check_size = get_check_size(filename1, extension, filename2); 304 | printf("Setting check size: %d\n", check_size); 305 | if (check_size < 4) { 306 | printf("---ERROR---\n"); 307 | printf("Invalid parameters:\n"); 308 | printf(" must have a name in the following format .\n"); 309 | printf("Check size is the lenght of the header for particular format.\n Choose the format that has a header not shorter than 4 bytes.\n"); 310 | system("pause"); 311 | return (-1); 312 | } 313 | 314 | printf("Searching the key..."); 315 | DWORD init_seed = time(NULL); 316 | wchar_t *key = NULL; 317 | size_t limit = 100; 318 | do { 319 | DWORD uid_seed = find_start_seed(unique_id, extension, init_seed); 320 | key = find_key(filename1, filename2, check_size, uid_seed, limit); 321 | init_seed = uid_seed - 1; 322 | } while (!key); 323 | 324 | size_t key_len = lstrlenW(key); 325 | BOOL res = aes_decrypt_file(filename1, out_filename, key, key_len); 326 | if (res) { 327 | printf("[+] Finished successfuly.\n"); 328 | printf("[+] Check if the output file is valid: \"%S\"\n", out_filename); 329 | printf("[+] Save your key: %S\n", key); 330 | 331 | char* key_filename = "princess_key.txt"; 332 | dump_key(key_filename, key); 333 | printf("[+] Key dumped to: %s\n", key_filename); 334 | 335 | } else { 336 | printf("[ERROR] Decrypting your file failed!\n"); 337 | } 338 | system("pause"); 339 | return 0; 340 | } 341 | --------------------------------------------------------------------------------