본문 바로가기

보안/안드로이드

com.devuni.flashlight v4.9.4 안드로이드 어플리케이션 분석

아쉽게도 안드로이드 5.1.5 버전에서는 개인정보를 가져가는 부분을 확인할 수 없었다.

하지만 앱이 업데이트 되면서 수정되었을 수 있으므로 이전 버전을 분석하기로 결정했다.


1. 어플리케이션 정보


 이름 : 플래쉬라이트

 버전 : 4.9.4

 패키지 이름 : com.devuni.flashlight

 설치SDK 버전 : 17



2. 시그니처 정보


 CN : Nikolay Ananiev

 timeFrom : 090525191210  (Tue Nov 14 02:53:11 KST 1972)

 timeTo : 20590513191210  (Fri Jun 28 11:59:51 KST 2622)



3. 해쉬값


 SHA256 : 469fa3f1102ecbcae99b6166c7bb8cbe7fc29a48a5656380d16c1302ae36c9c3

 MD5 : dceb4f387b6108296becb538e2c5aa97



4.퍼미션 정보


1) android.permission.CAMERA

 - 어플리케이션에서 언제든 카메라를 사용하여 사진과 동영상을 촬영하는 것을 허용합니다.

2) android.permission.FLASHLIGHT

 - 어플리케이션에서 플래시를 조절하는 것을 허용합니다.

3) android.permission.VIBRATE

 - 어플리케이션에서 진동을 조절하는 것을 허용합니다. 

4) android.permission.WAKE_LOCK

 - 어플리케이션이 휴대폰이 잠자기 모드로 전환하지 않게 설정할 수 있도록 허용합니다.

5) android.permission.INTERNET

 - 어플리케이션에서 네트워크 소켓을 추가하는 것을 허용합니다. 

6) android.permission.ACCESS_NETWORK_STATE

 - 어플리케이션에서 모든 네트워크의 상태를 볼 수 있도록 허용합니다.

7) android.permission.READ_PHONE_STATE <-이부분이 수정되었다.

 - 어플리케이션에서 전화 기능을 사용하는 것을 허용합니다.

 - 이 권한이 허가된 애플리케이션은 전화번호, 디바이스의 일련번호, 통화 실행 여부, 통화가 연결된 전화번호 등을 알아낼 수 있습니다.




5. Activity


1) com.devuni.flashlight.MainActivity

2) com.devuni.light.LightActivity

3) com.devuni.flashlight.WidgetConfigureActivity

4) com.google.ads.AdActivity <- 최신 버전에서 제거 되었다.

5) com.millennialmedia.android.MMAdViewOverlayActivity <-최신 버전에서 제거 되었다.

6) com.millennialmedia.android.VideoPlayer <- 최신 버전에서 제거 되었다.



6. Service


1) com.devuni.flashlight.WidgetService <- 최신 버전에서 제거 되었다.

2) com.devuni.flashlight.ShakeService <- 최신 버전에서 제거 되었다.



7. Receiver


1) com.devuni.flashlight.WidgetProvider

2) com.devuni.flashlight.ShakeProvider <- 최신 버전에서 제거 되었다.



8. So 파일


1) armeabi/libnative.so

2) armeabi-v7a/libnative.so

3) mips/libnative.so

4) x86/libnative.so



9. 바이러스 토탈 분석 결과


바이러스 토탈(www.virustotal.com) 홈페이지에서 어플리케이션의 분석결과를 확인했습니다. 항상 느끼는 거지만 정적분석의 한계를 느끼게 해줍니다. 결국 사람이 분석을 해야한다는 것....


1) 바이러스 확인 (1/55)




2) 위험 분석


DEX 파일에는 API의 reflection 를 이용합니다.

DEX 파일은 공유 라이브러리를 로드합니다.

DEX 파일은 암호화 기능을 이용합니다.

APK 패키지에는 공유 ELF 라이브러리가 포함되어 있습니다.

애플리케이션이 인터넷에 액세스 할 수 있도록 권한이 되어있습니다.

애플리케이션이 개인 정보에 액세스 할 수 있도록 권한이 되어있습니다.

그 외에 위험을 생각할 수 있는 권한이 있습니다.



3) 퍼미션 기반의 api


 WRITE_SETTINGS

 Landroid/provider/Settings$System;->putInt(Landroid/content/ContentResolver; Ljava/lang/String; I)Z called from Lcom/devuni/flashlight/BaseLayout;->setBrightnessMode(I)V


 ACCESS_NETWORK_STATE

Landroid/net/ConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo; called from Lcom/google/ads/util/AdUtil;->d(Landroid/content/Context;)Ljava/lang/String;

Landroid/net/ConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo; called from Lcom/millennialmedia/android/MMAdViewSDK;->getConnectionType(Landroid/content/Context;)Ljava/lang/String;

Landroid/net/ConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo; called from Lcom/millennialmedia/android/MMAdViewSDK;->getConnectionType(Landroid/content/Context;)Ljava/lang/String;

Landroid/net/ConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo; called from Lcom/millennialmedia/android/MMAdViewSDK;->getConnectionType(Landroid/content/Context;)Ljava/lang/String;

Landroid/net/ConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo; called from Lcom/millennialmedia/android/MMAdViewSDK;->getConnectionType(Landroid/content/Context;)Ljava/lang/String;

Landroid/net/ConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo; called from Lcom/millennialmedia/android/MMAdViewSDK;->isConnected(Landroid/content/Context;)Z

Landroid/net/ConnectivityManager;->getActiveNetworkInfo()Landroid/net/NetworkInfo; called from Lcom/millennialmedia/android/MMAdViewSDK;->isConnected(Landroid/content/Context;)Z



 INTERNET

Ljava/net/ServerSocket;-><init>()V called from Lcom/millennialmedia/android/VideoPlayer$VideoServer;-><init>(Lcom/millennialmedia/android/VideoPlayer; Ljava/lang/String; Z)V

Ljava/net/ServerSocket;->bind(Ljava/net/SocketAddress;)V called from Lcom/millennialmedia/android/VideoPlayer$VideoServer;-><init>(Lcom/millennialmedia/android/VideoPlayer; Ljava/lang/String; Z)V

Ljava/net/URL;->openConnection()Ljava/net/URLConnection; called from Lcom/google/ads/b;->run()V

Ljava/net/URL;->openConnection()Ljava/net/URLConnection; called from Lcom/google/ads/w;->run()V

Ljava/net/URL;->openConnection()Ljava/net/URLConnection; called from Lcom/millennialmedia/android/HttpHeadRequest;->sendRequest(Ljava/lang/String;)Ljava/lang/String;

Ljava/net/URL;->openConnection()Ljava/net/URLConnection; called from Lcom/millennialmedia/android/MMAdViewController$5;->run()V

Ljava/net/URL;->openConnection()Ljava/net/URLConnection; called from Lcom/millennialmedia/android/MMAdViewController;->downloadComponent(Ljava/lang/String; Ljava/lang/String; Ljava/io/File;)Z

Ljava/net/URL;->openConnection()Ljava/net/URLConnection; called from Lcom/millennialmedia/android/VideoPlayer$NetworkingThread;->run()V

Ljava/net/URL;->openConnection()Ljava/net/URLConnection; called from Lcom/millennialmedia/android/MMFileManager;->downloadFile(Ljava/util/HashMap;)Lcom/millennialmedia/android/MMJSResponse;

Ljava/net/HttpURLConnection;->connect()V called from Lcom/google/ads/b;->run()V

Ljava/net/HttpURLConnection;->connect()V called from Lcom/google/ads/w;->run()V

Ljava/net/HttpURLConnection;->connect()V called from Lcom/millennialmedia/android/HttpHeadRequest;->sendRequest(Ljava/lang/String;)Ljava/lang/String;

Ljava/net/HttpURLConnection;->connect()V called from Lcom/millennialmedia/android/MMAdViewController$5;->run()V

Ljava/net/HttpURLConnection;->connect()V called from Lcom/millennialmedia/android/MMAdViewController;->downloadComponent(Ljava/lang/String; Ljava/lang/String; Ljava/io/File;)Z

Ljava/net/HttpURLConnection;->connect()V called from Lcom/millennialmedia/android/VideoPlayer$NetworkingThread;->run()V

Lorg/apache/http/impl/client/DefaultHttpClient;-><init>(Lorg/apache/http/conn/ClientConnectionManager; Lorg/apache/http/params/HttpParams;)V called from Lcom/flurry/android/FlurryAgent;->a(Lorg/apache/http/params/HttpParams;)Lorg/apache/http/client/HttpClient;

Lorg/apache/http/impl/client/DefaultHttpClient;-><init>(Lorg/apache/http/params/HttpParams;)V called from Lcom/flurry/android/FlurryAgent;->a(Lorg/apache/http/params/HttpParams;)Lorg/apache/http/client/HttpClient;

Lorg/apache/http/impl/client/DefaultHttpClient;-><init>()V called from Lcom/flurry/android/u;->d(Ljava/lang/String;)Ljava/lang/String;

Lorg/apache/http/impl/client/DefaultHttpClient;-><init>()V called from Lcom/millennialmedia/android/HttpGetRequest;-><init>()V

Landroid/webkit/WebView;-><init>(Landroid/content/Context;)V called from Lcom/flurry/android/CatalogActivity;->onCreate(Landroid/os/Bundle;)V

Landroid/webkit/WebView;-><init>(Landroid/content/Context;)V called from Lcom/google/ads/h;-><init>(Landroid/content/Context; Lcom/google/ads/AdSize;)V

Landroid/webkit/WebView;-><init>(Landroid/content/Context;)V called from Lcom/google/ads/util/AdUtil;->i(Landroid/content/Context;)Ljava/lang/String;

Landroid/webkit/WebView;-><init>(Landroid/content/Context;)V called from Lcom/millennialmedia/android/MMAdViewController;-><init>(Lcom/millennialmedia/android/MMAdView;)V

Landroid/webkit/WebView;-><init>(Landroid/content/Context;)V called from Lcom/millennialmedia/android/MMAdViewWebOverlay;-><init>(Landroid/content/Context; I J Ljava/lang/String; Z Ljava/lang/String; Z Z Z)V

Ljava/net/Socket;-><init>()V called from Lcom/devuni/flashlight/CustomExceptionHandler$1;->run()V

Ljava/net/Socket;-><init>()V called from Lcom/devuni/light/Light$2;->run()V



 WAKE_LOCK

Landroid/media/MediaPlayer;->start()V called from Lcom/millennialmedia/android/MillennialMediaView;->start()V

Landroid/media/MediaPlayer;->stop()V called from Lcom/millennialmedia/android/MillennialMediaView;->stopPlayback()V

Landroid/media/MediaPlayer;->start()V called from Lcom/millennialmedia/android/MMMedia;->playAudio(Ljava/util/HashMap;)Lcom/millennialmedia/android/MMJSResponse;



 VIBRATE

Landroid/app/NotificationManager;->notify(I Landroid/app/Notification;)V called from Lcom/devuni/light/Light;->showNotification()V

Landroid/media/AudioManager;->getRingerMode()I called from Lcom/google/ads/util/AdUtil;->g(Landroid/content/Context;)Lcom/google/ads/util/AdUtil$a;

Landroid/os/Vibrator;->vibrate(J)V called from Lcom/devuni/light/Light$3;->run()V

Landroid/os/Vibrator;->vibrate(J)V called from Lcom/millennialmedia/android/MMAdViewController$MMJSInterface;->vibrate(I)V

Landroid/os/Vibrator;->vibrate(J)V called from Lcom/millennialmedia/android/MMAdViewWebOverlay$OverlayJSInterface;->shouldVibrate(J)V

Landroid/os/Vibrator;->cancel()V called from Lcom/devuni/flashlight/widgets/BaseWidget;->vibrate(J)V

Landroid/os/Vibrator;->vibrate(J)V called from Lcom/devuni/flashlight/widgets/BaseWidget;->vibrate(J)V

Landroid/os/Vibrator;->vibrate(J)V called from Lcom/millennialmedia/android/MMNotification;->vibrate(Ljava/util/HashMap;)Lcom/millennialmedia/android/MMJSResponse;



 WRITE_SETTINGS

Landroid/hardware/Camera;->open()Landroid/hardware/Camera; called from Lcom/devuni/light/LightCamera;->isAvailable()I

Landroid/hardware/Camera;->open()Landroid/hardware/Camera; called from Lcom/devuni/light/LightCameraAutofocus;->isAvailable()I

Landroid/hardware/Camera;->open()Landroid/hardware/Camera; called from Lcom/devuni/light/LightHTC;->isAvailable()I



10. 소스분석 (분석 tool: jd-gui)



5.1.5버전과 다르게 광고 라이브러리 파일이 난독화가 되어있지 않았습니다. 물론 완벽하게 디컴파일하지는 못했지만 저번보다는 쉽게 확인할 수 있을 듯 합니다.

저번과 달리 퍼미션 READ_PHONE_STATE가 추가되어서 개인정보가 수집할 확률이 높아졌으므로 좀 더 정밀하게 확인을 할려고 합니다. 아래 그림과 같이 2개의 퍼미션이 있으면 개인정보를 수집할 확률이 높기 때문입니다.



확인할 함수는 다음과 같습니다.





(참고논문 : Permlyzer: Analyzing Permission Usage in Android Applications, Wei Xu, Fangfang Zhang, and Sencun Zhu)


보통 악성앱은 다음과 같은 패턴으로 악성행위를 합니다.



(참고논문 : DroidMiner: Automated Mining and Characterization of Fine-grained Malicious

Behaviors in Android Applications, Chao Yang, Zhaoyan Xu, Guofei Gu, Vinod Yegneswaran, Phillip Porras)


먼저 jd-gui를 이용해 소스를 추출하고 각 소스가 불러오는 API를 확인했습니다.


여기서 걸러낼 API는 다음과 같습니다.


 android.telephony

 java.net

 org.apache.http


입니다. 이 API를 호출하는 소스를 필터링합니다. 


해당 어플은 READ_PHONE_STATE 퍼미션을 사용했지만

 개인정보 유출의 핵심 API인 android.telephony를 사용하는 파일은 없었습니다.

 광고를 위해 다음과 같은 퍼미션을 등록해야하기 때문에 

READ_PHONE_STATE를 사용한 것으로 보입니다.

 android.app.Activity.MMAdView
 






네트워크 관련해 위험한 소스파일을 분석한 결과는 다음과 같습니다.


파일이름 

 com.devuni.light.Light.java

중요한

사용 API 

 android.app.Notification

 android.app.NotificationManager

 android.content.pm.PackageManager

 java.net.InetSocketAddress

 java.net.Socket

의심목록

 Notification을 이용해 앱을 프로세스가 실행시킬 수 있고

 패키지매니저를 이용해 사용자가 설치한 앱 목록을 확인할 수 있다. 

 또한 소켓을 이용해 인터넷에 접속할 수 있다. 

 분석결과

 만약 어플리케이션이 문제가 생겼을 때 디바이스의 정보를 보내는 소스이다.

 이것도 유출이라면 유출일 수 있겠지만... 버그리포팅이 과연 유출일까 싶다.

 






파일이름 

 com.flurry.android.FlurryAgent.java

중요한

사용 API 

 android.content.pm.PackageInfo

 android.content.pm.PackageManager

 android.location.Location

 android.location.LocationListener

 android.location.LocationManager

 org.apache.http.client.HttpClient

의심목록

 패키지매니저를 이용해 사용자가 설치한 앱 목록을 확인할 수 있다. 

 만약 퍼미션이 있다면 사용자의 위치정보를 가져갈 수 있다.

 웹에 통신할 수 있다.
 분석결과

 5.1.5 최신버전에서 있었던 문제가 되었던 코드이다. 하지만 퍼미션이 없으므로 정보를 가져갈 수 없다. 

 




파일이름 

 com.google.ads.util.AdUtil.java

중요한

사용 API 

 android.content.BroadcastReceiver

 android.content.pm.ActivityInfo

 android.content.pm.PackageInfo

 android.content.pm.PackageInfo

 android.location.Location

 android.media.AudioManager

 android.net.ConnectivityManager

 android.net.NetworkInfo

 java.net.HttpURLConnection

 javax.crypto.Cipher

 javax.crypto.spec.SecretKeySpec

의심목록

 알람을 이용해 앱을 실행할 수 있다.

 패키지매니저를 이용해 사용자가 설치한 앱 목록을확인할 수 있다.

 퍼미션이 있다면 위치정보를 확인할 수 있다.

 음악정보를 가져갈 수 있다.

 인터넷에 연결할 수 있다.

 암호화할 수 있다.

분석 결과

 이건 구글에서 제공하는 것이다.



파일이름 

 com.millennialmedia.android.MMAdViewController.java

중요한

사용 API 

 android.content.pm.PackageManager

 android.location.Location

 android.os.Environment

 android.webkit.WebView

 java.net.HttpURLConnection

의심목록

 패키지매니저를 이용해 사용자가 설치한 앱 목록을확인할 수 있다.

 퍼미션이 있다면 위치정보를 확인할 수 있다.

 사용자 설정 정보를 가져갈 수 있다.

 인터넷에 연결할 수 있다.

 분석결과

 만약 광고에 위치정보 및 개인 정보를 넣었다면 문제가 되었을 수 있다.

 하지만 com.devuni.ads.MMProvider의 init() 함수를 본 결과

 넣은 정보는 width와 height (광고의 크기)  정보만 넣었다.

 따라서 문제가 없다.


  com.millennialmedia.android.MMAdViewController의 getURLMetaValues() 함수

  com.devuni.ads.MMProvider의 init() 함수


파일이름 

 com.millennialmedia.android.VideoPlayer.java

중요한

사용 API 

 android.content.BroadcastReceiver

 android.os.Environment

 java.net.ServerSocket

 java.net.HttpURLConnection

의심목록

 알람을 이용해 앱을 실행할 수 있다.

 사용자 설정 정보를 가져갈 수 있다.

 인터넷에 연결할 수 있다.

분석 결과

 여기에서는 비디오 광고를 다운받아 캐쉬메모리에 저장하고 보여주기 위한 용도이다.

 




10. 결론


난독화가 되어있지 않아서 쉽게 분석할 수 있었다.  우선 결론만 말하면 광고라이브러리는 많은 개인정보를 엄유출할 수 있는 코드가 포함되어있다. 만약 개발자가 그러한 정보(성별, 나이, 위치정보 등)를 넣었다면 개인정보를 유출할 수 있었다. 하지만 이 어플리케이션은 그러한 정보를 넣지 않았다. 따라서 사용자가 광고를 클릭하더라도 개인정보가 유출되지 않는다.