├── .gitignore ├── LICENSE ├── ReadMe ├── cli_for_tools ├── config.txt ├── find_exes_and_dlls.py ├── get_all_strings.py ├── get_crypto_calls.py ├── get_vuln_functions_list.py ├── permission_check.bat └── version_detect.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | __pycache__ 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | 30 | # Translations 31 | *.mo 32 | 33 | # Mr Developer 34 | .mr.developer.cfg 35 | .project 36 | .pydevproject 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 arvinddoraiswamy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /ReadMe: -------------------------------------------------------------------------------- 1 | Scripts: 2 | 3 | 1. Find all Exe, DLL and Sys files and copy them to a central directory. - find_exes_and_dlls.py 4 | 5 | 2. Disassemble a list of files and run strings on all IDBs. - get_all_strings.py 6 | 7 | 3. Run simple 'grep' wrapper on all strings output with customizable keyword list. - cli_for_tools 8 | 9 | 4. Run Burp version grabbing extension. Add more headers to watch out for in responses. - version_detect.py 10 | 11 | 5. Check OS permissions of all files in specific directories. - permission_check.bat 12 | 13 | 6. Extract file metadata from files. - cli_for_tools 14 | 15 | 7. Extract insecure functions from IDBs. - get_vuln_functions_list.py 16 | 17 | 8. Verify that all files in given directories are signed. - cli_for_tools 18 | 19 | 9. Search for weak algorithms in IDBs. - get_crypto_calls.py 20 | 21 | Command Line Shortcuts: cli_for_tools 22 | 23 | 1. Tshark and Rawcap. 24 | 2. Deleting certificates from a signed executable. 25 | -------------------------------------------------------------------------------- /cli_for_tools: -------------------------------------------------------------------------------- 1 | 1) Find all EXE, DLL and SYS files. Make sure config.txt exists in the same directory as that of the script. 2 | python find_exes_and_dlls.py 3 | 4 | 2) Get list of strings from all the stored IDB files. 5 | FOR %x IN ("C:\data\IDBstore\AllIDBs\*.idb") do idaw -A -L"C:\data\strings_batch_log.txt" -S"C:\data\Python_scripts\get_all_strings.py" "%x" 6 | 7 | 3) Search for passwords and keys inside the output for 'strings' 8 | egrep -inr 'password|key' strings*.txt 9 | 10 | 4) Use Burp Extension version_detect.py and configure client to pass through Burp. The extension will record all the version information that leaks via the server headers. 11 | 12 | 5) Check permissions for all relevant files, registry keys, processes, threads and services. The commands for all these are in the file permission_check.bat. It just uses the Sysinternals tool accesschk.exe to check permissions. Duplicate as many lines as needed. It's up to the engineer to find out the relevant resources. 13 | 14 | 6) Get metadata from all of the relevant files to check for information leakage. 15 | FOR /F "usebackq delims=" %x IN (C:\data\file_list.txt) do wmic datafile get Name,Description,Manufacturer where name="%x" >> "C:\data\metadata_info.txt" 16 | 17 | 7) Get potentially dangerous functions from a list of files found from previous command [EXE, DLL, SYS]. 18 | FOR /F "usebackq delims=" %x IN (C:\data\file_list.txt) do idaw -c -o"C:\data\IDBstore" -L"C:\data\batch_log.txt" -A -S"C:\data\Python_scripts\get_vuln_functions_list.py" "%x" 19 | 20 | 8) Check if all EXE, DLL and SYS files are signed 21 | FOR /F "usebackq delims=" %x IN (C:\data\file_list.txt) do "C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\signtool.exe" verify /pa "%x" >> "C:\data\signed_files.txt" 22 | 23 | 9) Get all crypto related calls. Copy of the vuln functions script..in essence...but searches for a different set of APIs and the purpose is different, hence separated the script. Again, this can be done by looking at the IDBs. 24 | FOR %x IN ("C:\data\IDBstore\AllIDBs\*.idb") do idaw -A -L"C:\data\crypto_log.txt" -o"C:\data\IDBstore" -S"C:\data\Python_scripts\get_crypto_calls.py" "%x" 25 | 26 | Other useful commands: 27 | 28 | 1) Running tshark and capturing all packets a client sends out. Could do it with Wireshark too I guess, but this is probably lighter and less likely (based on ZERO conclusive evidence :)) to crash. 29 | - Get list of interface names on Windows - tshark -D 30 | - Sniff on the interface on which all traffic is passing - tshark -i -w 31 | 32 | 2) Wireshark on windows did not capture packets on the loopback interface. Hence I used rawcap. Rawcap can be used in interactive mode. Just run rawcap.exe and then enter the loopback address and an output file. 33 | - RawCap.exe 127.0.0.1 localhost_capture.pcap 34 | 35 | 3) Delete certificates from signed executables - delcert.exe . Delcert can be downloaded from here - http://forum.xda-developers.com/showthread.php?p=2508061. I have no clue if it contains malware or not, but it does what it says. Run it in a VM disconnected from the network if you're paranoid :) 36 | -------------------------------------------------------------------------------- /config.txt: -------------------------------------------------------------------------------- 1 | #List of directories which contain interesting files 2 | directories=C:\Program Files\;C:\Program Files\dir1;C:\Program Files\dir2; 3 | #Types of files that you want to disassemble 4 | vuln_functions_file_types=exe;dll;sys 5 | -------------------------------------------------------------------------------- /find_exes_and_dlls.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import re 3 | import os 4 | 5 | def read_config_file(): 6 | f=open('config.txt','rU') 7 | for line in f: 8 | m=re.search(r'^#',line) 9 | if not m: 10 | t1=line.split('=') 11 | conf[t1[0]] = t1[1] 12 | f.close() 13 | 14 | def search_for_applicable_files(): 15 | dirs=[] 16 | extensions=[] 17 | 18 | dirs=conf['directories'].split(';') 19 | extensions=conf['vuln_functions_file_types'].split(';') 20 | 21 | for dirname in dirs: 22 | dirname.rstrip() 23 | for root,dirs,filename_list in os.walk(dirname): 24 | for f1 in filename_list: 25 | if f1.endswith(".exe") or f1.endswith(".dll") or f1.endswith(".sys"): 26 | filelist.append(os.path.join(root,f1)) 27 | 28 | def write_to_file(): 29 | f=open('C:\data\Exe_file_list.txt','w') 30 | for filename in filelist: 31 | f.write(filename+'\n') 32 | f.close() 33 | 34 | conf={} 35 | filelist=[] 36 | read_config_file() 37 | search_for_applicable_files() 38 | write_to_file() 39 | -------------------------------------------------------------------------------- /get_all_strings.py: -------------------------------------------------------------------------------- 1 | import idaapi 2 | import idautils 3 | 4 | def get_all_strings(): 5 | #Get a list of strings stored in that segment 6 | list_of_strings = idautils.Strings() 7 | for string in list_of_strings: 8 | f.write(str(string)+'\n') 9 | 10 | #Wait for analysis to complete 11 | idaapi.autoWait() 12 | 13 | #Write results to output file 14 | output_dir="C:\data\IDBstore\Strings_output\\" 15 | output_filename='strings_'+str(GetInputFile())+'.txt' 16 | f=open(output_dir+output_filename,'a') 17 | get_all_strings() 18 | 19 | #Close and exit 20 | f.close() 21 | idc.Exit(0) 22 | -------------------------------------------------------------------------------- /get_crypto_calls.py: -------------------------------------------------------------------------------- 1 | import re 2 | import idaapi 3 | import idautils 4 | 5 | def search_for_vuln_api(): 6 | #Repeat for list of segments 7 | for n in xrange(idaapi.get_segm_qty()): 8 | #Get number of segments 9 | seg = idaapi.getnseg(n) 10 | if seg: 11 | #Get list of functions in that segment 12 | funcs=idautils.Functions(seg.startEA, seg.endEA) 13 | #Search for vuln functions inside binary and print occurences to output file. This is NOT to be directly reported; perform manual analysis before doing so. 14 | if funcs: 15 | for name in funcs: 16 | each_function_disassembly = list(idautils.FuncItems(name)) 17 | for e in each_function_disassembly: 18 | for vulnfunc in vuln_function_list: 19 | pattern=vulnfunc+r'$' 20 | m=re.search(pattern,idc.GetDisasm(e)) 21 | if m: 22 | f.write(idc.GetFuncOffset(e)+' --> '+idc.GetDisasm(e)+'\n\n') 23 | else: 24 | f.write('Failed to get function names and hence cannot parse stuff\n') 25 | 26 | #DPAPI, OpenSSL Blowfish, WinHTTP certificate query - Keep adding as and when you come across an API 27 | vuln_function_list = ['CryptProtectData','CryptUnprotectData','EVP_CIPHER_CTX_init','EVP_EncryptInit_ex','EVP_DecryptInit_ex','EVP_EncryptUpdate','EVP_DecryptUpdate','BF_set_key','WinHTTPQueryOption'] 28 | pattern = [] 29 | conf = {} 30 | 31 | #List of vulnerable functions that are searched for inside the IDB. Add more functions here. 32 | vuln_function_list=[''] 33 | 34 | #Wait for analysis to complete 35 | idaapi.autoWait() 36 | 37 | #Write results to output file 38 | output_dir="C:\data\IDBstore\\" 39 | output_filename=str(GetInputFile())+'.txt' 40 | f=open(output_dir+output_filename,'a') 41 | search_for_vuln_api() 42 | 43 | #Close and exit 44 | f.close() 45 | idc.Exit(0) 46 | -------------------------------------------------------------------------------- /get_vuln_functions_list.py: -------------------------------------------------------------------------------- 1 | import re 2 | import idaapi 3 | import idautils 4 | 5 | def search_for_vuln_api(): 6 | #Repeat for list of segments 7 | for n in xrange(idaapi.get_segm_qty()): 8 | #Get number of segments 9 | seg = idaapi.getnseg(n) 10 | if seg: 11 | #Get list of functions in that segment 12 | funcs=idautils.Functions(seg.startEA, seg.endEA) 13 | #Search for vuln functions inside binary and print occurences to output file. This is NOT to be directly reported; perform manual analysis before doing so. 14 | if funcs: 15 | for name in funcs: 16 | each_function_disassembly = list(idautils.FuncItems(name)) 17 | for e in each_function_disassembly: 18 | for vulnfunc in vuln_function_list: 19 | pattern=vulnfunc+r'$' 20 | m=re.search(pattern,idc.GetDisasm(e)) 21 | if m: 22 | f.write(idc.GetFuncOffset(e)+' --> '+idc.GetDisasm(e)+'\n\n') 23 | else: 24 | f.write('Failed to get function names and hence cannot parse stuff\n') 25 | 26 | vuln_function_list = [] 27 | pattern = [] 28 | conf = {} 29 | 30 | #List of vulnerable functions that are searched for inside the IDB. Add more functions here. 31 | vuln_function_list=['strcpy','strcat','gets','sprintf','vsprintf','scanf','memcpy','printf'] 32 | 33 | #Wait for analysis to complete 34 | idaapi.autoWait() 35 | 36 | #Write results to output file 37 | output_dir="C:\data\IDBstore\\" 38 | output_filename=str(GetInputFile())+'.txt' 39 | f=open(output_dir+output_filename,'a') 40 | search_for_vuln_api() 41 | 42 | #Close and exit 43 | f.close() 44 | idc.Exit(0) 45 | -------------------------------------------------------------------------------- /permission_check.bat: -------------------------------------------------------------------------------- 1 | #Check permissions on a file or directory. 2 | C:\tools\SysInternals\accesschk.exe "users" "" -s -w 3 | 4 | #Check permissions on a registry key. 5 | C:\tools\SysInternals\accesschk.exe "users" -k "" -s -w 6 | 7 | #Check permissions on a service. 8 | C:\tools\SysInternals\accesschk.exe "users" -c 9 | 10 | #Check permissions on a process and all its threads. 11 | C:\tools\SysInternals\accesschk.exe "users" -p -t 12 | 13 | #Check permissions on Global objects. You can find these by using WinObj from the SysInternals tool suite 14 | C:\tools\SysInternals\accesschk.exe "users" -wo \BaseNamedObjects\ 15 | C:\tools\SysInternals\accesschk.exe "users" -wo \Callback\ 16 | C:\tools\SysInternals\accesschk.exe "users" -wo \Device\ 17 | C:\tools\SysInternals\accesschk.exe "users" -wo \Driver\ 18 | C:\tools\SysInternals\accesschk.exe "users" -wo \FileSystem\ 19 | -------------------------------------------------------------------------------- /version_detect.py: -------------------------------------------------------------------------------- 1 | #Get server header from every response and dump it into a file 2 | #Search response bodies for a set of common versions 3 | 4 | from burp import IBurpExtender 5 | from burp import IHttpListener 6 | from burp import IProxyListener 7 | import re 8 | import sys 9 | import os 10 | 11 | unique_banners={} 12 | list_of_platforms=['iis','apache','tomcat','weblogic','websphere','jetty','gws','ibm','oracle','nginx'] 13 | urls_in_scope=['securityinnovation.com','testblah.com','qa.blah.com','qa.ooboob.com'] 14 | 15 | #Adding directory to the path where Python searches for modules 16 | module_folder = os.path.dirname('/home/arvind/Documents/Me/My_Projects/Git/WebAppsec/BurpExtensions/modules/') 17 | sys.path.insert(0, module_folder) 18 | import webcommon 19 | 20 | class BurpExtender(IBurpExtender, IHttpListener, IProxyListener): 21 | def registerExtenderCallbacks(self,callbacks): 22 | # Get a reference to the Burp helpers object 23 | self._helpers = callbacks.getHelpers() 24 | 25 | # set our extension name 26 | callbacks.setExtensionName("Platform Information Extractor") 27 | 28 | # register ourselves as an HTTP listener 29 | callbacks.registerHttpListener(self) 30 | 31 | # register ourselves as a Proxy listener 32 | callbacks.registerProxyListener(self) 33 | 34 | def processProxyMessage(self,messageIsRequest,message): 35 | response_byte_array=message.getMessageInfo().getResponse() 36 | 37 | request_http_service=message.getMessageInfo().getHttpService() 38 | request_byte_array=message.getMessageInfo().getRequest() 39 | request_object=self._helpers.analyzeRequest(request_http_service, request_byte_array) 40 | 41 | #Extract hostname from header 42 | hostname=webcommon.get_host_header_from_request(self,request_object) 43 | #hostname=BurpExtender.get_host_header_from_request(self,request_object) 44 | 45 | #Check if the URL is in scope. This is to eliminate stray traffic. 46 | if hostname and hostname[1] in urls_in_scope: 47 | if not messageIsRequest: 48 | responseInfo = self._helpers.analyzeResponse(response_byte_array) 49 | 50 | #Extract banner from response 51 | banner=webcommon.get_banner_from_response(self,responseInfo) 52 | if banner not in unique_banners.keys(): 53 | unique_banners[banner]='' 54 | print banner 55 | 56 | #Extract platform specific content from response 57 | responseBody=webcommon.get_response_body(self,response_byte_array,responseInfo) 58 | responseBody_string=self._helpers.bytesToString(responseBody) 59 | 60 | for platform_name in list_of_platforms: 61 | regex=re.compile('.{30}%s.{30}'%platform_name,re.IGNORECASE|re.DOTALL) 62 | m2=regex.search(responseBody_string) 63 | if m2: 64 | print m2.group(0)+'\n'+'-'*30+'\n' 65 | --------------------------------------------------------------------------------