Forráskód Böngészése

Add new voicemails capability

Rich Infante 7 éve
szülő
commit
fd83d969bd
4 módosított fájl, 132 hozzáadás és 7 törlés
  1. 16 1
      Readme.md
  2. 3 2
      package.json
  3. 89 3
      tools/index.js
  4. 24 1
      tools/util/iphone_backup.js

+ 16 - 1
Readme.md

@@ -57,7 +57,7 @@ ibackuptool -b $UDID --report apps
 # List Recent Web History
 ibackuptool -b $UDID --report webhistory
 
-# List Recent Photos Geolocations
+# List Recent Photos Geolocations (iOS 9+)
 ibackuptool -b $UDID --report photolocations
 
 # List iOS Notes
@@ -65,6 +65,21 @@ ibackuptool -b $UDID --report notes
 
 # List iOS Notes from old database that may exist
 ibackuptool -b $UDID --report oldnotes
+
+# List calls
+ibackuptool -b $UDID --report calls
+
+# List voicemails 
+ibackuptool -b $UDID --report voicemail
+
+# List voicemail files (iOS 9+)
+ibackuptool -b $UDID --report voicemail-files
+
+# Export voicemail files (iOS 9+)
+ibackuptool -b $UDID --report voicemail-files --export ./ExportedVoicemails
+
+# List wifi networks 
+ibackuptool -b $UDID --report wifi
 ```
 
 ### Messages Access

+ 3 - 2
package.json

@@ -1,6 +1,6 @@
 {
   "name": "ibackuptool",
-  "version": "2.0.1",
+  "version": "2.0.2",
   "description": "Read Messages and info from iOS Backups",
   "main": "tools/index.js",
   "scripts": {
@@ -11,13 +11,14 @@
     "ibackuptool": "tools/index.js"
   },
   "preferGlobal": true,
-  "repository" : "https://github.com/richinfante/iphonebackuptools",
+  "repository": "https://github.com/richinfante/iphonebackuptools",
   "author": "@richinfante",
   "license": "MIT",
   "dependencies": {
     "bplist-parser": "^0.1.1",
     "chalk": "^1.1.3",
     "commander": "^2.12.2",
+    "fs-extra": "^4.0.3",
     "plist": "^2.0.1",
     "sqlite3": "^3.1.8",
     "strip-ansi": "^4.0.0"

+ 89 - 3
tools/index.js

@@ -1,7 +1,7 @@
 #!/usr/bin/env node
 
 const chalk = require('chalk')
-const fs = require('fs')
+const fs = require('fs-extra')
 const program = require('commander')
 const path = require('path')
 const { URL } = require('url')
@@ -11,7 +11,7 @@ const normalizeCols = require('./util/normalize.js')
 var base = path.join(process.env.HOME, '/Library/Application Support/MobileSync/Backup/')
 
 program
-    .version('2.0.0')
+    .version('2.0.2')
     .option('-l, --list', 'List Backups')
     .option('-c, --conversations', 'List Conversations')
     .option('-m, --messages <conversation_id>', 'List Conversations')
@@ -22,6 +22,7 @@ program
     .option(`-v, --verbose`, 'Verbose debugging output')
     .option(`-x, --no-color`, 'Disable colorized output')
     .option('-z, --dump', 'Dump a ton of raw JSON formatted data instead of formatted output')
+    .option(`-e, --extract <dir>`, 'Extract data for commands. reports: voicemail')
     
 program.on('--help', function(){
     console.log('')
@@ -373,7 +374,91 @@ if(program.list) {
             .catch((e) => {
                 console.log('[!] Encountered an Error:', e)
             })
-    }  else if(program.report == 'wifi') {
+    }  else if(program.report == 'voicemail') {
+        if(!program.backup) {
+            console.log('use -b or --backup <id> to specify backup.')
+            process.exit(1)
+        }
+
+
+        // Grab the backup
+        var backup = iPhoneBackup.fromID(program.backup, base)
+        backup.getVoicemailsList()
+            .then((items) => {
+
+                if(program.dump) {
+                    console.log(JSON.stringify(items, null, 4))
+                    return
+                }
+
+                var items = items.map(el => [
+                    el.ROWID + '',
+                    el.XFORMATTEDDATESTRING,
+                    el.sender + '',
+                    el.token + '',
+                    el.duration + '',
+                    el.expiration + '',
+                    el.trashed_date + '',
+                    el.flags + ''
+                ])
+
+                items = [['ID', 'Date', 'Sender', 'Token', 'Duration', 'Expiration', 'Trashed', 'Flags'], ['-', '-', '-', '-', '-', '-', '-', '-'], ...items]
+                items = normalizeCols(items).map(el => el.join(' | ').replace(/\n/g, '')).join('\n')
+                
+                if(!program.color) { items = stripAnsi(items) }
+
+                console.log(items)
+            })
+            .catch((e) => {
+                console.log('[!] Encountered an Error:', e)
+            })
+    } else if(program.report == 'voicemail-files') {
+        if(!program.backup) {
+            console.log('use -b or --backup <id> to specify backup.')
+            process.exit(1)
+        }
+
+
+        // Grab the backup
+        var backup = iPhoneBackup.fromID(program.backup, base)
+        backup.getVoicemailFileList()
+            .then((list) => {
+
+                if(program.dump) {
+                    console.log(JSON.stringify(list, null, 4))
+                    return
+                }
+
+                if(program.extract) {
+                    for(var item of list) {
+                        try {
+                        var outDir = path.join(program.extract, path.basename(item.relativePath))
+                        fs.ensureDirSync(path.dirname(outDir))
+                        fs.createReadStream(backup.getFileName(item.fileID)).pipe(fs.createWriteStream(outDir));
+                        item.output_dir = outDir
+                        }catch(e) {
+                            console.log(`Couldn't Export: ${item.relativePath}`, e)
+                        }
+                    }
+                }
+
+                var items = list.map(el => [
+                    el.fileID + '',
+                    el.relativePath,
+                    el.output_dir || '<not exported>'
+                ])
+
+                items = [['ID', 'Path', 'Exported Path'], ['-', '-', '-'], ...items]
+                items = normalizeCols(items).map(el => el.join(' | ').replace(/\n/g, '')).join('\n')
+                
+                if(!program.color) { items = stripAnsi(items) }
+
+                console.log(items)
+            })
+            .catch((e) => {
+                console.log('[!] Encountered an Error:', e)
+            })
+    } else if(program.report == 'wifi') {
         if(!program.backup) {
             console.log('use -b or --backup <id> to specify backup.')
             process.exit(1)
@@ -413,6 +498,7 @@ if(program.list) {
     } else {
         console.log('')
         console.log('  [!] Unknown Option type:', program.report)
+        console.log('  [!] It\'s possible this tool is out-of date.')
         console.log('')
         program.outputHelp()
     }

+ 24 - 1
tools/util/iphone_backup.js

@@ -17,7 +17,8 @@ const databases = {
   Locations: '4096c9ec676f2847dc283405900e284a7c815836',
   WebHistory: 'e74113c185fd8297e140cfcf9c99436c5cc06b57',
   Photos: '12b144c0bd44f2b3dffd9186d3f9c05b917cee25',
-  WiFi: 'ade0340f576ee14793c607073bd7e8e409af07a8'
+  WiFi: 'ade0340f576ee14793c607073bd7e8e409af07a8',
+  Voicemail: '992df473bbb9e132f4b3b6e4d33f72171e97bc7a'
 }
 
 var cache = {}
@@ -306,6 +307,28 @@ class iPhoneBackup {
     })
   }
 
+  getVoicemailsList () {
+    return new Promise((resolve, reject) => {
+      var messagedb = this.getDatabase(databases.Voicemail)
+      messagedb.all(`SELECT *, datetime(date, 'unixepoch') AS XFORMATTEDDATESTRING from voicemail ORDER BY date ASC`, async function (err, rows) {
+        if (err) reject(err)
+        resolve(rows)
+      })
+    })
+  }
+
+  getVoicemailFileList () {
+    return new Promise((resolve, reject) => {
+      var messagedb = this.getDatabase('Manifest.db', true)
+      messagedb.all(`SELECT * from FILES where relativePath like 'Library/Voicemail/%.amr'`, async function (err, rows) {
+        if (err) reject(err)
+
+        resolve(rows)
+      })
+    
+    })
+  }
+
   getWifiList () {
     return new Promise((resolve, reject) => {
       var filename = this.getFileName(databases.WiFi)