From 6c5be27eaeffce0704e87ff18492e681128e3cf2 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 25 Jun 2014 16:34:28 -0400 Subject: [PATCH 1/5] Initial commit in main project from @shahit2 repo --- .../modules/android/AndroidIngestModule.java | 169 ++++++++++++++ .../modules/android/AndroidModuleFactory.java | 63 ++++++ .../android/BrowserLocationAnalyzer.java | 132 +++++++++++ .../autopsy/modules/android/Bundle.properties | 2 + .../android/CacheLocationAnalyzer.java | 147 +++++++++++++ .../modules/android/CallLogAnalyzer.java | 131 +++++++++++ .../modules/android/ContactAnalyzer.java | 147 +++++++++++++ .../android/GoogleMapLocationAnalyzer.java | 167 ++++++++++++++ .../modules/android/KMLFileCreator.java | 208 ++++++++++++++++++ .../modules/android/TangoMessageAnalyzer.java | 142 ++++++++++++ .../modules/android/TextMessageAnalyzer.java | 133 +++++++++++ .../modules/android/WWFMessageAnalyzer.java | 130 +++++++++++ .../autopsy/modules/iOS/Bundle.properties | 2 + .../autopsy/modules/iOS/CallLogAnalyzer.java | 131 +++++++++++ .../autopsy/modules/iOS/ContactAnalyzer.java | 196 +++++++++++++++++ .../modules/iOS/TextMessageAnalyzer.java | 133 +++++++++++ .../autopsy/modules/iOS/iOSIngestModule.java | 53 +++++ .../autopsy/modules/iOS/iOSModuleFactory.java | 63 ++++++ 18 files changed, 2149 insertions(+) create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties create mode 100755 Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java create mode 100755 Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java new file mode 100755 index 0000000000..87138ee305 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java @@ -0,0 +1,169 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import java.util.ArrayList; +import java.util.HashMap; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; +import org.sleuthkit.autopsy.ingest.IngestModule; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; +import org.sleuthkit.autopsy.ingest.IngestJobContext; +import org.sleuthkit.autopsy.ingest.IngestMessage; +import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; +import org.sleuthkit.autopsy.ingest.IngestServices; + +class AndroidIngestModule implements DataSourceIngestModule { + + private static final HashMap fileCountsForIngestJobs = new HashMap<>(); + private IngestJobContext context = null; + private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); + private static final Logger logger = Logger.getLogger(AndroidIngestModule.class.getName()); + private IngestServices services = IngestServices.getInstance(); + + @Override + public void startUp(IngestJobContext context) throws IngestModuleException { + this.context = context; + } + + @Override + public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) { + + + services.postMessage(IngestMessage.createMessage(IngestMessage.MessageType.INFO, AndroidModuleFactory.getModuleName(), "Started {0}")); + + + ArrayList errors = new ArrayList<>(); + progressBar.switchToDeterminate(9); + + try { + ContactAnalyzer FindContacts = new ContactAnalyzer(); + FindContacts.findContacts(); + progressBar.progress(1); + if (context.isJobCancelled()) { + return IngestModule.ProcessResult.OK; + } + } catch (Exception e) { + errors.add("Error getting Contacts"); + } + try { + CallLogAnalyzer FindCallLogs = new CallLogAnalyzer(); + FindCallLogs.findCallLogs(); + progressBar.progress(2); + if (context.isJobCancelled()) { + return IngestModule.ProcessResult.OK; + } + } catch (Exception e) { + errors.add("Error getting Call Logs"); + } + try { + TextMessageAnalyzer FindTexts = new TextMessageAnalyzer(); + FindTexts.findTexts(); + progressBar.progress(3); + if (context.isJobCancelled()) { + return IngestModule.ProcessResult.OK; + } + } catch (Exception e) { + errors.add("Error getting Text Messages"); + } + try { + TangoMessageAnalyzer FindTangoMessages = new TangoMessageAnalyzer(); + FindTangoMessages.findTangoMessages(); + progressBar.progress(4); + if (context.isJobCancelled()) { + return IngestModule.ProcessResult.OK; + } + } catch (Exception e) { + errors.add("Error getting Tango Messages"); + } + try { + WWFMessageAnalyzer FindWWFMessages = new WWFMessageAnalyzer(); + FindWWFMessages.findWWFMessages(); + progressBar.progress(5); + if (context.isJobCancelled()) { + return IngestModule.ProcessResult.OK; + } + } catch (Exception e) { + errors.add("Error getting Words with Friends Messages"); + } + try { + GoogleMapLocationAnalyzer FindGoogleMapLocations = new GoogleMapLocationAnalyzer(); + FindGoogleMapLocations.findGeoLocations(); + progressBar.progress(6); + if (context.isJobCancelled()) { + return IngestModule.ProcessResult.OK; + } + } catch (Exception e) { + errors.add( "Error getting Google Map Locations"); + } + try { + BrowserLocationAnalyzer FindBrowserLocations = new BrowserLocationAnalyzer(); + FindBrowserLocations.findGeoLocations(); + progressBar.progress(7); + } catch (Exception e) { + errors.add("Error getting Browser Locations"); + } + if (context.isJobCancelled()) { + return IngestModule.ProcessResult.OK; + } + try { + CacheLocationAnalyzer FindCacheLocations = new CacheLocationAnalyzer(); + FindCacheLocations.findGeoLocations(); + progressBar.progress(8); + } catch (Exception e) { + errors.add("Error getting Cache Locations"); + } + try { + KMLFileCreator KMLFileCreator = new KMLFileCreator(); + KMLFileCreator.CreateKML(); + progressBar.progress(9); + } catch (Exception e) { + errors.add("Error creating KML"); + } + + // create the final message for inbox + StringBuilder errorMessage = new StringBuilder(); + String errorMsgSubject; + IngestMessage.MessageType msgLevel = IngestMessage.MessageType.INFO; + if (errors.isEmpty() == false) { + msgLevel = IngestMessage.MessageType.ERROR; + errorMessage.append("Errors were encountered"); + for (String msg : errors) { + errorMessage.append("
  • ").append(msg).append("
  • \n"); //NON-NLS + } + errorMessage.append("\n"); //NON-NLS + + if (errors.size() == 1) { + errorMsgSubject = "One error was found"; + } else { + errorMsgSubject = "errors found: " +errors.size(); + } + } else { + errorMessage.append( "No errors"); + errorMsgSubject ="No errors"; + } + final IngestMessage msg = IngestMessage.createMessage(msgLevel, AndroidModuleFactory.getModuleName(),"Ingest Finished"); + services.postMessage(msg); + + return IngestModule.ProcessResult.OK; + } + + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java new file mode 100755 index 0000000000..b3e49a0135 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java @@ -0,0 +1,63 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import org.openide.util.lookup.ServiceProvider; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.ingest.IngestModuleFactory; +import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; +import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; + + +@ServiceProvider(service = IngestModuleFactory.class) // +public class AndroidModuleFactory extends IngestModuleFactoryAdapter { + + private static final String VERSION_NUMBER = "1.0.0"; + + static String getModuleName() { + return NbBundle.getMessage(AndroidModuleFactory.class, "AndroidModuleFactory.moduleName"); + } + + @Override + public String getModuleDisplayName() { + return getModuleName(); + } + + @Override + public String getModuleDescription() { + return NbBundle.getMessage(AndroidModuleFactory.class, "AndroidModuleFactory.moduleDescription"); + } + + @Override + public String getModuleVersionNumber() { + return VERSION_NUMBER; + } + + @Override + public boolean isDataSourceIngestModuleFactory() { + return true; + } + + @Override + public DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings settings) { + return new AndroidIngestModule(); + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java new file mode 100755 index 0000000000..5d83c76f02 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java @@ -0,0 +1,132 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + +class BrowserLocationAnalyzer { + + private Connection connection = null; + private ResultSet resultSet = null; + private Statement statement = null; + private String dbPath = ""; + private long fileId = 0; + private java.io.File jFile = null; + private String moduleName= AndroidModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(BrowserLocationAnalyzer.class.getName()); + + public void findGeoLocations() { + List absFiles; + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name LIKE 'CachedGeoposition%.db'"); //get exact file names + if (absFiles.isEmpty()) { + return; + } + for (AbstractFile AF : absFiles) { + try { + if (AF.getSize() ==0) continue; + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); + ContentUtils.writeToFile(AF,jFile); + dbPath = jFile.toString(); //path of file as string + fileId = AF.getId(); + findGeoLocationsInDB(dbPath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Browser Location files", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding Browser Location files", e); + + } + } + + private void findGeoLocationsInDB(String DatabasePath, long fId) { + if (DatabasePath == null || DatabasePath.isEmpty()) { + return; + } + try { + Class.forName("org.sqlite.JDBC"); //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); + statement = connection.createStatement(); + } catch (ClassNotFoundException | SQLException e) { + logger.log(Level.SEVERE, "Error connecting to sql database", e); + } + + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + AbstractFile f = skCase.getAbstractFileById(fId); + try { + resultSet = statement.executeQuery( + "Select timestamp, latitude, longitude, accuracy FROM CachedPosition;"); + + BlackboardArtifact bba; + String timestamp; // unix time + String latitude; + String longitude; + String accuracy; //measure of how accurate the gps location is. + + + while (resultSet.next()) { + timestamp = resultSet.getString("timestamp"); + latitude= resultSet.getString("latitude"); + longitude = resultSet.getString("longitude"); + accuracy = resultSet.getString("accuracy"); + + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(),moduleName,latitude)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(),moduleName, longitude)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),moduleName, timestamp)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),moduleName, "Browser Location History")); + // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)); + + + } + + } catch (Exception e) { + logger.log(Level.SEVERE, "Error Putting artifacts to Blackboard", e); + } finally { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error Putting artifacts to Blackboard", e); + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties new file mode 100755 index 0000000000..da74d9519e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties @@ -0,0 +1,2 @@ +AndroidModuleFactory.moduleName=Android Mobile Device Analysis +AndroidModuleFactory.moduleDescription=An Android mobile forensics add-on to Autopsy diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java new file mode 100755 index 0000000000..7407e0c094 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java @@ -0,0 +1,147 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + +class CacheLocationAnalyzer { + + private String filePath = ""; + private long fileId = 0; + private java.io.File jFile = null; + private String moduleName= AndroidModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(CacheLocationAnalyzer.class.getName()); + public void findGeoLocations() { + List absFiles; + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name ='cache.cell'OR name='cache.wifi'"); //get exact file names + if (absFiles.isEmpty()) { + return; + } + for (AbstractFile AF : absFiles) { + try { + if (AF.getSize() ==0) continue; + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); + ContentUtils.writeToFile(AF,jFile); + filePath = jFile.toString(); //path of file as string + fileId = AF.getId(); + findGeoLocationsInFile(filePath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing cached Location files", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding cached Location files", e); + } + } + + private void findGeoLocationsInFile(String filePath, long fId) { + if (filePath == null || filePath.isEmpty()) { + return; + } + String fileName=filePath.contains("cell")? "cache.cell":"cache.wifi"; + File file = new File(filePath); //cache.cell or cache.wifi + byte[] bytes; // will temporarily hold bytes to be converted into the correct data types + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + InputStream inputStream = new FileInputStream(file); + AbstractFile f = skCase.getAbstractFileById(fId); + BlackboardArtifact bba; + String timestamp; // unix time + String latitude; + String longitude; + String confidence; + String accuracy; //measure of how accurate the gps location is. + + bytes = new byte[(int) 2]; // version + inputStream.read(bytes); + bytes = new byte[(int) 2]; + inputStream.read(bytes); //number of location entries + int iterations = new BigInteger(bytes).intValue(); + + for (int i = 0; i < iterations; i++) { //loop through every entry + bytes = new byte[(int) 2]; + inputStream.read(bytes); + bytes = new byte[(int) 1]; + inputStream.read(bytes); + while (new BigInteger(bytes).intValue() != 0) //pass through non important values until the start of accuracy(around 7-10 bytes) + { + inputStream.read(bytes); + } + bytes = new byte[(int) 3]; + inputStream.read(bytes); + if (new BigInteger(bytes).intValue()<=0){//This refers to a location that could not be calculated. + bytes = new byte[(int) 28]; //read rest of the row's bytes + inputStream.read(bytes); + continue; + } + accuracy=""+new BigInteger(bytes).intValue(); + + bytes = new byte[(int) 4]; + inputStream.read(bytes); + confidence=""+new BigInteger(bytes).intValue(); + + bytes = new byte[(int) 8]; + inputStream.read(bytes); + latitude=""+toDouble(bytes); + + bytes = new byte[(int) 8]; + inputStream.read(bytes); + longitude= ""+toDouble(bytes); + + bytes = new byte[(int) 8]; + inputStream.read(bytes); + timestamp = ""+new BigInteger(bytes).intValue(); + + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(),moduleName,latitude)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(),moduleName, longitude)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),moduleName, timestamp)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),moduleName, fileName+" Location History")); + + //Not storing these for now. + // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)); + // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(),moduleName, confidence)); + } + + }catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Cached GPS locations to Blackboard", e); + } + } + + public static double toDouble(byte[] bytes) { + return ByteBuffer.wrap(bytes).getDouble(); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java new file mode 100755 index 0000000000..691a1a180b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java @@ -0,0 +1,131 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + + class CallLogAnalyzer { + + private Connection connection = null; + private ResultSet resultSet = null; + private Statement statement = null; + private String dbPath = ""; + private long fileId = 0; + private java.io.File jFile = null; + private String moduleName= AndroidModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(CallLogAnalyzer.class.getName()); + + public void findCallLogs() { + List absFiles; + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name ='contacts2.db' OR name ='contacts.db'"); //get exact file names + if (absFiles.isEmpty()) { + return; + } + for (AbstractFile AF : absFiles) { + try { + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); + ContentUtils.writeToFile(AF,jFile); + dbPath = jFile.toString(); //path of file as string + fileId = AF.getId(); + findCallLogsInDB(dbPath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Call logs", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding Call logs", e); + } + } + + private void findCallLogsInDB(String DatabasePath, long fId) { + if (DatabasePath == null || DatabasePath.isEmpty()) { + return; + } + try { + Class.forName("org.sqlite.JDBC"); //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); + statement = connection.createStatement(); + } catch (ClassNotFoundException | SQLException e) { + logger.log(Level.SEVERE, "Error opening database", e); + } + + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + AbstractFile f = skCase.getAbstractFileById(fId); + try { + resultSet = statement.executeQuery( + "SELECT number,date,duration,type, name FROM calls ORDER BY date DESC;"); + + BlackboardArtifact bba; + String name; // name of person dialed or called. null if unregistered + String number; //string phone number + String duration; //duration of call in seconds + String date; // Unix time + String type; // 1 incoming, 2 outgoing, 3 missed + + while (resultSet.next()) { + name = resultSet.getString("name"); + number = resultSet.getString("number"); + duration = resultSet.getString("duration"); + date = resultSet.getString("date"); + type = resultSet.getString("type"); + + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); //create a call log and then add attributes from result set. + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(),moduleName, number)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), moduleName, date)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), moduleName, duration+date)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, type)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, name)); + + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); + } finally { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing the database", e); + } + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); + } + + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java new file mode 100755 index 0000000000..8505a5b16f --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java @@ -0,0 +1,147 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +class ContactAnalyzer { + + private Connection connection = null; + private ResultSet resultSet = null; + private Statement statement = null; + private String dbPath = ""; + private long fileId = 0; + private java.io.File jFile = null; + private String moduleName= AndroidModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(ContactAnalyzer.class.getName()); + + public void findContacts() { + + List absFiles; + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name ='contacts2.db' OR name ='contacts.db'"); //get exact file names + if (absFiles.isEmpty()) { + return; + } + for (AbstractFile AF : absFiles) { + try { + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); + ContentUtils.writeToFile(AF,jFile); + dbPath = jFile.toString(); //path of file as string + fileId = AF.getId(); + findContactsInDB(dbPath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Contacts", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding Contacts", e); + } + } + + /** + * + * @param DatabasePath + * @param fId Will create artifact from a database given by the path The + * fileId will be the Abstract file associated with the artifacts + */ + private void findContactsInDB(String DatabasePath, long fId) { + if (DatabasePath == null || DatabasePath.isEmpty()) { + return; + } + try { + Class.forName("org.sqlite.JDBC"); //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); + statement = connection.createStatement(); + } catch (ClassNotFoundException | SQLException e) { + logger.log(Level.SEVERE, "Error opening database", e); + } + + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + AbstractFile f = skCase.getAbstractFileById(fId); + try { + // get display_name, mimetype(email or phone number) and data1 (phonenumber or email address depending on mimetype) + //sorted by name, so phonenumber/email would be consecutive for a person if they exist. + resultSet = statement.executeQuery( + "SELECT mimetype,data1, name_raw_contact.display_name AS display_name \n" + + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" + + "JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) " + + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" + + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" + + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" + + "ORDER BY name_raw_contact.display_name ASC;"); + + BlackboardArtifact bba; + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); + String name; + String oldName = ""; + String mimetype; // either phone or email + String data1; // the phone number or email + while (resultSet.next()) { + name = resultSet.getString("display_name"); + data1 = resultSet.getString("data1"); + mimetype = resultSet.getString("mimetype"); +// System.out.println(resultSet.getString("data1") + resultSet.getString("mimetype") + resultSet.getString("display_name")); //Test code + if (name.equals(oldName) == false) { + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, name)); + } + if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, data1)); + } else { + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID(), moduleName, data1)); + } + oldName = name; + } + + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); + } finally { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); + } + + } + + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java new file mode 100755 index 0000000000..5b090f9408 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java @@ -0,0 +1,167 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + + +class GoogleMapLocationAnalyzer { + + private Connection connection = null; + private ResultSet resultSet = null; + private Statement statement = null; + private String dbPath = ""; + private long fileId = 0; + private java.io.File jFile = null; + private String moduleName = AndroidModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(GoogleMapLocationAnalyzer.class.getName()); + + public void findGeoLocations() { + List absFiles; + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name ='da_destination_history'"); //get exact file name + if (absFiles.isEmpty()) { + return; + } + for (AbstractFile AF : absFiles) { + try { + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); + ContentUtils.writeToFile(AF,jFile); + dbPath = jFile.toString(); //path of file as string + fileId = AF.getId(); + findGeoLocationsInDB(dbPath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Google map locations", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding Google map locations", e); + } + } + + private void findGeoLocationsInDB(String DatabasePath, long fId) { + if (DatabasePath == null || DatabasePath.isEmpty()) { + return; + } + try { + Class.forName("org.sqlite.JDBC"); //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); + statement = connection.createStatement(); + } catch (ClassNotFoundException | SQLException e) { + logger.log(Level.SEVERE, "Error opening database", e); + } + + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + AbstractFile f = skCase.getAbstractFileById(fId); + try { + resultSet = statement.executeQuery( + "Select time,dest_lat,dest_lng,dest_title,dest_address,source_lat,source_lng FROM destination_history;"); + + BlackboardArtifact bba; + String time; // unix time + String dest_lat; + String dest_lng; + String dest_title; // name of the location + String dest_address; + String source_lat; + String source_lng; + + while (resultSet.next()) { + time = resultSet.getString("time"); + dest_lat = resultSet.getString("dest_lat"); + dest_lng = resultSet.getString("dest_lng"); + dest_title = resultSet.getString("dest_title"); + dest_address = resultSet.getString("dest_address"); + source_lat = resultSet.getString("source_lat"); + source_lng = resultSet.getString("source_lng"); + + //add periods 6 decimal places before the end. + if(dest_lat.length()>6)dest_lat = dest_lat.substring(0, dest_lat.length()-6) + "." + dest_lat.substring(dest_lat.length()-6, dest_lat.length()) ; + if(dest_lng.length()>6)dest_lng = dest_lng.substring(0, dest_lng.length()-6) + "." + dest_lng.substring(dest_lng.length()-6, dest_lng.length()) ; + if(source_lat.length()>6)source_lat = source_lat.substring(0, source_lat.length()-6) + "." + source_lat.substring(source_lat.length()-6, source_lat.length()) ; + if(source_lng.length()>6)source_lng = source_lng.substring(0, source_lng.length()-6) + "." + source_lng.substring(source_lng.length()-6, source_lng.length()) ; + +// bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT);//src +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID(), moduleName, "Source")); +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, source_lat)); +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), moduleName, source_lng)); +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, time)); +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DESCRIPTION.getTypeID(), moduleName, "Google Maps History")); +// +// bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT);//dest +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID(), moduleName, "Destination")); +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, time)); +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, dest_lat)); +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), moduleName, dest_lng)); +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, dest_title)); +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID(), moduleName, dest_address)); +// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "Google Maps History")); + + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID(), moduleName, "Destination")); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, time)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID(), moduleName, dest_lat)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID(), moduleName, dest_lng)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID(), moduleName, source_lat)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID(), moduleName, source_lng)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, dest_title)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID(), moduleName, dest_address)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "Google Maps History")); + + + + + + } + + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Google map locations to the Blackboard", e); + } finally { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing the database", e); + } + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Google map locations to the Blackboard", e); + } + + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java b/Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java new file mode 100755 index 0000000000..0e1c2069a9 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java @@ -0,0 +1,208 @@ +/* + * + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.Namespace; +import org.jdom2.output.Format; +import org.jdom2.output.XMLOutputter; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + +public class KMLFileCreator { + + private Case currentCase; + private SleuthkitCase skCase; + private String reportPath; + + public void CreateKML() { + + reportPath = Case.getCurrentCase().getTempDirectory() + "ReportKML.kml"; //NON-NLS + String reportPath2 = Case.getCurrentCase().getTempDirectory() + "ReportKML.txt"; //NON-NLS + currentCase = Case.getCurrentCase(); + skCase = currentCase.getSleuthkitCase(); + + try { + + BufferedWriter out = null; + try { + out = new BufferedWriter(new FileWriter(reportPath2)); + + String lat = ""; // temp latitude + String lon = ""; //temp longitude + String destlon = ""; + String destlat = ""; + for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT)) { + lat = ""; + lon = ""; + for (BlackboardAttribute attribute : artifact.getAttributes()) { + if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude + { + lat = attribute.getValueString(); + } + if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude + { + lon = attribute.getValueString(); + } + } + if (!lon.isEmpty() && !lat.isEmpty()) { + out.write(lat + ";" + lon + "\n"); + + } + } + for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE)) { + lat = ""; + lon = ""; + for (BlackboardAttribute attribute : artifact.getAttributes()) { + if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID()) //latitude + { + lat = attribute.getValueString(); + } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID()) //longitude + { + destlat = attribute.getValueString(); + } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID()) //longitude + { + lon = attribute.getValueString(); + } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID()) //longitude + { + destlon = attribute.getValueString(); + } + + } + if (!lon.isEmpty() && !lat.isEmpty()) { + out.write(lat + ";" + lon + "\n"); + } + if (!destlon.isEmpty() && !destlat.isEmpty()) { + out.write(destlat + ";" + destlon + "\n"); + + } + } + out.flush(); + out.close(); + /* + * Step 1: generate XML stub + */ + Namespace ns = Namespace.getNamespace("", "http://earth.google.com/kml/2.2"); //NON-NLS + // kml + Element kml = new Element("kml", ns); //NON-NLS + Document kmlDocument = new Document(kml); + + // Document + Element document = new Element("Document", ns); //NON-NLS + kml.addContent(document); + + // name + Element name = new Element("name", ns); //NON-NLS + name.setText("Java Generated KML Document"); //NON-NLS + document.addContent(name); + + /* + * Step 2: add in Style elements + */ + + // Style + Element style = new Element("Style", ns); //NON-NLS + style.setAttribute("id", "redIcon"); //NON-NLS + document.addContent(style); + + // IconStyle + Element iconStyle = new Element("IconStyle", ns); //NON-NLS + style.addContent(iconStyle); + + // color + Element color = new Element("color", ns); //NON-NLS + color.setText("990000ff"); //NON-NLS + iconStyle.addContent(color); + + // Icon + Element icon = new Element("Icon", ns); //NON-NLS + iconStyle.addContent(icon); + + // href + Element href = new Element("href", ns); //NON-NLS + href.setText("http://www.cs.mun.ca/~hoeber/teaching/cs4767/notes/02.1-kml/circle.png"); //NON-NLS + icon.addContent(href); + /* + * Step 3: read data from source location and + * add in a Placemark for each data element + */ + + File file = new File(reportPath2); + BufferedReader reader; + + reader = new BufferedReader(new FileReader(file)); + + String line = reader.readLine(); + while (line != null) { + String[] lineParts = line.split(";"); + if (lineParts.length == 2) { + String coordinates = lineParts[1].trim() + "," + lineParts[0].trim(); //lat,lon + // Placemark + Element placemark = new Element("Placemark", ns); //NON-NLS + document.addContent(placemark); + + // styleUrl + Element pmStyleUrl = new Element("styleUrl", ns); //NON-NLS + pmStyleUrl.setText("#redIcon"); //NON-NLS + placemark.addContent(pmStyleUrl); + + // Point + Element pmPoint = new Element("Point", ns); //NON-NLS + placemark.addContent(pmPoint); + + // coordinates + Element pmCoordinates = new Element("coordinates", ns); //NON-NLS + + pmCoordinates.setText(coordinates); + pmPoint.addContent(pmCoordinates); + + } + // read the next line + line = reader.readLine(); + } + /* + * Step 4: write the XML file + */ + try { + XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()); + FileOutputStream writer = new FileOutputStream(reportPath); + outputter.output(kmlDocument, writer); + writer.close(); + } catch (IOException ex) { + } + } catch (IOException ex) { + } + } catch (TskCoreException ex) { + } + + + } +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java new file mode 100755 index 0000000000..cfca851281 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java @@ -0,0 +1,142 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.apache.commons.codec.binary.Base64; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + + class TangoMessageAnalyzer { + private Connection connection = null; + private ResultSet resultSet = null; + private Statement statement = null; + private String dbPath = ""; + private long fileId = 0; + private java.io.File jFile = null; + private String moduleName= AndroidModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(TangoMessageAnalyzer.class.getName()); + + public void findTangoMessages() { + List absFiles; + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name ='tc.db' "); //get exact file names + if (absFiles.isEmpty()) { + return; + } + for (AbstractFile AF : absFiles) { + try { + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); + ContentUtils.writeToFile(AF,jFile); + dbPath = jFile.toString(); //path of file as string + fileId = AF.getId(); + findTangoMessagesInDB(dbPath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Tango messages", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding Tango messages", e); + } + + } + private void findTangoMessagesInDB(String DatabasePath, long fId) { + if (DatabasePath == null || DatabasePath.isEmpty()) { + return; + } + try { + Class.forName("org.sqlite.JDBC"); //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); + statement = connection.createStatement(); + } catch (ClassNotFoundException | SQLException e) { + logger.log(Level.SEVERE, "Error opening database", e); + } + + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + AbstractFile f = skCase.getAbstractFileById(fId); + try { + resultSet = statement.executeQuery( + "Select conv_id, create_time,direction,payload FROM messages ORDER BY create_time DESC;"); + + BlackboardArtifact bba; + String conv_id; // seems to wrap around the message found in payload after decoding from base-64 + String create_time; // unix time + String direction; // 1 incoming, 2 outgoing + String payload; // seems to be a base64 message wrapped by the conv_id + + + while (resultSet.next()) { + conv_id = resultSet.getString("conv_id"); + create_time = resultSet.getString("create_time"); + direction = resultSet.getString("direction"); + payload = resultSet.getString("payload"); + + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create a call log and then add attributes from result set. + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, create_time)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, direction)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName, decodeMessage(conv_id,payload))); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName,"Tango Message" )); + + } + + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Tango messages to the Blackboard", e); + } finally { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Tango messages to the Blackboard", e); + } + } + + //take the message string which is wrapped by a certain string, and return the text enclosed. + private String decodeMessage(String wrapper, String message) + { + String result= ""; + byte[] decoded = Base64.decodeBase64(message); + try{ + String Z= new String (decoded,"UTF-8"); + result = Z.split(wrapper)[1]; + }catch(Exception e){ + logger.log(Level.SEVERE, "Error decoding a Tango message", e); + } + return result; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java new file mode 100755 index 0000000000..6b0bd55b9e --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java @@ -0,0 +1,133 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + + + class TextMessageAnalyzer { + private Connection connection = null; + private ResultSet resultSet = null; + private Statement statement = null; + private String dbPath = ""; + private long fileId = 0; + private java.io.File jFile = null; + List absFiles; + private String moduleName= AndroidModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(TextMessageAnalyzer.class.getName()); + + + void findTexts() { + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name ='mmssms.db'"); //get exact file name + if (absFiles.isEmpty()) { + return; + } + for (AbstractFile AF : absFiles) { + try { + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); + ContentUtils.writeToFile(AF,jFile); + dbPath = jFile.toString(); //path of file as string + fileId = AF.getId(); + findTextsInDB(dbPath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing text messages", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding text messages", e); + } + } + private void findTextsInDB(String DatabasePath, long fId) { + if (DatabasePath == null || DatabasePath.isEmpty()) { + return; + } + try { + Class.forName("org.sqlite.JDBC"); //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); + statement = connection.createStatement(); + } catch (ClassNotFoundException | SQLException e) { + logger.log(Level.SEVERE, "Error opening database", e); + } + + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + AbstractFile f = skCase.getAbstractFileById(fId); + try { + resultSet = statement.executeQuery( + "Select address,date,type,subject,body FROM sms;"); + + BlackboardArtifact bba; + String address; // may be phone number, or other addresses + String date;//unix time + String type; // message received in inbox = 1, message sent = 2 + String subject;//message subject + String body; //message body + while (resultSet.next()) { + address = resultSet.getString("address"); + date = resultSet.getString("date"); + type = resultSet.getString("type"); + subject = resultSet.getString("subject"); + body = resultSet.getString("body"); + + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create Message artifact and then add attributes from result set. + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, address)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, date)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, type)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT.getTypeID(), moduleName, subject)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName, body)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName,"SMS Message" )); + + } + + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); + } finally { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); + } + + } + + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java new file mode 100755 index 0000000000..f01c25430d --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java @@ -0,0 +1,130 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.android; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + + class WWFMessageAnalyzer { + private Connection connection = null; + private ResultSet resultSet = null; + private Statement statement = null; + private String dbPath = ""; + private long fileId = 0; + private java.io.File jFile = null; + private String moduleName= AndroidModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(WWFMessageAnalyzer.class.getName()); + public void findWWFMessages() { + List absFiles; + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name ='WordsFramework' "); //get exact file names + if (absFiles.isEmpty()) { + return; + } + for (AbstractFile AF : absFiles) { + try { + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); + ContentUtils.writeToFile(AF,jFile); + dbPath = jFile.toString(); //path of file as string + fileId = AF.getId(); + findWWFMessagesInDB(dbPath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing WWF messages", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding WWF messages", e); + } + } + private void findWWFMessagesInDB(String DatabasePath, long fId) { + if (DatabasePath == null || DatabasePath.isEmpty()) { + return; + } + try { + Class.forName("org.sqlite.JDBC"); //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); + statement = connection.createStatement(); + } catch (ClassNotFoundException | SQLException e) { + logger.log(Level.SEVERE, "Error opening database", e); + } + + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + AbstractFile f = skCase.getAbstractFileById(fId); + try { + resultSet = statement.executeQuery( + "SELECT message,created_at,user_id,game_id FROM chat_messages ORDER BY game_id DESC, created_at DESC;"); + + BlackboardArtifact bba; + String message; // WWF Message + String created_at; // unix time + String user_id; // the ID of the user who sent the message. + String game_id; // ID of the game which the the message was sent. + + + while (resultSet.next()) { + message = resultSet.getString("message"); + created_at = resultSet.getString("created_at"); + user_id = resultSet.getString("user_id"); + game_id = resultSet.getString("game_id"); + + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create a call log and then add attributes from result set. + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, created_at)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, user_id)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MSG_ID.getTypeID(), moduleName, game_id)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName,message)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName,"Words With Friends Message" )); + + } + + + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing WWF messages to the Blackboard", e); + } finally { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing WWF messages to the Blackboard", e); + } + + } + + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties new file mode 100755 index 0000000000..c10b2cebec --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties @@ -0,0 +1,2 @@ +iOSModuleFactory.moduleName=iOS Mobile Device Analysis +iOSModuleFactory.moduleDescription=An iOS mobile forensics add-on to Autopsy diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java new file mode 100755 index 0000000000..966c538443 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java @@ -0,0 +1,131 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.iOS; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + + class CallLogAnalyzer { + + private Connection connection = null; + private ResultSet resultSet = null; + private Statement statement = null; + private String dbPath = ""; + private long fileId = 0; + private java.io.File jFile = null; + private String moduleName= iOSModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(CallLogAnalyzer.class.getName()); + + public void findCallLogs() { + List absFiles; + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name ='contacts2.db' OR name ='contacts.db'"); //get exact file names + if (absFiles.isEmpty()) { + return; + } + for (AbstractFile AF : absFiles) { + try { + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName().replaceAll("[<>%|\"/:*\\\\]", "")); + ContentUtils.writeToFile(AF,jFile); + dbPath = jFile.toString(); //path of file as string + fileId = AF.getId(); + findCallLogsInDB(dbPath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Call logs", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding Call logs", e); + } + } + + private void findCallLogsInDB(String DatabasePath, long fId) { + if (DatabasePath == null || DatabasePath.isEmpty()) { + return; + } + try { + Class.forName("org.sqlite.JDBC"); //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); + statement = connection.createStatement(); + } catch (ClassNotFoundException | SQLException e) { + logger.log(Level.SEVERE, "Error opening database", e); + } + + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + AbstractFile f = skCase.getAbstractFileById(fId); + try { + resultSet = statement.executeQuery( + "SELECT number,date,duration,type, name FROM calls ORDER BY date DESC;"); + + BlackboardArtifact bba; + String name; // name of person dialed or called. null if unregistered + String number; //string phone number + String duration; //duration of call in seconds + String date; // Unix time + String type; // 1 incoming, 2 outgoing, 3 missed + + while (resultSet.next()) { + name = resultSet.getString("name"); + number = resultSet.getString("number"); + duration = resultSet.getString("duration"); + date = resultSet.getString("date"); + type = resultSet.getString("type"); + + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); //create a call log and then add attributes from result set. + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(),moduleName, number)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), moduleName, date)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), moduleName, duration+date)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, type)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, name)); + + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); + } finally { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing the database", e); + } + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); + } + + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java new file mode 100755 index 0000000000..b689c8d779 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java @@ -0,0 +1,196 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.iOS; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.ReadContentInputStream; +class ContactAnalyzer { + + private Connection connection = null; + private ResultSet resultSet = null; + private Statement statement = null; + private String dbPath = ""; + private long fileId = 0; + private java.io.File jFile = null; + private String moduleName= iOSModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(ContactAnalyzer.class.getName()); + + public void findContacts() { + + List absFiles; + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name LIKE '%call_history%' "); //get exact file names + if (absFiles.isEmpty()) { //asdfkjasfakljsdfhlaksdjfhasdlkjf + return; + } + for (AbstractFile AF : absFiles) { + try { + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName().replaceAll("[<>%|\"/:*\\\\]", "")); + //jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), i+".txt"); + ContentUtils.writeToFile(AF,jFile); + //copyFileUsingStreams(AF,jFile); + //copyFileUsingStream(AF,jFile); + dbPath = jFile.toString(); //path of file as string + fileId = AF.getId(); + //findContactsInDB(dbPath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Contacts", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding Contacts", e); + } + } + + /** + * + * @param DatabasePath + * @param fId Will create artifact from a database given by the path The + * fileId will be the Abstract file associated with the artifacts + */ + private void findContactsInDB(String DatabasePath, long fId) { + if (DatabasePath == null || DatabasePath.isEmpty()) { + return; + } + try { + Class.forName("org.sqlite.JDBC"); //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); + statement = connection.createStatement(); + } catch (ClassNotFoundException | SQLException e) { + logger.log(Level.SEVERE, "Error opening database", e); + } + + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + AbstractFile f = skCase.getAbstractFileById(fId); + try { + // get display_name, mimetype(email or phone number) and data1 (phonenumber or email address depending on mimetype) + //sorted by name, so phonenumber/email would be consecutive for a person if they exist. + resultSet = statement.executeQuery( + "SELECT mimetype,data1, name_raw_contact.display_name AS display_name \n" + + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" + + "JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) " + + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" + + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" + + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" + + "ORDER BY name_raw_contact.display_name ASC;"); + + BlackboardArtifact bba; + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); + String name; + String oldName = ""; + String mimetype; // either phone or email + String data1; // the phone number or email + while (resultSet.next()) { + name = resultSet.getString("display_name"); + data1 = resultSet.getString("data1"); + mimetype = resultSet.getString("mimetype"); +// System.out.println(resultSet.getString("data1") + resultSet.getString("mimetype") + resultSet.getString("display_name")); //Test code + if (name.equals(oldName) == false) { + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, name)); + } + if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, data1)); + } else { + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID(), moduleName, data1)); + } + oldName = name; + } + + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); + } finally { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); + } + + } + + public static void copyFileUsingStream(AbstractFile file, File jFile) throws IOException { + InputStream is = new ReadContentInputStream(file); + OutputStream os = new FileOutputStream(jFile); + byte[] buffer = new byte[8192]; + int length; + try { + while ((length = is.read(buffer)) != -1) { + os.write(buffer, 0, length); + System.out.println(length); + os.flush(); + + } + + } finally { + is.close(); + os.close(); + } + } + public static void copyFileUsingStreams(AbstractFile file, File jFile) { + InputStream istream; + OutputStream ostream=null; + int c; + final int EOF = -1; + istream = new ReadContentInputStream(file); + //File outFile = new File("Data.txt"); + // System.out.println("Type characters to write in File – Press Ctrl+z to end "); + try { + ostream = new FileOutputStream(jFile); + while ((c = istream.read()) != EOF) + ostream.write(c); + } catch (IOException e) { + System.out.println("Error: " + e.getMessage()); + } finally { + try { + istream.close(); + ostream.close(); + } catch (IOException e) { + System.out.println("File did not close"); + } + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java new file mode 100755 index 0000000000..e3b788d076 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java @@ -0,0 +1,133 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.iOS; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.logging.Level; +import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.BlackboardArtifact; +import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + + + class TextMessageAnalyzer { + private Connection connection = null; + private ResultSet resultSet = null; + private Statement statement = null; + private String dbPath = ""; + private long fileId = 0; + private java.io.File jFile = null; + List absFiles; + private String moduleName= iOSModuleFactory.getModuleName(); + private static final Logger logger = Logger.getLogger(TextMessageAnalyzer.class.getName()); + + + void findTexts() { + try { + SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); + absFiles = skCase.findAllFilesWhere("name ='mmssms.db'"); //get exact file name + if (absFiles.isEmpty()) { + return; + } + for (AbstractFile AF : absFiles) { + try { + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(),AF.getName().replaceAll("[<>%|\"/:*\\\\]", "")); + ContentUtils.writeToFile(AF,jFile); + dbPath = jFile.toString(); //path of file as string + fileId = AF.getId(); + findTextsInDB(dbPath, fileId); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing text messages", e); + } + } + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error finding text messages", e); + } + } + private void findTextsInDB(String DatabasePath, long fId) { + if (DatabasePath == null || DatabasePath.isEmpty()) { + return; + } + try { + Class.forName("org.sqlite.JDBC"); //load JDBC driver + connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); + statement = connection.createStatement(); + } catch (ClassNotFoundException | SQLException e) { + logger.log(Level.SEVERE, "Error opening database", e); + } + + Case currentCase = Case.getCurrentCase(); + SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { + AbstractFile f = skCase.getAbstractFileById(fId); + try { + resultSet = statement.executeQuery( + "Select address,date,type,subject,body FROM sms;"); + + BlackboardArtifact bba; + String address; // may be phone number, or other addresses + String date;//unix time + String type; // message received in inbox = 1, message sent = 2 + String subject;//message subject + String body; //message body + while (resultSet.next()) { + address = resultSet.getString("address"); + date = resultSet.getString("date"); + type = resultSet.getString("type"); + subject = resultSet.getString("subject"); + body = resultSet.getString("body"); + + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create Message artifact and then add attributes from result set. + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, address)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, date)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, type)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT.getTypeID(), moduleName, subject)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName, body)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName,"SMS Message" )); + + } + + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); + } finally { + try { + resultSet.close(); + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } + } + } catch (Exception e) { + logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); + } + + } + + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java new file mode 100755 index 0000000000..ec688f31f4 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java @@ -0,0 +1,53 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.iOS; + +import java.util.HashMap; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; +import org.sleuthkit.autopsy.ingest.IngestModule; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; +import org.sleuthkit.autopsy.ingest.IngestJobContext; +import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; +import org.sleuthkit.autopsy.ingest.IngestServices; + +class iOSIngestModule implements DataSourceIngestModule { + + private static final HashMap fileCountsForIngestJobs = new HashMap<>(); + private IngestJobContext context = null; + private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); + private static final Logger logger = Logger.getLogger(iOSModuleFactory.class.getName()); + private IngestServices services = IngestServices.getInstance(); + + @Override + public void startUp(IngestJobContext context) throws IngestModule.IngestModuleException { + this.context = context; + } + + @Override + public IngestModule.ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) { + + ContactAnalyzer FindContacts = new ContactAnalyzer(); + FindContacts.findContacts(); + return IngestModule.ProcessResult.OK; + } + + +} diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java new file mode 100755 index 0000000000..eb95f2c935 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java @@ -0,0 +1,63 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2014 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.modules.iOS; + +import org.openide.util.lookup.ServiceProvider; +import org.openide.util.NbBundle; +import org.sleuthkit.autopsy.ingest.IngestModuleFactory; +import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; +import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; +import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; + + +@ServiceProvider(service = IngestModuleFactory.class) // +public class iOSModuleFactory extends IngestModuleFactoryAdapter { + + private static final String VERSION_NUMBER = "1.0.0"; + + static String getModuleName() { + return NbBundle.getMessage(iOSModuleFactory.class, "iOSModuleFactory.moduleName"); + } + + @Override + public String getModuleDisplayName() { + return getModuleName(); + } + + @Override + public String getModuleDescription() { + return NbBundle.getMessage(iOSModuleFactory.class, "iOSModuleFactory.moduleDescription"); + } + + @Override + public String getModuleVersionNumber() { + return VERSION_NUMBER; + } + + @Override + public boolean isDataSourceIngestModuleFactory() { + return true; + } + + @Override + public DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings settings) { + return new iOSIngestModule(); + } + +} From df4880b109cc962836a31e0ecc72c0c5e3d63b16 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 25 Jun 2014 16:54:39 -0400 Subject: [PATCH 2/5] Save times in Unix epoch (not milliseconds). Fixed compiler warnings --- .../android/BrowserLocationAnalyzer.java | 8 ++-- .../android/CacheLocationAnalyzer.java | 24 +++++------ .../modules/android/CallLogAnalyzer.java | 34 ++++++++------- .../android/GoogleMapLocationAnalyzer.java | 41 ++++++++----------- .../modules/android/TangoMessageAnalyzer.java | 3 +- .../modules/android/TextMessageAnalyzer.java | 4 +- .../modules/android/WWFMessageAnalyzer.java | 9 +--- 7 files changed, 56 insertions(+), 67 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java index 5d83c76f02..503ba26b76 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java @@ -92,17 +92,15 @@ class BrowserLocationAnalyzer { "Select timestamp, latitude, longitude, accuracy FROM CachedPosition;"); BlackboardArtifact bba; - String timestamp; // unix time + Long timestamp; // unix time String latitude; String longitude; - String accuracy; //measure of how accurate the gps location is. - + while (resultSet.next()) { - timestamp = resultSet.getString("timestamp"); + timestamp = Long.valueOf(resultSet.getString("timestamp")) / 1000; latitude= resultSet.getString("latitude"); longitude = resultSet.getString("longitude"); - accuracy = resultSet.getString("accuracy"); bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(),moduleName,latitude)); diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java index 7407e0c094..bfb6054c19 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java @@ -79,51 +79,51 @@ class CacheLocationAnalyzer { InputStream inputStream = new FileInputStream(file); AbstractFile f = skCase.getAbstractFileById(fId); BlackboardArtifact bba; - String timestamp; // unix time + String latitude; String longitude; String confidence; String accuracy; //measure of how accurate the gps location is. - bytes = new byte[(int) 2]; // version + bytes = new byte[2]; // version inputStream.read(bytes); - bytes = new byte[(int) 2]; + bytes = new byte[2]; inputStream.read(bytes); //number of location entries int iterations = new BigInteger(bytes).intValue(); for (int i = 0; i < iterations; i++) { //loop through every entry - bytes = new byte[(int) 2]; + bytes = new byte[2]; inputStream.read(bytes); - bytes = new byte[(int) 1]; + bytes = new byte[1]; inputStream.read(bytes); while (new BigInteger(bytes).intValue() != 0) //pass through non important values until the start of accuracy(around 7-10 bytes) { inputStream.read(bytes); } - bytes = new byte[(int) 3]; + bytes = new byte[3]; inputStream.read(bytes); if (new BigInteger(bytes).intValue()<=0){//This refers to a location that could not be calculated. - bytes = new byte[(int) 28]; //read rest of the row's bytes + bytes = new byte[28]; //read rest of the row's bytes inputStream.read(bytes); continue; } accuracy=""+new BigInteger(bytes).intValue(); - bytes = new byte[(int) 4]; + bytes = new byte[4]; inputStream.read(bytes); confidence=""+new BigInteger(bytes).intValue(); - bytes = new byte[(int) 8]; + bytes = new byte[8]; inputStream.read(bytes); latitude=""+toDouble(bytes); - bytes = new byte[(int) 8]; + bytes = new byte[8]; inputStream.read(bytes); longitude= ""+toDouble(bytes); - bytes = new byte[(int) 8]; + bytes = new byte[8]; inputStream.read(bytes); - timestamp = ""+new BigInteger(bytes).intValue(); + Long timestamp = new BigInteger(bytes).longValue(); bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(),moduleName,latitude)); diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java index 691a1a180b..bbed059e35 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java @@ -90,26 +90,34 @@ import org.sleuthkit.datamodel.TskCoreException; "SELECT number,date,duration,type, name FROM calls ORDER BY date DESC;"); BlackboardArtifact bba; - String name; // name of person dialed or called. null if unregistered - String number; //string phone number - String duration; //duration of call in seconds - String date; // Unix time - String type; // 1 incoming, 2 outgoing, 3 missed while (resultSet.next()) { - name = resultSet.getString("name"); - number = resultSet.getString("number"); - duration = resultSet.getString("duration"); - date = resultSet.getString("date"); - type = resultSet.getString("type"); + // name of person dialed or called. null if unregistered + String name = resultSet.getString("name"); + String number = resultSet.getString("number"); + //duration of call in seconds + Long duration = Long.valueOf(resultSet.getString("duration")); + Long date = Long.valueOf(resultSet.getString("date")) / 1000; + + String direction = ""; + switch (Integer.valueOf(resultSet.getString("type"))) { + case 1: + direction = "Incoming"; + break; + case 2: + direction = "Outgoing"; + break; + case 3: + direction = "Missed"; + break; + } bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); //create a call log and then add attributes from result set. bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(),moduleName, number)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), moduleName, date)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), moduleName, duration+date)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, type)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, direction)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, name)); - } } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); @@ -125,7 +133,5 @@ import org.sleuthkit.datamodel.TskCoreException; } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); } - } - } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java index 5b090f9408..8e569cb5a9 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java @@ -91,28 +91,27 @@ class GoogleMapLocationAnalyzer { "Select time,dest_lat,dest_lng,dest_title,dest_address,source_lat,source_lng FROM destination_history;"); BlackboardArtifact bba; - String time; // unix time - String dest_lat; - String dest_lng; - String dest_title; // name of the location - String dest_address; - String source_lat; - String source_lng; + + while (resultSet.next()) { - time = resultSet.getString("time"); - dest_lat = resultSet.getString("dest_lat"); - dest_lng = resultSet.getString("dest_lng"); - dest_title = resultSet.getString("dest_title"); - dest_address = resultSet.getString("dest_address"); - source_lat = resultSet.getString("source_lat"); - source_lng = resultSet.getString("source_lng"); + Long time = Long.valueOf(resultSet.getString("time")) / 1000; + String dest_lat = resultSet.getString("dest_lat"); + String dest_lng = resultSet.getString("dest_lng"); + String dest_title = resultSet.getString("dest_title"); + String dest_address = resultSet.getString("dest_address"); + String source_lat = resultSet.getString("source_lat"); + String source_lng = resultSet.getString("source_lng"); //add periods 6 decimal places before the end. - if(dest_lat.length()>6)dest_lat = dest_lat.substring(0, dest_lat.length()-6) + "." + dest_lat.substring(dest_lat.length()-6, dest_lat.length()) ; - if(dest_lng.length()>6)dest_lng = dest_lng.substring(0, dest_lng.length()-6) + "." + dest_lng.substring(dest_lng.length()-6, dest_lng.length()) ; - if(source_lat.length()>6)source_lat = source_lat.substring(0, source_lat.length()-6) + "." + source_lat.substring(source_lat.length()-6, source_lat.length()) ; - if(source_lng.length()>6)source_lng = source_lng.substring(0, source_lng.length()-6) + "." + source_lng.substring(source_lng.length()-6, source_lng.length()) ; + if(dest_lat.length()>6) + dest_lat = dest_lat.substring(0, dest_lat.length()-6) + "." + dest_lat.substring(dest_lat.length()-6, dest_lat.length()) ; + if(dest_lng.length()>6) + dest_lng = dest_lng.substring(0, dest_lng.length()-6) + "." + dest_lng.substring(dest_lng.length()-6, dest_lng.length()) ; + if(source_lat.length()>6) + source_lat = source_lat.substring(0, source_lat.length()-6) + "." + source_lat.substring(source_lat.length()-6, source_lat.length()) ; + if(source_lng.length()>6) + source_lng = source_lng.substring(0, source_lng.length()-6) + "." + source_lng.substring(source_lng.length()-6, source_lng.length()) ; // bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT);//src // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID(), moduleName, "Source")); @@ -140,10 +139,6 @@ class GoogleMapLocationAnalyzer { bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, dest_title)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID(), moduleName, dest_address)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "Google Maps History")); - - - - } @@ -161,7 +156,5 @@ class GoogleMapLocationAnalyzer { } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing Google map locations to the Blackboard", e); } - } - } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java index cfca851281..f7a9fb5bfa 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java @@ -91,14 +91,13 @@ import org.sleuthkit.datamodel.TskCoreException; BlackboardArtifact bba; String conv_id; // seems to wrap around the message found in payload after decoding from base-64 - String create_time; // unix time String direction; // 1 incoming, 2 outgoing String payload; // seems to be a base64 message wrapped by the conv_id while (resultSet.next()) { conv_id = resultSet.getString("conv_id"); - create_time = resultSet.getString("create_time"); + Long create_time = Long.valueOf(resultSet.getString("create_time")) / 1000; direction = resultSet.getString("direction"); payload = resultSet.getString("payload"); diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java index 6b0bd55b9e..e60ba0d0ed 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java @@ -91,13 +91,13 @@ import org.sleuthkit.datamodel.TskCoreException; BlackboardArtifact bba; String address; // may be phone number, or other addresses - String date;//unix time + String type; // message received in inbox = 1, message sent = 2 String subject;//message subject String body; //message body while (resultSet.next()) { address = resultSet.getString("address"); - date = resultSet.getString("date"); + Long date = Long.valueOf(resultSet.getString("date")) / 1000; type = resultSet.getString("type"); subject = resultSet.getString("subject"); body = resultSet.getString("body"); diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java index f01c25430d..7607a3d5d5 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java @@ -88,14 +88,13 @@ import org.sleuthkit.datamodel.TskCoreException; BlackboardArtifact bba; String message; // WWF Message - String created_at; // unix time String user_id; // the ID of the user who sent the message. String game_id; // ID of the game which the the message was sent. while (resultSet.next()) { message = resultSet.getString("message"); - created_at = resultSet.getString("created_at"); + Long created_at = Long.valueOf(resultSet.getString("created_at")) / 1000; user_id = resultSet.getString("user_id"); game_id = resultSet.getString("game_id"); @@ -105,10 +104,7 @@ import org.sleuthkit.datamodel.TskCoreException; bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MSG_ID.getTypeID(), moduleName, game_id)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName,message)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName,"Words With Friends Message" )); - } - - } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing WWF messages to the Blackboard", e); } finally { @@ -123,8 +119,5 @@ import org.sleuthkit.datamodel.TskCoreException; } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing WWF messages to the Blackboard", e); } - } - - } From 681fa0bf4ed1297a38da8eac17e7e47f2355fa45 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 25 Jun 2014 16:58:37 -0400 Subject: [PATCH 3/5] Updated names of mobile modules --- .../org/sleuthkit/autopsy/modules/android/Bundle.properties | 4 ++-- Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties index da74d9519e..ce4df81615 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/android/Bundle.properties @@ -1,2 +1,2 @@ -AndroidModuleFactory.moduleName=Android Mobile Device Analysis -AndroidModuleFactory.moduleDescription=An Android mobile forensics add-on to Autopsy +AndroidModuleFactory.moduleName=Android Analyzer +AndroidModuleFactory.moduleDescription=Extracts system and third-party app data. diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties index c10b2cebec..183b0ba88a 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties @@ -1,2 +1,2 @@ -iOSModuleFactory.moduleName=iOS Mobile Device Analysis -iOSModuleFactory.moduleDescription=An iOS mobile forensics add-on to Autopsy +iOSModuleFactory.moduleName=iOS Analyzer +iOSModuleFactory.moduleDescription=Extracts system and 3rd party app data From 4bc93248a45099b5e5876dae86ee30aa4f7eb2bc Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 8 Jul 2014 18:25:02 -0400 Subject: [PATCH 4/5] fixed Android GPS time bug, cleaned up Android code, disablede iOS code. moved KML logic to KML report module --- .../modules/android/AndroidIngestModule.java | 61 ++++----- .../modules/android/AndroidModuleFactory.java | 1 - .../android/BrowserLocationAnalyzer.java | 103 ++++++--------- .../android/CacheLocationAnalyzer.java | 109 +++++++-------- .../modules/android/CallLogAnalyzer.java | 117 ++++++++-------- .../modules/android/ContactAnalyzer.java | 119 ++++++++--------- .../android/GoogleMapLocationAnalyzer.java | 125 ++++++++---------- .../modules/android/KMLFileCreator.java | 4 +- .../modules/android/TangoMessageAnalyzer.java | 124 ++++++++--------- .../modules/android/TextMessageAnalyzer.java | 113 +++++++--------- .../modules/android/WWFMessageAnalyzer.java | 101 +++++++------- .../autopsy/modules/iOS/CallLogAnalyzer.java | 18 +-- .../autopsy/modules/iOS/ContactAnalyzer.java | 71 +++++----- .../modules/iOS/TextMessageAnalyzer.java | 27 ++-- .../autopsy/modules/iOS/iOSIngestModule.java | 5 +- .../autopsy/modules/iOS/iOSModuleFactory.java | 2 +- .../sleuthkit/autopsy/report/ReportKML.java | 52 ++++++++ 17 files changed, 558 insertions(+), 594 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java index 87138ee305..2a72054218 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java @@ -45,17 +45,13 @@ class AndroidIngestModule implements DataSourceIngestModule { @Override public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) { - - services.postMessage(IngestMessage.createMessage(IngestMessage.MessageType.INFO, AndroidModuleFactory.getModuleName(), "Started {0}")); - ArrayList errors = new ArrayList<>(); progressBar.switchToDeterminate(9); try { - ContactAnalyzer FindContacts = new ContactAnalyzer(); - FindContacts.findContacts(); + ContactAnalyzer.findContacts(); progressBar.progress(1); if (context.isJobCancelled()) { return IngestModule.ProcessResult.OK; @@ -63,9 +59,9 @@ class AndroidIngestModule implements DataSourceIngestModule { } catch (Exception e) { errors.add("Error getting Contacts"); } + try { - CallLogAnalyzer FindCallLogs = new CallLogAnalyzer(); - FindCallLogs.findCallLogs(); + CallLogAnalyzer.findCallLogs(); progressBar.progress(2); if (context.isJobCancelled()) { return IngestModule.ProcessResult.OK; @@ -73,9 +69,9 @@ class AndroidIngestModule implements DataSourceIngestModule { } catch (Exception e) { errors.add("Error getting Call Logs"); } + try { - TextMessageAnalyzer FindTexts = new TextMessageAnalyzer(); - FindTexts.findTexts(); + TextMessageAnalyzer.findTexts(); progressBar.progress(3); if (context.isJobCancelled()) { return IngestModule.ProcessResult.OK; @@ -83,9 +79,9 @@ class AndroidIngestModule implements DataSourceIngestModule { } catch (Exception e) { errors.add("Error getting Text Messages"); } + try { - TangoMessageAnalyzer FindTangoMessages = new TangoMessageAnalyzer(); - FindTangoMessages.findTangoMessages(); + TangoMessageAnalyzer.findTangoMessages(); progressBar.progress(4); if (context.isJobCancelled()) { return IngestModule.ProcessResult.OK; @@ -93,9 +89,9 @@ class AndroidIngestModule implements DataSourceIngestModule { } catch (Exception e) { errors.add("Error getting Tango Messages"); } + try { - WWFMessageAnalyzer FindWWFMessages = new WWFMessageAnalyzer(); - FindWWFMessages.findWWFMessages(); + WWFMessageAnalyzer.findWWFMessages(); progressBar.progress(5); if (context.isJobCancelled()) { return IngestModule.ProcessResult.OK; @@ -103,40 +99,43 @@ class AndroidIngestModule implements DataSourceIngestModule { } catch (Exception e) { errors.add("Error getting Words with Friends Messages"); } + try { - GoogleMapLocationAnalyzer FindGoogleMapLocations = new GoogleMapLocationAnalyzer(); - FindGoogleMapLocations.findGeoLocations(); + GoogleMapLocationAnalyzer.findGeoLocations(); progressBar.progress(6); if (context.isJobCancelled()) { return IngestModule.ProcessResult.OK; } } catch (Exception e) { - errors.add( "Error getting Google Map Locations"); + errors.add("Error getting Google Map Locations"); } + try { - BrowserLocationAnalyzer FindBrowserLocations = new BrowserLocationAnalyzer(); - FindBrowserLocations.findGeoLocations(); + BrowserLocationAnalyzer.findGeoLocations(); progressBar.progress(7); + if (context.isJobCancelled()) { + return IngestModule.ProcessResult.OK; + } } catch (Exception e) { errors.add("Error getting Browser Locations"); } - if (context.isJobCancelled()) { - return IngestModule.ProcessResult.OK; - } + try { - CacheLocationAnalyzer FindCacheLocations = new CacheLocationAnalyzer(); - FindCacheLocations.findGeoLocations(); + CacheLocationAnalyzer.findGeoLocations(); progressBar.progress(8); } catch (Exception e) { errors.add("Error getting Cache Locations"); } + + /* I'm not sure why we have this in here since we have a KML report module ... try { - KMLFileCreator KMLFileCreator = new KMLFileCreator(); - KMLFileCreator.CreateKML(); + KMLFileCreator kMLFileCreator = new KMLFileCreator(); + kMLFileCreator.createKml(); progressBar.progress(9); } catch (Exception e) { errors.add("Error creating KML"); } + */ // create the final message for inbox StringBuilder errorMessage = new StringBuilder(); @@ -151,19 +150,17 @@ class AndroidIngestModule implements DataSourceIngestModule { errorMessage.append("\n"); //NON-NLS if (errors.size() == 1) { - errorMsgSubject = "One error was found"; + errorMsgSubject = "One error was found"; } else { - errorMsgSubject = "errors found: " +errors.size(); + errorMsgSubject = "errors found: " + errors.size(); } } else { - errorMessage.append( "No errors"); - errorMsgSubject ="No errors"; + errorMessage.append("No errors"); + errorMsgSubject = "No errors"; } - final IngestMessage msg = IngestMessage.createMessage(msgLevel, AndroidModuleFactory.getModuleName(),"Ingest Finished"); + final IngestMessage msg = IngestMessage.createMessage(msgLevel, AndroidModuleFactory.getModuleName(), "Ingest Finished"); services.postMessage(msg); return IngestModule.ProcessResult.OK; } - - } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java index b3e49a0135..1a809f98ae 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidModuleFactory.java @@ -25,7 +25,6 @@ import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; - @ServiceProvider(service = IngestModuleFactory.class) // public class AndroidModuleFactory extends IngestModuleFactoryAdapter { diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java index 503ba26b76..69add3d978 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/BrowserLocationAnalyzer.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.android; +import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -35,34 +36,25 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; class BrowserLocationAnalyzer { - - private Connection connection = null; - private ResultSet resultSet = null; - private Statement statement = null; - private String dbPath = ""; - private long fileId = 0; - private java.io.File jFile = null; - private String moduleName= AndroidModuleFactory.getModuleName(); + + private static final String moduleName = AndroidModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(BrowserLocationAnalyzer.class.getName()); - - public void findGeoLocations() { - List absFiles; + + public static void findGeoLocations() { try { SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); - absFiles = skCase.findAllFilesWhere("name LIKE 'CachedGeoposition%.db'"); //get exact file names - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile AF : absFiles) { + List abstractFiles = skCase.findAllFilesWhere("name LIKE 'CachedGeoposition%.db'"); //get exact file names + + for (AbstractFile abstractFile : abstractFiles) { try { - if (AF.getSize() ==0) continue; - jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); - ContentUtils.writeToFile(AF,jFile); - dbPath = jFile.toString(); //path of file as string - fileId = AF.getId(); - findGeoLocationsInDB(dbPath, fileId); + if (abstractFile.getSize() == 0) { + continue; + } + File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); + ContentUtils.writeToFile(abstractFile, jFile); + findGeoLocationsInDB(jFile.toString(), abstractFile); } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Browser Location files", e); + logger.log(Level.SEVERE, "Error parsing Browser Location files", e); } } } catch (TskCoreException e) { @@ -71,7 +63,10 @@ class BrowserLocationAnalyzer { } } - private void findGeoLocationsInDB(String DatabasePath, long fId) { + private static void findGeoLocationsInDB(String DatabasePath, AbstractFile f) { + Connection connection = null; + ResultSet resultSet = null; + Statement statement = null; if (DatabasePath == null || DatabasePath.isEmpty()) { return; } @@ -81,50 +76,38 @@ class BrowserLocationAnalyzer { statement = connection.createStatement(); } catch (ClassNotFoundException | SQLException e) { logger.log(Level.SEVERE, "Error connecting to sql database", e); + return; } - Case currentCase = Case.getCurrentCase(); - SleuthkitCase skCase = currentCase.getSleuthkitCase(); try { - AbstractFile f = skCase.getAbstractFileById(fId); - try { - resultSet = statement.executeQuery( - "Select timestamp, latitude, longitude, accuracy FROM CachedPosition;"); + resultSet = statement.executeQuery( + "Select timestamp, latitude, longitude, accuracy FROM CachedPosition;"); - BlackboardArtifact bba; - Long timestamp; // unix time - String latitude; - String longitude; - + while (resultSet.next()) { + Long timestamp = Long.valueOf(resultSet.getString("timestamp")) / 1000; + double latitude = Double.valueOf(resultSet.getString("latitude")); + double longitude = Double.valueOf(resultSet.getString("longitude")); - while (resultSet.next()) { - timestamp = Long.valueOf(resultSet.getString("timestamp")) / 1000; - latitude= resultSet.getString("latitude"); - longitude = resultSet.getString("longitude"); - - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(),moduleName,latitude)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(),moduleName, longitude)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),moduleName, timestamp)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),moduleName, "Browser Location History")); - // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)); - - - } - - } catch (Exception e) { - logger.log(Level.SEVERE, "Error Putting artifacts to Blackboard", e); - } finally { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); - } + BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, latitude)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), moduleName, longitude)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, timestamp)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "Browser Location History")); + // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)); } } catch (Exception e) { logger.log(Level.SEVERE, "Error Putting artifacts to Blackboard", e); + } finally { + try { + if (resultSet != null) { + resultSet.close(); + } + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } } + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java index bfb6054c19..89d5472f25 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/CacheLocationAnalyzer.java @@ -36,29 +36,26 @@ import org.sleuthkit.datamodel.TskCoreException; class CacheLocationAnalyzer { - private String filePath = ""; - private long fileId = 0; - private java.io.File jFile = null; - private String moduleName= AndroidModuleFactory.getModuleName(); + private static final String moduleName = AndroidModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(CacheLocationAnalyzer.class.getName()); - public void findGeoLocations() { - List absFiles; + + public static void findGeoLocations() { + try { SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); - absFiles = skCase.findAllFilesWhere("name ='cache.cell'OR name='cache.wifi'"); //get exact file names - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile AF : absFiles) { + List abstractFiles = skCase.findAllFilesWhere("name ='cache.cell' OR name='cache.wifi'"); //get exact file names + + for (AbstractFile abstractFile : abstractFiles) { try { - if (AF.getSize() ==0) continue; - jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); - ContentUtils.writeToFile(AF,jFile); - filePath = jFile.toString(); //path of file as string - fileId = AF.getId(); - findGeoLocationsInFile(filePath, fileId); + if (abstractFile.getSize() == 0) { + continue; + } + File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); + ContentUtils.writeToFile(abstractFile, jFile); + + findGeoLocationsInFile(jFile, abstractFile); } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing cached Location files", e); + logger.log(Level.SEVERE, "Error parsing cached Location files", e); } } } catch (TskCoreException e) { @@ -66,82 +63,72 @@ class CacheLocationAnalyzer { } } - private void findGeoLocationsInFile(String filePath, long fId) { - if (filePath == null || filePath.isEmpty()) { - return; - } - String fileName=filePath.contains("cell")? "cache.cell":"cache.wifi"; - File file = new File(filePath); //cache.cell or cache.wifi + private static void findGeoLocationsInFile(File file, AbstractFile f) { + byte[] bytes; // will temporarily hold bytes to be converted into the correct data types - Case currentCase = Case.getCurrentCase(); - SleuthkitCase skCase = currentCase.getSleuthkitCase(); + try { InputStream inputStream = new FileInputStream(file); - AbstractFile f = skCase.getAbstractFileById(fId); - BlackboardArtifact bba; - - String latitude; - String longitude; - String confidence; - String accuracy; //measure of how accurate the gps location is. bytes = new byte[2]; // version inputStream.read(bytes); + bytes = new byte[2]; inputStream.read(bytes); //number of location entries + int iterations = new BigInteger(bytes).intValue(); - + for (int i = 0; i < iterations; i++) { //loop through every entry bytes = new byte[2]; inputStream.read(bytes); + bytes = new byte[1]; inputStream.read(bytes); - while (new BigInteger(bytes).intValue() != 0) //pass through non important values until the start of accuracy(around 7-10 bytes) - { + while (new BigInteger(bytes).intValue() != 0) { //pass through non important values until the start of accuracy(around 7-10 bytes) inputStream.read(bytes); } bytes = new byte[3]; inputStream.read(bytes); - if (new BigInteger(bytes).intValue()<=0){//This refers to a location that could not be calculated. + if (new BigInteger(bytes).intValue() <= 0) {//This refers to a location that could not be calculated. bytes = new byte[28]; //read rest of the row's bytes inputStream.read(bytes); continue; - } - accuracy=""+new BigInteger(bytes).intValue(); - + } + String accuracy = "" + new BigInteger(bytes).intValue(); + bytes = new byte[4]; inputStream.read(bytes); - confidence=""+new BigInteger(bytes).intValue(); - + String confidence = "" + new BigInteger(bytes).intValue(); + bytes = new byte[8]; inputStream.read(bytes); - latitude=""+toDouble(bytes); - + double latitude = toDouble(bytes); + bytes = new byte[8]; inputStream.read(bytes); - longitude= ""+toDouble(bytes); - + double longitude = toDouble(bytes); + bytes = new byte[8]; inputStream.read(bytes); - Long timestamp = new BigInteger(bytes).longValue(); - - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(),moduleName,latitude)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(),moduleName, longitude)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),moduleName, timestamp)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),moduleName, fileName+" Location History")); - + Long timestamp = new BigInteger(bytes).longValue() / 1000; + + BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, latitude)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), moduleName, longitude)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, timestamp)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, file.getName() + " Location History")); + //Not storing these for now. - // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)); - // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(),moduleName, confidence)); + // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)); + // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(),moduleName, confidence)); } - - }catch (Exception e) { + + } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing Cached GPS locations to Blackboard", e); } } - public static double toDouble(byte[] bytes) { - return ByteBuffer.wrap(bytes).getDouble(); - } + private static double toDouble(byte[] bytes) { + return ByteBuffer.wrap(bytes).getDouble(); + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java index bbed059e35..481d3aa23c 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/CallLogAnalyzer.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.android; +import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -34,18 +35,12 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; - class CallLogAnalyzer { +class CallLogAnalyzer { - private Connection connection = null; - private ResultSet resultSet = null; - private Statement statement = null; - private String dbPath = ""; - private long fileId = 0; - private java.io.File jFile = null; - private String moduleName= AndroidModuleFactory.getModuleName(); + private static final String moduleName = AndroidModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(CallLogAnalyzer.class.getName()); - - public void findCallLogs() { + + public static void findCallLogs() { List absFiles; try { SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); @@ -53,13 +48,12 @@ import org.sleuthkit.datamodel.TskCoreException; if (absFiles.isEmpty()) { return; } - for (AbstractFile AF : absFiles) { + for (AbstractFile abstractFile : absFiles) { try { - jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); - ContentUtils.writeToFile(AF,jFile); - dbPath = jFile.toString(); //path of file as string - fileId = AF.getId(); - findCallLogsInDB(dbPath, fileId); + File jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); + ContentUtils.writeToFile(abstractFile, jFile); + + findCallLogsInDB(jFile.toString(), abstractFile); } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing Call logs", e); } @@ -69,7 +63,11 @@ import org.sleuthkit.datamodel.TskCoreException; } } - private void findCallLogsInDB(String DatabasePath, long fId) { + private static void findCallLogsInDB(String DatabasePath, AbstractFile f) { + Connection connection = null; + ResultSet resultSet = null; + Statement statement = null; + if (DatabasePath == null || DatabasePath.isEmpty()) { return; } @@ -78,60 +76,57 @@ import org.sleuthkit.datamodel.TskCoreException; connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); statement = connection.createStatement(); } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); + logger.log(Level.SEVERE, "Error opening database", e); + return; } - Case currentCase = Case.getCurrentCase(); - SleuthkitCase skCase = currentCase.getSleuthkitCase(); try { - AbstractFile f = skCase.getAbstractFileById(fId); - try { - resultSet = statement.executeQuery( - "SELECT number,date,duration,type, name FROM calls ORDER BY date DESC;"); + resultSet = statement.executeQuery( + "SELECT number,date,duration,type, name FROM calls ORDER BY date DESC;"); - BlackboardArtifact bba; + BlackboardArtifact bba; - while (resultSet.next()) { - // name of person dialed or called. null if unregistered - String name = resultSet.getString("name"); - String number = resultSet.getString("number"); - //duration of call in seconds - Long duration = Long.valueOf(resultSet.getString("duration")); - Long date = Long.valueOf(resultSet.getString("date")) / 1000; - - String direction = ""; - switch (Integer.valueOf(resultSet.getString("type"))) { - case 1: - direction = "Incoming"; - break; - case 2: - direction = "Outgoing"; - break; - case 3: - direction = "Missed"; - break; - } + while (resultSet.next()) { + // name of person dialed or called. null if unregistered + String name = resultSet.getString("name"); + String number = resultSet.getString("number"); + //duration of call in seconds + Long duration = Long.valueOf(resultSet.getString("duration")); + Long date = Long.valueOf(resultSet.getString("date")) / 1000; - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); //create a call log and then add attributes from result set. - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(),moduleName, number)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), moduleName, date)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), moduleName, duration+date)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, direction)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, name)); - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); - } finally { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing the database", e); + String direction = ""; + switch (Integer.valueOf(resultSet.getString("type"))) { + case 1: + direction = "Incoming"; + break; + case 2: + direction = "Outgoing"; + break; + case 3: + direction = "Missed"; + break; } + + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); //create a call log and then add attributes from result set. + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, number)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), moduleName, date)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), moduleName, duration + date)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, direction)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, name)); } } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); + } finally { + try { + if (resultSet != null) { + resultSet.close(); + } + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing the database", e); + } } + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java index 8505a5b16f..173d506372 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/ContactAnalyzer.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.android; +import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -27,24 +28,19 @@ import java.util.List; import java.util.logging.Level; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.autopsy.datamodel.ContentUtils; + class ContactAnalyzer { - private Connection connection = null; - private ResultSet resultSet = null; - private Statement statement = null; - private String dbPath = ""; - private long fileId = 0; - private java.io.File jFile = null; - private String moduleName= AndroidModuleFactory.getModuleName(); + private static final String moduleName = AndroidModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(ContactAnalyzer.class.getName()); - public void findContacts() { + public static void findContacts() { List absFiles; try { @@ -55,17 +51,15 @@ class ContactAnalyzer { } for (AbstractFile AF : absFiles) { try { - jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); - ContentUtils.writeToFile(AF,jFile); - dbPath = jFile.toString(); //path of file as string - fileId = AF.getId(); - findContactsInDB(dbPath, fileId); + File jFile = new File(Case.getCurrentCase().getTempDirectory(), AF.getName()); + ContentUtils.writeToFile(AF, jFile); + findContactsInDB(jFile.toString(), AF); } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Contacts", e); + logger.log(Level.SEVERE, "Error parsing Contacts", e); } } } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding Contacts", e); + logger.log(Level.SEVERE, "Error finding Contacts", e); } } @@ -75,7 +69,11 @@ class ContactAnalyzer { * @param fId Will create artifact from a database given by the path The * fileId will be the Abstract file associated with the artifacts */ - private void findContactsInDB(String DatabasePath, long fId) { + private static void findContactsInDB(String DatabasePath, AbstractFile f) { + Connection connection = null; + ResultSet resultSet = null; + Statement statement = null; + if (DatabasePath == null || DatabasePath.isEmpty()) { return; } @@ -85,63 +83,58 @@ class ContactAnalyzer { statement = connection.createStatement(); } catch (ClassNotFoundException | SQLException e) { logger.log(Level.SEVERE, "Error opening database", e); + return; } - Case currentCase = Case.getCurrentCase(); - SleuthkitCase skCase = currentCase.getSleuthkitCase(); try { - AbstractFile f = skCase.getAbstractFileById(fId); - try { - // get display_name, mimetype(email or phone number) and data1 (phonenumber or email address depending on mimetype) - //sorted by name, so phonenumber/email would be consecutive for a person if they exist. - resultSet = statement.executeQuery( - "SELECT mimetype,data1, name_raw_contact.display_name AS display_name \n" - + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" - + "JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) " - + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" - + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" - + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" - + "ORDER BY name_raw_contact.display_name ASC;"); + // get display_name, mimetype(email or phone number) and data1 (phonenumber or email address depending on mimetype) + //sorted by name, so phonenumber/email would be consecutive for a person if they exist. + resultSet = statement.executeQuery( + "SELECT mimetype,data1, name_raw_contact.display_name AS display_name \n" + + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" + + "JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) " + + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" + + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" + + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" + + "ORDER BY name_raw_contact.display_name ASC;"); - BlackboardArtifact bba; - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); - String name; - String oldName = ""; - String mimetype; // either phone or email - String data1; // the phone number or email - while (resultSet.next()) { - name = resultSet.getString("display_name"); - data1 = resultSet.getString("data1"); - mimetype = resultSet.getString("mimetype"); + BlackboardArtifact bba; + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); + String name; + String oldName = ""; + String mimetype; // either phone or email + String data1; // the phone number or email + while (resultSet.next()) { + name = resultSet.getString("display_name"); + data1 = resultSet.getString("data1"); + mimetype = resultSet.getString("mimetype"); // System.out.println(resultSet.getString("data1") + resultSet.getString("mimetype") + resultSet.getString("display_name")); //Test code - if (name.equals(oldName) == false) { - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, name)); - } - if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, data1)); - } else { - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID(), moduleName, data1)); - } - oldName = name; + if (name.equals(oldName) == false) { + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, name)); } - - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); - } finally { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); + if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, data1)); + } else { + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL.getTypeID(), moduleName, data1)); } + oldName = name; } + } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); + logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); + } finally { + try { + if (resultSet != null) { + resultSet.close(); + } + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } } } - } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java index 8e569cb5a9..0174b81e1f 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/GoogleMapLocationAnalyzer.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.android; +import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -34,19 +35,12 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; - class GoogleMapLocationAnalyzer { - private Connection connection = null; - private ResultSet resultSet = null; - private Statement statement = null; - private String dbPath = ""; - private long fileId = 0; - private java.io.File jFile = null; - private String moduleName = AndroidModuleFactory.getModuleName(); + private static final String moduleName = AndroidModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(GoogleMapLocationAnalyzer.class.getName()); - - public void findGeoLocations() { + + public static void findGeoLocations() { List absFiles; try { SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); @@ -54,23 +48,25 @@ class GoogleMapLocationAnalyzer { if (absFiles.isEmpty()) { return; } - for (AbstractFile AF : absFiles) { + for (AbstractFile abstractFile : absFiles) { try { - jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); - ContentUtils.writeToFile(AF,jFile); - dbPath = jFile.toString(); //path of file as string - fileId = AF.getId(); - findGeoLocationsInDB(dbPath, fileId); + File jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); + ContentUtils.writeToFile(abstractFile, jFile); + findGeoLocationsInDB(jFile.toString(), abstractFile); } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Google map locations", e); + logger.log(Level.SEVERE, "Error parsing Google map locations", e); } } } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding Google map locations", e); + logger.log(Level.SEVERE, "Error finding Google map locations", e); } } - private void findGeoLocationsInDB(String DatabasePath, long fId) { + private static void findGeoLocationsInDB(String DatabasePath, AbstractFile f) { + Connection connection = null; + ResultSet resultSet = null; + Statement statement = null; + if (DatabasePath == null || DatabasePath.isEmpty()) { return; } @@ -80,39 +76,24 @@ class GoogleMapLocationAnalyzer { statement = connection.createStatement(); } catch (ClassNotFoundException | SQLException e) { logger.log(Level.SEVERE, "Error opening database", e); + return; } - Case currentCase = Case.getCurrentCase(); - SleuthkitCase skCase = currentCase.getSleuthkitCase(); try { - AbstractFile f = skCase.getAbstractFileById(fId); - try { - resultSet = statement.executeQuery( - "Select time,dest_lat,dest_lng,dest_title,dest_address,source_lat,source_lng FROM destination_history;"); + resultSet = statement.executeQuery( + "Select time,dest_lat,dest_lng,dest_title,dest_address,source_lat,source_lng FROM destination_history;"); - BlackboardArtifact bba; + while (resultSet.next()) { + Long time = Long.valueOf(resultSet.getString("time")) / 1000; + String dest_title = resultSet.getString("dest_title"); + String dest_address = resultSet.getString("dest_address"); + + double dest_lat = convertGeo(resultSet.getString("dest_lat")); + double dest_lng = convertGeo(resultSet.getString("dest_lng")); + double source_lat = convertGeo(resultSet.getString("source_lat")); + double source_lng = convertGeo(resultSet.getString("source_lng")); - - while (resultSet.next()) { - Long time = Long.valueOf(resultSet.getString("time")) / 1000; - String dest_lat = resultSet.getString("dest_lat"); - String dest_lng = resultSet.getString("dest_lng"); - String dest_title = resultSet.getString("dest_title"); - String dest_address = resultSet.getString("dest_address"); - String source_lat = resultSet.getString("source_lat"); - String source_lng = resultSet.getString("source_lng"); - - //add periods 6 decimal places before the end. - if(dest_lat.length()>6) - dest_lat = dest_lat.substring(0, dest_lat.length()-6) + "." + dest_lat.substring(dest_lat.length()-6, dest_lat.length()) ; - if(dest_lng.length()>6) - dest_lng = dest_lng.substring(0, dest_lng.length()-6) + "." + dest_lng.substring(dest_lng.length()-6, dest_lng.length()) ; - if(source_lat.length()>6) - source_lat = source_lat.substring(0, source_lat.length()-6) + "." + source_lat.substring(source_lat.length()-6, source_lat.length()) ; - if(source_lng.length()>6) - source_lng = source_lng.substring(0, source_lng.length()-6) + "." + source_lng.substring(source_lng.length()-6, source_lng.length()) ; - // bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT);//src // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID(), moduleName, "Source")); // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, source_lat)); @@ -128,33 +109,39 @@ class GoogleMapLocationAnalyzer { // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, dest_title)); // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID(), moduleName, dest_address)); // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "Google Maps History")); - - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID(), moduleName, "Destination")); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, time)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID(), moduleName, dest_lat)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID(), moduleName, dest_lng)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID(), moduleName, source_lat)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID(), moduleName, source_lng)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, dest_title)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID(), moduleName, dest_address)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "Google Maps History")); - - } + BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY.getTypeID(), moduleName, "Destination")); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, time)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID(), moduleName, dest_lat)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID(), moduleName, dest_lng)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID(), moduleName, source_lat)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID(), moduleName, source_lng)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, dest_title)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID(), moduleName, dest_address)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "Google Maps History")); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Google map locations to the Blackboard", e); - } finally { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing the database", e); - } } + } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing Google map locations to the Blackboard", e); + } finally { + try { + if (resultSet != null) { + resultSet.close(); + } + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing the database", e); + } } } + + //add periods 6 decimal places before the end. + private static double convertGeo(String s) { + if (s.length() > 6) + return Double.valueOf(s.substring(0, s.length() - 6) + "." + s.substring(s.length() - 6, s.length())); + else + return Double.valueOf(s); + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java b/Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java index 0e1c2069a9..4efeb53993 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java @@ -43,7 +43,7 @@ public class KMLFileCreator { private SleuthkitCase skCase; private String reportPath; - public void CreateKML() { + public void createKml() { reportPath = Case.getCurrentCase().getTempDirectory() + "ReportKML.kml"; //NON-NLS String reportPath2 = Case.getCurrentCase().getTempDirectory() + "ReportKML.txt"; //NON-NLS @@ -127,7 +127,6 @@ public class KMLFileCreator { /* * Step 2: add in Style elements */ - // Style Element style = new Element("Style", ns); //NON-NLS style.setAttribute("id", "redIcon"); //NON-NLS @@ -203,6 +202,5 @@ public class KMLFileCreator { } catch (TskCoreException ex) { } - } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java index f7a9fb5bfa..23e4f07695 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/TangoMessageAnalyzer.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.android; +import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -35,31 +36,21 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; - class TangoMessageAnalyzer { - private Connection connection = null; - private ResultSet resultSet = null; - private Statement statement = null; - private String dbPath = ""; - private long fileId = 0; - private java.io.File jFile = null; - private String moduleName= AndroidModuleFactory.getModuleName(); +class TangoMessageAnalyzer { + + private static final String moduleName = AndroidModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(TangoMessageAnalyzer.class.getName()); - - public void findTangoMessages() { + + public static void findTangoMessages() { List absFiles; try { SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); absFiles = skCase.findAllFilesWhere("name ='tc.db' "); //get exact file names - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile AF : absFiles) { + for (AbstractFile abstractFile : absFiles) { try { - jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); - ContentUtils.writeToFile(AF,jFile); - dbPath = jFile.toString(); //path of file as string - fileId = AF.getId(); - findTangoMessagesInDB(dbPath, fileId); + File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); + ContentUtils.writeToFile(abstractFile, jFile); + findTangoMessagesInDB(jFile.toString(), abstractFile); } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing Tango messages", e); } @@ -67,9 +58,13 @@ import org.sleuthkit.datamodel.TskCoreException; } catch (TskCoreException e) { logger.log(Level.SEVERE, "Error finding Tango messages", e); } - } - private void findTangoMessagesInDB(String DatabasePath, long fId) { + + private static void findTangoMessagesInDB(String DatabasePath, AbstractFile f) { + Connection connection = null; + ResultSet resultSet = null; + Statement statement = null; + if (DatabasePath == null || DatabasePath.isEmpty()) { return; } @@ -79,63 +74,60 @@ import org.sleuthkit.datamodel.TskCoreException; statement = connection.createStatement(); } catch (ClassNotFoundException | SQLException e) { logger.log(Level.SEVERE, "Error opening database", e); + return; } - Case currentCase = Case.getCurrentCase(); - SleuthkitCase skCase = currentCase.getSleuthkitCase(); try { - AbstractFile f = skCase.getAbstractFileById(fId); - try { - resultSet = statement.executeQuery( - "Select conv_id, create_time,direction,payload FROM messages ORDER BY create_time DESC;"); + resultSet = statement.executeQuery( + "Select conv_id, create_time,direction,payload FROM messages ORDER BY create_time DESC;"); - BlackboardArtifact bba; - String conv_id; // seems to wrap around the message found in payload after decoding from base-64 - String direction; // 1 incoming, 2 outgoing - String payload; // seems to be a base64 message wrapped by the conv_id - - - while (resultSet.next()) { - conv_id = resultSet.getString("conv_id"); - Long create_time = Long.valueOf(resultSet.getString("create_time")) / 1000; - direction = resultSet.getString("direction"); - payload = resultSet.getString("payload"); - - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create a call log and then add attributes from result set. - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, create_time)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, direction)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName, decodeMessage(conv_id,payload))); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName,"Tango Message" )); + String conv_id; // seems to wrap around the message found in payload after decoding from base-64 + String direction; // 1 incoming, 2 outgoing + String payload; // seems to be a base64 message wrapped by the conv_id + while (resultSet.next()) { + conv_id = resultSet.getString("conv_id"); + Long create_time = Long.valueOf(resultSet.getString("create_time")) / 1000; + if (resultSet.getString("direction").equals("1")) { + direction = "Incoming"; + } else { + direction = "Outgoing"; } + payload = resultSet.getString("payload"); + + BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create a call log and then add attributes from result set. + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, create_time)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, direction)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName, decodeMessage(conv_id, payload))); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName, "Tango Message")); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Tango messages to the Blackboard", e); - } finally { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); - } } + } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing Tango messages to the Blackboard", e); + } finally { + try { + if (resultSet != null) { + resultSet.close(); + } + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } } } - //take the message string which is wrapped by a certain string, and return the text enclosed. - private String decodeMessage(String wrapper, String message) - { - String result= ""; - byte[] decoded = Base64.decodeBase64(message); - try{ - String Z= new String (decoded,"UTF-8"); - result = Z.split(wrapper)[1]; - }catch(Exception e){ + //take the message string which is wrapped by a certain string, and return the text enclosed. + private static String decodeMessage(String wrapper, String message) { + String result = ""; + byte[] decoded = Base64.decodeBase64(message); + try { + String Z = new String(decoded, "UTF-8"); + result = Z.split(wrapper)[1]; + } catch (Exception e) { logger.log(Level.SEVERE, "Error decoding a Tango message", e); - } - return result; - } + } + return result; + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java index e60ba0d0ed..bbf47f1223 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/TextMessageAnalyzer.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.android; +import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -34,33 +35,21 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +class TextMessageAnalyzer { - class TextMessageAnalyzer { - private Connection connection = null; - private ResultSet resultSet = null; - private Statement statement = null; - private String dbPath = ""; - private long fileId = 0; - private java.io.File jFile = null; - List absFiles; - private String moduleName= AndroidModuleFactory.getModuleName(); + private static final String moduleName = AndroidModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(TextMessageAnalyzer.class.getName()); - - - void findTexts() { + + public static void findTexts() { try { SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); - absFiles = skCase.findAllFilesWhere("name ='mmssms.db'"); //get exact file name - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile AF : absFiles) { + List absFiles = skCase.findAllFilesWhere("name ='mmssms.db'"); //get exact file name + + for (AbstractFile abstractFile : absFiles) { try { - jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); - ContentUtils.writeToFile(AF,jFile); - dbPath = jFile.toString(); //path of file as string - fileId = AF.getId(); - findTextsInDB(dbPath, fileId); + File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); + ContentUtils.writeToFile(abstractFile, jFile); + findTextsInDB(jFile.toString(), abstractFile); } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing text messages", e); } @@ -69,7 +58,12 @@ import org.sleuthkit.datamodel.TskCoreException; logger.log(Level.SEVERE, "Error finding text messages", e); } } - private void findTextsInDB(String DatabasePath, long fId) { + + private static void findTextsInDB(String DatabasePath, AbstractFile f) { + Connection connection = null; + ResultSet resultSet = null; + Statement statement = null; + if (DatabasePath == null || DatabasePath.isEmpty()) { return; } @@ -79,55 +73,50 @@ import org.sleuthkit.datamodel.TskCoreException; statement = connection.createStatement(); } catch (ClassNotFoundException | SQLException e) { logger.log(Level.SEVERE, "Error opening database", e); + return; } - Case currentCase = Case.getCurrentCase(); - SleuthkitCase skCase = currentCase.getSleuthkitCase(); try { - AbstractFile f = skCase.getAbstractFileById(fId); - try { - resultSet = statement.executeQuery( - "Select address,date,type,subject,body FROM sms;"); + resultSet = statement.executeQuery( + "Select address,date,type,subject,body FROM sms;"); - BlackboardArtifact bba; - String address; // may be phone number, or other addresses - - String type; // message received in inbox = 1, message sent = 2 - String subject;//message subject - String body; //message body - while (resultSet.next()) { - address = resultSet.getString("address"); - Long date = Long.valueOf(resultSet.getString("date")) / 1000; - type = resultSet.getString("type"); - subject = resultSet.getString("subject"); - body = resultSet.getString("body"); - - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create Message artifact and then add attributes from result set. - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, address)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, date)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, type)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT.getTypeID(), moduleName, subject)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName, body)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName,"SMS Message" )); + String address; // may be phone number, or other addresses + String direction; // message received in inbox = 1, message sent = 2 + String subject;//message subject + String body; //message body + while (resultSet.next()) { + address = resultSet.getString("address"); + Long date = Long.valueOf(resultSet.getString("date")) / 1000; + if (resultSet.getString("type").equals("1")) { + direction = "Incoming"; + } else { + direction = "Outgoing"; } + subject = resultSet.getString("subject"); + body = resultSet.getString("body"); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); - } finally { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); - } + BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create Message artifact and then add attributes from result set. + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, address)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, date)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, direction)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT.getTypeID(), moduleName, subject)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName, body)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName, "SMS Message")); } + } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); + } finally { + try { + if (resultSet != null) { + resultSet.close(); + } + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } } - } - - } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java index 7607a3d5d5..1abe891f09 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/WWFMessageAnalyzer.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.modules.android; +import java.io.File; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; @@ -34,30 +35,23 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; - class WWFMessageAnalyzer { - private Connection connection = null; - private ResultSet resultSet = null; - private Statement statement = null; - private String dbPath = ""; - private long fileId = 0; - private java.io.File jFile = null; - private String moduleName= AndroidModuleFactory.getModuleName(); +class WWFMessageAnalyzer { + + private static final String moduleName = AndroidModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(WWFMessageAnalyzer.class.getName()); - public void findWWFMessages() { + + public static void findWWFMessages() { List absFiles; try { SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); absFiles = skCase.findAllFilesWhere("name ='WordsFramework' "); //get exact file names - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile AF : absFiles) { + + for (AbstractFile abstractFile : absFiles) { try { - jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName()); - ContentUtils.writeToFile(AF,jFile); - dbPath = jFile.toString(); //path of file as string - fileId = AF.getId(); - findWWFMessagesInDB(dbPath, fileId); + File jFile = new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName()); + ContentUtils.writeToFile(abstractFile, jFile); + + findWWFMessagesInDB(jFile.toString(), abstractFile); } catch (Exception e) { logger.log(Level.SEVERE, "Error parsing WWF messages", e); } @@ -66,7 +60,12 @@ import org.sleuthkit.datamodel.TskCoreException; logger.log(Level.SEVERE, "Error finding WWF messages", e); } } - private void findWWFMessagesInDB(String DatabasePath, long fId) { + + private static void findWWFMessagesInDB(String DatabasePath, AbstractFile f) { + Connection connection = null; + ResultSet resultSet = null; + Statement statement = null; + if (DatabasePath == null || DatabasePath.isEmpty()) { return; } @@ -75,49 +74,43 @@ import org.sleuthkit.datamodel.TskCoreException; connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); statement = connection.createStatement(); } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); + logger.log(Level.SEVERE, "Error opening database", e); + return; } - Case currentCase = Case.getCurrentCase(); - SleuthkitCase skCase = currentCase.getSleuthkitCase(); try { - AbstractFile f = skCase.getAbstractFileById(fId); - try { - resultSet = statement.executeQuery( - "SELECT message,created_at,user_id,game_id FROM chat_messages ORDER BY game_id DESC, created_at DESC;"); + resultSet = statement.executeQuery( + "SELECT message,created_at,user_id,game_id FROM chat_messages ORDER BY game_id DESC, created_at DESC;"); - BlackboardArtifact bba; - String message; // WWF Message - String user_id; // the ID of the user who sent the message. - String game_id; // ID of the game which the the message was sent. - + String message; // WWF Message + String user_id; // the ID of the user who sent the message. + String game_id; // ID of the game which the the message was sent. - while (resultSet.next()) { - message = resultSet.getString("message"); - Long created_at = Long.valueOf(resultSet.getString("created_at")) / 1000; - user_id = resultSet.getString("user_id"); - game_id = resultSet.getString("game_id"); + while (resultSet.next()) { + message = resultSet.getString("message"); + Long created_at = Long.valueOf(resultSet.getString("created_at")) / 1000; + user_id = resultSet.getString("user_id"); + game_id = resultSet.getString("game_id"); - bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create a call log and then add attributes from result set. - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, created_at)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, user_id)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MSG_ID.getTypeID(), moduleName, game_id)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName,message)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName,"Words With Friends Message" )); - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing WWF messages to the Blackboard", e); - } finally { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); - } + BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create a call log and then add attributes from result set. + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, created_at)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, user_id)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MSG_ID.getTypeID(), moduleName, game_id)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName, message)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName, "Words With Friends Message")); } } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing WWF messages to the Blackboard", e); + logger.log(Level.SEVERE, "Error parsing WWF messages to the Blackboard", e); + } finally { + try { + if (resultSet != null) { + resultSet.close(); + } + statement.close(); + connection.close(); + } catch (Exception e) { + logger.log(Level.SEVERE, "Error closing database", e); + } } } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java index 966c538443..7de74ab10d 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java @@ -34,7 +34,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; - class CallLogAnalyzer { +class CallLogAnalyzer { private Connection connection = null; private ResultSet resultSet = null; @@ -42,9 +42,9 @@ import org.sleuthkit.datamodel.TskCoreException; private String dbPath = ""; private long fileId = 0; private java.io.File jFile = null; - private String moduleName= iOSModuleFactory.getModuleName(); + private String moduleName = iOSModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(CallLogAnalyzer.class.getName()); - + public void findCallLogs() { List absFiles; try { @@ -56,7 +56,7 @@ import org.sleuthkit.datamodel.TskCoreException; for (AbstractFile AF : absFiles) { try { jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName().replaceAll("[<>%|\"/:*\\\\]", "")); - ContentUtils.writeToFile(AF,jFile); + ContentUtils.writeToFile(AF, jFile); dbPath = jFile.toString(); //path of file as string fileId = AF.getId(); findCallLogsInDB(dbPath, fileId); @@ -78,7 +78,7 @@ import org.sleuthkit.datamodel.TskCoreException; connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); statement = connection.createStatement(); } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); + logger.log(Level.SEVERE, "Error opening database", e); } Case currentCase = Case.getCurrentCase(); @@ -104,22 +104,22 @@ import org.sleuthkit.datamodel.TskCoreException; type = resultSet.getString("type"); bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); //create a call log and then add attributes from result set. - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(),moduleName, number)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, number)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START.getTypeID(), moduleName, date)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), moduleName, duration+date)); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END.getTypeID(), moduleName, duration + date)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, type)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, name)); } } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); + logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); } finally { try { resultSet.close(); statement.close(); connection.close(); } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing the database", e); + logger.log(Level.SEVERE, "Error closing the database", e); } } } catch (Exception e) { diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java index b689c8d779..0e7ee51e76 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java @@ -39,6 +39,7 @@ import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.datamodel.ReadContentInputStream; + class ContactAnalyzer { private Connection connection = null; @@ -47,7 +48,7 @@ class ContactAnalyzer { private String dbPath = ""; private long fileId = 0; private java.io.File jFile = null; - private String moduleName= iOSModuleFactory.getModuleName(); + private String moduleName = iOSModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(ContactAnalyzer.class.getName()); public void findContacts() { @@ -62,19 +63,19 @@ class ContactAnalyzer { for (AbstractFile AF : absFiles) { try { jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName().replaceAll("[<>%|\"/:*\\\\]", "")); - //jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), i+".txt"); - ContentUtils.writeToFile(AF,jFile); + //jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), i+".txt"); + ContentUtils.writeToFile(AF, jFile); //copyFileUsingStreams(AF,jFile); //copyFileUsingStream(AF,jFile); dbPath = jFile.toString(); //path of file as string fileId = AF.getId(); //findContactsInDB(dbPath, fileId); } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Contacts", e); + logger.log(Level.SEVERE, "Error parsing Contacts", e); } } } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding Contacts", e); + logger.log(Level.SEVERE, "Error finding Contacts", e); } } @@ -112,7 +113,7 @@ class ContactAnalyzer { + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" + "ORDER BY name_raw_contact.display_name ASC;"); - BlackboardArtifact bba; + BlackboardArtifact bba; bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); String name; String oldName = ""; @@ -136,23 +137,23 @@ class ContactAnalyzer { } } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); + logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); } finally { try { resultSet.close(); statement.close(); connection.close(); } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); + logger.log(Level.SEVERE, "Error closing database", e); } } } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); + logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); } } - public static void copyFileUsingStream(AbstractFile file, File jFile) throws IOException { + public static void copyFileUsingStream(AbstractFile file, File jFile) throws IOException { InputStream is = new ReadContentInputStream(file); OutputStream os = new FileOutputStream(jFile); byte[] buffer = new byte[8192]; @@ -160,9 +161,9 @@ class ContactAnalyzer { try { while ((length = is.read(buffer)) != -1) { os.write(buffer, 0, length); - System.out.println(length); + System.out.println(length); os.flush(); - + } } finally { @@ -170,27 +171,29 @@ class ContactAnalyzer { os.close(); } } - public static void copyFileUsingStreams(AbstractFile file, File jFile) { - InputStream istream; - OutputStream ostream=null; - int c; - final int EOF = -1; - istream = new ReadContentInputStream(file); + + public static void copyFileUsingStreams(AbstractFile file, File jFile) { + InputStream istream; + OutputStream ostream = null; + int c; + final int EOF = -1; + istream = new ReadContentInputStream(file); //File outFile = new File("Data.txt"); - // System.out.println("Type characters to write in File – Press Ctrl+z to end "); - try { - ostream = new FileOutputStream(jFile); - while ((c = istream.read()) != EOF) - ostream.write(c); - } catch (IOException e) { - System.out.println("Error: " + e.getMessage()); - } finally { - try { - istream.close(); - ostream.close(); - } catch (IOException e) { - System.out.println("File did not close"); - } - } - } + // System.out.println("Type characters to write in File – Press Ctrl+z to end "); + try { + ostream = new FileOutputStream(jFile); + while ((c = istream.read()) != EOF) { + ostream.write(c); + } + } catch (IOException e) { + System.out.println("Error: " + e.getMessage()); + } finally { + try { + istream.close(); + ostream.close(); + } catch (IOException e) { + System.out.println("File did not close"); + } + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java index e3b788d076..c2881dedab 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java @@ -34,19 +34,18 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +class TextMessageAnalyzer { - class TextMessageAnalyzer { - private Connection connection = null; + private Connection connection = null; private ResultSet resultSet = null; private Statement statement = null; private String dbPath = ""; private long fileId = 0; private java.io.File jFile = null; List absFiles; - private String moduleName= iOSModuleFactory.getModuleName(); + private String moduleName = iOSModuleFactory.getModuleName(); private static final Logger logger = Logger.getLogger(TextMessageAnalyzer.class.getName()); - - + void findTexts() { try { SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase(); @@ -56,8 +55,8 @@ import org.sleuthkit.datamodel.TskCoreException; } for (AbstractFile AF : absFiles) { try { - jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(),AF.getName().replaceAll("[<>%|\"/:*\\\\]", "")); - ContentUtils.writeToFile(AF,jFile); + jFile = new java.io.File(Case.getCurrentCase().getTempDirectory(), AF.getName().replaceAll("[<>%|\"/:*\\\\]", "")); + ContentUtils.writeToFile(AF, jFile); dbPath = jFile.toString(); //path of file as string fileId = AF.getId(); findTextsInDB(dbPath, fileId); @@ -69,7 +68,8 @@ import org.sleuthkit.datamodel.TskCoreException; logger.log(Level.SEVERE, "Error finding text messages", e); } } - private void findTextsInDB(String DatabasePath, long fId) { + + private void findTextsInDB(String DatabasePath, long fId) { if (DatabasePath == null || DatabasePath.isEmpty()) { return; } @@ -89,7 +89,7 @@ import org.sleuthkit.datamodel.TskCoreException; resultSet = statement.executeQuery( "Select address,date,type,subject,body FROM sms;"); - BlackboardArtifact bba; + BlackboardArtifact bba; String address; // may be phone number, or other addresses String date;//unix time String type; // message received in inbox = 1, message sent = 2 @@ -101,26 +101,26 @@ import org.sleuthkit.datamodel.TskCoreException; type = resultSet.getString("type"); subject = resultSet.getString("subject"); body = resultSet.getString("body"); - + bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create Message artifact and then add attributes from result set. bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER.getTypeID(), moduleName, address)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), moduleName, date)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION.getTypeID(), moduleName, type)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT.getTypeID(), moduleName, subject)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT.getTypeID(), moduleName, body)); - bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName,"SMS Message" )); + bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE.getTypeID(), moduleName, "SMS Message")); } } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); + logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); } finally { try { resultSet.close(); statement.close(); connection.close(); } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); + logger.log(Level.SEVERE, "Error closing database", e); } } } catch (Exception e) { @@ -129,5 +129,4 @@ import org.sleuthkit.datamodel.TskCoreException; } - } diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java index ec688f31f4..16b4e1689f 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java @@ -43,11 +43,8 @@ class iOSIngestModule implements DataSourceIngestModule { @Override public IngestModule.ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) { - ContactAnalyzer FindContacts = new ContactAnalyzer(); FindContacts.findContacts(); - return IngestModule.ProcessResult.OK; + return IngestModule.ProcessResult.OK; } - - } diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java index eb95f2c935..4723407df0 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java +++ b/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java @@ -26,7 +26,7 @@ import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; -@ServiceProvider(service = IngestModuleFactory.class) // +//@ServiceProvider(service = IngestModuleFactory.class) // public class iOSModuleFactory extends IngestModuleFactoryAdapter { private static final String VERSION_NUMBER = "1.0.0"; diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java index 5dc0fd2381..2db559e52b 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java @@ -145,8 +145,60 @@ class ReportKML implements GeneralReportModule { // lat lon path name } } + + for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT)) { + lat = 0; + lon = 0; + for (BlackboardAttribute attribute : artifact.getAttributes()) { + if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude + { + lat = attribute.getValueDouble(); + } + if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude + { + lon = attribute.getValueDouble(); + } + } + if (lon != 0 && lat != 0) { + out.write(lat + ";" + lon + "\n"); + } + } + for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE)) { + lat = 0; + lon = 0; + double destlat = 0; + double destlon = 0; + String name = ""; + for (BlackboardAttribute attribute : artifact.getAttributes()) { + if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID()) //latitude + { + lat = attribute.getValueDouble(); + } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID()) //longitude + { + destlat = attribute.getValueDouble(); + } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID()) //longitude + { + lon = attribute.getValueDouble(); + } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID()) //longitude + { + destlon = attribute.getValueDouble(); + } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID()) //longitude + { + name = attribute.getValueString(); + } + + } + if (lon != 0 && lat != 0) { + out.write(lat + ";" + lon + ";;" + name + "\n"); + } + if (destlat != 0 && destlon != 0) { + out.write(destlat + ";" + destlon + ";;" + name + "\n"); + } + } + out.flush(); out.close(); + progressPanel.increment(); /* * Step 1: generate XML stub From f387732e002d0c62f06bb8cf0fbf66d5618ba90b Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 9 Jul 2014 10:33:06 -0400 Subject: [PATCH 5/5] moved KML logic from Android to report module. Cleaned up Android inbox messages --- .../modules/android/AndroidIngestModule.java | 16 +- .../modules/android/KMLFileCreator.java | 206 ------------------ .../sleuthkit/autopsy/report/ReportKML.java | 55 +++-- 3 files changed, 40 insertions(+), 237 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java index 2a72054218..7966be7abb 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/modules/android/AndroidIngestModule.java @@ -45,7 +45,7 @@ class AndroidIngestModule implements DataSourceIngestModule { @Override public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) { - services.postMessage(IngestMessage.createMessage(IngestMessage.MessageType.INFO, AndroidModuleFactory.getModuleName(), "Started {0}")); + services.postMessage(IngestMessage.createMessage(IngestMessage.MessageType.INFO, AndroidModuleFactory.getModuleName(), "Started Analysis")); ArrayList errors = new ArrayList<>(); progressBar.switchToDeterminate(9); @@ -127,16 +127,6 @@ class AndroidIngestModule implements DataSourceIngestModule { errors.add("Error getting Cache Locations"); } - /* I'm not sure why we have this in here since we have a KML report module ... - try { - KMLFileCreator kMLFileCreator = new KMLFileCreator(); - kMLFileCreator.createKml(); - progressBar.progress(9); - } catch (Exception e) { - errors.add("Error creating KML"); - } - */ - // create the final message for inbox StringBuilder errorMessage = new StringBuilder(); String errorMsgSubject; @@ -158,8 +148,8 @@ class AndroidIngestModule implements DataSourceIngestModule { errorMessage.append("No errors"); errorMsgSubject = "No errors"; } - final IngestMessage msg = IngestMessage.createMessage(msgLevel, AndroidModuleFactory.getModuleName(), "Ingest Finished"); - services.postMessage(msg); + + services.postMessage(IngestMessage.createMessage(msgLevel, AndroidModuleFactory.getModuleName(), "Finished Analysis: " + errorMsgSubject, errorMessage.toString())); return IngestModule.ProcessResult.OK; } diff --git a/Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java b/Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java deleted file mode 100755 index 4efeb53993..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/android/KMLFileCreator.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * - * Autopsy Forensic Browser - * - * Copyright 2014 Basis Technology Corp. - * contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.modules.android; - -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import org.jdom2.Document; -import org.jdom2.Element; -import org.jdom2.Namespace; -import org.jdom2.output.Format; -import org.jdom2.output.XMLOutputter; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.TskCoreException; - -public class KMLFileCreator { - - private Case currentCase; - private SleuthkitCase skCase; - private String reportPath; - - public void createKml() { - - reportPath = Case.getCurrentCase().getTempDirectory() + "ReportKML.kml"; //NON-NLS - String reportPath2 = Case.getCurrentCase().getTempDirectory() + "ReportKML.txt"; //NON-NLS - currentCase = Case.getCurrentCase(); - skCase = currentCase.getSleuthkitCase(); - - try { - - BufferedWriter out = null; - try { - out = new BufferedWriter(new FileWriter(reportPath2)); - - String lat = ""; // temp latitude - String lon = ""; //temp longitude - String destlon = ""; - String destlat = ""; - for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT)) { - lat = ""; - lon = ""; - for (BlackboardAttribute attribute : artifact.getAttributes()) { - if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude - { - lat = attribute.getValueString(); - } - if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude - { - lon = attribute.getValueString(); - } - } - if (!lon.isEmpty() && !lat.isEmpty()) { - out.write(lat + ";" + lon + "\n"); - - } - } - for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE)) { - lat = ""; - lon = ""; - for (BlackboardAttribute attribute : artifact.getAttributes()) { - if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID()) //latitude - { - lat = attribute.getValueString(); - } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID()) //longitude - { - destlat = attribute.getValueString(); - } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID()) //longitude - { - lon = attribute.getValueString(); - } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID()) //longitude - { - destlon = attribute.getValueString(); - } - - } - if (!lon.isEmpty() && !lat.isEmpty()) { - out.write(lat + ";" + lon + "\n"); - } - if (!destlon.isEmpty() && !destlat.isEmpty()) { - out.write(destlat + ";" + destlon + "\n"); - - } - } - out.flush(); - out.close(); - /* - * Step 1: generate XML stub - */ - Namespace ns = Namespace.getNamespace("", "http://earth.google.com/kml/2.2"); //NON-NLS - // kml - Element kml = new Element("kml", ns); //NON-NLS - Document kmlDocument = new Document(kml); - - // Document - Element document = new Element("Document", ns); //NON-NLS - kml.addContent(document); - - // name - Element name = new Element("name", ns); //NON-NLS - name.setText("Java Generated KML Document"); //NON-NLS - document.addContent(name); - - /* - * Step 2: add in Style elements - */ - // Style - Element style = new Element("Style", ns); //NON-NLS - style.setAttribute("id", "redIcon"); //NON-NLS - document.addContent(style); - - // IconStyle - Element iconStyle = new Element("IconStyle", ns); //NON-NLS - style.addContent(iconStyle); - - // color - Element color = new Element("color", ns); //NON-NLS - color.setText("990000ff"); //NON-NLS - iconStyle.addContent(color); - - // Icon - Element icon = new Element("Icon", ns); //NON-NLS - iconStyle.addContent(icon); - - // href - Element href = new Element("href", ns); //NON-NLS - href.setText("http://www.cs.mun.ca/~hoeber/teaching/cs4767/notes/02.1-kml/circle.png"); //NON-NLS - icon.addContent(href); - /* - * Step 3: read data from source location and - * add in a Placemark for each data element - */ - - File file = new File(reportPath2); - BufferedReader reader; - - reader = new BufferedReader(new FileReader(file)); - - String line = reader.readLine(); - while (line != null) { - String[] lineParts = line.split(";"); - if (lineParts.length == 2) { - String coordinates = lineParts[1].trim() + "," + lineParts[0].trim(); //lat,lon - // Placemark - Element placemark = new Element("Placemark", ns); //NON-NLS - document.addContent(placemark); - - // styleUrl - Element pmStyleUrl = new Element("styleUrl", ns); //NON-NLS - pmStyleUrl.setText("#redIcon"); //NON-NLS - placemark.addContent(pmStyleUrl); - - // Point - Element pmPoint = new Element("Point", ns); //NON-NLS - placemark.addContent(pmPoint); - - // coordinates - Element pmCoordinates = new Element("coordinates", ns); //NON-NLS - - pmCoordinates.setText(coordinates); - pmPoint.addContent(pmCoordinates); - - } - // read the next line - line = reader.readLine(); - } - /* - * Step 4: write the XML file - */ - try { - XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()); - FileOutputStream writer = new FileOutputStream(reportPath); - outputter.output(kmlDocument, writer); - writer.close(); - } catch (IOException ex) { - } - } catch (IOException ex) { - } - } catch (TskCoreException ex) { - } - - } -} diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java index 2db559e52b..e2d109599a 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java @@ -95,6 +95,9 @@ class ReportKML implements GeneralReportModule { progressPanel.increment(); + // @@@ BC: I don't get why we do this in two passes. + // Why not just print the coordinates as we find them and make some utility methods to do the printing? + // Should pull out time values for all of these points and store in TimeSpan element try { BufferedWriter out = null; @@ -163,12 +166,14 @@ class ReportKML implements GeneralReportModule { out.write(lat + ";" + lon + "\n"); } } + for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE)) { lat = 0; lon = 0; double destlat = 0; double destlon = 0; String name = ""; + String location = ""; for (BlackboardAttribute attribute : artifact.getAttributes()) { if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID()) //latitude { @@ -185,14 +190,22 @@ class ReportKML implements GeneralReportModule { } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID()) //longitude { name = attribute.getValueString(); + } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID()) //longitude + { + location = attribute.getValueString(); } - } + + // @@@ Shoudl do something more fancy with these in KML and store them as a single point. + String display = name; + if (display.isEmpty()) + display = location; + if (lon != 0 && lat != 0) { - out.write(lat + ";" + lon + ";;" + name + "\n"); + out.write(lat + ";" + lon + ";;" + display + " (Start)\n"); } if (destlat != 0 && destlon != 0) { - out.write(destlat + ";" + destlon + ";;" + name + "\n"); + out.write(destlat + ";" + destlon + ";;" + display + " (End)\n"); } } @@ -257,28 +270,33 @@ class ReportKML implements GeneralReportModule { String line = reader.readLine(); while (line != null) { String[] lineParts = line.split(";"); - if (lineParts.length == 4) { + if (lineParts.length > 1) { String coordinates = lineParts[1].trim() + "," + lineParts[0].trim(); //lat,lon // Placemark Element placemark = new Element("Placemark", ns); //NON-NLS document.addContent(placemark); - // name - Element pmName = new Element("name", ns); //NON-NLS - pmName.setText(lineParts[3].trim()); - placemark.addContent(pmName); + if (lineParts.length == 4) { + // name + Element pmName = new Element("name", ns); //NON-NLS + pmName.setText(lineParts[3].trim()); + placemark.addContent(pmName); - // Path - Element pmPath = new Element("Path", ns); //NON-NLS - pmPath.setText(lineParts[2].trim()); - placemark.addContent(pmPath); + String savedPath = lineParts[2].trim(); + if (savedPath.isEmpty() == false) { + // Path + Element pmPath = new Element("Path", ns); //NON-NLS + pmPath.setText(savedPath); + placemark.addContent(pmPath); - // description - Element pmDescription = new Element("description", ns); //NON-NLS - String xml = "