19 package org.sleuthkit.autopsy.modules.android;
22 import java.sql.Connection;
23 import java.sql.DriverManager;
24 import java.sql.ResultSet;
25 import java.sql.SQLException;
26 import java.sql.Statement;
27 import java.util.List;
28 import java.util.logging.Level;
29 import org.apache.commons.codec.binary.Base64;
30 import org.openide.util.NbBundle;
46 class TangoMessageAnalyzer {
48 private static final String moduleName = AndroidModuleFactory.getModuleName();
49 private static final Logger logger = Logger.getLogger(TangoMessageAnalyzer.class.getName());
50 private static Blackboard blackboard;
52 public static void findTangoMessages(Content dataSource, FileManager fileManager) {
53 blackboard = Case.getCurrentCase().getServices().getBlackboard();
54 List<AbstractFile> absFiles;
56 absFiles = fileManager.findFiles(dataSource,
"tc.db");
57 for (AbstractFile abstractFile : absFiles) {
59 File jFile =
new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName());
60 ContentUtils.writeToFile(abstractFile, jFile);
61 findTangoMessagesInDB(jFile.toString(), abstractFile);
62 }
catch (Exception e) {
63 logger.log(Level.SEVERE,
"Error parsing Tango messages", e);
66 }
catch (TskCoreException e) {
67 logger.log(Level.SEVERE,
"Error finding Tango messages", e);
71 private static void findTangoMessagesInDB(String DatabasePath, AbstractFile f) {
72 Connection connection = null;
73 ResultSet resultSet = null;
74 Statement statement = null;
76 if (DatabasePath == null || DatabasePath.isEmpty()) {
80 Class.forName(
"org.sqlite.JDBC");
81 connection = DriverManager.getConnection(
"jdbc:sqlite:" + DatabasePath);
82 statement = connection.createStatement();
83 }
catch (ClassNotFoundException | SQLException e) {
84 logger.log(Level.SEVERE,
"Error opening database", e);
89 resultSet = statement.executeQuery(
90 "SELECT conv_id, create_time,direction,payload FROM messages ORDER BY create_time DESC;");
96 while (resultSet.next()) {
97 conv_id = resultSet.getString(
"conv_id");
98 Long create_time = Long.valueOf(resultSet.getString(
"create_time")) / 1000;
99 if (resultSet.getString(
"direction").equals(
"1")) {
100 direction =
"Incoming";
102 direction =
"Outgoing";
104 payload = resultSet.getString(
"payload");
106 BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE);
107 bba.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, create_time));
108 bba.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, direction));
109 bba.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, decodeMessage(conv_id, payload)));
110 bba.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName,
111 NbBundle.getMessage(TangoMessageAnalyzer.class,
112 "TangoMessageAnalyzer.bbAttribute.tangoMessage")));
116 blackboard.indexArtifact(bba);
117 }
catch (Blackboard.BlackboardException ex) {
118 logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class,
"Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex);
119 MessageNotifyUtil.Notify.error(
120 NbBundle.getMessage(Blackboard.class,
"Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
123 }
catch (Exception e) {
124 logger.log(Level.SEVERE,
"Error parsing Tango messages to the Blackboard", e);
127 if (resultSet != null) {
132 }
catch (Exception e) {
133 logger.log(Level.SEVERE,
"Error closing database", e);
139 private static String decodeMessage(String wrapper, String message) {
141 byte[] decoded = Base64.decodeBase64(message);
143 String Z =
new String(decoded,
"UTF-8");
144 result = Z.split(wrapper)[1];
145 }
catch (Exception e) {
146 logger.log(Level.SEVERE,
"Error decoding a Tango message", e);