#!/usr/bin/python2
'''
Title: SkypeFreak
Description: A cross platform forensic tool for Skype
Author: Osanda Malith (@OsandaMalith)
URL: http://osandamalith.github.io/SkypeFreak/

Disclaimer: This tool is meant for ethical (legal) purposes only.

Notes:	Please note this tool may contain errors, and
	is provided "as it is". There is no guarantee
	that it will work on your target systems(s), as
	the code may have to be adapted. 
	This is to avoid script kiddie abuse as well.
	
License:
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''
import os
import sqlite3
import optparse
import sys

def Profile(skypeDB, PathName):
	connexion = sqlite3.connect(skypeDB)
	c = connexion.cursor()
	c.execute("SELECT fullname, skypename, city, country,\
		datetime(profile_timestamp,'unixepoch') FROM Accounts")
	print '[*] --- Details of %s' % (os.path.basename(PathName)) +' ---'
	profile = '[*] --- Details of %s' % (os.path.basename(PathName)) +' ---\n'
	for row in c:
		print '[+] User: %s ' %(str(row[0]))
		profile += '[+] User: %s \n' %(str(row[0]))
		print '[+] Skype Username: %s'%(str(row[1]))
		profile += '[+] Skype Username: %s\n'%(str(row[1]))
		print '[+] Country: %s' % (str(row[2]))
		profile += '[+] Country: %s\n' % (str(row[2]))
		print '[+] Location: %s'% (str(row[3]))
		profile += '[+] Location: %s\n'% (str(row[3]))
		print '[+] Profile Date: %s'%(str(row[4]))

	while True:
		
		choice = raw_input("\n[~] Generate Output?\n")
		choice = choice.lower()
	
		if choice[0] == 'y':
			try:
				output = profile
				output += "\n[*] This file was Generated by Skype Freak\n[~] http://osandamalith.github.io/SkypeFreak/"
				filename = str(raw_input("[~] Enter a Filename: "))
				file = open(filename+'.txt' , "w")
				file.write(output)
				file.close()
				print '[~] File Saved to ' + os.path.abspath(filename) + '.txt'
				mainMenu(skypeDB, PathName)
				break
			except Exception, e:
				print '[!] Access Denied! Directory is not writable. Probably you are in C:\\ drive'
		if choice[0] == 'n':
			mainMenu(skypeDB, PathName)
			break 
		

def Contacts(skypeDB, PathName):
	connexion = sqlite3.connect(skypeDB)
	c = connexion.cursor()
	c.execute("SELECT displayname, skypename, country, city, about, phone_mobile, homepage, \
		birthday , datetime(lastonline_timestamp,'unixepoch') FROM Contacts;")
	print '\n[*] --- Found Contacts --- '
	contacts = '[*] --- Found Contacts of %s' % (os.path.basename(PathName)) +' ---\n'
	for row in c:
		print '[+] User: %s\n' %(str(row[0]))
		contacts += '\n\n[+] User: %s' %(str(row[0]))
		print '[+] Skype Username: %s' %(str(row[1]))
		contacts += '\n[+] Skype Username: %s\n' %(str(row[1]))
		if str(row[2])!= 'None':
			contacts += '[+] Country: %s\n' %(str(row[2]))
			print '[+] Country: %s' %(str(row[2]))
		if str(row[3])!= 'None':
			contacts += '[+] City: %s\n' %(str(row[3]))
			print '[+] City: %s' %(str(row[3]))
		if str(row[4])!= 'None':
			contacts += '[+] About Text: %s\n' %(str(row[4]))
			print '[+] About Text: %s' %(str(row[4]))
		if str(row[5])!= 'None':
			contacts += '[+] Mobile Number: %s\n' %(str(row[5]))
			print '[+] Mobile Number: %s' %(str(row[5]))
		if str(row[6])!= 'None':
			contacts += '[+] Homepage URL: %s\n' %(str(row[6]))
			print '[+] Homepage URL: %s' %(str(row[6]))
		if str(row[7])!= 'None':
			contacts += '[+] Birthday: %s\n' %(str(row[7]))
			print '[+] Birthday: %s' %(str(row[7]))
		if str(row[8])!= 'None':
			contacts += '[+] Last Online Date: %s\n' %(str(row[8]))
			print '[+] Last Online Date: %s' %(str(row[8]))

	while True:
		try:
			choice = raw_input("\n[~] Generate Output?\n")
			choice = choice.lower()
		except (NameError, SyntaxError, EOFError):
			print '[!] Error Occured'
		if choice[0] == 'y':
			try:
				output = contacts
				output += "\n[*] This file was Generated by Skype Freak\n[~] http://osandamalith.github.io/SkypeFreak/"
				filename = str(raw_input("[~] Enter a Filename: "))
				file = open(filename+'.txt' , "w")
				file.write(output)
				file.close()
				print '[~] File Saved to ' + os.path.abspath(filename) + '.txt'
				mainMenu(skypeDB, PathName)
				break
			except Exception, e:
				print '[!] Access Denied! Directory is not writable. Probably you are in C:\\ drive'
		if choice[0] == 'n':
			mainMenu(skypeDB, PathName)
			break 


def Calls(skypeDB, PathName):
	connexion = sqlite3.connect(skypeDB)
	c = connexion.cursor()
	c.execute("SELECT datetime(begin_timestamp,'unixepoch'), time(duration,'unixepoch'), \
		is_incoming, identity  FROM calls, conversations WHERE calls.conv_dbid = conversations.id;")
	print '\n[*] --- Found Calls --- '
	calls = '[*] --- Found Calls of %s' % (os.path.basename(PathName)) +' ---\n'
	for row in c:
		
		print '[+] Date: %s'%(str(row[0])) + ' | Partner: %s' %(str(row[3]))
		if (str(row[1])) != 'None':
			print '[+] Call Duration: %s' %(str(row[1])) 
		if ((str(row[2])) == '1'):
			print '[~] This was an Incoming Call\n'
		else: 
			print '[~] This was an Outgoing Call\n'
			#output
		
		calls += '[+] Date: %s'%(str(row[0])) + ' | Partner: %s\n' %(str(row[3]))
		if (str(row[1])) != 'None':
			calls += '[+] Call Duration: %s\n' %(str(row[1]))
		if ((str(row[2])) == '1'):
			calls += '[~] This was an Incoming Call\n\n'
		else: 
			calls += '[~] This was an Outgoing Call\n\n'
	
	while True:
		try:
			choice = raw_input("\n[~] Generate Output?\n")
			choice = choice.lower()
		except (NameError, SyntaxError, EOFError):
			print '[!] Error Occured'
		if choice[0] == 'y':
			try:
				output = calls
				output += "\n[*] This file was Generated by Skype Freak\n[~] http://osandamalith.github.io/SkypeFreak/"
				filename = str(raw_input("[~] Enter a Filename: "))
				file = open(filename+'.txt' , "w")
				file.write(output)
				file.close()
				print '[~] File Saved to ' + os.path.abspath(filename) + '.txt'
				mainMenu(skypeDB, PathName)
				break
			except Exception, e:
				print '[!] Access Denied! Directory is not writable. Probably you are in C:\\ drive'
		if choice[0] == 'n':
			mainMenu(skypeDB, PathName)
			break 

def Msgs(skypeDB, PathName):
	connexion = sqlite3.connect(skypeDB)
	c = connexion.cursor()
	c.execute("SELECT datetime(timestamp,'unixepoch'), \
		dialog_partner, author, body_xml FROM Messages;")
	msgs = '[*] --- Messages Found of %s' % (os.path.basename(PathName)) +' ---\n'
	for row in c:
		try:
			if 'partlist' not in str(row[3]):
				if str(row[1]) != str(row[2]):
					msgDirection = 'To ' + str(row[1]) + ': '
				else:
					msgDirection = 'From ' + str(row[2]) + ': '
				print 'Time: ' + str(row[0]) + ' ' \
				+ msgDirection + str(row[3])
				
				msgs += 'Time: ' + str(row[0]) + ' ' + msgDirection + str(row[3]) + '\n'
		except:
			pass

	while True:
		try:
			choice = raw_input("[~] Generate Output?\n")
			choice = choice.lower()
		except (NameError, SyntaxError, EOFError):
			print '[!] Error Occured'
		if choice[0] == 'y':
			try:
				output = msgs
				output += "\n[*] This file was Generated by Skype Freak\n[~] http://osandamalith.github.io/SkypeFreak/"
				filename = str(raw_input("[~] Enter Filename: "))
				file = open(filename+'.txt' , "w")
				file.write(output)
				file.close()
				print '[~] File Saved to ' + os.path.abspath(filename) + '.txt'
				mainMenu(skypeDB, PathName)
				break
			except Exception, e:
				print '[!] Access Denied! Directory is not writable. Probably you are in C:\\ drive'
		if choice[0] == 'n':
			mainMenu(skypeDB, PathName)
			break 

def fullReport(skypeDB, PathName):
	connexion = sqlite3.connect(skypeDB)
	c = connexion.cursor()
	c.execute("SELECT fullname, skypename, city, country,\
		datetime(profile_timestamp,'unixepoch') FROM Accounts")
	profile = '[*] --- Details of %s' % (os.path.basename(PathName)) +' ---\n\n'
	for row in c:
		profile += '[+] User: %s \n' %(str(row[0]))
		profile += '[+] Skype Username: %s\n'%(str(row[1]))
		profile += '[+] Country: %s\n' % (str(row[2]))
		profile += '[+] Location: %s\n'% (str(row[3]))

	c.execute("SELECT displayname, skypename, country, city, about, phone_mobile, homepage, \
		birthday , datetime(lastonline_timestamp,'unixepoch') FROM Contacts;")
	
	contacts = '\n\n[*] --- Found Contacts of %s' % (os.path.basename(PathName)) +' ---\n\n'
	for row in c:
		contacts += '\n\n[+] User: %s' %(str(row[0]))
		contacts += '\n[+] Skype Username: %s\n' %(str(row[1]))
		if str(row[2])!= 'None':
			contacts += '[+] Country: %s\n' %(str(row[2]))
		if str(row[3])!= 'None':
			contacts += '[+] City: %s\n' %(str(row[3]))
		if str(row[4])!= 'None':
			contacts += '[+] About Text: %s\n' %(str(row[4]))
		if str(row[5])!= 'None':
			contacts += '[+] Mobile Number: %s\n' %(str(row[5]))
		if str(row[6])!= 'None':
			contacts += '[+] Homepage URL: %s\n' %(str(row[6]))
		if str(row[7])!= 'None':
			contacts += '[+] Birthday: %s\n' %(str(row[7]))
		if str(row[8])!= 'None':
			contacts += '[+] Last Online Date: %s\n' %(str(row[8]))
	
	c.execute("SELECT datetime(begin_timestamp,'unixepoch'), time(duration,'unixepoch'), \
		is_incoming, identity  FROM calls, conversations WHERE calls.conv_dbid = conversations.id;")
	
	calls = '\n\n[*] --- Found Calls of %s' % (os.path.basename(PathName)) +' ---\n\n'
	for row in c:
		
		calls += '[+] Date: %s'%(str(row[0])) + ' | Partner: %s\n' %(str(row[3]))
		if (str(row[1])) != 'None':
			calls += '[+] Call Duration: %s\n' %(str(row[1]))
		if ((str(row[2])) == '1'):
			calls += '[~] This was an Incoming Call\n\n'
		else: 
			calls += '[~] This was an Outgoing Call\n\n'
	
	connexion = sqlite3.connect(skypeDB)
	c.execute("SELECT datetime(timestamp,'unixepoch'), \
		dialog_partner, author, body_xml FROM Messages;")
	msgs = '\n\n[*] --- Messages Found of %s' % (os.path.basename(PathName)) +' ---\n\n'
	for row in c:
		try:
			if 'partlist' not in str(row[3]):
				if str(row[1]) != str(row[2]):
					msgDirection = 'To ' + str(row[1]) + ': '
				else:
					msgDirection = 'From ' + str(row[2]) + ': '
				msgs += 'Time: ' + str(row[0]) + ' ' + msgDirection + str(row[3]) + '\n'
		except:
			pass
			
	output = profile + contacts + calls + msgs
	output += "\n[*] This file was Generated by Skype Freak\n[~] http://osandamalith.github.io/SkypeFreak/"
	filename = str(raw_input("[~] Enter Filename: "))
	file = open(filename+'.txt' , "w")
	file.write(output)
	file.close()
	print '[~] File Saved to ' + os.path.abspath(filename) + '.txt'
	mainMenu(skypeDB, PathName)
	

def mainMenu(skypeDB, PathName):
	while True:
		try:
			choice = raw_input("[~] Go to Main Menu?\n")
			choice = choice.lower()
		except (NameError, SyntaxError, EOFError):
			print '[!] Error Occured'
		if choice[0] == 'y':
			banner(skypeDB, PathName)
		if choice[0] == 'n':
			sys.exit(0) 

def banner(skypeDB, PathName):
	
	if os.name == "nt":
		os.system('cls')
	else:
		os.system('clear')
	
	print  '''
8""""8                         
8      e   e  e    e eeeee eeee
8eeeee 8   8  8    8 8   8 8   
    88 8eee8e 8eeee8 8eee8 8eee
e   88 88   8   88   88    88  
8eee88 88   8   88   88    88ee
                               
	8""""                         
	8     eeeee  eeee eeeee e   e 
	8eeee 8   8  8    8   8 8   8 
	88    8eee8e 8eee 8eee8 8eee8e
	88    88   8 88   88  8 88   8
	88    88   8 88ee 88  8 88   8

'''
	print  '%s' %('[*] A creation of Osanda Malith\n[*] Follow @OsandaMalith\n[*] URL: http://osandamalith.github.io/SkypeFreak/') + '\n'
	
	while True:
		try:
			choice = int(raw_input("[~] What Do You Like to Investigate? \
				\n1. Profile\n2. Contact\n3. Calls\n4. Messages\n5. Generate Full Report\n6. Exit\n" ))
		except ValueError:
			print '[!] Enter Only a Number'
			continue
		if choice == 1:
			Profile(skypeDB, PathName)
			break
		if choice == 2:
			Contacts(skypeDB, PathName)
			break
		if choice == 3:
			Calls(skypeDB, PathName)
			break
		if choice == 4:
			Msgs(skypeDB, PathName)
			break
		if choice == 5:
			fullReport(skypeDB, PathName)
			break
		if choice == 6:
			sys.exit(0)
		else:
			print '[!] Invalid Choice'



def menu(username):

	if os.name == "nt":
		PathName = os.getenv('appdata') + "\\Skype\\" + username
	elif os.name == "posix":
		PathName = os.getenv('HOME') + "/.Skype/" + username
	
	if PathName == None : 
		print '[!] Please Enter a valid Skype username ' 

	elif ((os.name == "posix") and (os.path.isdir(PathName) == False)):
		PathName = os.getenv('HOME') + "/Library/Application Support/Skype/" + username
		skypeDB = os.path.join(PathName, 'main.db')
		
		if os.path.isfile(skypeDB):
			banner(skypeDB,PathName)

		
	elif os.path.isdir(PathName) == False:
		print '[!] Username Does Not Exist ' 
		
	else:
		skypeDB = os.path.join(PathName, 'main.db')
		
		if os.path.isfile(skypeDB):
			banner(skypeDB,PathName)

def main():
	try:
		if os.name == "nt":
			os.system('cls')
		else:
			os.system('clear')
		while True:
			username = str(raw_input("[~] Enter your Skype Username: "))
			menu(username)
			break
				
	except (KeyboardInterrupt):
		print '[!] Ctrl + C detected\n[!] Exiting'
		sys.exit(0)
	except (EOFError):
		print '[!] Ctrl + D detected\n[!] Exiting'
		sys.exit(0)
		
			

if __name__ == "__main__": 
	main()	
