아래 코드를 이어서 분석
public final int onStartCommand(Intent intent, int i2, int i3) {
String str;
String str2;
String str3;
String str4;
Thread thread;
String str5;
int iM2535 = C1032.m2535("۠ۨۨ");
Thread thread2 = null;
String str6 = null;
while (true) {
switch (iM2535) {
case 56293:
case 1746818:
case 1752670:
iM2535 = C1025.f + (C1023.f4365 / 6412) < 0 ? C1058.m2711("ۨ۟۟") : (C1050.f4392 - C1022.f4364) + 1753444;
break;
case 56356:
String strM2476 = C1023.m2476(intent);
if (C1058.f4402 * (C1075.f4419 | (-2499)) >= 0) {
iM2535 = C1032.m2535("ۢ۟۠");
str6 = strM2476;
} else {
iM2535 = (C1073.f4417 / C1055.f4399) + 1751653;
str6 = strM2476;
}
break;
case 56414:
thread = new Thread(new RunnableC0019q(C1067.f4411 ^ (-625), this), C1051.m2668(m2663(), 492, C1020.f4362 ^ (-960), 1703));
if ((C1050.f4392 ^ (C1040.f4382 / (-3268))) < 0) {
str5 = "ۣۨۨ";
iM2535 = C1068.m2771(str5);
thread2 = thread;
} else {
iM2535 = C1067.m2764("ۣ۟ۧ");
thread2 = thread;
}
break;
case 1746819:
if (C1031.f4373 >= 0) {
str = "ۡۥ";
iM2535 = C1059.m2718(str);
} else {
C1020.m2452();
str4 = "۟ۧ۠";
iM2535 = C1029.m2519(str4);
}
break;
case 1747748:
C1047.m2635(thread2);
iM2535 = C1046.f4388 + (C1036.f4378 ^ 7498) >= 0 ? C1049.m2649("ۨۨۦ") : (C1060.f4404 | C1041.f4383) + 1750631;
break;
case 1747868:
if (C1032.f4374 * (C1064.f4408 - 3537) <= 0) {
iM2535 = C1064.m2747("ۣۡ");
} else {
C1043.f4385 = 4;
str3 = "ۨ۠ۨ";
iM2535 = C1045.m2622(str3);
}
break;
case 1747936:
if (intent == null) {
if (C1041.f4383 - (C1050.f4392 + 6568) < 0) {
iM2535 = C1067.f4411 + C1065.f4409 + 1753428;
} else {
C1041.m2594();
str2 = "ۣۦۤ";
iM2535 = C1023.m2469(str2);
}
break;
} else if (C1031.f4373 >= 0) {
}
break;
case 1749571:
C1067.m2768(this, true);
str3 = "ۤ۟ۡ";
iM2535 = C1045.m2622(str3);
break;
case 1749573:
if (C1048.m2641(C1051.m2668(m2663(), 504, C1047.f4389 ^ (-862), 566), str6)) {
iM2535 = (C1056.f4400 - C1023.f4365) ^ (-1751895);
} else if (C1025.f + (C1023.f4365 / 6412) < 0) {
}
break;
case 1750753:
if (C1043.m2606(this)) {
if (C1053.m2682() > 0) {
str2 = "ۨۦۨ";
iM2535 = C1023.m2469(str2);
} else {
C1068.m2774();
iM2535 = C1068.m2771("ۣ۟ۦ");
}
break;
} else if (C1032.f4374 * (C1064.f4408 - 3537) <= 0) {
}
break;
case 1751494:
if (C1021.f4363 > 0) {
str4 = "ۥۦ۟";
iM2535 = C1029.m2519(str4);
} else {
C1041.m2594();
iM2535 = C1031.m2528("۠ۢۦ");
}
break;
case 1751625:
C1038.m2576(this);
if (C1027.f4369 < 0) {
str2 = "ۦ۟ۢ";
iM2535 = C1023.m2469(str2);
} else {
C1065.f4409 = 26;
iM2535 = C1049.m2649("ۢ۟ۢ");
}
break;
case 1751649:
if (C1054.m2683() < 0) {
str3 = "۟ۤ";
iM2535 = C1045.m2622(str3);
} else {
iM2535 = C1040.m2588("ۦ۟ۢ");
}
break;
case 1751653:
if (C1048.m2641(C1055.m2694(m2663(), 434, C1024.f4366 ^ 384, 1670), str6)) {
str2 = "ۣۦۤ";
iM2535 = C1023.m2469(str2);
} else if (C1055.m2692() <= 0) {
iM2535 = (C1033.f4375 * C1040.f4382) + 1678999;
} else {
str5 = "ۣۧۡ";
thread = thread2;
iM2535 = C1068.m2771(str5);
thread2 = thread;
}
break;
case 1751774:
if (C1055.m2692() <= 0) {
}
break;
case 1753417:
return 1;
case 1753538:
return C1069.f4413 ^ 346;
case 1755562:
C1043.m2607(C1062.m2737(m2663(), 466, C1056.f4400 ^ 61, 3093), C1058.m2714(m2663(), 473, C1048.f4390 ^ (-163), 2338));
if ((C1051.f4395 ^ (C1059.f4403 ^ (-5623))) < 0) {
str3 = "ۢ۟۠";
iM2535 = C1045.m2622(str3);
} else {
C1068.m2774();
iM2535 = C1074.m2810("ۡۥ");
}
break;
case 1755619:
this.f1818b = thread2;
if (C1042.f4384 <= 0) {
C1047.m2631();
iM2535 = C1065.m2753("ۨۦۨ");
} else {
iM2535 = (C1056.f4400 / C1052.f4396) + 1747748;
}
break;
case 1755622:
if (C1039.f4381 < 0) {
iM2535 = C1040.m2588("۠ۨۨ");
} else {
str = "ۢ۠ۤ";
iM2535 = C1059.m2718(str);
}
break;
}
}
}
- case 1750753: if의 조건인 m2606 함수 안으로 들어가보면 아래와 같다.
안드로이드에서 Service는 화면이 꺼져 있거나 앱을 닫아도 백그라운드에서 계속 실행되는 컴포넌트를 말한다. 그리고 Handler는 특정 작업이나 메시지를 순차적으로 처리하는 역할을 한다. 즉, 이 함수에 들어오는 obj는 백그라운드 작업을 관리하는 객체이다. C1020.m2452() <= 0 라는 조건문이 참이어야만 정상값을 반환하는 데, 특정 환경(분석 환경)이 감지되면 정상 작동을 멈추도록 설계한 것 같다.public static boolean m2606(Object obj) { if (C1020.m2452() <= 0) { return ((ServiceHandler) obj).f1817a; } return false; }
- case 1751625: m2576으로 들어가면, 아래와 같은 함수가 나온다.
m1476 함수로 들어가면, 아래와 같다.public static void m2576(Object obj) { if (C1048.m2644() <= 0) { ((ServiceHandler) obj).m1476e(); } }
public final void m1476e() {
String str;
String str2;
String str3;
String str4;
String str5;
Thread threadM2557;
String str6;
ParcelFileDescriptor parcelFileDescriptor = null;
Thread thread = null;
String strM2778 = null;
int iM2676 = C1052.m2676("ۣۡۢ");
while (true) {
switch (iM2676) {
case 56482:
threadM2557 = C1035.m2557(this);
str5 = "ۣ۟ۥ";
iM2676 = C1027.m2500(str5);
thread = threadM2557;
break;
case 1746753:
strM2778 = C1069.m2778(m2663(), 390, C1056.f4400 ^ 61, 1195);
if (C1026.m2495() < 0) {
str = "ۧۦۨ";
iM2676 = C1054.m2688(str);
} else {
C1075.m2811();
str = "ۨۢۤ";
iM2676 = C1054.m2688(str);
}
break;
case 1746817:
if (thread == null) {
iM2676 = (C1074.f4418 % C1040.f4382) ^ (-1754454);
} else if ((C1049.f4391 | (C1071.f4415 ^ 2207)) < 0) {
iM2676 = (C1028.f4370 | C1054.f4398) + 1751723;
} else {
str2 = "ۨۧ۠";
iM2676 = C1060.m2724(str2);
}
break;
case 1746843:
C1023.m2475(this);
if (C1070.m2783() >= 0) {
C1040.m2591();
iM2676 = C1058.m2711("ۦۡۢ");
} else {
iM2676 = C1053.f4397 + C1067.f4411 + 1750206;
}
break;
case 1747653:
C1067.m2768(this, false);
iM2676 = (C1048.f4390 % C1027.f4369) + 1747021;
break;
case 1747772:
iM2676 = C1066.f4410 > 0 ? C1069.m2781("۟۟") : C1072.m2797("ۣ۟ۡ");
break;
case 1747775:
case 1755585:
str3 = C1041.f4383 % (C1075.f4419 ^ 5134) <= 0 ? "ۡ۟ۦ" : "ۣۨ۠";
iM2676 = C1075.m2812(str3);
break;
case 1748706:
if (!C1043.m2606(this)) {
if (C1062.f4406 <= 0) {
C1028.m2503();
iM2676 = C1052.m2676("ۣۡۢ");
} else {
iM2676 = (C1073.f4417 / C1057.f4401) + 1748804;
}
} else if (C1066.f4410 > 0) {
}
break;
case 1748804:
case 1749572:
break;
case 1749574:
try {
C1033.m2539(parcelFileDescriptor);
str = "ۨۢۤ";
iM2676 = C1054.m2688(str);
} catch (IOException e2) {
C1043.m2603(strM2778, C1054.m2689(m2663(), 412, C1030.f4372 ^ (-176), 1728), e2);
if (C1051.m2665() <= 0) {
C1074.f4418 = 93;
str6 = "ۣ۟ۥ";
} else {
str6 = "ۨۧ۠";
}
iM2676 = C1022.m2467(str6);
}
break;
case 1750539:
this.f1817a = false;
if (C1030.m2526() >= 0) {
C1035.m2554();
iM2676 = C1031.m2528("۟ۤ۠");
} else {
iM2676 = (C1067.f4411 % C1052.f4396) + 57118;
}
break;
case 1750600:
this.f1818b = null;
str = "ۧۥۥ";
iM2676 = C1054.m2688(str);
break;
case 1750811:
this.f1819c = null;
str2 = "۠۟ۤ";
iM2676 = C1060.m2724(str2);
break;
case 1751530:
C1025.m2489(thread);
if (C1048.f4390 < 0) {
str3 = "ۣۡۦ";
iM2676 = C1075.m2812(str3);
} else {
iM2676 = C1048.m2642("ۦۥۤ");
}
break;
case 1751740:
break;
case 1753479:
if (C1020.f4362 / (C1023.f4365 | (-9728)) != 0) {
C1063.f4407 = 61;
iM2676 = C1049.m2649("ۣۡ۠");
} else {
iM2676 = C1049.m2649("ۨۢۤ");
}
break;
case 1753605:
iM2676 = parcelFileDescriptor == null ? (C1025.f ^ C1058.f4402) + 1747711 : C1023.f4365 - (C1044.f4386 ^ 5756) >= 0 ? C1074.m2810("ۥۧ") : C1030.f4372 + C1050.f4392 + 1750499;
break;
case 1754537:
if (C1040.f4382 <= 0) {
C1061.m2726();
str5 = "ۥۧۥ";
threadM2557 = thread;
} else {
str5 = "ۣۡۢ";
threadM2557 = thread;
}
iM2676 = C1027.m2500(str5);
thread = threadM2557;
break;
case 1754539:
iM2676 = (C1074.f4418 % C1040.f4382) ^ (-1754454);
break;
case 1754567:
ParcelFileDescriptor parcelFileDescriptorM2734 = C1062.m2734(this);
if (C1026.f4368 / (C1053.f4397 - 9053) != 0) {
iM2676 = C1053.m2677("ۣۨ۠");
parcelFileDescriptor = parcelFileDescriptorM2734;
} else {
iM2676 = (C1047.f4389 * C1075.f4419) ^ 1574155;
parcelFileDescriptor = parcelFileDescriptorM2734;
}
break;
case 1754601:
C1043.m2607(strM2778, C1026.m2491(m2663(), 397, C1046.f4388 ^ 428, 2197));
if (C1073.f4417 % (C1073.f4417 * (-5181)) >= 0) {
C1052.f4396 = 52;
str4 = "ۤ۠ۦ";
} else {
str4 = "ۣ۟ۧ";
}
iM2676 = C1047.m2629(str4);
break;
case 1754661:
iM2676 = (C1070.f4414 - C1026.f4368) ^ 1749746;
break;
case 1755434:
if (C1042.f4384 / (C1020.f4362 | (-2882)) < 0) {
str4 = "ۣ۠ۢ";
iM2676 = C1047.m2629(str4);
} else {
C1020.f4362 = 12;
iM2676 = C1029.m2519("ۧۤۨ");
}
break;
}
return;
}
}
switch-case로 난독화가 되어있어서 보기가 어렵다. 중요한 부분만 보자면, ParcelFileDescriptor parcelFileDescriptorM2734 = C1062.m2734(this); 이 부분에서는 이 앱이 기기 내부의 특정 파일, 데이터베이스, 혹은 외부 서버와 연결된 통신 통로를 연다는 것을 알 수 있고, threadM2557 = C1035.m2557(this); 이 코드를 통해 스드를 생성하고 뒤에서 실행한다는 것을 알 수 있다. 마지막에 열었던 파일을 닫으려면 this.f1817a = false;을 통해 흔적을 지우며 서비스를 종료한다는 것을 알 수 있다. 간단하게 보면, 이 함수는 조용히특정 파일을 열어서 백그라운드 스레드를 띄워 가동한 뒤, 목적을 달성하면 흔적을 지우고 꺼지는 일련의 백그라운드 동작 프로세스를 실행한다.
- case 1751653: m2641함수로 들어와보면 아래와 같다.
public static boolean m2641(Object obj, Object obj2) {
if (C1035.m2554() <= 0) {
return ((String) obj).equals(obj2);
}
return false;
}
인자로 들어온 두 값이 같으면 true, 다르면 false를 반환한다. 그러면 인자는 어떤 코드일까. 인자 안의 m2694 함수로 들어가보면 아래와 같다.
public static String m2694(short[] sArr, int i2, int i3, int i4) {
char[] cArr = new char[i3];
for (int i5 = 0; i5 < i3; i5++) {
cArr[i5] = (char) (sArr[i2 + i5] ^ i4);
}
return new String(cArr);
}
암호화되어 있던 short형 정수 배열을 우리가 읽을 수 있는 String으로 변환해 주는 아주 전형적인 XOR 복호화 함수가 나온다. i3 크기만큼의 새로운 char 배열을 만들고 암호화된 배열의 특정 시작 위치(i2)부터 값을 하나씩 가져와서 복호화 키 값(i4)과 XOR 연산을 한다. 계산된 숫자를 다시 char로 변환 후, cArr 이라는 새로운 문자열을 반환한다.
위의 함수들과 연관지어서 해석하면,
- m2663() 메서드로 암호화된 전체 데이터 배열을 가져옴
- 434번째 위치부터 시작
- C1024.f4366 ^ 384 글자 수만큼 1670이라는 키를 이용해 XOR 복호화를 수행
- 복호화되어 나온 진짜 텍스트가 다른 값(str6)과 일치하는지(equals) 비교
위와 같다. 만약 일치한다면 다른 곳으로 분기하도록 한다. else if일 때는 C1055.m2692() <= 0를 만족하면 실행되는데, 들어가면 764^881의 값을 반환하는 것을 알 수 있다. 그래서 일치하지 않는다면, else까지는 가지않고 else if에서 다른 분기 위치가 정해지는 것을 알 수 있다.
- case 1755562:m2607 함수로 들어가보면 아래와 같다.
obj를 태그로 하고, obj2가 그 내용으로 로그를 만든다. 공격자가 원하는 행동을 시작할 때 로그를 남기는 것 같다. 그러고 다른 곳으로 분기하도록 한다.public static int m2607(Object obj, Object obj2) { if (C1051.m2665() >= 0) { return Log.i((String) obj, (String) obj2); } return 0; }
- case 1755619: 현재 떠 있는 스레드(thread2) 정보를 클래스 내부 변수(this.f1818b)에 백업 후 C1042.f4384 <= 0이면, m2631 실행. f4384는 882로 실행되지 않음. 무조건 else의 코드가 실행됨. else에서는 (58)/(-759)+1747748으로 case 1747748로 분기된다. 1747748은 아래 코드이다.
case 1747748:
C1047.m2635(thread2);
_go = C1046.f4388 + (C1036.f4378 ^ 7498) >= 0 ? C1049.m2649("ۨۨۦ") : (C1060.f4404 | C1041.f4383) + 1750631;
break;
m2635 함수의 내용이 m2480 변수가 0보다 크면 ((Thread) obj).start(); 로 인자로 받은 스레드(thread2)를 실제로 구동하는 것인데, m2480이 ( -835)^(-739)으로 0보다 큰 값이 나와 백그라운드 작업(thread2)을 시작시키고, 삼항 연산자로 다음 case에 분기하도록 한다.
'악성코드' 카테고리의 다른 글
| 6주차_Jadx(1) (0) | 2026.05.18 |
|---|---|
| 5주차_Frida(1) (0) | 2026.05.11 |
| 4주차_학습용 악성코드 동적분석 (0) | 2026.04.02 |
| 3주차_학습용 악성코드 정적분석 (0) | 2026.03.29 |
| 2주차_악성코드 분석 툴 (0) | 2026.03.23 |