-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathapkeval.pl
executable file
·1356 lines (921 loc) · 35.3 KB
/
apkeval.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#!/usr/bin/perl
#phoenix
# Copyright 2013 Parth Patel (Original Author)
# Copyright 2013 Nathaniel "DrWhom" Husted (Extended)
#
# 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.
use strict;
use Getopt::Std;
use URI::Find;
use URI::Encode;
use Proc::Background;
getopts('ha:p:dsenr');
our($opt_h, $opt_a, $opt_p, $opt_d, $opt_s, $opt_e, $opt_n, $opt_r);
# SPADE Startup delay
# Number of seconds to wait for SPADE to start.
# Decrease to ~20-30 if your snapshot already has the SPADE binaries DexOpted. This would
# have been done if you started spade (make spade-kernel) prior before saving
# your snapshot.
our $SPADESTARTUP = 120;
our $SCANDEVICE = ""; # default device (virtual/phone) on which all the scans will run
our $SCANDRUN = ""; # found scan device to be attached
our $dAVD = ""; # default 'android virtual device' on which the scans will run if no scandevice attached
our $GAPI = ""; # Google Safe Browsing API to evaluate URLs being accessed by each app
our $ADBPORT = ""; # port number on which emulator is running (e.g 5554)
our @ARRDEVICES = ""; # output of 'adb devices' command to scan the attached devices and/or detect if the launched emulator came to life
our @ADBSER = ""; # output of 'adb start-server' command to check if adb server started successfully
our $DEVICEID = ""; # device id of an android device connected to the machine, used to point adb commands to extract the .apk files from the device
our @ARRPKGLIST = ""; # list of installed packages on an android device
our @ALLFILES = ""; # list of all the .apk files for which we will be running a scan
our %HAPK = ""; # data structure to hold the values of .apk file name, application name, version code, version number, package name, launcher activity, timestamps of events..etc
our $SETPATHAPK = ""; # a path where the .apk files are located (can be the path given by the user or the local path in EXCTRACTED_TIMESTAMP directory where .apk files are extracted
our $PATHJOIN = ""; # a variable to add an extra / at the end of the path in case if user hasn't provided like that in the arguement
our $PID4BL = ""; # process id to launch adb logs in order to accurately track the boot process of an emulator
our $TIME4DIR = `date '+%m_%d_%y-%H:%M:%S'`; # time stamp of the moment when the scan has been launched
chomp $TIME4DIR;
our $TESTDIR = "TEST_" . $TIME4DIR; # location of the test result directory with a time stamp of the moment when the scan was launched
our $PWD = `pwd`; # current path
chomp $PWD;
our $EXTRCTAPK = $PWD . "/EXTRACTEDAPKS_$TIME4DIR"; # name of the local directory where all the .apk files will be extracted from the android device
our $HOSTIP = ""; # ip address of the host machine
our $IFACE = ""; # interface on which you want to sniff the network traffic
our $TIMEADBSTART = ""; # time stamp of the event when you launch the adb log right at the start of test cycle
our $TIMEADBSTOP = ""; # time stamp of the event when you end the adb log right at the end of test cycle
our $TXTADBPKT = ""; # location of the adb log file and network traffic file
our @ARRLENGTH = ""; # array for holding packet lengths of network traffic capture while test cycle
our $APK = ""; # apk file being worked on
our $RGC = ""; # no of gestures to send to an app. more no gestures may trigger more behaviors but it can cause app to crash and even emulator. default no of gestures is 55.
our $Tm = ""; # merination time of an app. in other words, the amount of time delay between stages of test cycle. larger the Tm time, longer the app will spend in test cycle and more data will be collectedcw.it increases the idle time in the test cycle.
# Autoflush stdout
$|++;
# Help function will be called if no arguments were given or if -h was provided as an arguemnt
sub help()
{
print <<EOF;
" Welcome to ApkEval ! "
-h Help
-a "path of an APK file you want to scan"
-p "path of a directory of APK files you want to scan"
-d "scan an Android Device you have attached with the machine running ASEF"
-s "select the scan device to be the device id listed in configurator file"
-e "extensive scan mode where it will collect kernel logs, memory dump, running process at each stage"
-n "use a pre-existing snapshot of an emulated virtual devices (disables SDCard creation on startup)"
-r "collect data with the SPADE provenance system. SPADE must be preinstalled into a snapshot enabled emulated virtual device. REQUIRES -n"
EOF
exit;
}
if ($opt_h) { &help; }
# Must enable snapshots to enable SPADE because, currently, SPADE is not
# built-in to Android and must be installed in to a custom AVD with
# snapshots enabled (so that state can be saved between boots).
if ($opt_r && !$opt_n) { &help; }
if ((!$opt_h) && (!$opt_a) && (!$opt_p) && (!$opt_d) && (!$opt_s) && (!$opt_e) && (!$opt_n)) { &help; }
# A S E F - Phase 1 : Passive
# Will try to configure and collect data required to run tests in this phase
# Initialization mode - Configurator module
# Configurator function will take all the necessary parameters to configure this tool and will store is in configurator.txt file. once this file is properly configured, it won't prompt for these parameters.
sub configurator()
{
print "\n\n\n\n ASEF ==> Running a configurator for ASEF ............. \n";
open(FCONFIG, "configurator.txt") or die "Can't open configurator.txt file \n";
while(<FCONFIG>)
{
if($_ =~ m/(^Default AVD \=\s*)(.*)/)
{
our $dAVD = $2;
chomp $dAVD;
print "\n Using default AVD = $dAVD \n";
}
if($_ =~ m/(^Google Safe Browsing API \=\s*)(.*)/)
{
our $GAPI = $2;
chomp $GAPI;
print "\n Using Google Safe Browsing API key = $GAPI \n";
}
if($_ =~ m/(^Host IP \=\s*)(.*)/)
{
our $HOSTIP = $2;
chomp $HOSTIP;
}
if($_ =~ m/(^interface \=\s*)(.*)/)
{
our $IFACE = $2;
chomp $IFACE;
print "\n Using packet capturing tool 'tcpdump' on $HOSTIP at interface $IFACE \n";
}
if($_ =~ m/(^AD \=\s*)(.*)/)
{
if ($opt_s)
{
our $SCANDEVICE = $2;
chomp $SCANDEVICE;
print "\n Found an android scan device listed in the configurator file :- $SCANDEVICE \n";
}
}
if($_ =~ m/(^RGC \=\s*)(.*)/)
{
our $RGC = $2;
chomp $RGC;
if ($RGC == "") { $RGC = 55; } # if no of gestures are not give, it's default value will be taken which is 55
print "\n Will send $RGC number of gestures to each app inside the activity mode of a test cycle \n";
}
if($_ =~ m/(^Tm \=\s*)(.*)/)
{
our $Tm = $2;
chomp $Tm;
if ($Tm == "") { $Tm = 5; } # if test cycle time duration is not tuned through Tm, it's default value will be taken which is 60 seconds
print "\n Tm is set to be $Tm seconds \n";
}
}
}
&configurator;
# Initialization mode : adb refresh
# adb refresh is a recursive function which will start adb server and assure it have lauched successfully
sub adbrefresh()
{
# print "\n Killing adb server.......... \n";
`adb kill-server`;
# print "\n Starting adb server.......... \n";
@ADBSER = `adb start-server`;
if (!@ADBSER) { &adbrefresh(); } # this is a recursive function because at times adb server fails to start and in that case this will take care of it until it successfully starts...
# print @ADBSER;
}
# Initialization mode : Device Detect
# devicescanner function will be called if -d option was provided as an argument. It will scan the attached device and report it to $DEVICEID. In case if no device was found, it will exit the program and will ask user to attach a device to the machine. Also the device should have the 'USB Debugging Mode' enabled before connecting to the machine running A S E F.
sub devicescanner()
{
print "\n Starting the adb server........ \n\n";
&adbrefresh();
# print @ADBSER;
foreach (@ADBSER)
{
if ($_ =~ m/(\* daemon not running. starting it now on port )(\d+)(\s\*)/)
{ $ADBPORT = $2; }
if ($_ =~ m/daemon started successfully/)
{ print "\n adb server started successfully on port :- $ADBPORT\n"; }
}
if($ADBPORT == "") { print "\nadb server failed to start....... please run the tool again !\n"; exit; }
print "\n ASEF ==> Device Scanner is scanning for attached Android Device........... \n";
@ARRDEVICES = `adb devices`;
# print @ARRDEVICES;
my $TMPCK = 0;
foreach(@ARRDEVICES)
{
if ($_ =~ m/List of devices attached/)
{
$TMPCK++;
}
if ($TMPCK == 1 )
{
if ($_ !~ m/device/ && $_ !~ m/emulator/)
{
print "\n No devices found...\n Please attach an android device and run this tool again........ please enable \"USB debugging mode\" in Android Device to be detected \n";
exit;
}
}
if ($_ =~ m/(.*?)(\s*device)/ )
{
if ($1 !~ m/List/ && $1 !~ m/emulator/ && $1 !~ m/$SCANDEVICE/)
{
print "\n Found a connected device :- $1 \n\n\n";
$DEVICEID = $1;
$TMPCK = 0;
}
}
}
}
# Normalization mode : Extractor module
# extractor will extract all the .apk files from the attached android device and will store it on a local directory named EXTRACTOR_TIMESTAMP
sub extractor()
{
print "\n ASEF ==> Extractor is running on..... Device ID :- $DEVICEID ...........\n\n";
print "\n Extracting all the files to the local directory :- $EXTRCTAPK \n";
`mkdir $EXTRCTAPK`;
@ARRPKGLIST = `adb -s $DEVICEID shell pm list packages`;
# print @ARRPKGLIST;
my $APKPATH = "";
my $APKCNT = 0;
my $BKAPKPATH = "";
foreach (@ARRPKGLIST)
{
if ($APKCNT == 5) { last; } # if you have 50+ applications installed, you can just use this counter to only do it for 5 if you are only interested in it'd demo...
$_ =~ s/package\://g;
#print $_;
$APKPATH = `adb -s $DEVICEID shell pm path $_`;
if ($APKPATH !~ m/package\:\/system/)
{
chomp ($APKPATH);
$BKAPKPATH = $APKPATH;
$BKAPKPATH =~ s/package\://g;
$APKCNT++;
$APKPATH =~ s/package\:\/.*\///g;
print "\n Found apk file $APKCNT :- $APKPATH \n";
print " ......Extracting apk file to the local directory :- ";
`adb -s $DEVICEID pull $BKAPKPATH $EXTRCTAPK`;
}
}
print "\n Total number of Applications extracted :- $APKCNT \n\n";
}
if($opt_d)
{
&devicescanner;
&extractor;
if($EXTRCTAPK !~ m/.*\/$/)
{
$PATHJOIN = "/";
}
$SETPATHAPK = $EXTRCTAPK . $PATHJOIN ;
opendir (EDIR, $EXTRCTAPK);
my @ALLTMPFILES = "";
@ALLTMPFILES = readdir(EDIR);
my $COUNT = 0;
foreach (@ALLTMPFILES)
{
if ($_ =~ m/.*\.apk$/)
{
$ALLFILES[$COUNT] = $_ ;
$COUNT++;
print "\n";
print $COUNT.") ";
print $_;
}
}
closedir EDIR;
# print @ALLFILES;
}
if($opt_a)
{
chomp $opt_a;
# print $opt_a;
if($opt_a =~ m/(\/.*\/)(.*\.apk)/)
{
$SETPATHAPK = $1;
@ALLFILES = $2;
}
if($opt_a =~ m/.*\.apk/ && $opt_a !~ m/\//g)
{
$SETPATHAPK = $PWD;
@ALLFILES = $opt_a;
}
if($opt_a !~ m/.*\.apk$/)
{
print "\n Please only give .apk files to scan...... \n";
exit;
}
print "\n Application to scan :- @ALLFILES \n\n";
}
if($opt_p)
{
my @ALLTMPFILES = "";
chomp $opt_p;
if($opt_p !~ m/.*\/$/)
{
$PATHJOIN = "/";
}
$SETPATHAPK = $opt_p . $PATHJOIN ;
print "\n\n Location of the Directory :- $opt_p \n\n";
opendir (PDIR, $opt_p);
@ALLTMPFILES = readdir(PDIR);
my $COUNT = 0;
foreach (@ALLTMPFILES)
{
if ($_ =~ m/.*\.apk$/)
{
$ALLFILES[$COUNT] = $_ ;
$COUNT++;
print "\n";
print $COUNT.") ";
print $_;
}
}
# print @ALLFILES;
print "\n\n Total number of apk files found = $COUNT\n\n";
}
# Organization mode : converter module
# converter module converts the metadata associated with .apk files and populates the hash table where they are better organized. It increases the accessebility of the information associated with applications.
sub converter()
{
print "\n Inside converter module \n\n";
# print @ALLFILES;
my $apk = "";
my $FULLPATH = "";
my $PKGNM = "";
my $LAUNCHACT = "";
my @AAPTDUMP = "";
my $DUMP = "";
my $VERCODE = "";
my $VERNAME = "";
my $APPLABLE = "";
foreach $apk (@ALLFILES)
{
print "\n Print local path for $apk :- $SETPATHAPK \n";
$FULLPATH = $SETPATHAPK . "\"" . $apk . "\"";
@AAPTDUMP = `aapt dump badging $FULLPATH`;
foreach $DUMP (@AAPTDUMP)
{
if($DUMP =~ m/(^package\: name\=)('.*?')( versionCode\=)(.*?)( versionName\=)(.*)/)
{
$PKGNM = $2;
$VERCODE = $4;
$VERNAME = $6;
}
if($DUMP =~ m/(^launchable\-activity\: name\=)('.*?')(\s*.*)/)
{
$LAUNCHACT = $2;
}
if($DUMP =~ m/(^application\-label\:)('.*')/)
{
$APPLABLE = $2;
}
}
%HAPK->{$apk} = ( { pkgnm => $PKGNM , launchact => $LAUNCHACT , vercode => $VERCODE , vername => $VERNAME , applable => $APPLABLE , adbstart => "" , adbstop => ""}, );
}
foreach $apk ( keys %HAPK )
{
if($apk !~ m/.*\.apk/)
{ next ;}
sleep(1);
print "\n\n application name :- $apk";
print "\n packagename :- ";
print $HAPK{$apk} -> {pkgnm} ;
print "\n launcher activity :- ";
print $HAPK{$apk} -> {launchact} ;
print "\n version code :- ";
print $HAPK{$apk} -> {vercode} ;
print "\n version name :- ";
print $HAPK{$apk} -> {vername} ;
print "\n app lable :- ";
print $HAPK{$apk} -> {applable} ;
}
}
if(@ALLFILES)
{
print "\n Calling a converter module :- \n";
&converter();
}
else
{
print "\n No APK files to work on \n";
exit;
}
# Organizer mode : Test Hierarchy module
# organizer will create a TEST DIRECTORY with a TIME STAMP in it's name. It will also create the sub-directory hierarchy for each application in order to store the results associated with each application
sub organizer()
{
sleep(1);
print "\nInside Organizer \n";
# print @_;
print "\n\n ---- Creating the master TEST RESULT DIRECTORY :- $TESTDIR ----\n\n";
`mkdir $TESTDIR`;
my $TMPAPKFILE = "";
my $APKTESTDIR = "";
my $i = 0;
foreach (@ALLFILES)
{
$i++;
$TMPAPKFILE = "\"" . $_ . "\"";
my $APKTESTDIR = $TESTDIR ."/" . $TMPAPKFILE ;
sleep(1);
print "\n$i) $APKTESTDIR";
`mkdir $APKTESTDIR`;
}
}
print "\n\n Calling Organizer module to organize test results \n\n";
&organizer();
print "\n Done creating the Test result hierarchy ....... \n\n";
# A S E F : Active Phase
# Launch mode : virtual device launcher module
# avdlauncher will be called to check if the default device (virtual/phone) is running. If it's found running, it will proceed with the test cycle. If it's not found running then it will be launched.
my $CMD4AVDLAUNCH = "";
our $PROC4AVDLAUNCH;
sub avdlauncher()
{
sleep(1);
@ARRDEVICES = `adb devices`;
print @ARRDEVICES;
foreach (@ARRDEVICES)
{
if($_ =~ m/(emulator.*?)(\s*device)/)
{
print "\n\n Found default AVD to be running......... \n\n";
$SCANDEVICE = $1;
print $SCANDEVICE;
}
}
if(!$SCANDEVICE)
{
print "\n\n Going to launch default AVD :- $dAVD \n\n";
# We're starting without a pre-created snapshot so set the partition size
if(!$opt_n) {
$CMD4AVDLAUNCH = "emulator -avd $dAVD -partition-size 1024 -wipe-data -no-snapshot-load";
print "\n Starting the emulator for AVD $dAVD with 1GB Internal Storage & 1 GB SD Card :- \n\n";
}
else {
$CMD4AVDLAUNCH = "emulator -avd $dAVD -no-snapshot-save";
print "\n Starting the emulator for AVD $dAVD with pre-created, default, snapshot:- \n\n";
}
$PROC4AVDLAUNCH = Proc::Background->new($CMD4AVDLAUNCH);
$PROC4AVDLAUNCH->alive;
}
my $FLAG = 0;
my $FOUNDEMU = "";
my $PSEMU = "";
while(!$SCANDEVICE)
{
@ARRDEVICES = `adb devices`;
my $FOUNDEMU = `adb devices |grep emulator`;
chomp $FOUNDEMU;
my $PSEMU = `ps -a |grep emulator |grep -v grep |awk '{print \$1}'`;
foreach (@ARRDEVICES)
{
if($_ =~ m/emulator.*offline/ && $FLAG == 0)
{
print "\n Default AVD $dAVD has been lauched in background... but it is still in 'offline' mode... waiting for $dAVD to come to 'online' state.........";
$FLAG = 1;
}
if($_ =~ m/emulator.*offline/ && $FLAG == 1)
{
sleep(1);
print ".";
}
if($_ =~ m/(emulator.*?)(\s*device)/)
{
print "\n\n $dAVD came to life.... and now it's in online mode ..... \n\n";
$SCANDEVICE = $1;
$PID4BL = `./execadblogcat.sh $SCANDEVICE bootlog.txt`;
print "\n Waiting for $dAVD to complete the boot process....";
}
if($PSEMU && !$FOUNDEMU)
{
#print "\n ADB server has failed to recognize emulator device...... \n";
#print "\n Going to run adbrefresh ....... \n";
&adbrefresh();
}
}
}
if($PID4BL)
{
if(!$opt_n) {
while(!`cat bootlog.txt |grep "SurfaceFlinger.*Boot is finished"`)
{
sleep(1);
print ".";
}
}
else {
# When the emulator starts up an image with a snapshot, there is no
# guarantee that the bootlog will contain any messages about the
# Boot being finished. In this case we just look for the first
# actual logcat entry because at this point we know the snapshot
# is up and running.
while(!`cat bootlog.txt |grep " [A-Z]/[A-Za-z]*\(.*\): "`)
{
sleep(1);
print ".";
}
}
print "\n\n Boot Completed !!";
chomp $PID4BL;
# `./killproc.sh $PID4BL`;
# print "\n Invisible swipe coming in 15 seconds............";
# my $CNT = 0;
# while($CNT <= 15)
# {
# $CNT++;
# print ".";
# sleep(1);
# }
sleep(1);
`adb -s $SCANDEVICE shell input keyevent 82`;
print "\n AVD unlocked !\n";
}
}
# call virtual device launcher module only if the -s option is not selected. if user wants to run all the tests on physical android device, -s can be selected and virtual device boot process will be bypassed....
if (!$opt_s && !$opt_r)
{
print "\n\n Calling AVD LAUNCHER module ...... \n\n";
&avdlauncher();
}
if ($opt_s)
{
@ARRDEVICES = `adb devices`;
foreach(@ARRDEVICES)
{
if($_ =~ m/$SCANDEVICE\s*device/)
{
print "\n Found the scanning devices $SCANDEVICE to be connected ..... \n";
$SCANDRUN = "RUNNING";
}
}
if (!$SCANDRUN)
{
print "\n scanning device not found / couldn't detect ... going to exit now... please reconnect the scanning device and start the tool again... \n";
exit;
}
}
# Test Cycle : test cycle module
sub avdtestcycle()
{
print "\n Inside AVD test cycle module ..... \n";
my $APKFULLPATH = "";
my $APKRESULTPATH = "";
my $ADBLOG4APK = "";
my $TCPDUMP4APK = "";
my $PID4ADBLOG = "";
my $PID4TCPDUMP = "";
my $LAUNCHAPK = "";
my $PACKAGENAME = "";
my @PSADB = "";
my @PSTCPDUMP = "";
my $PS = "";
# following block is commented out and only used if processes are not cleaned proper after each test cycle. this may kill all relevent processes before beginning.
# @PSADB = `ps -a |grep adb.*logcat.*time |awk '{print $1}'`;
# foreach $PS (@PSADB)
# {
# chomp $PS;
# `./killproc.sh $PS`;
# }
# `killall -v tcpdump`;
my $TESTROUND = 0;
foreach (@ALLFILES)
{
print "========= TEST CYCLE FOR $_ ===========";
# Use this $TESTROUND if you want to just see this tool as a demo purpose only and you can restrict it to run it only for few test cycles (e.g. 4 apps in here)
#$TESTROUND++;
#if ($TESTROUND == 4) { last; }
if($opt_r) {
# We load a new snapshot for each run under SPADE
&avdlauncher();
}
$APKFULLPATH = $SETPATHAPK . "\"" . $_ . "\"";
$APKRESULTPATH = $PWD . "\/" . $TESTDIR . "\/" . "\"" . $_ . "\"";
print "\n Going to flush adb messages from the device $SCANDEVICE ...... ";
`adb -s $SCANDEVICE logcat -c`; # this will flush all the adb log message history from the device. not performing this step can cause False Postives and overlaps on various app results. If the message history is suppose to be preserved, in that case this can be replaced by another technique where it will collect all the adb log data without flushing it and later chop it based on time stamps.
sleep(1);
$ADBLOG4APK = $APKRESULTPATH . "\/" . "adb_log.txt";
print "\n Starting to capture all logevents for the application $_ at location :- $ADBLOG4APK \n";
$TIMEADBSTART = `date '+%m-%d %H:%M:%S'`;
$HAPK{$_} -> {adbstart} = $TIMEADBSTART;
print "\n adb logcat started at this time stamp $TIMEADBSTART \n";
$PID4ADBLOG = `./execadblogcat.sh $SCANDEVICE $ADBLOG4APK`;
sleep(1);
$TCPDUMP4APK = $APKRESULTPATH . "\/" . "network_traffic.txt";
print "\n Starting to capture all network traffic for the application $_ at location :- $TCPDUMP4APK \n";
print "./pktcap.sh $IFACE $HOSTIP $TCPDUMP4APK";
$PID4TCPDUMP = `./pktcap.sh $IFACE $HOSTIP $TCPDUMP4APK`;
sleep(1);
if($opt_r) {
# Start the SPADE application
print "\n Starting SPADE to capture system call provenance. \n";
`adb -s $SCANDEVICE shell am start -n spade.android/spade.android.Main`;
sleep(1);
`adb -s $SCANDEVICE shell am broadcast -a spade.android.CONTROL -e action start`;
my $CNT = 0;
while( ($CNT < $SPADESTARTUP) && (!`cat bootlog.txt |grep "SPADE: Launch complete - Running Now"`) )
{
sleep(1);
print ".";
$CNT++;
}
if ( $CNT >= $SPADESTARTUP )
{
print "Unable to detect successful launch of SPADE. Proceeding anyway";
}
else
{
print "\n SPADE launched\n";
}
}
print "\n\n Getting ready to install Application $_ from the location ..........$APKFULLPATH";
print "\n\n Installing $_ now :- \n";
system("adb -s $SCANDEVICE install $APKFULLPATH");
sleep($Tm);
$LAUNCHAPK = $HAPK{$_} -> {pkgnm} . "/" . $HAPK{$_} -> {launchact} ;
print " \n Going to launch $_ using the launcher activity $LAUNCHAPK \n";
system("adb -s $SCANDEVICE shell am start -n $LAUNCHAPK");
sleep($Tm);
$PACKAGENAME = $HAPK{$_} -> {pkgnm};
print "\n Sending random gestures ... \n";
system("adb -s $SCANDEVICE shell monkey -p $PACKAGENAME $RGC");
sleep($Tm);
print "\n Done testing... uninstalling now .... \n";
system("adb -s $SCANDEVICE uninstall $PACKAGENAME");
sleep(1);
`./killproc.sh $PID4ADBLOG`;
$TIMEADBSTOP = `date '+%m-%d %H:%M:%S'`;
$HAPK{$_} -> {adbstop} = $TIMEADBSTOP;
print "\n adb logcat stopped at this time stamp $TIMEADBSTOP \n";
`./killproc.sh $PID4TCPDUMP`; #make sure logged in user on a machine has right permission to kill processes, orelse it will be an overlap
`killall -v tcpdump` ; #user can also run 'cat sudo_password |killall -v tcpdump' if the logged in user doesn't have enough previlages, however this technique inside the script is not recommended for many reasons
if($opt_r) {
# Shutdown SPADE
print "\n Shutting down SPADE \n";
# `adb -s $SCANDEVICE shell am broadcast -a spade.android.CONTROL -e action finish`;
`adb shell touch /sdcard/shutdown`;
my $CNT=0;
while( ($CNT < 10) && (!`cat bootlog.txt |grep "SPADE: Shutdown Complete"`) )
{
sleep(1);
print ".";
$CNT++;
}
if ( $CNT >= 10 )
{
print "\nUnable to detect normal shutdown of SPADE. Proceeding anyway\n";
}
else
{
print "\n SPADE shutdown complete\n";
}
print "\n Saving SPADE graph data to $APKRESULTPATH/graph.dot \n";
# Pull dot file off from AVD with name the same as the current malware.
`adb -s $SCANDEVICE pull /sdcard/audit.dot $APKRESULTPATH/graph.dot`;
# Delete dot file on the device
`adb -s $SCANDEVICE shell rm /sdcard/audit.dot`;
$SCANDEVICE="";
# shutdown the emulator
$PROC4AVDLAUNCH->die;
$PROC4AVDLAUNCH->wait;
}
`./killproc.sh $PID4BL`;
sleep(1);
}
}
&avdtestcycle();
# A S E F : Interpret Phase
#=================================== PARSERS ====================================================
foreach (@ALLFILES)
{
$APK = $_;
# my @ARRLENGTH = "";
# $TESTDIR = "TEST_05_08_12-17:11:32"; # there can be an extra option to cover this case where you have already ran tests using A S E F and collected the data but just want to parse it again, so by poining it to the right test directory, parser will parse those files instead ....
$TXTADBPKT = $PWD . "\/" . $TESTDIR . "\/" . "\"" . $_ . "\"" . "\/" . "\*\.txt";
print "\n inside parser module ...... \n";
print "\n Time when adb log started for the app $_ :- ";