반응형

모의해커라면 frida를 이용하여 모바일 앱 동적 분석을 자주 합니다.

예전 같으면 꿈도 못꿨을 모바일 앱 리버싱이 정말 많이 편해졌죠. 신입 모의해커도 프리다는 기본으로 다룰 줄 아는 시대입니다.

그러나, frida JavaScript API 라는 무기를 하나 가졌을 뿐입니다.

전쟁터에 무기 딱 하나 들고 참전했는데, 여러가지 이유로 해당 무기를 사용 못하게 되면 참 난감해지겠죠. 그래서, frida는 코어 모듈을 떼어다가 다른 무기를 만들 수 있게끔 제공하고 있습니다.

무기를 하나 더 들고 참전하는 만큼 다양한 상황에 좀 더 유연하게 대처가 가능합니다.

 

frida-gum은 c언어로 작성되었으며, 이를 static library로 제공하고 있어서 프로그램에 포함하여 코드 작성이 가능합니다.

예를 들어, 악성 앱이 실행되면서 랜덤한 이름의 so파일을 생성해서 사용하고 삭제하는 로직이라면 lsposed와 frida-gum의 gum_process_enumerate_modules 함수를 이용해서 덤프를 뜰 수 있습니다.

#include "frida-gum.h"
#include "com_hackcatml_test_MainModule.h"

#include <sstream>
#include <regex>
#include <sys/mman.h>
#include <thread>

static bool isModuleFound = false;
static std::regex modulePattern("so파일 정규식 패턴");
static std::string sofile_dir = "/data/data/com.hackcatml.test/files/";

void dump_so(uintptr_t module_base, unsigned long sofile_size) {
    
    std::stringstream module_base_hexstr;
    module_base_hexstr << "0x" << std::hex << module_base;

    LOGD("module base: %p", module_base);
    LOGD("module base hex string: %s", module_base_hexstr.str().c_str());
    LOGD("module size: %lu", sofile_size);

    std::string sofile_path = sofile_dir + "dump[" + module_base_hexstr.str() +"].so";
	
    int dfd = open(sofile_path.c_str(), O_RDWR  | O_CREAT, 0777);
    if(dfd >= -1){
        LOGD("gonna write file");
        ftruncate(dfd, sofile_size);
        // file memory mapping
        void *dest = mmap(nullptr, sofile_size, PROT_WRITE | PROT_READ, MAP_SHARED, dfd, 0);
        // 모듈 base 주소의 메모리 프로텍트를 'rwx'로 설정하여 access violation 방지
        mprotect((void *)module_base, sofile_size, PROT_READ | PROT_WRITE | PROT_EXEC);
        // memory copy
        memmove(dest, reinterpret_cast<const void *>(module_base), sofile_size);
        // memory unmapping
        munmap(dest, sofile_size);
        close(dfd);
    } else {
        LOGD("failed to open file");
    }
}

static gboolean
moduleFound(const GumModuleDetails * details, gpointer user_data)
{
    const char* path = details->path;
    if(std::regex_match(path, modulePattern)){
        LOGD("found! %s", path);

        isModuleFound = true;
        std::thread t(dump_so, details->range->base_address, details->range->size);
        t.detach();

        return false;
    }
    return true;
}

void on_library_loaded(const char *name, void *handle){
    if(!isModuleFound){
        gum_process_enumerate_modules(moduleFound, NULL);
    }
}

__attribute__((constructor))
void before_main(void)
{
    gum_init_embedded ();
    LOGD("frida-gum init!");
}

extern "C" __attribute__((visibility("default")))
NativeOnModuleLoaded native_init(const NativeAPIEntries *entries)
{
    LOGD("native init!");

    return on_library_loaded;
}

 

반응형

'Information Security > Android' 카테고리의 다른 글

PmsHook 해봅시다  (0) 2023.05.30
LSPlant test  (1) 2022.11.06
갤럭시 s10(SM-G973N) Android 12 루팅  (9) 2022.05.21
안드로이드 SVC 루팅탐지 로직  (7) 2022.03.14
Intent Sniffing  (0) 2022.03.14

+ Recent posts