개요
**대응방법**
0. AndroidManifest.xml 의 <application> 부분에 android:debuggable 값을 true/false로 설정
1. 디버깅 비활성화
2. 디버깅 시 사용되는 ptrace 선점 안티디버깅
3. 디버깅 시 발생되는 SIGTRAP 시그널 무시
4. ppid를 확인하여 앱을 실행 시킨 프로세스가 디버깅툴(GDB or LLDB)인지 확인
5."/proc/self/status" 파일 내용 중 TracerPid 값 확인
**우회**
디버깅 탐지 기능 취약점은
앱이 동작할 때 동적 디버깅 도구로 디버깅 가능 여부에 따라 취약한지 결정되는데
LLDB나 GDB, IDA와 같은 동적 디버깅 도구로 앱에 attach을 때 디버깅이 가능하면 취약한 것이다.
공격자는 애플리케이션 동적 디버깅을 통하여 코드 흐름 파악, 메모리 상태 분석, 실행 흐름을 조작가능하다.
디버깅이 가능 할 때의 취약점들이다.
- 디버깅 허용 설정:
- 앱이 디버깅을 허용하는 설정을 가지고 있어서, 개발자 모드나 디버깅 옵션을 쉽게 활성화할 수 있는 경우.
- 디버깅 플래그 검사 부재:
- 앱의 코드에 디버깅을 감지하는 코드 또는 플래그가 존재하지 않아서 디버깅을 감지하거나 방지할 수 없는 경우
- 디버깅 관련 API 활용:
- 앱이 디버깅 관련 API를 사용하여 디버깅을 탐지하고 이에 대응하지 않는 경우
- 디버거 탐지:
- 앱이 디버거를 탐지하는 기능을 가지고 있지만, 이 기능이 우회될 수 있는 경우
- 디버깅 로그 노출:
- 앱의 디버깅 로그가 사용자에게 노출되거나, 로그에서 개인 정보가 노출되는 경우
- SSL 인증서 무시:
- 앱이 SSL 인증서의 유효성을 검사하지 않고 디버깅을 위해 사용자가 만든 인증서를 허용하는 경우
- 디버깅 중 예외 노출:
- 앱이 디버깅 중에 예외를 노출하여 앱의 내부 정보를 노출하는 경우
- 디버깅 명령어 사용:
- 앱이 실행 중에 디버깅 명령어를 사용하도록 허용하여 디버깅을 용이하게 하는 경우
- 악용 가능한 변수 노출:
- 디버깅 중에 악성 사용자가 중요한 변수 값을 수정하여 앱의 동작을 악용할 수 있는 경우입니다.
- 디버깅으로 인한 성능 저하:
- 디버그 모드로 실행되는 경우, 앱의 성능이 저하되거나, 디버깅 정보 수집으로 인한 부하로 인해 보안적인 문제가 발생할 수 있습니다.
안드로이드의 대응방안을 알아보겠다.
대응방법
0. AndroidManifest.xml 의 <application> 부분에 android:debuggable 값을 true/false로 설정
1. 디버깅 비활성화
2. 디버깅 시 사용되는 ptrace 선점 안티디버깅
3. 디버깅 시 발생되는 SIGTRAP 시그널 무시
4. ppid를 확인하여 앱을 실행 시킨 프로세스가 디버깅툴(GDB or LLDB)인지 확인
5."/proc/self/status" 파일 내용 중 TracerPid 값 확인
1.
public class DebugProtection {
private static final String DEBUG_FLAG_PROPERTY = "debug.enable";
public static void disableDebug() {
System.setProperty(DEBUG_FLAG_PROPERTY, "false");
}
}
2 ,3 .
// ptrace 차단
int main() {
prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
{
// 앱 코드
}
return 0;
}
// SIGTRAP 무시
void signal_handler(int signum) {
}
int main() {
struct sigaction sa;
sa.sa_handler = signal_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGTRAP, &sa, NULL);
return 0;
}
// C++
int main() {
signal(SIGTRAP, SIG_IGN);
{
// 앱 코드
}
return 0;
}
위 코드는 동적 디버깅 도구를 이용하여 앱에 attach시 ptrace 시스템을 호출해서 attach 하게 되는데
그 ptace를 차단해서 attach되는 것을 막는 원리이다.
또한 동적 디버깅 도구에서 attach시 디버깅 시 사용되는 대표적인 SIGTRAP 신호가 발생되는데 그것을 무시하면서 동적 디버깅 도구가 붙지 못하게 된다.
더불어 위의 코드는 안드로이드에서 ptrace 차단과 SIGTRAP 무시를 구현하는 방법이다. 안드로이드 앱에서는 일반적으로 안드로이드 NDK(Native Development Kit)를 사용하여 C/C++ 코드를 작성하고, 해당 코드를 앱에 통합한다. 따라서 주로 C/C++로 작성된 코드를 JNI(Java Native Interface)를 통해 Java 코드에서 호출하는 방식으로 사용한다.
네이티브 라이브러리 Import 방법
추가 알아야 할 점
|
다음은 각 코드가 앱의 어떤 부분에 들어가야 하는지 알아보겠다.
- ptrace 차단 코드:
- 이 코드는 안드로이드 NDK로 작성된 C/C++ 코드에 포함되어야 한다.
- 일반적으로 Android.mk 또는 CMakeLists.txt 파일과 같은 빌드 설정 파일에 해당 코드를 추가하고, NDK를 사용하여 빌드하여 라이브러리를 생성한다.
- 그런 다음 Java 코드에서 JNI를 통해 해당 라이브러리를 호출하고, JNI 메서드를 통해 해당 기능을 활성화하면 된다.
- SIGTRAP 무시 코드:
- 마찬가지로, 이 코드도 안드로이드 NDK로 작성된 C/C++ 코드에 포함되어야 한다.
- Android.mk 또는 CMakeLists.txt 파일과 같은 빌드 설정 파일에 해당 코드를 추가하고, NDK를 사용하여 빌드하여 라이브러리를 생성한다.
- Java 코드에서 JNI를 통해 해당 라이브러리를 호출하고, JNI 메서드를 통해 해당 기능을 활성화하면 된다.
C/C++ 코드를 NDK를 사용하여 빌드하는 방법은 매우 복잡하므로 자세한 방법은 별도의 안드로이드 NDK 관련 문서를 참조하길 바란다.
+
native void ptrace_intercept();
public class PtraceProtection {
static {
System.loadLibrary("ptrace_intercept");
}
public static void disablePtrace() {
ptrace_intercept();
}
}
위의 코드는 ptrace_intercept() 라는 ptrace를 보호하는 라이브러리 중 하나를 사용해서 막는 원리라고한다.
4.
bool checkDebugTool() {
char filePath[32], fileRead[128];
FILE* file;
snprintf(filePath, 24, "/proc/%d/cmdline", getppid());
file = fopen(filePath, "r");
fgets(fileRead, 128, file);
fclose(file);
if(!strcmp(fileRead, "gdb")) {
return true;
}
if(!strcmp(fileRead, “lldb”)) {
return true;
}
return false;
}
GDB 와 LLDB의 소문자만 비교하지말고 대/소문자 모두 확인할 수 있도록 조건을 추가하여 확실하게 탐지한다.
5.
앱의 "/proc/self/status" 파일 내용 중 TracerPid 값이 있는지 확인하는 방법이며 디버깅툴이 앱을 실행시킨 경우 TracerPid가 0보다 큰 값을 가지게 되므로 TracePid 탐지 루틴을 적용하여 디버깅 탐지 기능을 만들 수 있다.
bool checkDebugTool() {
int TPid;
char buf[512];
const char *str = "TracerPid:";
size_t strSize = strlen(str);
std::string strDebugging = "NONE";
FILE* file = fopen("/proc/self/status", "r");
while (fgets(buf, 512, file)) {
if (!strncmp(buf, str, strSize)) {
sscanf(buf, "TracerPid: %d", &TPid);
if (TPid != 0) {
strDebugging = buf;
fclose(file);
return true
}
}
}
fclose(file);
return false;
}
+
`/proc/self/status` 파일은 리눅스 기반 운영 체제에서 실행 중인 프로세스에 대한 정보를 제공하는 가상 파일이다. 안드로이드 앱의 경우, 안드로이드 운영 체제는 리눅스 커널 위에서 실행되므로, 이 파일을 통해 현재 실행 중인 앱 프로세스에 대한 정보를 얻을 수 있다.
`/proc/self/status` 파일의 내용은 현재 프로세스의 상태와 관련된 정보를 포함한다. 예를 들어, 프로세스 ID, 메모리 사용량, 스레드 정보, 파일 디스크립터, CPU 사용량 등이 포함될 수 있다. 이 정보를 통해 앱의 동작 및 성능을 분석하거나 모니터링할 수 있다.
(안드로이드 앱에서는 `/proc/self/status` 파일을 직접적으로 접근하는 것은 권장되지 않지만 앱 개발자는 안드로이드 프레임워크에서 제공하는 API를 사용하여 필요한 정보를 얻어오는것을 권장한다. 예를 들면, `android.os.Process` 클래스의 메서드를 사용하여 현재 앱의 프로세스 ID를 가져오거나, `android.os.Debug` 클래스의 메서드를 사용하여 메모리 사용량 정보를 얻을 수 있다.)
코드를 자세히 보면 위 두 개의 코드 모두 C/C++ 코드이므로 앱에서 이 코드를 사용하기 위해서는 JNI를 사용해야 한다.
추가 방법
https://als2019.tistory.com/84
내가 만든 앱은 내가 지키자! (루팅감지, 디버깅감지) 2/3
개요 지난번 글에 이어 이번에는 앱이 배포된 뒤 크래커에 의해 디버깅 되는 것을 막는 방법에 대해 설명하도록 하겠습니다. 개발자가 엄청난 노력을 기울여 시큐어 코딩을 하고 코드를 난독화
als2019.tistory.com
조치 시 결과
해당 취약점에 대한 조치가 완료되었을 때 IDA로 점검 시
이와같은 문구가 뜨게 되어있다.
안티 디버깅 우회 방법
1. 코드 패치
2. 린엔진으로 ptrace 후킹
-nop 우회 시도
-suspend 우회 시도
http://linforum.kr/bbs/board.php?bo_table=linEngines
린엔진 소개
린엔진은 안드로이드 앱 분석을 목적으로 사용되는 강력한 분석 도구입니다.악성코드 분석, 앱 보호솔루션 BMT, 모드앱 분석, 자사의 게임/일반 어플리케이션 모의해킹(보안성검토)등에 사용할
linforum.kr
3. frida로 우회
![](https://t1.daumcdn.net/keditor/emoticon/niniz/large/002.gif)
'모바일 > Android' 카테고리의 다른 글
[Android] 메모리 덤프 ? 4가지 알아볼게요 (0) | 2023.08.28 |
---|---|
[Android] 소스코드 난독화 (0) | 2023.08.02 |
[Android] 동적 디버깅 탐지 (0) | 2023.07.13 |
[Android] Magisk 헬조선을 이용한 루팅-2 (0) | 2023.07.12 |
[Anodroid] Magisk 헬조선을 이용한 루팅 (0) | 2023.07.12 |