꿈을꾸는 파랑새

오늘은 몸캠 악성코드인 secret-gallery.apk에 대해서 간단하게 글을 적어보겠습니다. 일단 몸캠이라고 하는 것은 몸캠 이라는 것은 영어로는 sextortion로 부르고 있으며 피해자로부터 성적 호기심 등을 이용해서 몰래 녹화, 녹음을 통해서 금전 및 가상화폐 등을 요구하는 범죄입니다.

보통 몸캠 하자고 유혹하여 해킹 어플을 설치하게 하거나 해킹 링크로의 접속을 유도하고 상대방에게 노출 사진을 찍게 하게 하고 이것을 스마트폰에 저장된 연락처에 퍼뜨리겠다는 협박을 통해 돈을 뜯어내는 사기 방법입니다. 일단 먼저 악성코드 해쉬값은 다음과 같습니다.
파일명:secret-gallery.apk
사이즈:5.55 MB
CRC32:5f1ca0b7
MD5:b7651f00c339a845a931edc8dd7875ca
SHA-1:ca8c2810ddaf9b2620241b61f7d7dd31950d4669
SHA-256:a71d28fbf6884f0d3a6cbe1612873319d4f025a36b4f1fe84ddbad3b7f63bdca
SHA-512: 54db7a250ec4c8906c60ed64b9aca1dbb307794aeff6b588c01a1657656073321b4f73b83778cc16d23420476eadff468fd594f889d223bfb43fcb74477ad1af
일단 앱을 설치해서 실행하면 제대로 실행은 안 되지만 이미 다른 변종으로 장사하고 있지만 저는 해당 secret gallery.apk을 하겠습니다. 먼저 해당 악성코드 유포 사이트는 다음입니다.

https://down.preciousalbum58(.)com

몸캠 피싱 메인 화면 정보
몸캠 피싱 메인 화면 정보

이고 해당 악성코드 유포 사이트에 접속하면 다음과 같은 화면을 볼 수가 있습니다.
사적인gallery
무료체험 신청하기
※ 아래버튼을누르고무료다운로드받으세요
앨범 금고 - 사진 숨기기
갤러리에서 개인 사진 및 민감한 비디오를 숨기고
휴대 전화에 실시간 개인 정보 보호 기능을 제공합니다!
일상을 공유하며
서로를 알아가 보세요
수 많은 대화, 사진 공유, 영상 공유 등
나의 인연에 대해 더욱 깊이 알아보세요!
무료 무제한 저장용량
클라우드 백업
숨겨진 사진은 자신의 장치에만 로컬로 저장되며
어떤 서버에도 업로드되지 않습니다.

iOS 접속시 화면
iOS 접속시 화면

물론 해당 악성코드 유포 사이트도 업데이트 되어서 지금은 변경되었습니다.
그래서 서버는 한국에서 일본 도쿄로 변경 한마디로 자주 바꾸는 것 같습니다.
현재는 다음과 같습니다.
터치 한 번으로 찾는 글로벌 인연
데이트글로브에서 외국인 친구를 만나 특별한 데이트를 경험해보세요.
일본, 대만, 베트남 등 다양한 해외 이성 회원과 만나 데이트할 수 있도록 매일 무료로 인연을 추천드려요!
영업 방식을 이제는 국제 연애로 변경을 한것 같습니다.
그리고 해당 사이트 웹 소스를 보면 다음과 같이 HTML로 구성된 것을 확인할 수가 있습니다.

data-id="e966c80" data-element_type="column">
<div class="elementor-widget-wrap elementor-element-populated">
<div class="elementor-element elementor-element-1bbd4f8 elementor-widget elementor-widget-image"
data-id="1bbd4f8" data-element_type="widget"
data-widget_type="image.default">
<div class="elementor-widget-container">
<a href="/uploads/secret-gallery(.)apk">
<img width="204" height="63"                                                                            src="static/picture/google(.)png"
class="attachment-large size-large"
lt="" decoding="async"
loading="lazy"/>
</div>
<div class="elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-6d6f9ff"
data-id="6d6f9ff" data-element_type="column">
<div class="elementor-widget-wrap elementor-element-populated">
<div class="elementor-element elementor-element-c3c08ca elementor-widget elementor-widget-image"
data-id="c3c08ca" data-element_type="widget"
data-widget_type="image.default">
<div class="elementor-widget-container">
<a href="https://vklyh(.)com/tny4k">
<img width="204" height="63"
src="static/picture/apple(.)png"
class="attachment-large size-large"
alt="" decoding="async"
loading="lazy"/>

이걸 굳이 이야기하면 다음과 같습니다.
이미지는 img 요소의 src 속성 값을 통해 지정된 경로에서 가져오고 첫 번째 열(column)에서는 "static/picture/google(.)png" 경로에서 이미지를 가져오고, 두 번째 열(column)에서는 "static/picture/apple(.)png" 경로에서 이미지를 가져옴
img 요소의 width와 height 속성은 이미지의 크기를 지정하며, class 속성은 스타일을 지정하는 CSS 클래스 이름을 나타내며 decoding 속성은 이미지 디코딩 방식을 설정하며, loading 속성은 이미지 로딩 방식을 설정

몸캠 악성코드 인터넷 관련 코드
몸캠 악성코드 인터넷 관련 코드


각각 div 요소와 img 요소는 클래스 이름을 가지고 있으며 해당  클래스 이름은 CSS 스타일 시트에서 해당 요소의 스타일을 지정하는 데 사용됩니다. 이러한 스타일은 웹 페이지의 레이아웃, 색상, 글꼴 등을 결정
a 요소는 href 속성을 사용하여 클릭 시 이동할 링크를 지정 번째 열(column)의 a 요소는 "/uploads/secret-gallery(.)apk"로 설정 두 번째 열(column)의 a 요소는 "https://vklyh(.)com/tny4k"로 설정되어 있음
여기서 다른 링크가 있는 것을 볼 수가 있는데 해당 링크는 애플의 아이폰으로 접속하면 해당 사이트로 날려 버리는 역할을 합니다.

https://vklyh(.)com/tny4k

그리고 해당 링크를 통해서 접속하면 사파리(Safari)이 있는데 어차피 여기는 피싱 사이트 역할이며 해당 부분의 소스는 다음과 같습니다.
이 링크는 Safari
제발Safari열기

애플 iOS 접속 화면 웹소스
애플 iOS 접속 화면 웹소스

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<meta http-equiv="Content-Language" content="zh-CN">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0,maximum-scale=1.0, user-scalable=no">
<meta property="og:title" content="Precious앨범">
<meta property="og:image" content="/storage/app/2023/0209/09163558ehqf(.)png">
<meta property="og:description" content="">

언어를 보면 zh-CN 즉 중국어가 보입니다.
해당 악성코드 권한을 보면 다음과 같은 메세지가 나오는 것을 확인할 수가 있습니다.
Error decode manifest: 안드로이드 앱에서 발생하는 오류 메시지이며 안드로이드 앱의 매니페스트 파일은 앱의 구성 정보를 포함하고 있으며, 앱이 설치된 디바이스에서 앱이 작동하는 방식을 결정하는데 해당 파일이 손상되거나 디코딩되지 못하면 앱은 작동하지 않을 경우 발생

몸캠 악성코드 권한
몸캠 악성코드 권한


해당 사이트 내용은 다음과 같습니다.
Precious앨범
소개
【Precious앨범】 Apple의 공식 추천 앱
평가 및 리뷰
4.9
전체 점수 5
10088점수
새로운 기능
버전5.6.0
정보
공급자:Precious앨범
설치 패키지 크기:994.3K
적합성:iOS 필요 14.0 또는 더 높게. iPhone, iPad 및 iPodtouch와 호환됩니다.
언어:한국어
연령 등급:4+
가격:비어 있는
한마디로 미완성품?
그리고 androidx.core.location.GpsStatusWrapper 부분에서 GPS 관련 코드들이 있는 것을 확인할 수가 있습니다.

GPS 관련 코드
GPS 관련 코드

public GpsStatusWrapper(GpsStatus gpsStatus) {
        GpsStatus gpsStatus2 = (GpsStatus) Preconditions.checkNotNull(gpsStatus);
        this.mWrapped = gpsStatus2;
        this.mCachedSatelliteCount = -1;
        this.mCachedIterator = gpsStatus2.getSatellites().iterator();
        this.mCachedIteratorPosition = -1;
        this.mCachedSatellite = null;
    }

    @Override // androidx.core.location.GnssStatusCompat
    public int getSatelliteCount() {
        int i;
        synchronized (this.mWrapped) {
            if (this.mCachedSatelliteCount == -1) {
                for (GpsSatellite gpsSatellite : this.mWrapped.getSatellites()) {
                    this.mCachedSatelliteCount++;
                }
                this.mCachedSatelliteCount++;
            }
            i = this.mCachedSatelliteCount;
        }
        return i;
    }
    @Override // androidx.core.location.GnssStatusCompat
    public int getConstellationType(int i) {
        if (Build.VERSION.SDK_INT < 24) {
            return 1;
        }
        return getConstellationFromPrn(getSatellite(i).getPrn());
    }

    @Override // androidx.core.location.GnssStatusCompat
    public int getSvid(int i) {
        if (Build.VERSION.SDK_INT < 24) {
            return getSatellite(i).getPrn();
        }
        return getSvidFromPrn(getSatellite(i).getPrn());
    }

이며 해당 코드의 의미는 다음과 같습니다.
안드로이드 AP 에서 GPS 상태 정보를 다루는 GpsStatusWrapper 클래스의 일부 해당 클래스는 안드로이드 버전 호환성을 위해 androidx.core.location.GnssStatusCompat 인터페이스를 구현
getSatelliteCount() 메서드는 위성 수를 반환 메서드는 동기화 블록 내에서 실행 먼저 mCachedSatelliteCount 필드가 -1인지 확인하고, 그렇다면 래핑된 GpsStatus 객체의 위성을 순회하면서 mCachedSatelliteCount를 증가 그다음, mCachedSatelliteCount를 1 증가시키고, 그 값을 반환
해당 메서드는 GpsStatusWrapper 클래스의 GpsStatus를 캐시하고, 각 호출에서 위성 수를 계산하여 다음 호출에서 캐시 된 값을 사용하므로, 성능 향상을 위해 캐시 기능을 구현됩니다.
해당 코드 자체가 악성 코드 아니지만, 만약 악용을 한다고 하면 GPS 상태 정보를 악의적인 목적으로 수집을 진행하면 해당 코드는 사용자의 개인 정보를 수집하는 데 사용될 수 있으며 또한, 해당 코드를 사용하여 GPS 상태 정보를 조작할 수 있다면, 사용자의 위치를 가장하는 등의 위조된 위치 정보를 제공할 수 있으며, 해당 부분은 사용자가 나쁘게 사용이 될 수가 있습니다.
kotlin.io.TextStreamsKt 에서는 인터넷에서 텍스트 또는 바이트로 구성돼 있습니다.

몸캠 악성코드 인터넷 관련 코드
몸캠 악성코드 인터넷 관련 코드

static /* synthetic */ String readText$default(URL url, Charset charset, int i, Object obj) {
        if ((i & 1) != 0) {
            charset = Charsets.UTF_8;
        }
        Intrinsics.checkNotNullParameter(url, "<this>");
        Intrinsics.checkNotNullParameter(charset, "charset");
        return new String(readBytes(url), charset);
    }

    public static final byte[] readBytes(URL url) {
        Intrinsics.checkNotNullParameter(url, "<this>");
        InputStream openStream = url.openStream();
        try {
            InputStream it = openStream;
            Intrinsics.checkNotNullExpressionValue(it, "it");
            byte[] readBytes = ByteStreamsKt.readBytes(it);
            CloseableKt.closeFinally(openStream, null);
            return readBytes;
        } finally {
        }
    }

    public static final void forEachLine(Reader reader, Function1<? super String, Unit> action) {
        Intrinsics.checkNotNullParameter(reader, "<this>");
        Intrinsics.checkNotNullParameter(action, "action");
        BufferedReader bufferedReader = reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader, 8192);
        try {
            for (String str : lineSequence(bufferedReader)) {
                action.invoke(str);
            }
            Unit unit = Unit.INSTANCE;
            CloseableKt.closeFinally(bufferedReader, null);
        } finally {
        }
    }
}

readText$default 함수는 URL에서 텍스트를 읽어오는 함수이며 charset 파라미터를 통해 인코딩을 지정 만약 charset 파라미터가 제공되지 않으면 UTF-8 인코딩을 사용
readBytes 함수는 URL에서 바이트를 읽어오는 함수 openStream() 메서드를 사용하여 URL의 InputStream을 열고 그 후, ByteStreamsKt.readBytes() 함수를 사용하여 InputStream에서 모든 바이트를 읽어옵니다. 마지막으로, CloseableKt.closeFinally() 함수를 사용하여 InputStream을 닫습니다.
해당 코드는 자바 라이브러리를 사용하여 작성된 것으로, 주요한 보안 문제는 없음 그러나, 악성코드가 사용한다면 다음과 같은 문제가 발생
URL이 악성 코드로부터 제공되었다면, readBytes 함수가 URL에서 읽은 데이터가 악성 코드인지를 확인하지 않기 때문에 악성 코드가 실행될 수 있음
readText$default 함수에서 제공되는 인코딩이 악성 코드로부터 제공된 경우, 악성 코드가 임의의 인코딩을 제공하거나 알 수 없는 인코딩을 사용할 수 있기 때문에 보안 문제가 발생할 수 있음
androidx.core.telephony.TelephonyManagerCompat 부분에서는 스마트폰의 IMEI 관련 코드들이 있습니다.

악성코드 IMEI 관련 코드
악성코드 IMEI 관련 코드

public class TelephonyManagerCompat {
    private static Method sGetDeviceIdMethod;
    private static Method sGetSubIdMethod;

    public static String getImei(TelephonyManager telephonyManager) {
        if (Build.VERSION.SDK_INT >= 26) {
            return Api26Impl.getImei(telephonyManager);
        }
        int subscriptionId = getSubscriptionId(telephonyManager);
        if (subscriptionId != Integer.MAX_VALUE && subscriptionId != -1) {
            return Api23Impl.getDeviceId(telephonyManager, SubscriptionManagerCompat.getSlotIndex(subscriptionId));
        }
        return telephonyManager.getDeviceId();
    }

    public static int getSubscriptionId(TelephonyManager telephonyManager) {
        if (Build.VERSION.SDK_INT >= 30) {
            return Api30Impl.getSubscriptionId(telephonyManager);
        }
        try {
            if (sGetSubIdMethod == null) {
                Method declaredMethod = TelephonyManager.class.getDeclaredMethod("getSubId", new Class[0]);
                sGetSubIdMethod = declaredMethod;
                declaredMethod.setAccessible(true);
            }
            Integer num = (Integer) sGetSubIdMethod.invoke(telephonyManager, new Object[0]);
            if (num == null || num.intValue() == -1) {
                return Integer.MAX_VALUE;
            }
            return num.intValue();
        } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException unused) {
            return Integer.MAX_VALUE;
        }
    }

해당 코드는 TelephonyManager 클래스를 사용하여 IMEI 및 구독 ID와 같은 휴대폰 정보를 가져오는 데 사용되며 해당 코드는 안드로이드 버전에 따라 다른 API를 사용해서 API 26 이상이면 Api26Impl 클래스에서 구현한 기능을 사용
이걸 악용하며 다음과 같은 정보가 수집됩니다.
getImei() 함수는 TelephonyManager 클래스를 사용하여 IMEI를 검색
IMEI는 개인 식별 정보이므로 악성 코드가 해당 함수를 사용하여 사용자의 개인 정보를 수집할 수 있음
getSubscriptionId() 함수는 구독 ID를 검색
구독 ID는 SIM 카드에 할당된 고유 식별자이며, SIM 카드와 연결된 사용자의 개인 정보를 악성 코드가 수집할 수 있음
sGetSubIdMethod 및 sGetDeviceIdMethod와 같은 정적 필드는 private 메서드에 액세스하기 위해 사용 메서드에 액세스하는 데 성공하면 악성 코드는 개인 정보를 수집하거나 변경할 수 있음
해당 코드는 휴대폰(스마트폰)의 개인 정보를 처리하기 때문에 출처를 신뢰할 수 없는 앱이나 코드에서 사용하지 않는 것이 좋으며 또한, 해당 코드를 사용하기 전에는 앱의 권한 요청을 확인하는 것이 좋습니다.
그리고 인증서 정보는 없습니다.

악성코드 IMEI 관련 코드
악성코드 IMEI 관련 코드

2023-02-25 10:55:00 UTC 기준 바이러스토탈 결과는 다음과 같습니다.
Alibaba:TrojanSpy:Android/Agent.79b47065
Antiy-AVL:Trojan/Generic.ASMalwAD.16
Arcabit:Trojan.Generic.D3E9E824
Avast-Mobile:APK:RepMalware [Trj]
Avira (no cloud):ANDROID/Spy.Agent.faeav
BitDefender:Trojan.GenericKD.65660964
BitDefenderFalx:Android.Riskware.Agent.KIG
Cynet:Malicious (score: 99)
Emsisoft:Trojan.GenericKD.65660964 (B)
eScan:Trojan.GenericKD.65660964
ESET-NOD32:A Variant Of Android/Spy.Agent.CMX
Fortinet:Android/Agent.CMX!tr
GData:Trojan.GenericKD.65660964
Google:Detected
Ikarus:Win32.Outbreak
K7GW:Spyware ( 0059dd5c1 )
Kaspersky:HEUR:Trojan-Spy.AndroidOS.Agent.adc
Lionic:Trojan.AndroidOS.Agent.C!c
MAX:Malware (ai Score=87)
McAfee:Artemis!B7651F00C339
McAfee-GW-Edition:Artemis!Trojan
Microsoft:Trojan:Script/Wacatac.B!ml
Symantec:Trojan.Gen.MBT
Symantec Mobile Insight:AppRisk:Generisk
Tencent:Dos.Trojan-Spy.Agent.Jflw
Trellix (FireEye):Trojan.GenericKD.65660964
Trustlook:Android.Malware.Spyware
즉 기본적으로 스마트폰에서 인지도 있는 백신 앱을 설치해서 사용하고 백신앱은 2개 사용지 스마트폰이 오작동할 수가 있으며 구글 플레이 스토어,갤럭시 스토어,원 스토어 같은 공식 스토어를 사용을 하며 구글 플레이 스토어 에서도 악성코드가 올라오니 백신 앱을 사용을 하는 것을 추천합니다.

그리드형

공유하기

facebook twitter kakaoTalk kakaostory naver band