๋์ค์ด์ ๋ธ ํ๋ ์์ํฌ Capstone-engine ํ์ฉํ๊ธฐ
๋์ค์ด์ ๋ธ ํ๋ ์์ํฌ Capstone-engine ํ์ฉํ๊ธฐ ๊ด๋ จ
๋ค์ด๊ฐ๋ฉฐ
์ด ๊ธ์์๋ ๋์ค์ด์ ๋ธ ํ๋ ์์ํฌ์ธ Capstone-engine์ ํ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๊ณ ์ ํฉ๋๋ค.
ํํ์ด์ง ์๊ฐ๊ธ(https://www.capstone-engine.org/)์ ์ํ๋ฉด Capstone์ Capstone-engine์ ๋ฐ์ด๋๋ฆฌ ๋ถ์๊ณผ ๋ฆฌ๋ฒ์ฑ์ ์์ด the ultimate disassembly engine์ผ๋ก ๋ง๋๋ ๊ฒ ๋ชฉํ๋ผ๊ณ ํฉ๋๋ค. ์ฌ๊ธฐ์์๋ Python API๋ฅผ ์ด์ฉํด ๋์ค์ด์ ๋ธ ๋๊ตฌ๋ฅผ ๋ง๋ค์ด ๋ณด๊ณ , ์ ํ๋ฆฌ์ผ์ด์ ๋ฐํ์ ์ ์ด๋ฅผ ๋์ค์ด์ ๋ธํ๋ ๋ฐ C API๋ฅผ ์ด์ฉํด ๋ณด๊ฒ ์ต๋๋ค.
Python API ์ฌ์ฉ๋ฒ
Capstone ์ Python API๋ฅผ ์ด์ฉํ๋ฉด ๋๋ง์ ํ์ด์ฌ ๋์ค์ด์ ๋ธ ๋๊ตฌ๋ฅผ ๋ง๋ค ์ ์์ต๋๋ค.
Capstone ์ค์น(macOS)
pip install capstone # (for intel macOS)
pip install --pre --no-binary capstone capstone # (for m1, m2 macOS)
Windows ๋ฑ ๋ค๋ฅธ ํ๋ซํผ์ ๊ฒฝ์ฐ https://www.capstone-engine.org/documentation.html์ ์ฐธ๊ณ ํ์ฌ ์ค์นํ๋ฉด ๋๊ฒ ์ต๋๋ค.
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋์ค์ด์
๋ธํ๊ณ ์ ํ๋ ํฅ์ค ์ฝ๋๋ฅผ ์ ์ด ์ฃผ๊ณ , ์ํคํ
์ฒ ๋ฐ ๋ชจ๋๋ฅผ ์ ํ ๋ค disasm_lite()
๋ฉ์๋๋ก ๋์ค์ด์
๋ธํด ์ฃผ๋ฉด ๋ฉ๋๋ค.
๋ฐํ์ ์ฌ์ฉ๋ฒ
์ ํ๋ฆฌ์ผ์ด์ ๋ฐํ์ ์์ ๋์ค์ด์ ๋ธ์ด ํ์ํ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. ์ด๋ Capstone C API๋ฅผ ์ด์ฉํ์ฌ ํ๋ก๊ทธ๋๋ฐํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์์๋ Android ์ฑ ๋ฐํ์ ์์ Capstone์ ์ด์ฉํด ๋์ค์ด์ ๋ธํด ๋ณด๊ณ ์ ํฉ๋๋ค.
C ํ๋ก๊ทธ๋๋ฐ ์์ ์ฝ๋๋ https://www.capstone-engine.org/lang_c.html์ ๋์ ์๋๋ฐ์. ๋ชจ๋ฐ์ผ์์ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง๋ ์์ธํ ๋์ ์์ง ์์ต๋๋ค. ๋คํํ frida/frida-gum
์์ Capstone API๋ฅผ ์ ๊ณตํด ์ฃผ๊ณ ์์ต๋๋ค.
arm64์ฉ frida-gum static library๋ https://github.com/frida/frida/releases/download/16.1.11/frida-gum-devkit-16.1.11-android-arm64.tar.xz์์ ๋ค์ด๋ก๋ํ ์ ์์ต๋๋ค.
๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
Android ๋ค์ดํฐ๋ธ ํ๋ก์ ํธ์์ ๊ธฐ๋ณธ์ ์ธ ์ฌ์ฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค. ๋์ค์ด์
๋ธํ๊ณ ์ ํ๋ ํฅ์ค ์ฝ๋๋ฅผ ์ ์ด ์ฃผ๊ณ , ์ํคํ
์ฒ ๋ฐ ๋ชจ๋๋ฅผ ์ ํ ๋ค cs_disasm()
ํจ์๋ก ๋์ค์ด์
๋ธํด ์ฃผ๋ฉด ๋ฉ๋๋ค.
๋ค์์ ์ ์ฒด ์์ค ์ฝ๋์ ๋๋ค.
#include <jni.h>
#include <string>
#include <stdio.h>
#include <inttypes.h>
#include <android/log.h>
#include "include/frida-gum.h"
#ifndef LOG_TAG
#define LOG_TAG "[nhncloud]"
#endif
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
static const uint8_t CODE[] = {0xc8, 0x02, 0x40, 0xf9, 0x08, 0x01, 0x00, 0xb5, 0x08, 0x1c, 0xa0, 0x4e, 0xe0, 0x03, 0x15, 0xaa};
void disassemble() {
csh capstone;
cs_insn * insn;
size_t count;
cs_open (CS_ARCH_ARM64, CS_MODE_ARM, &capstone);
cs_option (capstone, CS_OPT_DETAIL, CS_OPT_ON);
insn = cs_malloc (capstone);
count = cs_disasm(capstone, CODE, sizeof(CODE), 0x1000, 0, &insn);
if (count > 0) {
size_t j;
for (j = 0; j < count; j++) {
LOGD("0x%" PRIx64":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic,
insn[j].op_str);
}
cs_free(insn, count);
} else {
LOGD("ERROR: Failed to disassemble given code!\n");
}
cs_close (&capstone);
}
extern "C" JNIEXPORT jstring
JNICALL
Java_com_nhncloud_capstonetest_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
disassemble();
return env->NewStringUTF(hello.c_str());
}
์์ฉ ์ฌ์ฉ๋ฒ
ํน์ ๋ฉ๋ชจ๋ฆฌ ํจํด์ ์ค์บํ๊ณ , ํด๋น ํจํด์ด ๋ฐ๊ฒฌ๋ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์์์ Capstone API๋ฅผ ์ด์ฉํด ๋์ค์ด์ ๋ธ ํ ๊ทธ ๊ฒฐ๊ณผ๊ฐ์ ๋ํด ์ถ๊ฐ ๋์(์: ํํน, ๋ฉ๋ชจ๋ฆฌ ํจ์น ๋ฑ)์ ๊ณ ๋ คํด ๋ณผ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํ๊น ํจ์์ offset์ด ๋งค ๋น๋๋ง๋ค ๋ฌ๋ผ์ ธ๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ๋์ค์ด์ ๋ธํ ๊ฒฐ๊ณผ๊ฐ์ ๋ํด ์ถ๊ฐ ๋์์ ์ํํ๋ ๊ฒ์ด๊ณ , ๋ณดํต ๋์ค์ด์ ๋ธํ ๊ฒฐ๊ณผ๊ฐ์ ์์ค ์ฝ๋๊ฐ ๋ณํ์ง ์๋ ํ ๋์ผํ ํํ๋ฅผ ๋ณด์ด๊ธฐ ๋๋ฌธ์ด์ฃ .
์๋ฅผ ๋ค์ด 'libxxx.so'๋ผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ฉ๋ชจ๋ฆฌ์์ AA AA AA AA BB BB BB BB CC CC CC CC DD DD DD DD
ํจํด์ ์ค์บํฉ๋๋ค. ํด๋น ํจํด์ด ๋ฐ๊ฒฌ๋ ์ฃผ์์์ 0xc๋งํผ ๋จ์ด์ง ์์น๋ฅผ ๋์ค์ด์
๋ธํ๋ฉด ํญ์ ์ด๋ค ํจ์๋ก branchํ๋ b #0xabcdef
์
๋๋ค. 0xabcdef
ํจ์๋ ๋ถํ์ํ ๊ธฐ๋ฅ์ด๋ฏ๋ก ๋ฉ๋ชจ๋ฆฌ ํจ์น๋ฅผ ํตํด ์๋ํ์ง ์๋๋ก ํ๊ณ ์ถ์ต๋๋ค. ๋ค์์ ์ด์ ๋ํ ์์ ์ฝ๋์
๋๋ค.
#include <jni.h>
#include <string>
#include <stdio.h>
#include <inttypes.h>
#include <android/log.h>
#include "include/frida-gum.h"
#ifndef LOG_TAG
#define LOG_TAG "[nhncloud]"
#endif
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
// disassemble using capstone api
static void
disassemble (const guint8* code, gsize size, guint64 address, std::string& mnemonic, std::string& op_str)
{
csh capstone;
cs_insn * insn;
#ifdef __aarch64__
cs_open (CS_ARCH_ARM64, CS_MODE_ARM, &capstone);
#elif __arm__
cs_open (CS_ARCH_ARM, static_cast<cs_mode>(CS_MODE_ARM | CS_MODE_THUMB), &capstone);
#endif
cs_option (capstone, CS_OPT_DETAIL, CS_OPT_ON);
insn = cs_malloc (capstone);
while (cs_disasm_iter (capstone, &code, &size, &address, insn))
{
op_str = std::string(insn->op_str);
mnemonic = std::string(insn->mnemonic);
}
cs_free (insn, 1);
cs_close (&capstone);
}
int mem_scan_match_count = 0;
static gboolean
mem_scan_match_func (GumAddress address, gsize size, gpointer user_data)
{
mem_scan_match_count++;
if (mem_scan_match_count == 1)
{
unsigned char* data;
gsize n_bytes_read;
LOGD("match at %p", (void*)address);
data = gum_memory_read(reinterpret_cast<gconstpointer>(address + 0xc), 4, &n_bytes_read);
std::string op_str, mnemonic;
disassemble(data, n_bytes_read, (address + 0xc), mnemonic, op_str);
// op_str is "#0xabcdef"
size_t pos = op_str.find("0x");
std::string hex_str = op_str.substr(pos + 2);
uint64_t value = std::stoull(hex_str, <span class="hljs-literal">nullptr, 16);
// memory patch
const guint8 patch[] = {0xc0, 0x03, 0x5f, 0xd6};
gum_memory_write((void*)value, patch, 4);
return TRUE;
}
else
{
return FALSE;
}
}
void mem_scan_with_pattern(const GumModuleDetails* m, const char* mem_scan_pattern)
{
GumMatchPattern* mem_pattern = gum_match_pattern_new_from_string(mem_scan_pattern);
gum_try_mprotect(reinterpret_cast<gpointer>(m->range->base_address), m->range->size, GUM_PAGE_RWX);
gum_memory_scan(m->range, mem_pattern, mem_scan_match_func, <span class="hljs-literal">NULL);
}
__attribute__((constructor))
void native_init(void)
{
gum_init_embedded ();
LOGD("frida-gum initialized!");
uint64_t libxxx_base = gum_module_find_base_address("libxxx.so");
const GumModuleDetails* m = gum_module_map_find(gum_module_map_new(), libxxx_base);
// scan memory pattern
const char* mem_scan_pattern = "AA AA AA AA BB BB BB BB CC CC CC CC DD DD DD DD";
mem_scan_with_pattern(m, mem_scan_pattern);
}
๋๊ฐ๋ฉฐ
์ด ๊ธ์์๋ ๋์ค์ด์ ๋ธ ๋๊ตฌ๋ฅผ ๋ง๋ค๊ฑฐ๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ฐํ์ ์ ๋์ค์ด์ ๋ธํ๋ ๋ฐ Capstone-engine์ ํ์ฉํด ๋ณด๋ ์๋ฅผ ๋ค๋ค์ต๋๋ค. ์ง์ ์ฌ์ฉํด ๋ณด๋ API๋ ๊ฐ๋จํ๊ณ ์ง๊ด์ ์ด์ด์ ๋งค์ฐ ์ ์ฉํด ๋ณด์์ต๋๋ค. ์์ ์๊ฐํด ๋๋ฆฐ ๊ณต์ ํํ์ด์ง์์๋ ๋ค์ํ ์๋ฃ๋ฅผ ์ ๊ณตํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด๋ ค์ ์์ด ์ฌ์ฉํด ๋ณด์ค ์ ์์ ๊ฑฐ๋ผ ์๊ฐ๋ฉ๋๋ค. ๊ธด ๊ธ์ ์ฝ์ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค. ๐