2222import android .content .Intent ;
2323import android .content .SharedPreferences ;
2424import android .os .Bundle ;
25+ import android .os .FileObserver ;
2526import android .support .v7 .app .AppCompatActivity ;
2627import android .text .Html ;
2728import android .view .LayoutInflater ;
5051import org .csploit .android .tools .TcpDump ;
5152
5253import java .io .File ;
54+ import java .io .IOException ;
5355import java .net .InetAddress ;
5456import java .util .ArrayList ;
5557import java .util .Collections ;
@@ -79,6 +81,7 @@ public class Sniffer extends AppCompatActivity implements AdapterView.OnItemClic
7981 private boolean mDumpToFile = false ;
8082 private String mPcapFileName = null ;
8183 private Child mTcpdumpProcess = null ;
84+ private FileObserver mFileActivity = null ;
8285
8386 public class AddressStats implements Comparable <AddressStats >{
8487 public String mAddress = "" ;
@@ -402,6 +405,14 @@ private void setStoppedState(){
402405 mTcpdumpProcess .kill ();
403406 mTcpdumpProcess = null ;
404407 }
408+
409+ if (mDumpToFile ) {
410+ if (mFileActivity != null ) {
411+ mFileActivity .stopWatching ();
412+ mFileActivity = null ;
413+ }
414+ }
415+
405416 Sniffer .this .runOnUiThread (new Runnable () {
406417 @ Override
407418 public void run () {
@@ -415,6 +426,44 @@ public void run() {
415426 });
416427 }
417428
429+ private void addNewTarget (final AddressStats stats ){
430+ Sniffer .this .runOnUiThread (new Runnable () {
431+ @ Override
432+ public void run () {
433+ mAdapter .addStats (stats );
434+ mAdapter .notifyDataSetChanged ();
435+ }
436+ });
437+ }
438+
439+ private void updateStats (final AddressStats stats , final long len ){
440+ Sniffer .this .runOnUiThread (new Runnable () {
441+ @ Override
442+ public void run () {
443+ long deltat ;
444+ stats .mBytes += len ;
445+
446+ deltat = (java .lang .System .currentTimeMillis () - stats .mSampledTime );
447+
448+ if (deltat >= mSampleTime ) {
449+ stats .mBandwidth = (stats .mBytes - stats .mSampledBytes ) / deltat ;
450+ stats .mSampledTime = java .lang .System .currentTimeMillis ();
451+ stats .mSampledBytes = stats .mBytes ;
452+ }
453+ mAdapter .notifyDataSetChanged ();
454+ }
455+ });
456+ }
457+
458+ private void showMessage (final String text ){
459+ Sniffer .this .runOnUiThread (new Runnable () {
460+ @ Override
461+ public void run () {
462+ Toast .makeText (Sniffer .this , text , Toast .LENGTH_LONG ).show ();
463+ }
464+ });
465+ }
466+
418467 private void setSpoofErrorState (final String error ){
419468 Sniffer .this .runOnUiThread (new Runnable (){
420469 @ Override
@@ -425,10 +474,59 @@ public void run(){
425474 });
426475 }
427476
477+ /**
478+ * Monitor a pcap file for changes, in order to let the user know that the capture is running.
479+ */
480+ private void startMonitoringPcapFile (){
481+ final String str_address = (System .getCurrentTarget ().getType () == Target .Type .NETWORK ) ? System .getCurrentTarget ().getDisplayAddress ().split ("/" )[0 ] : System .getCurrentTarget ().getDisplayAddress ();
482+
483+ final File pcapfile = new File (mPcapFileName );
484+ try {
485+ pcapfile .createNewFile ();
486+ }catch (IOException io )
487+ {
488+ Toast .makeText (this , "File not created: " + io .getLocalizedMessage (), Toast .LENGTH_LONG ).show ();
489+ return ;
490+ }
491+
492+ mFileActivity = new FileObserver (mPcapFileName ) {
493+ @ Override
494+ public void onEvent (int event , String s ) {
495+ switch (event ){
496+ case FileObserver .CLOSE_WRITE :
497+ showMessage (getString (R .string .saved ) + ":\n " + mPcapFileName );
498+ break ;
499+ case FileObserver .MODIFY :
500+
501+ AddressStats stats = mAdapter .getStats (str_address );
502+ updateStats (stats , pcapfile .length ());
503+ break ;
504+ case FileObserver .OPEN :
505+ showMessage (getString (R .string .dumping_traffic_to ) + mPcapFileName );
506+ break ;
507+ default :
508+ break ;
509+ }
510+ }
511+ };
512+ final AddressStats stats = new AddressStats (str_address );
513+ stats .mBytes = 0 ;
514+ stats .mSampledTime = java .lang .System .currentTimeMillis ();
515+ addNewTarget (stats );
516+ // android docs: The monitored file or directory must exist at this time,or else no events will be reported
517+ mFileActivity .startWatching ();
518+ }
519+
428520 private void setStartedState (){
521+ if (mRunning )
522+ setStoppedState ();
429523
430- if (mDumpToFile )
431- Toast .makeText (Sniffer .this , getString (R .string .dumping_traffic_to ) + mPcapFileName , Toast .LENGTH_SHORT ).show ();
524+ if (mDumpToFile ) {
525+ mSampleTime = 100 ;
526+ startMonitoringPcapFile ();
527+ }
528+ else
529+ mSampleTime = 1000 ;
432530
433531 try {
434532 mSpoofSession .start (new OnSessionReadyListener (){
@@ -453,7 +551,6 @@ public void onSessionReady(){
453551 @ Override
454552 public void onPacket (InetAddress src , InetAddress dst , int len ) {
455553 long now = java .lang .System .currentTimeMillis ();
456- long deltat ;
457554 AddressStats stats = null ;
458555 String stringAddress = null ;
459556
@@ -472,25 +569,11 @@ public void onPacket(InetAddress src, InetAddress dst, int len) {
472569 stats .mBytes = len ;
473570 stats .mSampledTime = now ;
474571 } else {
475- stats .mBytes += len ;
476-
477- deltat = (now - stats .mSampledTime );
478-
479- if (deltat >= mSampleTime ) {
480- stats .mBandwidth = (stats .mBytes - stats .mSampledBytes ) / deltat ;
481- stats .mSampledTime = java .lang .System .currentTimeMillis ();
482- stats .mSampledBytes = stats .mBytes ;
483- }
572+ updateStats (stats , len );
484573 }
485574
486575 final AddressStats fstats = stats ;
487- Sniffer .this .runOnUiThread (new Runnable () {
488- @ Override
489- public void run () {
490- mAdapter .addStats (fstats );
491- mAdapter .notifyDataSetChanged ();
492- }
493- });
576+ addNewTarget (fstats );
494577 }
495578 });
496579 } catch ( ChildManager .ChildNotStartedException e ) {
0 commit comments