 보안설정방법
해당 프로세스가 디버거에 의해 제어 받고 있는지 확인하고 탐지, 종료하는 루틴을 삽입하여 해당 프로세스를 강제 종료시켜야 함(한가지 방식 적용이 아닌 아래의 방식을 모두 적용하여 프로세스 실행 중 주기적인 검증 수행 필요)
 
<Android>
소스 구현 영역에 따라 SDK(Java)와 NDK(C, Natice)로 구현 가능함.

<참고. SDK Java 소스 구현 방안>
[구현 방안 1 : 디버그 프로세스 탐지]
static int detect_isDebuggerPresent(){
     if(Debug.isDebuggerConnected())
          return 1;
     else return 0;
}


[구현 방안 2 : 디버깅 시 브레이크 포인트가 걸리는 시간 측정]
static boolean detect_threadCpuTimeNanos () {
long start = Debug.threadCpuTimeNanos ();
for(int i = 0; i <1000000; ++i )
continue;
long stop = Debug.threadCpuTimeNanos();
if(stop - start < 10000000)
return false ;
else
return true ;
}


<참고. NDK C 소스 구현 방안>
구현 방안 1 : 디버그 프로세스 탐지]
JNIEXPORT jboolean JNICALL Java_poc_c_detectdebuggerConnected (JNIEnv* env,jobject dontuse)
if(gDvm.debuggerConnected || gDvm.debuggerActive){
           return JNI_TRUE ;
     return JNI_FALSE ;
 }

[구현 방안 2 : process status 파일 확인]
#ifndef JNI_ANDROID_ANTI_DEBUG_H_
#define JNI_ANDROID_ANTI_DEBUG_H_

#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif

#endif /* JNI_ANDROID_ANTI_DEBUG_H_ */
#include <android/log.h>
#include <jni.h>
#include <string>
#include <sys/ptrace.h>
#include <unistd.h>
#include <stdlib.h>
#include <chrono>
#include <thread>

void be_attached_check()
{
    try
    {
        const int bufsize = 1024;
        char filename[bufsize];
        char line[bufsize];
        int pid = getpid();
        sprintf(filename, "/proc/%d/status", pid);
        FILE* fd = fopen(filename, "r");
        if (fd != nullptr)
        {
            while (fgets(line, bufsize, fd))
            {
                if (strncmp(line, "TracerPid", 9) == 0)
                {
                    int statue = atoi(&line[10]);
                    LOGD("%s", line);
                    if (statue != 0)
                    {
                        LOGD("be attached !! kill %d", pid);
                        fclose(fd);
                        int ret = kill(pid, SIGKILL);
                    }
                    break;
                }
            }
            fclose(fd);
        } else
        {
            LOGD("open %s fail...", filename);
        }
    } catch (...)
    {

    }

}
void thread_task(int n)
{
    while (true)
    {
        LOGD("start be_attached_check...");
        be_attached_check();
        std::this_thread::sleep_for(std::chrono::seconds(n));
    }
}
void anti_debug()
{
    LOGD("call anti_debug ......");
    auto checkThread = std::thread(thread_task, 1);
    checkThread.detach();
}

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    anti_debug();
    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK)
    {
        return -1;
    }
    return JNI_VERSION_1_6;
}

[구현 방안 3 : ptrace 선점을 통한 디버거process attach 방지]

#include <jni.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <pthread.h>

static int child_pid;
void * monitor_pid(void *pVoid) {
    int status;
    waitpid(child_pid, &status, 0);
    /* Child status should never change. */
    _exit(0); // Commit seppuku
}

void anti_debug() {
    child_pid = fork();
    if (child_pid == 0)
    {
        int ppid = getppid();
        int status;
        if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0)
        {
            waitpid(ppid, &status, 0);
            ptrace(PTRACE_CONT, ppid, NULL, NULL);
            while (waitpid(ppid, &status, 0)) {
                if (WIFSTOPPED(status)) {
                    ptrace(PTRACE_CONT, ppid, NULL, NULL);
                } else {
                    // Process has exited
                    _exit(0);
                }
            }
        }

    } else {
        pthread_t t;
        /* Start the monitoring thread */
        pthread_create(&t, NULL, monitor_pid, (void *)NULL);
    }
}

JNIEXPORT void JNICALL
Java_sg_vantagepoint_antidebug_MainActivity_antidebug(JNIEnv *env, jobject instance) {
    anti_debug();
}

<iOS>
아래는 프로그램이 디버거로 제어를 받고 있는지 탐지, 종료하는 예제코드임.

<참고. 구현 방안>
[구현 방안 1]
//  main.m
//  ProtectionSample
#import <Cocoa/Cocoa.h>
#include <sys/ptrace.h>

int main(int argc, char *argv[])
{
    //Build settings -> Other C Flags: -DDEBUG
#ifdef DEBUG
    //do nothing
#else
    ptrace(PT_DENY_ATTACH, 0, 0, 0);
#endif
    return NSApplicationMain(argc,  (const char **) argv);

[구현 방안 2]
#import <dlfcn.h>
#import <sys/types.h>

typedef int (*ptrace_ptr_t)(int _request, pid_t _pid, caddr_t _addr, int _data);
#if !defined(PT_DENY_ATTACH)
#define PT_DENY_ATTACH 31
#endif  // !defined(PT_DENY_ATTACH)
void disable_gdb() {
void* handle = dlopen(0, RTLD_GLOBAL | RTLD_NOW);
ptrace_ptr_t ptrace_ptr = dlsym(handle, "ptrace");
ptrace_ptr(PT_DENY_ATTACH, 0, 0, 0);
dlclose(handle);
}

[방안 3 : 파일 변경 확인 또는 디버거에 의한 실행 확인 방법]
NSString* bundlePath = [[NSBundle mainBundle] bundlePath];
NSString* path = [NSString stringWithFormat:@"%@/Info.plist", bundlePath];
NSString* path2 = [NSString stringWithFormat:@"%@/AppName", bundlePath];
NSDate* infoModifiedDate = [[[NSFileManager defaultManager] fileAttributesAtPath:path traverseLink:YES] fileModificationDate];
NSDate* infoModifiedDate2 = [[[NSFileManager defaultManager] fileAttributesAtPath:path2 traverseLink:YES] fileModificationDate];
NSDate* pkgInfoModifiedDate = [[[NSFileManager defaultManager] fileAttributesAtPath:[[[NSBundle mainBundle] resourcePath] 
stringByAppendingPathComponent:@"PkgInfo"] traverseLink:YES] fileModificationDate];
if([infoModifiedDate timeIntervalSinceReferenceDate] > [pkgInfoModifiedDate timeIntervalSinceReferenceDate]) {  
//파일 변경
}
if([infoModifiedDate2 timeIntervalSinceReferenceDate] > [pkgInfoModifiedDate timeIntervalSinceReferenceDate]) { 
//파일변경
}

'모바일' 카테고리의 다른 글

android jadx tool  (0) 2021.12.11
dex2jar 에러 경로 참고  (0) 2021.12.11
LLDB 디버깅 명령어 건  (0) 2021.08.31
딥링크란??  (0) 2021.08.03
3utools GPS 변경 건  (0) 2021.07.02
블로그 이미지

wtdsoul

,