├── LICENSE ├── README.md ├── extract_strings.py ├── file_scan.py ├── freq_analysis.py ├── gibbersense.py ├── rotation_cipher.py ├── string_scan.py └── visualizer_module.py /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gibbersense 2 | 3 | Found a Gibberish string or file in the wild and dont know what is it? Throw it to GibberSense, it might try to make some sense out of it. 4 | 5 | Being an extensible framework, we are adding more to the capabilities of GibberSense. 6 | 7 | 8 | Extract Sense out of Gibberish stuff 9 | 10 | 11 | (An Open Source Initiative by - SECURITY MONX ) 12 | 13 | 14 | Gibber Sense Documentation 15 | 16 | File Name : README 17 | 18 | Author : @ajithatti 19 | 20 | Org : Security Monx 21 | 22 | Version : 0.0.1 23 | 24 | Purpose : Gives introduction of Gibber Sense 25 | 26 | 27 | 28 | 29 | Table Of Contents : 30 | 31 | A. Licenses Information 32 | B. Introduction to Gibber Sense 33 | C. Dependencies 34 | D. Using Gibber Sense 35 | E. Features 36 | F. Note 37 | G. Contributors 38 | 39 | 40 | 41 | 42 | A. Licenses Information 43 | 44 | The Unlicense (http://unlicense.org/) 45 | 46 | 47 | 48 | 49 | B. Introduction to Gibber Sense 50 | 51 | Gibber Sense is a python based tool and extension to LAMMA also known as BCAF (Basic Crypt Analysis Framework) module. 52 | The best use case Gibber Sense is to verify the robustness of encryption libraries if they are free from any backdoor or flaws. But it can also be used to guess type of encryption , hashing schemes, type of encrypted session cookies. If you trying to develop your own secrete encryption scheme, Try and see what GibberSense has to say about it. 53 | 54 | Gibber Sense takes 2 types of inputs Strings and Files. Once you feed any gibberish input, it tries to make sense out of it using statistical and basic crypt analysis 55 | 56 | Gibber Sense can identify 100 different string formats and can give you directions for further investigations. 57 | For Files, Gibber Sense offers - 58 | * Content type analysis, 59 | * Strings extraction, 60 | * Frequency Analysis, 61 | * Decryption of substitution ciphers, 62 | * Attempts decryption with all popular encryption schemes using null keys, 63 | * Entropy visualization 64 | * XORring 65 | * and pattern analysis. 66 | 67 | 68 | C. Dependencies : Gibber Sense uses following python modules : 69 | 70 | 1. magic - Identifies the File Type 71 | 72 | pip install python-magic 73 | 74 | 2. PIL - Python Imaging Library 75 | 76 | pip install pil 77 | 78 | 79 | 80 | D. Using Gibber Sense : 81 | 82 | 1. Gibber Sense is a command line tool 83 | 84 | $ python gibbersense.py 85 | 86 | .d8888b. d8b 888 888 .d8888b. 87 | d88P Y88b Y8P 888 888 d88P Y88b 88 | 888 888 888 888 Y88b. 89 | 888 888 88888b. 88888b. .d88b. 888d888 "Y888b. .d88b. 88888b. .d8888b .d88b. 90 | 888 88888 888 888 "88b 888 "88b d8P Y8b 888P" "Y88b. d8P Y8b 888 "88b 88K d8P Y8b 91 | 888 888 888 888 888 888 888 88888888 888 "888 88888888 888 888 "Y8888b. 88888888 92 | Y88b d88P 888 888 d88P 888 d88P Y8b. 888 Y88b d88P Y8b. 888 888 X88 Y8b. 93 | "Y8888P88 888 88888P" 88888P" "Y8888 888 "Y8888P" "Y8888 888 888 88888P" "Y8888 94 | 95 | 96 | 97 | gibbersense.py [-h] [-s] [-f] [-o] 98 | 99 | Purpose : Gibber Sense accepts any gibberish string or file and 100 | tries to extract sense out of it 101 | 102 | 103 | -h [--help] : prints this usage help 104 | -s [--string] : provide a string parameter to Gibber Sense 105 | -f [--file] : proivde a file path parameter to Gibber Sense 106 | -o [--out] : save the result of analysis to this file 107 | 108 | 109 | 110 | 2. Analyze a String 111 | 112 | $ python gibbersense.py -s "eb5b3ed9d88a9a43d95a4a97958190c0" 113 | 114 | [+] Processing String eb5b3ed9d88a9a43d95a4a97958190c0 115 | 116 | 117 | [+] Statistical Analysis : 118 | 119 | String Length = 32 120 | 121 | [+] Findings : 122 | 123 | May be the string is MD4 Sum 124 | 125 | May be the string is MD5 Sum 126 | 127 | May be the string is NTLM Token 128 | 129 | You can check with https://crackstation.net/ if they have cracked this string 130 | 131 | The string is hexa decimal 132 | 133 | 134 | [+] Analysis complete... 135 | 136 | 137 | 138 | 3. Analyze a file 139 | python gibbersense.py -f test.pdf 140 | 141 | [+] Processing File : test.pdf 142 | 143 | 144 | [+] Gibber Sense Statistical Analysis 145 | 146 | % of printable ASCII Chars : 38 147 | % of printable LOW Chars : 12 148 | % of printable HIGH Chars : 49 149 | number of printable NULL Chars : 2026 150 | File size in number of Chars : 526477 151 | 152 | [+] Findings : 153 | 154 | 155 | The file type is found to be BINARY 156 | 157 | File Type : PDF document, version 1.4 158 | 159 | [+] Suggestions 160 | 161 | The visualization of file < test.pdf > is stored in < test.pdf.png > 162 | 163 | [+] Analysis complete... 164 | 165 | 166 | 167 | 168 | $ python gibbersense.py -f rot.txt .pdf 169 | 170 | [+] Processing File : rot.txt 171 | 172 | 173 | The visualization of file < rot.txt > is stored in < rot.txt.png > 174 | [+] Gibber Sense Statistical Analysis 175 | 176 | % of printable ASCII Chars : 99 177 | % of printable LOW Chars : 0 178 | % of printable HIGH Chars : 0 179 | number of printable NULL Chars : 0 180 | File size in number of Chars : 3568 181 | 182 | [+] Findings : 183 | 184 | 185 | The file type is found to be TEXT 186 | 187 | File Type : UTF-8 Unicode text, with very long lines 188 | 189 | [+] Suggestions 190 | 191 | Looks like an Encoded file. Try decoding or substitution cipher 192 | 193 | Consider Frequency analysis of the Text file 194 | 195 | The visualization of file < rot.txt > is stored in < rot.txt.png > 196 | 197 | [+] Analysis complete... 198 | 199 | 200 | 201 | 202 | E. Features : 203 | 204 | The Gibber Sense tool is aimed at assist in basic crypt-analysis : 205 | 206 | 1. BASIC : 207 | Gibber Sense attempts to check if a file conents are text or binary. 208 | Looks for English contents in the Text file. 209 | based on the contents it suggests next course of action. 210 | 211 | 2. Statistical Analysis : 212 | Gibber Sense provides stastical analysis of text contents. 213 | be able to extend the functionalities easily by adding custom 214 | plugins. 215 | 216 | 3. Visualization : 217 | Gibber Sense generated pixel map for the contents of a file to 218 | visually detect the randomness/patterns. 219 | 220 | 4. Basic Cryptanalysis : 221 | Gibber Sense has scripts to perform rotation ciphers, XOR crypt and 222 | decryption with aes-128-xxx-mode with NULL passwords. 223 | 224 | 225 | F. Note : 226 | 227 | We are putting more analysis behind Gibber Sense. Help us to make it better by reaching us at 228 | 229 | a j i t [ a t ] s e c u r i t y m o n x [ d o t ] c o m 230 | 231 | 232 | 233 | 234 | G.Contributors 235 | 236 | 1. Ajit Hatti - @ajithatti 237 | 238 | -------------------------------------------------------------------------------- /extract_strings.py: -------------------------------------------------------------------------------- 1 | # 2 | # # 3 | # .d8888b. d8b 888 888 .d8888b. # 4 | # d88P Y88b Y8P 888 888 d88P Y88b # 5 | # 888 888 888 888 Y88b. # 6 | # 888 888 88888b. 88888b. .d88b. 888d888 "Y888b. .d88b. 88888b. .d8888b .d88b. # 7 | # 888 88888 888 888 "88b 888 "88b d8P Y8b 888P" "Y88b. d8P Y8b 888 "88b 88K d8P Y8b # 8 | # 888 888 888 888 888 888 888 88888888 888 "888 88888888 888 888 "Y8888b. 88888888 # 9 | # Y88b d88P 888 888 d88P 888 d88P Y8b. 888 Y88b d88P Y8b. 888 888 X88 Y8b. # 10 | # "Y8888P88 888 88888P" 88888P" "Y8888 888 "Y8888P" "Y8888 888 888 88888P' "Y8888 # 11 | # # 12 | # 13 | # (beta) 14 | # 15 | # 16 | # Plugin Name : freq_analysis.py 17 | # Plugin ID : fqa-01 18 | # Plugin Purpose : Provides frequency analysis of a file contents. 19 | # Used to analyse subsitution cipher. 20 | # 21 | # Plugin Author : @ajithatti 22 | # 23 | # Plugin Version : 0.0.1 24 | # Plugin Status : beta 25 | # 26 | ################################################################################ 27 | 28 | 29 | 30 | # Include Section 31 | import os.path 32 | import getopt 33 | import os 34 | import re 35 | import sys 36 | from sys import argv, stdout 37 | 38 | from PIL import Image 39 | import random 40 | import string 41 | 42 | # -------------------------------------------------------------------------------- 43 | # Function : usage 44 | # 45 | # Purpose : Proivde a mini help on usage of this program 46 | # 47 | # Parameters : None 48 | # 49 | # Returns : None 50 | 51 | def usage(script): 52 | print "\n\n %s [-o] [-i] " %script 53 | print "\n Purpose : Computes the frequency distribution each alphabet" 54 | print " present in a file. Used for crypt analysis of " 55 | print " common subsitution ciphers of English text" 56 | print "\n" 57 | print " -o [--out] : stores the frequency distribution table in a givne file" 58 | print " -i [--in] : path of a file to be analyzed" 59 | print " \n\n\n" 60 | 61 | sys.exit(2) 62 | 63 | 64 | pass # USAGE BLOCK 65 | 66 | 67 | # -------------------------------------------------------------------------------- 68 | # Function : usage 69 | # 70 | # Purpose : Proivde a mini help on usage of this program 71 | # 72 | # Parameters : None 73 | # 74 | # Returns : None 75 | 76 | 77 | def log( message, sink) : 78 | 79 | sink.write(message) 80 | pass 81 | 82 | 83 | # -------------------------------------------------------------------------------- 84 | # Function : usage 85 | # 86 | # Purpose : Proivde a mini help on usage of this program 87 | # 88 | # Parameters : None 89 | # 90 | # Returns : None 91 | 92 | def strings(in_file): 93 | 94 | min = 4 95 | 96 | with open(in_file, "rb") as f: 97 | result = "" 98 | for c in f.read(): 99 | if c in string.printable: 100 | result += c.strip() 101 | continue 102 | if len(result) >= min: 103 | yield result 104 | result = "" 105 | if len(result) >= min: # catch result at EOF 106 | yield result 107 | 108 | 109 | # -------------------------------------------------------------------------------- 110 | # Function : usage 111 | # 112 | # Purpose : Proivde a mini help on usage of this program 113 | # 114 | # Parameters : None 115 | # 116 | # Returns : None 117 | 118 | 119 | def extract_string(in_file, sink): 120 | 121 | for s in strings(in_file): 122 | log(("\n"+s), sink) 123 | 124 | 125 | pass 126 | 127 | 128 | # -------------------------------------------------------------------------------- 129 | # Function : main 130 | # 131 | # Purpose : Extracts ASCII/UNICODE Strings from a given file 132 | # 133 | # Parameters : in - path of a file to be analyzed 134 | # out - file to store extracted strings [OPTIONAL] 135 | # 136 | 137 | 138 | def main(argv): 139 | 140 | 141 | # Initialize the variables 142 | in_file = "" 143 | out_file = "" 144 | this_script = argv[0] 145 | sink = stdout 146 | 147 | 148 | if len(argv) < 3: 149 | usage(this_script) 150 | sys.exit(2) 151 | pass # if block 152 | 153 | # --- try block 154 | 155 | try: 156 | opts, args = getopt.getopt(argv[1:], "o:i:",["out=", "in="]) 157 | 158 | 159 | except getopt.GetoptError: 160 | usage(this_script) 161 | sys.exit(2) 162 | pass # TRY BLOCK 163 | 164 | #---- Process the arguments passed to the script 165 | 166 | for opt, arg in opts: 167 | 168 | if opt in ("-i", "--in"): 169 | in_file = arg 170 | elif opt in ("-o", "--out"): 171 | out_file = arg 172 | 173 | pass # IF BLOCK 174 | pass # FOR BLOCK 175 | 176 | 177 | if( out_file != ""): 178 | sink = open(out_file, "w") 179 | pass 180 | 181 | if( in_file == ""): 182 | print "\n File name for extracting strings is not specified, Exiting \n\n" 183 | return (-2) 184 | pass 185 | 186 | 187 | extract_string(in_file, sink) 188 | print ("\n") 189 | 190 | pass # main 191 | 192 | 193 | #------------------------------------------------------------------------------- 194 | # 195 | # Kick off the script 196 | 197 | if __name__ == "__main__": 198 | 199 | main (sys.argv[0:]) 200 | 201 | pass # IF BLOCK 202 | -------------------------------------------------------------------------------- /file_scan.py: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # 4 | # 5 | # .d8888b. d8b 888 888 .d8888b. 6 | # d88P Y88b Y8P 888 888 d88P Y88b 7 | # 888 888 888 888 Y88b. 8 | # 888 888 88888b. 88888b. .d88b. 888d888 "Y888b. .d88b. 88888b. .d8888b .d88b. 9 | # 888 88888 888 888 "88b 888 "88b d8P Y8b 888P" "Y88b. d8P Y8b 888 "88b 88K d8P Y8b 10 | # 888 888 888 888 888 888 888 88888888 888 "888 88888888 888 888 "Y8888b. 88888888 11 | # Y88b d88P 888 888 d88P 888 d88P Y8b. 888 Y88b d88P Y8b. 888 888 X88 Y8b. 12 | # "Y8888P88 888 88888P" 88888P" "Y8888 888 "Y8888P" "Y8888 888 888 88888P' "Y8888 13 | # 14 | # 15 | # (BETA) 16 | # 17 | # 18 | # Plugin Name : gibbersense.py 19 | # Plugin ID : gbrsns-01 20 | # Plugin Purpose : Gibber Sense Deamon 21 | # 22 | # Plugin Author : @ajithatti 23 | # 24 | # Plugin Version : 0.0.1 25 | # Plugin Status : beta 26 | # 27 | #==================================================================================================================================== 28 | 29 | # Include Section 30 | import subprocess 31 | import os 32 | import os.path 33 | import sys 34 | import getopt 35 | from sys import argv, stdout 36 | 37 | import visualizer_module as vizm 38 | import string_scan as sscan 39 | import magic 40 | 41 | # Plugin Informaiton 42 | 43 | # Env Variable 44 | 45 | # Plugin Mode 46 | 47 | # Settings 48 | 49 | # Report Findings 50 | 51 | #------------------------------------------------------------------------------ 52 | #Function : log 53 | # 54 | # Purpose : logs given string in to the designated sink 55 | # 56 | # Parameters : 1. message - message string to be logged 57 | # 2. The destination of the log 58 | # 59 | # Returns : None 60 | 61 | 62 | def log(message, sink): 63 | sink.write(message) 64 | pass 65 | 66 | 67 | 68 | # -------------------------------------------------------------------------------- 69 | # Function : usage 70 | # 71 | # Purpose : Proivde a mini help on usage of this program 72 | # 73 | # Parameters : None 74 | # 75 | # Returns : None 76 | 77 | def usage(script): 78 | print "\n\n %s [-h] [-s] [-f] " %script 79 | print "\n Purpose : Gibber Sense Deamon accepts any gibberish string or file and" 80 | print " tries to extract sense out of it" 81 | print "\n" 82 | print " -h [--help] : prints this usage help" 83 | print " -s [--string] : provide a string parameter to Gibber Sense" 84 | print " -f [--file] : proivde a file path parameter to Gibber Sense" 85 | print " \n\n\n" 86 | 87 | sys.exit(2) 88 | 89 | 90 | pass # USAGE BLOCK 91 | 92 | 93 | # -------------------------------------------------------------------------------- 94 | # Function : 95 | # 96 | # Purpose : 97 | # 98 | # Parameters : 99 | # 100 | # Returns : None 101 | 102 | 103 | def list_all_remote_scripts(path): 104 | indir = os.getcwd() 105 | 106 | prefix = "" 107 | 108 | if(indir.endswith("LAMMA")): 109 | prefix = "modules/remote-module/" 110 | 111 | if(indir.endswith("modules")): 112 | prefix = "remote-module/" 113 | 114 | indir = indir + "/" + prefix + path 115 | 116 | for root, dirs, filenames in sorted(os.walk(indir)): 117 | pos = indir.__len__() 118 | check_dir = root[pos:] 119 | if ( check_dir.find(".git") != -1): 120 | continue 121 | 122 | print "./" + root[pos:] + "/" 123 | 124 | for f in filenames: 125 | if f.endswith(".py"): 126 | if (f == "__init__.py"): 127 | continue 128 | print "\t ", f 129 | 130 | exit(0) 131 | 132 | 133 | pass 134 | 135 | 136 | 137 | 138 | # -------------------------------------------------------------------------------- 139 | # Function : get_path_prefix 140 | # 141 | # Purpose : based on from where the script is invoked, it returns the cwd 142 | # 143 | # Parameters : None 144 | # 145 | # Returns : relative cwd 146 | 147 | 148 | def get_path_prefix() : 149 | indir = os.getcwd() 150 | 151 | prefix = "" 152 | 153 | if (indir.endswith("LAMMA")): 154 | prefix = "modules/trust-module/" 155 | 156 | if (indir.endswith("modules")): 157 | prefix = "trust-module/" 158 | 159 | indir = indir + "/" + prefix 160 | 161 | return prefix 162 | pass 163 | 164 | 165 | 166 | 167 | def english_content_test(in_file): 168 | 169 | eng_count = 0 170 | word_count = 0 171 | with open (in_file) as f: 172 | for line in f: 173 | words = line.split() 174 | word_count += len (words) 175 | eng_count += sscan.english_test(line) 176 | pass 177 | pass 178 | 179 | ratio = float(eng_count)/float(word_count) 180 | 181 | if(ratio > float("0.5")): 182 | print ("\t\tThe content of the file is English") 183 | return True 184 | else : 185 | print ("\t\tLooks like an Encoded file. Try decoding or substitution cipher") 186 | return False 187 | 188 | pass 189 | 190 | 191 | 192 | def file_magic(in_file): 193 | 194 | 195 | print "\n\t\tFile Type :", magic.from_file(in_file) 196 | 197 | pass 198 | 199 | 200 | 201 | def file_scan(in_file): 202 | 203 | # 1. Stastical Analysis - tell the % of printable text, binary text, total text, file is Binary or text file 204 | image_file = vizm.drawImage(in_file) 205 | 206 | # 2. Generate Visuals 207 | out_file = in_file+".png" 208 | image_file.save(out_file) 209 | 210 | print "\n\t\tThe visualization of file <", in_file,"> is stored in <",out_file,">" 211 | 212 | 213 | 214 | vizm.print_stats() 215 | 216 | # 3. if Text file : read first 2 lines and see if its an english file 217 | 218 | file_magic(in_file) 219 | 220 | 221 | print "\n\t[+] Suggestions \n" 222 | 223 | 224 | if(vizm.FILE_TYPE["type"] == "TEXT" ): 225 | if(english_content_test(in_file) == False) : 226 | print ("\n\t\tConsider Frequency analysis of the Text file") 227 | pass 228 | pass 229 | # 4. if not english file then its a substitution cipher, do frequency analysis, else print english file 230 | 231 | 232 | # 5. do substituion cipher with a distance d 233 | # 6. if binary file: 234 | # 7. List the strings 235 | # 8. attempt simple decryption 236 | # 237 | 238 | 239 | pass 240 | 241 | 242 | 243 | 244 | # ------------------------------------------------------------------------------- 245 | # Function : main 246 | # 247 | # Purpose : The Gibber Sense script. 248 | # 249 | # Params : 1. argv (list) - list of command line arguments 250 | # 251 | # Returns : None 252 | 253 | 254 | def main(argv): 255 | 256 | # **** Lets process the arguments ********* 257 | 258 | # Initialize the variables 259 | 260 | this_script = argv[0] 261 | string = "" 262 | in_file = "" 263 | out_file = "" 264 | sink = stdout 265 | 266 | # ---- Show the usage for too few arguments 267 | 268 | if len(argv) < 3: 269 | usage(this_script) 270 | sys.exit(2) 271 | pass # if block 272 | 273 | # --- try block 274 | 275 | try: 276 | opts, args = getopt.getopt(argv[1:], "h:i:o:", 277 | ["help=", "in=", "out="]) 278 | 279 | 280 | except getopt.GetoptError: 281 | usage(this_script) 282 | sys.exit(2) 283 | pass # TRY BLOCK 284 | 285 | # ---- Process the arguments passed to the script 286 | 287 | for opt, arg in opts: 288 | if opt in ("-h", "--help"): 289 | usage(this_script) 290 | 291 | elif opt in ("-i", "--in"): 292 | in_file = arg 293 | 294 | elif opt in ("-o", "--out"): 295 | out_file = arg 296 | 297 | 298 | pass # IF BLOCK 299 | pass # FOR BLOCK 300 | 301 | # ---- collect the values and check 302 | 303 | 304 | if (in_file != ""): 305 | 306 | # process string 307 | print "Processing File ", string 308 | 309 | pass # if Block 310 | 311 | 312 | file_scan(in_file) 313 | 314 | pass # main 315 | 316 | 317 | 318 | 319 | # ------------------------------------------------------------------------------- 320 | # 321 | # Kick off the script 322 | 323 | if __name__ == "__main__": 324 | main(sys.argv[0:]) 325 | 326 | pass # IF BLOCK 327 | -------------------------------------------------------------------------------- /freq_analysis.py: -------------------------------------------------------------------------------- 1 | # 2 | # # 3 | # .d8888b. d8b 888 888 .d8888b. # 4 | # d88P Y88b Y8P 888 888 d88P Y88b # 5 | # 888 888 888 888 Y88b. # 6 | # 888 888 88888b. 88888b. .d88b. 888d888 "Y888b. .d88b. 88888b. .d8888b .d88b. # 7 | # 888 88888 888 888 "88b 888 "88b d8P Y8b 888P" "Y88b. d8P Y8b 888 "88b 88K d8P Y8b # 8 | # 888 888 888 888 888 888 888 88888888 888 "888 88888888 888 888 "Y8888b. 88888888 # 9 | # Y88b d88P 888 888 d88P 888 d88P Y8b. 888 Y88b d88P Y8b. 888 888 X88 Y8b. # 10 | # "Y8888P88 888 88888P" 88888P" "Y8888 888 "Y8888P" "Y8888 888 888 88888P' "Y8888 # 11 | # # 12 | # 13 | # (beta) 14 | # 15 | # 16 | # Plugin Name : freq_analysis.py 17 | # Plugin ID : fqa-01 18 | # Plugin Purpose : Provides frequency analysis of a file contents. 19 | # Used to analyse subsitution cipher. 20 | # 21 | # Plugin Author : @ajithatti 22 | # 23 | # Plugin Version : 0.0.1 24 | # Plugin Status : beta 25 | # 26 | ################################################################################ 27 | 28 | 29 | 30 | # Include Section 31 | import os.path 32 | import getopt 33 | import os 34 | import re 35 | import sys 36 | from sys import argv, stdout 37 | 38 | from PIL import Image 39 | import random 40 | 41 | 42 | # -------------------------------------------------------------------------------- 43 | # Function : usage 44 | # 45 | # Purpose : Proivde a mini help on usage of this program 46 | # 47 | # Parameters : None 48 | # 49 | # Returns : None 50 | 51 | def usage(script): 52 | print "\n\n %s [-o] [-i] " %script 53 | print "\n Purpose : Computes the frequency distribution each alphabet" 54 | print " present in a file. Used for crypt analysis of " 55 | print " common subsitution ciphers of English text" 56 | print "\n" 57 | print " -o [--out] : stores the frequency distribution table in a givne file" 58 | print " -i [--in] : path of a file to be analyzed" 59 | print " \n\n\n" 60 | 61 | sys.exit(2) 62 | 63 | 64 | pass # USAGE BLOCK 65 | 66 | 67 | # -------------------------------------------------------------------------------- 68 | # Function : usage 69 | # 70 | # Purpose : Proivde a mini help on usage of this program 71 | # 72 | # Parameters : None 73 | # 74 | # Returns : None 75 | 76 | 77 | def log( message, sink) : 78 | 79 | sink.write(message) 80 | pass 81 | 82 | 83 | buf = "" 84 | # -------------------------------------------------------------------------------- 85 | # Function : usage 86 | # 87 | # Purpose : Proivde a mini help on usage of this program 88 | # 89 | # Parameters : None 90 | # 91 | # Returns : None 92 | 93 | 94 | def file_process(in_file): 95 | 96 | f = open(in_file, "r") 97 | buf = f.read() 98 | return buf 99 | 100 | pass 101 | 102 | # -------------------------------------------------------------------------------- 103 | # Function : usage 104 | # 105 | # Purpose : Proivde a mini help on usage of this program 106 | # 107 | # Parameters : None 108 | # 109 | # Returns : None 110 | 111 | 112 | def print_table(table, in_file, sink): 113 | log( "\n\t\t\tFrequencey Distribution", sink) 114 | log("\n\t\t\t=======================", sink) 115 | log("\n\n", sink) 116 | 117 | 118 | outstr = "\n\tFile Name : "+ in_file + "\n\n" 119 | log(outstr, sink) 120 | 121 | i = 65 122 | while(i < 123): 123 | 124 | outstr = "\n\t"+ chr(i)+ " => "+ str(table[i]) 125 | log( outstr, sink) 126 | i += 1 127 | 128 | if(i == 91) : 129 | i = 97 130 | pass 131 | 132 | m = max(table) 133 | c = table.index(m) 134 | 135 | outstr = "\n\n\tHighest Freq of [" +chr(c)+ "] : "+ str(m) 136 | log(outstr, sink) 137 | 138 | dist = (101 - c) 139 | outstr= "\n\n\tThe distance from 'e' is "+ str(dist) 140 | log(outstr, sink) 141 | return dist 142 | 143 | 144 | pass 145 | 146 | 147 | 148 | # -------------------------------------------------------------------------------- 149 | # Function : usage 150 | # 151 | # Purpose : Proivde a mini help on usage of this program 152 | # 153 | # Parameters : None 154 | # 155 | # Returns : None 156 | 157 | 158 | def freq_analysis(in_file, sink): 159 | 160 | 161 | buf = file_process(in_file) 162 | 163 | l = len(buf) 164 | 165 | table = [0] * 255 166 | i = 0 167 | 168 | while (i < l) : 169 | 170 | c = ord(buf[i]) 171 | if( (c >= 65 and c <=90) or (c>= 97 and c <= 122)): 172 | table[c] +=1 173 | i +=1 174 | pass 175 | 176 | print_table(table, in_file, sink) 177 | 178 | pass 179 | 180 | 181 | # -------------------------------------------------------------------------------- 182 | # Function : main 183 | # 184 | # Purpose : Frequency analysis of contents of a file 185 | # 186 | # Parameters : in - path of a file to be analyzed 187 | # out - file in which frequency distribution is to be stored 188 | # 189 | # Returns : dist - Distance of hights frequency alphabet from 'e' 190 | 191 | 192 | def main(argv): 193 | 194 | 195 | # Initialize the variables 196 | in_file = "" 197 | out_file = "" 198 | this_script = argv[0] 199 | sink = stdout 200 | 201 | if len(argv) < 3: 202 | usage(this_script) 203 | sys.exit(2) 204 | pass # if block 205 | 206 | # --- try block 207 | 208 | try: 209 | opts, args = getopt.getopt(argv[1:], "o:i:",["out=", "in="]) 210 | 211 | 212 | except getopt.GetoptError: 213 | usage(this_script) 214 | sys.exit(2) 215 | pass # TRY BLOCK 216 | 217 | #---- Process the arguments passed to the script 218 | 219 | for opt, arg in opts: 220 | 221 | if opt in ("-i", "--in"): 222 | in_file = arg 223 | elif opt in ("-o", "--out"): 224 | out_file = arg 225 | pass # IF BLOCK 226 | pass # FOR BLOCK 227 | 228 | 229 | if( out_file != ""): 230 | sink = open (out_file, "w") 231 | pass 232 | 233 | if( in_file == ""): 234 | print "\n File name for frequency analysis is not specified, Exiting \n\n" 235 | return (-2) 236 | pass 237 | 238 | 239 | 240 | dist = freq_analysis( in_file, sink) 241 | 242 | return dist 243 | 244 | print "\n\n" 245 | 246 | pass # main 247 | 248 | 249 | #------------------------------------------------------------------------------- 250 | # 251 | # Kick off the script 252 | 253 | if __name__ == "__main__": 254 | 255 | main (sys.argv[0:]) 256 | 257 | pass # IF BLOCK 258 | -------------------------------------------------------------------------------- /gibbersense.py: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # 4 | # 5 | # .d8888b. d8b 888 888 .d8888b. 6 | # d88P Y88b Y8P 888 888 d88P Y88b 7 | # 888 888 888 888 Y88b. 8 | # 888 888 88888b. 88888b. .d88b. 888d888 "Y888b. .d88b. 88888b. .d8888b .d88b. .d8888b .d88b. 88888b.d88b. 9 | # 888 88888 888 888 "88b 888 "88b d8P Y8b 888P" "Y88b. d8P Y8b 888 "88b 88K d8P Y8b d88P" d88""88b 888 "888 "88b 10 | # 888 888 888 888 888 888 888 88888888 888 "888 88888888 888 888 "Y8888b. 88888888 888 888 888 888 888 888 11 | # Y88b d88P 888 888 d88P 888 d88P Y8b. 888 Y88b d88P Y8b. 888 888 X88 Y8b. d8b Y88b. Y88..88P 888 888 888 12 | # "Y8888P88 888 88888P" 88888P" "Y8888 888 "Y8888P" "Y8888 888 888 88888P' "Y8888 Y8P "Y8888P "Y88P" 888 888 888 13 | # 14 | # 15 | # (BETA) 16 | # 17 | # 18 | # Plugin Name : gibbersense.py 19 | # Plugin ID : gbrsns-01 20 | # Plugin Purpose : Gibber Sense Deamon 21 | # 22 | # Plugin Author : @ajithatti 23 | # 24 | # Plugin Version : 0.0.1 25 | # Plugin Status : beta 26 | # 27 | #==================================================================================================================================== 28 | 29 | # Include Section 30 | import subprocess 31 | import os 32 | import os.path 33 | import sys 34 | import getopt 35 | from sys import argv, stdout 36 | import string_scan as sscan 37 | import file_scan as fscan 38 | 39 | # Plugin Informaiton 40 | 41 | # Env Variable 42 | 43 | # Plugin Mode 44 | 45 | # Settings 46 | 47 | # Report Findings 48 | 49 | #------------------------------------------------------------------------------ 50 | #Function : log 51 | # 52 | # Purpose : logs given string in to the designated sink 53 | # 54 | # Parameters : 1. message - message string to be logged 55 | # 2. The destination of the log 56 | # 57 | # Returns : None 58 | 59 | 60 | def log(message, sink): 61 | sink.write(message) 62 | pass 63 | 64 | 65 | 66 | # -------------------------------------------------------------------------------- 67 | # Function : usage 68 | # 69 | # Purpose : Proivde a mini help on usage of this program 70 | # 71 | # Parameters : None 72 | # 73 | # Returns : None 74 | 75 | def usage(script): 76 | 77 | print"" 78 | print" .d8888b. d8b 888 888 .d8888b. " 79 | print" d88P Y88b Y8P 888 888 d88P Y88b " 80 | print" 888 888 888 888 Y88b. " 81 | print' 888 888 88888b. 88888b. .d88b. 888d888 "Y888b. .d88b. 88888b. .d8888b .d88b. ' 82 | print' 888 88888 888 888 "88b 888 "88b d8P Y8b 888P" "Y88b. d8P Y8b 888 "88b 88K d8P Y8b ' 83 | print' 888 888 888 888 888 888 888 88888888 888 "888 88888888 888 888 "Y8888b. 88888888 ' 84 | print" Y88b d88P 888 888 d88P 888 d88P Y8b. 888 Y88b d88P Y8b. 888 888 X88 Y8b. " 85 | print' "Y8888P88 888 88888P" 88888P" "Y8888 888 "Y8888P" "Y8888 888 888 88888P" "Y8888 ' 86 | print" " 87 | 88 | print "\n\n %s [-h] [-s] [-f] [-o] " %script 89 | print "\n Purpose : Gibber Sense accepts any gibberish string or file and" 90 | print " tries to extract sense out of it" 91 | print "\n" 92 | print " -h [--help] : prints this usage help" 93 | print " -s [--string] : provide a string parameter to Gibber Sense" 94 | print " -f [--file] : proivde a file path parameter to Gibber Sense" 95 | print " -o [--out] : save the result of analysis to this file" 96 | print " \n\n\n" 97 | 98 | sys.exit(2) 99 | 100 | 101 | pass # USAGE BLOCK 102 | 103 | 104 | # -------------------------------------------------------------------------------- 105 | # Function : 106 | # 107 | # Purpose : 108 | # 109 | # Parameters : 110 | # 111 | # Returns : None 112 | 113 | 114 | def list_all_remote_scripts(path): 115 | indir = os.getcwd() 116 | 117 | prefix = "" 118 | 119 | if(indir.endswith("LAMMA")): 120 | prefix = "modules/remote-module/" 121 | 122 | if(indir.endswith("modules")): 123 | prefix = "remote-module/" 124 | 125 | indir = indir + "/" + prefix + path 126 | 127 | for root, dirs, filenames in sorted(os.walk(indir)): 128 | pos = indir.__len__() 129 | check_dir = root[pos:] 130 | if ( check_dir.find(".git") != -1): 131 | continue 132 | 133 | print "./" + root[pos:] + "/" 134 | 135 | for f in filenames: 136 | if f.endswith(".py"): 137 | if (f == "__init__.py"): 138 | continue 139 | print "\t ", f 140 | 141 | exit(0) 142 | 143 | 144 | pass 145 | 146 | 147 | 148 | 149 | # -------------------------------------------------------------------------------- 150 | # Function : get_path_prefix 151 | # 152 | # Purpose : based on from where the script is invoked, it returns the cwd 153 | # 154 | # Parameters : None 155 | # 156 | # Returns : relative cwd 157 | 158 | 159 | def get_path_prefix() : 160 | indir = os.getcwd() 161 | 162 | prefix = "" 163 | 164 | if (indir.endswith("LAMMA")): 165 | prefix = "modules/trust-module/" 166 | 167 | if (indir.endswith("modules")): 168 | prefix = "trust-module/" 169 | 170 | indir = indir + "/" + prefix 171 | 172 | return prefix 173 | pass 174 | 175 | 176 | 177 | 178 | # ------------------------------------------------------------------------------- 179 | # Function : main 180 | # 181 | # Purpose : The Gibber Sense script. 182 | # 183 | # Params : 1. argv (list) - list of command line arguments 184 | # 185 | # Returns : None 186 | 187 | 188 | def main(argv): 189 | 190 | # **** Lets process the arguments ********* 191 | 192 | # Initialize the variables 193 | 194 | this_script = argv[0] 195 | string = "" 196 | in_file = "" 197 | out_file = "" 198 | sink = stdout 199 | 200 | # ---- Show the usage for too few arguments 201 | 202 | if len(argv) < 3: 203 | usage(this_script) 204 | sys.exit(2) 205 | pass # if block 206 | 207 | # --- try block 208 | 209 | try: 210 | opts, args = getopt.getopt(argv[1:], "h:s:f:o:", 211 | ["help=", "string=", "file=","out="]) 212 | 213 | 214 | except getopt.GetoptError: 215 | usage(this_script) 216 | sys.exit(2) 217 | pass # TRY BLOCK 218 | 219 | # ---- Process the arguments passed to the script 220 | 221 | for opt, arg in opts: 222 | if opt in ("-h", "--help"): 223 | usage(this_script) 224 | 225 | elif opt in ("-s", "--string"): 226 | string = arg 227 | 228 | elif opt in ("-f", "--file"): 229 | in_file = arg 230 | 231 | elif opt in ("-o", "--out"): 232 | out_file = arg 233 | 234 | 235 | pass # IF BLOCK 236 | pass # FOR BLOCK 237 | 238 | # ---- collect the values and check 239 | 240 | 241 | # --- Check if string is to be analyzed : flag [-s] 242 | 243 | if (string != ""): 244 | 245 | # process string 246 | print "\n [+] Processing String ", string, "\n" 247 | 248 | sscan.string_scan(string) 249 | 250 | pass # if Block 251 | 252 | 253 | # -- Check if file has to be analyzed : flag [-f] 254 | 255 | if (in_file != ""): 256 | # process string 257 | print "\n [+] Processing File :", in_file, "\n" 258 | 259 | fscan.file_scan(in_file) 260 | 261 | pass # if Block 262 | 263 | # -- Set the out file -- 264 | 265 | if (out_file != ""): 266 | sink = open(out_file, "a+") 267 | print " Reports will be stored in file => %s" %out_file 268 | cmd_string = cmd_string + " -o " + out_file 269 | pass 270 | 271 | print "\n\n\t[+] Analysis complete...\n\n" 272 | 273 | 274 | pass # main 275 | 276 | 277 | 278 | 279 | # ------------------------------------------------------------------------------- 280 | # 281 | # Kick off the script 282 | 283 | if __name__ == "__main__": 284 | main(sys.argv[0:]) 285 | 286 | pass # IF BLOCK 287 | -------------------------------------------------------------------------------- /rotation_cipher.py: -------------------------------------------------------------------------------- 1 | # 2 | # # 3 | # .d8888b. d8b 888 888 .d8888b. # 4 | # d88P Y88b Y8P 888 888 d88P Y88b # 5 | # 888 888 888 888 Y88b. # 6 | # 888 888 88888b. 88888b. .d88b. 888d888 "Y888b. .d88b. 88888b. .d8888b .d88b. # 7 | # 888 88888 888 888 "88b 888 "88b d8P Y8b 888P" "Y88b. d8P Y8b 888 "88b 88K d8P Y8b # 8 | # 888 888 888 888 888 888 888 88888888 888 "888 88888888 888 888 "Y8888b. 88888888 # 9 | # Y88b d88P 888 888 d88P 888 d88P Y8b. 888 Y88b d88P Y8b. 888 888 X88 Y8b. # 10 | # "Y8888P88 888 88888P" 88888P" "Y8888 888 "Y8888P" "Y8888 888 888 88888P' "Y8888 # 11 | # # 12 | # 13 | # (beta) 14 | # 15 | # 16 | # Plugin Name : freq_analysis.py 17 | # Plugin ID : fqa-01 18 | # Plugin Purpose : Provides frequency analysis of a file contents. 19 | # Used to analyse subsitution cipher. 20 | # 21 | # Plugin Author : @ajithatti 22 | # 23 | # Plugin Version : 0.0.1 24 | # Plugin Status : beta 25 | # 26 | ################################################################################ 27 | 28 | 29 | 30 | # Include Section 31 | import os.path 32 | import getopt 33 | import os 34 | import re 35 | import sys 36 | from sys import argv, stdout 37 | 38 | from PIL import Image 39 | import random 40 | 41 | 42 | # -------------------------------------------------------------------------------- 43 | # Function : usage 44 | # 45 | # Purpose : Proivde a mini help on usage of this program 46 | # 47 | # Parameters : None 48 | # 49 | # Returns : None 50 | 51 | def usage(script): 52 | print "\n\n %s [-o] [-i] " %script 53 | print "\n Purpose : Computes the frequency distribution each alphabet" 54 | print " present in a file. Used for crypt analysis of " 55 | print " common subsitution ciphers of English text" 56 | print "\n" 57 | print " -o [--out] : stores the frequency distribution table in a givne file" 58 | print " -i [--in] : path of a file to be analyzed" 59 | print " \n\n\n" 60 | 61 | sys.exit(2) 62 | 63 | 64 | pass # USAGE BLOCK 65 | 66 | 67 | # -------------------------------------------------------------------------------- 68 | # Function : usage 69 | # 70 | # Purpose : Proivde a mini help on usage of this program 71 | # 72 | # Parameters : None 73 | # 74 | # Returns : None 75 | 76 | 77 | def log( message, sink) : 78 | 79 | sink.write(message) 80 | pass 81 | 82 | 83 | buf = "" 84 | # -------------------------------------------------------------------------------- 85 | # Function : usage 86 | # 87 | # Purpose : Proivde a mini help on usage of this program 88 | # 89 | # Parameters : None 90 | # 91 | # Returns : None 92 | 93 | 94 | def file_process(in_file): 95 | 96 | f = open(in_file, "r") 97 | buf = f.read() 98 | return buf 99 | 100 | pass 101 | 102 | 103 | # -------------------------------------------------------------------------------- 104 | # Function : usage 105 | # 106 | # Purpose : Proivde a mini help on usage of this program 107 | # 108 | # Parameters : None 109 | # 110 | # Returns : None 111 | 112 | 113 | def rotate(in_file, dist, sink): 114 | 115 | 116 | buf = file_process(in_file) 117 | rot = "" 118 | 119 | l = len(buf) 120 | i = 0 121 | 122 | while (i < l) : 123 | 124 | c = ord(buf[i]) 125 | if( c >= 65 and c <=90) : 126 | c += int(dist) 127 | if (c > 90): 128 | c = c - 90 + 64 129 | elif( c>= 97 and c <= 122): 130 | c += int(dist) 131 | if (c > 122): 132 | c = c - 122 + 96 133 | pass 134 | i +=1 135 | rot += chr(c) 136 | pass 137 | 138 | 139 | log(rot, sink) 140 | 141 | pass 142 | 143 | 144 | # -------------------------------------------------------------------------------- 145 | # Function : main 146 | # 147 | # Purpose : Rottion Cipher, substitute current alphabet with next 'dth' 148 | # alphabet. Also known as Caesar Cipher 149 | # 150 | # Parameters : in - path of a file to be analyzed 151 | # out - file in which frequency distribution is to be stored 152 | # 153 | # Returns : dist - Distance of hights frequency alphabet from 'e' 154 | 155 | 156 | def main(argv): 157 | 158 | 159 | # Initialize the variables 160 | in_file = "" 161 | out_file = "" 162 | this_script = argv[0] 163 | dist = "" 164 | sink = stdout 165 | 166 | 167 | if len(argv) < 3: 168 | usage(this_script) 169 | sys.exit(2) 170 | pass # if block 171 | 172 | # --- try block 173 | 174 | try: 175 | opts, args = getopt.getopt(argv[1:], "o:i:d:",["out=", "in=","dist="]) 176 | 177 | 178 | except getopt.GetoptError: 179 | usage(this_script) 180 | sys.exit(2) 181 | pass # TRY BLOCK 182 | 183 | #---- Process the arguments passed to the script 184 | 185 | for opt, arg in opts: 186 | 187 | if opt in ("-i", "--in"): 188 | in_file = arg 189 | elif opt in ("-o", "--out"): 190 | out_file = arg 191 | elif opt in ("-d", "--dist"): 192 | dist = arg 193 | 194 | pass # IF BLOCK 195 | pass # FOR BLOCK 196 | 197 | 198 | if( out_file != ""): 199 | sink = open(out_file, "w") 200 | pass 201 | 202 | if( in_file == ""): 203 | print "\n File name for frequency analysis is not specified, Exiting \n\n" 204 | return (-2) 205 | pass 206 | 207 | if( dist == ""): 208 | print "\n Rotation Parameter is not specified, Exiting \n\n" 209 | return (-2) 210 | pass 211 | 212 | dist = int(dist) %26 213 | 214 | 215 | dist = rotate(in_file, dist, sink) 216 | 217 | return dist 218 | 219 | print "\n\n" 220 | 221 | pass # main 222 | 223 | 224 | #------------------------------------------------------------------------------- 225 | # 226 | # Kick off the script 227 | 228 | if __name__ == "__main__": 229 | 230 | main (sys.argv[0:]) 231 | 232 | pass # IF BLOCK 233 | -------------------------------------------------------------------------------- /string_scan.py: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # 4 | # 5 | # .d8888b. d8b 888 888 .d8888b. 6 | # d88P Y88b Y8P 888 888 d88P Y88b 7 | # 888 888 888 888 Y88b. 8 | # 888 888 88888b. 88888b. .d88b. 888d888 "Y888b. .d88b. 88888b. .d8888b .d88b. .d8888b .d88b. 88888b.d88b. 9 | # 888 88888 888 888 "88b 888 "88b d8P Y8b 888P" "Y88b. d8P Y8b 888 "88b 88K d8P Y8b d88P" d88""88b 888 "888 "88b 10 | # 888 888 888 888 888 888 888 88888888 888 "888 88888888 888 888 "Y8888b. 88888888 888 888 888 888 888 888 11 | # Y88b d88P 888 888 d88P 888 d88P Y8b. 888 Y88b d88P Y8b. 888 888 X88 Y8b. d8b Y88b. Y88..88P 888 888 888 12 | # "Y8888P88 888 88888P" 88888P" "Y8888 888 "Y8888P" "Y8888 888 888 88888P' "Y8888 Y8P "Y8888P "Y88P" 888 888 888 13 | # 14 | # 15 | # (BETA) 16 | # 17 | # 18 | # Plugin Name : gibbersense.py 19 | # Plugin ID : gbrsns-01 20 | # Plugin Purpose : Gibber Sense Deamon 21 | # 22 | # Plugin Author : @ajithatti 23 | # 24 | # Plugin Version : 0.0.1 25 | # Plugin Status : beta 26 | # 27 | #==================================================================================================================================== 28 | 29 | # Include Section 30 | import subprocess 31 | import os 32 | import os.path 33 | import sys 34 | import getopt 35 | import enchant 36 | import string 37 | 38 | 39 | from sys import argv, stdout 40 | 41 | # Plugin Informaiton 42 | 43 | # Env Variable 44 | 45 | # Plugin Mode 46 | 47 | # Settings 48 | 49 | # Report Findings 50 | 51 | #------------------------------------------------------------------------------ 52 | # Function : 53 | # 54 | # Purpose : 55 | # 56 | # Parameters : 57 | # 58 | # Returns : None 59 | 60 | 61 | def fun( ): 62 | 63 | print "Fun" 64 | 65 | pass 66 | 67 | 68 | 69 | #------------------------------------------------------------------------------ 70 | # Function : length_scan() 71 | # 72 | # Purpose : Based on length of string try to find some sense 73 | # 74 | # Parameters : string 75 | # 76 | # Returns : None 77 | 78 | 79 | def length_scan(string): 80 | 81 | print "" 82 | 83 | pass 84 | 85 | 86 | 87 | #------------------------------------------------------------------------------ 88 | # Function : english_test() 89 | # 90 | # Purpose : Based on length of string try to find some sense 91 | # 92 | # Parameters : string 93 | # 94 | # Returns : count of english words identified 95 | 96 | 97 | def english_test(string): 98 | 99 | dict_en = enchant.Dict("en_US") 100 | 101 | words = string.split() 102 | wcount = 0 103 | 104 | for word in words : 105 | if(dict_en.check(word)) : 106 | wcount +=1 107 | pass 108 | pass 109 | 110 | return wcount 111 | 112 | pass 113 | 114 | 115 | 116 | #------------------------------------------------------------------------------ 117 | # Function : isprime() 118 | # 119 | # Purpose : computes and tells if a number is prime or not 120 | # 121 | # Parameters : n number to be tested 122 | # 123 | # Returns : True or False 124 | 125 | 126 | 127 | def isprime(n): 128 | if n == 2: 129 | return True 130 | if n % 2 == 0: 131 | return False 132 | max = n**0.5+1 133 | i = 3 134 | while i <= max: 135 | if n % i == 0: 136 | return False 137 | i+=2 138 | return True 139 | pass 140 | 141 | 142 | #------------------------------------------------------------------------------ 143 | # Function : ishex() 144 | # 145 | # Purpose : checks if a string is hexadecimal 146 | # 147 | # Parameters : n number to be tested 148 | # 149 | # Returns : True or False 150 | 151 | 152 | 153 | def ishex(s): 154 | hex_digits = set(string.hexdigits) 155 | # if s is long, then it is faster to check against a set 156 | return all(c in hex_digits for c in s) 157 | pass 158 | 159 | 160 | 161 | 162 | #------------------------------------------------------------------------------ 163 | # Function : pattern_scan() 164 | # 165 | # Purpose : Based on the string pattern try to make some sense 166 | # 167 | # Parameters : string 168 | # 169 | # Returns : None 170 | 171 | 172 | def pattern_scan(string): 173 | 174 | 175 | words = string.split() 176 | wcount = len(words) 177 | 178 | eng_count = english_test(string) 179 | 180 | print "\n\t\tNumber of Wrods : ", wcount 181 | print "\n\t\tEnglish words =", eng_count 182 | 183 | ratio = float("0.0") 184 | ratio = float(eng_count)/float(wcount) 185 | 186 | if (ratio > float("0.5")): 187 | print "\n\t\t> The given string is a collection of English words" 188 | return False 189 | else : 190 | return True 191 | 192 | pass 193 | 194 | 195 | def check_special(string): 196 | 197 | words = string.split('/') 198 | 199 | eng_count = 0 200 | 201 | for word in words : 202 | 203 | eng_count += english_test(word) 204 | pass 205 | 206 | return eng_count 207 | 208 | pass 209 | 210 | #------------------------------------------------------------------------------ 211 | # Function : hash_scan() 212 | # 213 | # Purpose : Probaly the string is a hash we will see if we have seen the 214 | # string which gives this hash 215 | # 216 | # Parameters : string 217 | # 218 | # Returns : None 219 | 220 | 221 | def hash_scan(string): 222 | 223 | l = len(string) 224 | hashstr = False 225 | 226 | if(l == 32): 227 | print "\n\t\tMay be the string is", "MD4 Sum" 228 | print "\n\t\tMay be the string is", "MD5 Sum" 229 | print "\n\t\tMay be the string is", "NTLM Token" 230 | hashstr = True 231 | 232 | 233 | elif(l == 40): 234 | print "\n\t\tMay be the string is", "SHA1" 235 | hashstr = True 236 | 237 | elif(l == 56): 238 | print "\n\t\tMay be the string is", "SHA224" 239 | hashstr = True 240 | 241 | elif(l == 64): 242 | print "\n\t\tMay be the string is", "SHA256" 243 | hashstr = True 244 | 245 | elif(l == 96): 246 | print "\n\t\tMay be the string is", "SHA384" 247 | hashstr = True 248 | 249 | elif(l == 128): 250 | print "\n\t\tMay be the string is", "SHA512" 251 | hashstr = True 252 | 253 | if(hashstr): 254 | print "\n\t\tYou can check with https://crackstation.net/ if they have cracked this string" 255 | 256 | return not(hashstr) 257 | 258 | pass 259 | 260 | 261 | 262 | 263 | 264 | 265 | #------------------------------------------------------------------------------ 266 | # Function : string_scan() 267 | # 268 | # Purpose : analyze a given string 269 | # 270 | # Parameters : string 271 | # 272 | # 273 | # Returns : None 274 | 275 | 276 | def string_scan(org_string ): 277 | 278 | gibberish = True 279 | 280 | org_len = len(org_string) 281 | 282 | string = org_string.strip() 283 | 284 | new_len = len(string) 285 | 286 | print "\n\t[+] Statistical Analysis :" 287 | 288 | if(org_len != new_len): 289 | 290 | print "\n\t\t>> Removing leading and trailing spaces\n" 291 | 292 | print "\n\t\tString Length = ", new_len 293 | 294 | 295 | print "\n\t[+] Findings :" 296 | 297 | if ' ' in string : 298 | 299 | gibberish = pattern_scan(string) 300 | 301 | elif(string[new_len -1] == "="): 302 | print "\n\t\tMay be the string is BASE64 Encoded" 303 | 304 | elif(unicode(string, "utf-8").isnumeric()) : 305 | print "\n\t\tA numeric string" 306 | if(isprime(int(string)) ) : 307 | print "\n\t\tWow, its a prime number" 308 | elif( '/' in string): 309 | 310 | print "\n\t\tEnglish words in the string " , check_special(string) 311 | print "\n\t\tSpecially crafted string" 312 | gibberish = False 313 | 314 | 315 | else : 316 | gibberish = hash_scan(string) 317 | 318 | 319 | if(ishex(string)): 320 | print "\n\t\tThe string is hexa decimal" 321 | 322 | 323 | if(gibberish == True): 324 | print "\n\t\tThe string is Gibberish" 325 | 326 | 327 | pass 328 | 329 | 330 | 331 | 332 | -------------------------------------------------------------------------------- /visualizer_module.py: -------------------------------------------------------------------------------- 1 | # 2 | # # 3 | # .d8888b. d8b 888 888 .d8888b. # 4 | # d88P Y88b Y8P 888 888 d88P Y88b # 5 | # 888 888 888 888 Y88b. # 6 | # 888 888 88888b. 88888b. .d88b. 888d888 "Y888b. .d88b. 88888b. .d8888b .d88b. # 7 | # 888 88888 888 888 "88b 888 "88b d8P Y8b 888P" "Y88b. d8P Y8b 888 "88b 88K d8P Y8b # 8 | # 888 888 888 888 888 888 888 88888888 888 "888 88888888 888 888 "Y8888b. 88888888 # 9 | # Y88b d88P 888 888 d88P 888 d88P Y8b. 888 Y88b d88P Y8b. 888 888 X88 Y8b. # 10 | # "Y8888P88 888 88888P" 88888P" "Y8888 888 "Y8888P" "Y8888 888 888 88888P' "Y8888 # 11 | # # 12 | # 13 | # (beta) 14 | # 15 | # 16 | # Plugin Name : visualizer-module.py 17 | # Plugin ID : vm-01 18 | # Plugin Purpose : Provides visual representation of any given file. 19 | # this module accepts Text, PDF, Binary files.works 20 | # for files containing random numbers as well. 21 | # 22 | # Plugin Author : @ajithatti 23 | # 24 | # Plugin Version : 0.0.1 25 | # Plugin Status : beta 26 | # 27 | ################################################################################ 28 | 29 | 30 | 31 | # Include Section 32 | import os.path 33 | import getopt 34 | import os 35 | import re 36 | import sys 37 | from sys import argv, stdout 38 | 39 | from PIL import Image 40 | import random 41 | import string_scan as sscan 42 | import extract_strings as xstrings 43 | 44 | # Global Declearations 45 | 46 | buf = "" 47 | FILE_STATS = {} 48 | FILE_TYPE = {} 49 | 50 | 51 | 52 | FILE_STATS["stat_ascii"] = 0 53 | FILE_STATS["stat_lower"] = 0 54 | FILE_STATS["stat_higher"] = 0 55 | FILE_STATS["stat_null"] = 0 56 | FILE_STATS["total_len"] = 0 57 | 58 | 59 | FILE_TYPE["type"] = "" # Type is TEXT or BINARY or ENCRYPTED 60 | FILE_TYPE["content"] = "" 61 | FILE_TYPE["name"] = "" 62 | 63 | 64 | def print_stats(): 65 | 66 | 67 | stat_ascii = FILE_STATS["stat_ascii"] 68 | stat_lower = FILE_STATS["stat_lower"] 69 | stat_higher = FILE_STATS["stat_higher"] 70 | stat_null = FILE_STATS["stat_null"] 71 | total_len = FILE_STATS["total_len"] 72 | 73 | ascii_pc = int (float(stat_ascii)/float(total_len) *100) 74 | 75 | lower_pc = int(float(stat_lower )/float(total_len) *100) 76 | higher_pc = int(float(stat_higher )/float(total_len) *100) 77 | 78 | print "\t[+] Gibber Sense Statistical Analysis \n" 79 | print "\t\t % of printable ASCII Chars :", ascii_pc 80 | print "\t\t % of printable LOW Chars :", lower_pc 81 | print "\t\t % of printable HIGH Chars :", higher_pc 82 | print "\t\t number of printable NULL Chars :", stat_null 83 | print "\t\t File size in number of Chars :", total_len 84 | 85 | 86 | 87 | 88 | print "\n\t[+] Findings : \n\n" 89 | 90 | if (ascii_pc > 95): 91 | FILE_TYPE["type"] = "TEXT" 92 | else : 93 | 94 | word_count = 0 95 | eng_count = 0 96 | 97 | 98 | for string in xstrings.strings(FILE_TYPE["name"]) : 99 | 100 | #print string 101 | 102 | if('/' in string or ' ' in string) : 103 | 104 | eng_count = sscan.check_special(string) 105 | 106 | if(eng_count > 0) : 107 | 108 | FILE_TYPE["type"] = "BINARY" 109 | pass 110 | pass 111 | pass 112 | 113 | # application specific file 114 | # binary file 115 | 116 | if(eng_count == 0) : 117 | FILE_TYPE["type"] = "ENCRYPTED" 118 | 119 | print "\t\tThe file type is found to be " , FILE_TYPE["type"] 120 | 121 | pass 122 | 123 | 124 | # -------------------------------------------------------------------------------- 125 | # Function : usage 126 | # 127 | # Purpose : Proivde a mini help on usage of this program 128 | # 129 | # Parameters : None 130 | # 131 | # Returns : None 132 | 133 | def usage(script): 134 | print "\n\n %s [-o] [-i] " %script 135 | print "\n Purpose : Provides visual representation of a given file" 136 | print " can be used for visualizing Binary files, Random" 137 | print " Random Numbers, text, pdf files etc" 138 | print "\n" 139 | print " -o [--out] : stores the visualization of RNG in this file" 140 | print " -i [--in] : path of a file to be analyzed" 141 | print " \n\n\n" 142 | 143 | sys.exit(2) 144 | 145 | 146 | pass # USAGE BLOCK 147 | 148 | 149 | 150 | def log( message, sink) : 151 | 152 | sink.write(message) 153 | pass 154 | 155 | 156 | def file_process(in_file): 157 | 158 | f = open(in_file, "r") 159 | buf = f.read() 160 | return buf 161 | 162 | pass 163 | 164 | 165 | 166 | def drawImage(in_file): 167 | 168 | FILE_TYPE["name"] = in_file 169 | 170 | f = open(in_file, "r") 171 | buf = f.read() 172 | 173 | l = len(buf) 174 | FILE_STATS["total_len"] = l 175 | FILE_TYPE["content"] = buf 176 | 177 | h = l/100 + 1 178 | w = 100 179 | 180 | if (h > 1000) : 181 | max = int (l**0.5+1) 182 | # print " max =" , max 183 | w = max +1 184 | h = max +1 185 | pass 186 | 187 | 188 | # print "length = " , w 189 | # print "l/100 = ", h 190 | 191 | 192 | testImage = Image.new("RGB", (w, h), (255,255,255)) 193 | pixel = testImage.load() 194 | 195 | 196 | i = 0 197 | 198 | for x in range(w): 199 | for y in range(h): 200 | 201 | if(i < l): 202 | col = ord(buf[i]) 203 | #print "char", buf[i],"(", ord(buf[i]), ")" 204 | else : 205 | col = 255 206 | i +=1 207 | 208 | if(col >= 32 and col <=126): 209 | # visible text range 210 | b = col 211 | r = 0 212 | g = 0 213 | FILE_STATS["stat_ascii"] += 1 214 | 215 | elif(col < 32 and col > 0 ): 216 | # Low Range 217 | b = 0 218 | r = 0 219 | g = col 220 | FILE_STATS["stat_lower"] += 1 221 | 222 | elif(col > 126 and col < 255): 223 | # High Range 224 | b = 0 225 | r = col 226 | g = 0 227 | FILE_STATS["stat_higher"] += 1 228 | 229 | elif(col == 0): 230 | # Null 231 | b = 0 232 | r = 0 233 | g = 0 234 | FILE_STATS["stat_null"] += 1 235 | 236 | elif(col == 255): 237 | # Null 238 | b = 255 239 | r = 255 240 | g = 255 241 | 242 | red = r #random.randrange(0,255) 243 | blue = g #random.randrange(0,255) 244 | green = b #random.randrange(0,255) 245 | pixel[x,y]=(red,blue,green) 246 | pass 247 | 248 | f.close() 249 | 250 | 251 | return testImage 252 | 253 | pass 254 | 255 | 256 | 257 | # -------------------------------------------------------------------------------- 258 | # Function : main 259 | # 260 | # Purpose : converts file contents in to pixels to generate visualization 261 | # 262 | # Parameters : in - path of a file to be visually tested (optional) 263 | # out - *.png file in which the visual image is to be stored 264 | # 265 | # Returns : None 266 | 267 | 268 | def main(argv): 269 | 270 | 271 | # Initialize the variables 272 | in_file = "" 273 | out_file = "" 274 | this_script = argv[0] 275 | 276 | 277 | if len(argv) < 3: 278 | usage(this_script) 279 | sys.exit(2) 280 | pass # if block 281 | 282 | # --- try block 283 | 284 | try: 285 | opts, args = getopt.getopt(argv[1:], "o:i:",["out=", "in="]) 286 | 287 | 288 | except getopt.GetoptError: 289 | usage(this_script) 290 | sys.exit(2) 291 | pass # TRY BLOCK 292 | 293 | #---- Process the arguments passed to the script 294 | 295 | for opt, arg in opts: 296 | 297 | if opt in ("-i", "--in"): 298 | in_file = arg 299 | elif opt in ("-o", "--out"): 300 | out_file = arg 301 | pass # IF BLOCK 302 | pass # FOR BLOCK 303 | 304 | 305 | if( out_file == ""): 306 | print "\n File name to store the image is not specified, Exiting \n\n" 307 | return (-2) 308 | pass 309 | 310 | if( in_file == ""): 311 | print "\n File name to be visually analyzed \n\n" 312 | return (-2) 313 | pass 314 | 315 | 316 | 317 | 318 | 319 | finalImage = drawImage(in_file) 320 | finalImage.save(out_file) 321 | 322 | FILE_TYPE["name"] = in_file 323 | 324 | print_stats() 325 | print "\n\nThe visualization of file <", in_file, "> is stored in <", out_file, ">" 326 | print "\n\n" 327 | 328 | pass # main 329 | 330 | 331 | #------------------------------------------------------------------------------- 332 | # 333 | # Kick off the script 334 | 335 | if __name__ == "__main__": 336 | 337 | main (sys.argv[0:]) 338 | 339 | pass # IF BLOCK 340 | --------------------------------------------------------------------------------