Jaeho Choi

59 papers A* 5A 4B 2C 3Misc 1Journal 26Unranked 18
YearRankTypeTitle / Venue / Authors
2025 J jnl
CoRR
Jaeho Choi, Hyeri Kim, Kwang-Ho Kim, Jaesung Lee
2025 J jnl
CoRR
Asra Ali, Jaeho Choi, Bryant Gipson, Shruthi Gorantala, Jeremy Kun, Wouter Legiest, Lawrence Lim, Alexander Viand, Meron Zerihun Demissie, Hongren Zheng
2025 Misc conf
ICASSP
Shubo Yang, Soheil Hor, Jaeho Choi, Amin Arbabian
2025 A* conf
CVPR
Jaeho Choi, Soheil Hor, Shubo Yang, Amin Arbabian
2024 J jnl
Phys. Commun.
Junhao Duan, Jinyuan Gu, Wei Duan, Jaeho Choi
2024 J jnl
IEEE Internet Things Mag.
Xiaohui Gu, Wei Duan, Guoan Zhang, Miaowen Wen, Jaeho Choi, Pin-Han Ho
2024 J jnl
IEEE Wirel. Commun. Lett.
Xiaohui Gu, Guoan Zhang, Wei Duan, Jaeho Choi, Miaowen Wen, Pin-Han Ho
2024 J jnl
CoRR
Nayoung Choi, Youngjune Lee, Gyu-Hwung Cho, Haeyu Jeong, Jungmin Kong, Saehun Kim, Keunchan Park, Jaeho Choi, Sarah Cho, Inchang Jeong, Gyohee Nam, Sunghoon Han, Wonil Yang
2024 conf
EMNLP (Industry Track)
Nayoung Choi, Youngjune Lee, Gyu-Hwung Cho, Haeyu Jeong, Jungmin Kong, Saehun Kim, Keunchan Park, Sarah Cho, Inchang Jeong, Gyohee Nam, Sunghoon Han, Wonil Yang, Jaeho Choi
2024 J jnl
Phys. Commun.
Xu Fan, Wei Duan, Jaeho Choi
2024 J jnl
IEEE Access
Jaeho Choi, Jongwon Park, Kunsoo Huh
2023 J jnl
J. Ambient Intell. Humaniz. Comput.
Dogun Kim, Jaeho Choi, Sangyoon Ahn, Eunil Park
2023 J jnl
IEEE Wirel. Commun. Lett.
Xiaohui Gu, Guoan Zhang, Wei Duan, Miaowen Wen, Jaeho Choi, Pin-Han Ho
2023 J jnl
IEEE Access
Kyusang Yoon, Jaeho Choi, Kunsoo Huh
2023 J jnl
Inf. Sci.
Jaewan Moon, Yoonki Jeong, Dong-Kyu Chae, Jaeho Choi, Hyunjung Shim, Jongwuk Lee
2023 J jnl
IEEE Trans. Cogn. Commun. Netw.
Guoan Zhang, Xiaohui Gu, Wei Duan, Miaowen Wen, Jaeho Choi, Feifei Gao, Pin-Han Ho
2023 A* conf
NeurIPS
Soheil Hor, Shubo Yang, Jaeho Choi, Amin Arbabian
2023 J jnl
IEEE Trans. Consumer Electron.
Siyu Chen, Yancheng Ji, Yan Jiang, Wei Duan, Jaeho Choi, Guoan Zhang, Pin-Han Ho
2023 A conf
CIKM
Jaeho Choi, Yura Kim, Kwang-Ho Kim, Sung-Hwa Jung, Ikhyun Cho
2023 J jnl
IEEE Trans. Intell. Transp. Syst.
Biting Zhuo, Wei Duan, Juping Gu, Xiaohui Gu, Guoan Zhang, Yancheng Ji, Jaeho Choi, Miaowen Wen
2022 A* conf
ICDE
Hongjun Lim, Yeon-Chang Lee, Jin-Seo Lee, Sanggyu Han, Seunghyeon Kim, Yeon Jeong Jeong, Changbong Kim, Jaehun Kim, Sunghoon Han, Solbi Choi, Hanjong Ko, Dokyeong Lee, Jaeho Choi, Yungi Kim, Hong-Kyun Bae, Taeho Kim, JeeWon Ahn, Hyun-Soung You, Sang-Wook Kim
2022 J jnl
IEEE Wirel. Commun. Lett.
Mingxing Wang, Wei Duan, Guoan Zhang, Miaowen Wen, Jaeho Choi, Pin-Han Ho
2022 J jnl
CoRR
Jaeho Choi, Yura Kim, Kwang-Ho Kim, Sung-Hwa Jung, Ikhyun Cho
2021 conf
ICOIN
Jaeho Choi, Seunghyeok Oh, Joongheon Kim
2021 J jnl
Inf. Sci.
Yeon-Chang Lee, Taeho Kim, Jaeho Choi, Xiangnan He, Sang-Wook Kim
2021 conf
ICOIN
Joongheon Kim, Myungjae Shin, Dohyun Kim, Soohyun Park, Yeongeun Kang, Junghyun Kim, Haemin Lee, Won Joon Yun, Jaeho Choi, Seunghoon Park, Seunghyeok Oh, Jaesung Yoo
2021 conf
ICOIN
Jaeho Choi, Seunghyeok Oh, Soohyun Park, Jong-Kook Kim, Joongheon Kim
2021 conf
ICOIN
Seunghyeok Oh, Jaeho Choi, Jong-Kook Kim, Joongheon Kim
2020 conf
ICTC
Seunghyeok Oh, Jaeho Choi, Joongheon Kim
2020 J jnl
Trans. Emerg. Telecommun. Technol.
Wenjun Yu, Jaeho Choi
2020 conf
ICTC
Jaeho Choi, Joongheon Kim
2020 J jnl
CoRR
Jaeho Choi, Joongheon Kim
2020 J jnl
CoRR
Jaeho Choi, Seunghyeok Oh, Joongheon Kim
2020 conf
ICOIN
Jaeho Choi, Seunghyeok Oh, Joongheon Kim
2019 conf
ICTC
Jaeho Choi, Joongheon Kim
2019 A* conf
ICDE
Kyung-Jae Cho, Yeon-Chang Lee, Kyungsik Han, Jaeho Choi, Sang-Wook Kim
2019 A* conf
WWW
Dong-Kyu Chae, Jin-Soo Kang, Sang-Wook Kim, Jaeho Choi
2018 conf
ICCC Workshops
Jaeho Choi, Wei Duan, Haiyang Yu, Jinjuan Ju
2017 A conf
CIKM
Keunchan Park, Jisoo Lee, Jaeho Choi
2015 C conf
ICMV
Wenjun Yu, Jaeho Choi
2015 C conf
ICMV
Abdul Wahid, Su Mi Kim, Jaeho Choi
2015 conf
ISGT Asia
Muhammad Wardi Hadi, Nanang Hariyanto, Jaeho Choi
2015 C conf
ICMV
Haiyang Yu, Jaeho Choi
2013 J jnl
Internet High. Educ.
Youngju Lee, Jaeho Choi
2013 J jnl
Br. J. Educ. Technol.
Youngju Lee, Jaeho Choi, Taehyun Kim
2012 conf
ICHIT (2)
Seungyeol Lee, Jaeho Choi, Iksoo Kim
2012 J jnl
IEEE Syst. J.
Eel-Hwan Kim, Jae-Hong Kim, Se-Ho Kim, Jaeho Choi, Kwang Y. Lee, Ho-Chan Kim
2012 conf
ICADL
Yoseop Woo, Iksoo Kim, Jaeho Choi
2012 A conf
CIKM
Jaeho Choi, W. Bruce Croft, Jin Young Kim
2012 A conf
CIKM
Jaeho Choi, W. Bruce Croft
2011 J jnl
IEICE Electron. Express
G. Kim, Jaeho Choi
2010 J jnl
IEICE Electron. Express
Yong-Sung Park, Jaeho Choi
2009 conf
ICWN
Xin Wan, Ung Heo, Ji Qiu, Jaeho Choi
2009 conf
ICWN
Ji Qi, Ung Heo, Di Zhang, Jaeho Choi
2008 conf
ICWN
Ung Heo, Mamata Coirala, Qiu Peng, Jaeho Choi
2008 conf
ICWN
Mamata Koirala, Ung Heo, Qiu Peng, Jaeho Choi
2007 conf
IWSOS
Ung Heo, Deepak G. C., Jaeho Choi
2007 B conf
MASS
Zheng Wen, Ung Heo, Jaeho Choi
2002 B conf
GLOBECOM
Taeyoon Park, Jaechul Lee, Youngshin Ahn, Seungphil Lee, Jaeho Choi
redb/extractors/apk_extractors/apk_dex.py
← Index redb/extractors/apk_extractors/apk_dex.py python
import hashlib
import inspect
import json
from collections import Counter
from datetime import datetime, timezone
from typing import Any

import tlsh

from redb.extractors.enum import Tag
from redb.extractors.apk_extractor import APKExtractor
from redb.models.dataclasses import APKDexFile

# Sensitive API patterns categorized for malware analysis
SENSITIVE_API_CATEGORIES = {
    "reflection": [
        "Ljava/lang/reflect/Method;->invoke",
        "Ljava/lang/reflect/Field;->get",
        "Ljava/lang/reflect/Field;->set",
        "Ljava/lang/reflect/Constructor;->newInstance",
        "Ljava/lang/Class;->forName",
        "Ljava/lang/Class;->getMethod",
        "Ljava/lang/Class;->getDeclaredMethod",
        "Ljava/lang/Class;->getDeclaredField",
        "Ljava/lang/ClassLoader;->loadClass",
    ],
    "crypto": [
        "Ljavax/crypto/Cipher;->getInstance",
        "Ljavax/crypto/Cipher;->init",
        "Ljavax/crypto/spec/SecretKeySpec;-><init>",
        "Ljavax/crypto/spec/IvParameterSpec;-><init>",
        "Ljava/security/MessageDigest;->getInstance",
        "Ljava/security/KeyStore;->getInstance",
        "Ljavax/crypto/Mac;->getInstance",
    ],
    "dynamic_loading": [
        "Ldalvik/system/DexClassLoader;-><init>",
        "Ldalvik/system/PathClassLoader;-><init>",
        "Ldalvik/system/InMemoryDexClassLoader;-><init>",
        "Ldalvik/system/BaseDexClassLoader;-><init>",
        "Ljava/lang/Runtime;->exec",
        "Ljava/lang/ProcessBuilder;->start",
    ],
    "telephony": [
        "Landroid/telephony/TelephonyManager;->getDeviceId",
        "Landroid/telephony/TelephonyManager;->getSubscriberId",
        "Landroid/telephony/TelephonyManager;->getLine1Number",
        "Landroid/telephony/TelephonyManager;->getSimSerialNumber",
        "Landroid/telephony/TelephonyManager;->getNetworkOperator",
        "Landroid/telephony/TelephonyManager;->getSimOperator",
    ],
    "sms": [
        "Landroid/telephony/SmsManager;->sendTextMessage",
        "Landroid/telephony/SmsManager;->sendMultipartTextMessage",
        "Landroid/telephony/SmsManager;->sendDataMessage",
    ],
    "network": [
        "Ljava/net/HttpURLConnection;->connect",
        "Ljava/net/URL;->openConnection",
        "Lokhttp3/OkHttpClient;-><init>",
        "Lokhttp3/Request$Builder;->build",
        "Lorg/apache/http/client/HttpClient;->execute",
        "Landroid/webkit/WebView;->loadUrl",
        "Landroid/webkit/WebView;->setWebViewClient",
    ],
    "native": [
        "Ljava/lang/System;->loadLibrary",
        "Ljava/lang/System;->load",
        "Ljava/lang/Runtime;->loadLibrary",
    ],
    "device_info": [
        "Landroid/os/Build;->FINGERPRINT",
        "Landroid/os/Build;->MODEL",
        "Landroid/os/Build;->MANUFACTURER",
        "Landroid/os/Build;->PRODUCT",
        "Landroid/os/Build;->BRAND",
        "Landroid/os/Build;->DEVICE",
        "Landroid/os/Build;->HARDWARE",
        "Landroid/os/Build;->SERIAL",
        "Landroid/os/Build$VERSION;->SDK_INT",
        "Landroid/provider/Settings$Secure;->getString",
    ],
    "file_io": [
        "Ljava/io/FileOutputStream;-><init>",
        "Ljava/io/FileInputStream;-><init>",
        "Landroid/content/SharedPreferences;->edit",
        "Landroid/database/sqlite/SQLiteDatabase;->execSQL",
        "Landroid/database/sqlite/SQLiteDatabase;->rawQuery",
    ],
    "ipc": [
        "Landroid/content/ContentResolver;->query",
        "Landroid/content/ContentResolver;->insert",
        "Landroid/content/ContentResolver;->delete",
        "Landroid/content/Intent;-><init>",
        "Landroid/content/Context;->sendBroadcast",
        "Landroid/content/Context;->startService",
        "Landroid/content/Context;->bindService",
    ],
}


class APKDexExtractor(APKExtractor):

    def __init__(
        self, filepath, log, exporters=None, index_prefix=None,
        known_benign=False, known_malicious=False,
        apk=None,
    ):
        super().__init__(
            filepath, log, exporters, index_prefix,
            known_benign, known_malicious, apk,
        )
        self.dex_files = []
        self.log.debug(inspect.currentframe().f_code.co_name)

    def tag(self):
        return Tag.APK_DEX.value

    def _analyze_api_usage(self, dex):
        """Categorize sensitive API calls found in DEX bytecode."""
        api_usage = {cat: set() for cat in SENSITIVE_API_CATEGORIES}

        try:
            for method in dex.get_encoded_methods():
                code = method.get_code()
                if not code:
                    continue
                try:
                    bytecode = code.get_bc()
                    if not bytecode:
                        continue
                    for instruction in bytecode.get_instructions():
                        op_name = instruction.get_name()
                        if not op_name or not op_name.startswith("invoke"):
                            continue
                        output = instruction.get_output()
                        if not output:
                            continue
                        for category, patterns in SENSITIVE_API_CATEGORIES.items():
                            for pattern in patterns:
                                if pattern in output:
                                    api_usage[category].add(output.strip())
                                    break
                except Exception:
                    continue
        except Exception as e:
            self.log.warning(f"Error analyzing API usage: {e}")

        # Convert sets to sorted lists
        return {cat: sorted(calls) for cat, calls in api_usage.items() if calls}

    def _compute_obfuscation_indicators(self, classes, methods):
        """Compute obfuscation indicators from class/method names."""
        class_names = []
        for cls in classes:
            try:
                name = cls.get_name()
                if name:
                    class_names.append(name)
            except Exception:
                continue

        method_names = []
        for m in methods:
            try:
                name = m.get_name()
                if name and name not in ("<init>", "<clinit>"):
                    method_names.append(name)
            except Exception:
                continue

        if not class_names:
            return None

        # Short class names: extract just the class part from Dalvik notation
        short_class = 0
        for n in class_names:
            simple = n.split("/")[-1].rstrip(";")
            if len(simple) <= 2:
                short_class += 1

        short_method = sum(1 for n in method_names if len(n) <= 2)

        return {
            "short_class_names_pct": round(short_class / max(len(class_names), 1), 4),
            "short_method_names_pct": round(short_method / max(len(method_names), 1), 4),
            "non_ascii_identifiers": sum(1 for n in class_names if not n.isascii()),
            "avg_class_name_length": round(
                sum(len(n) for n in class_names) / max(len(class_names), 1), 2
            ),
        }

    def _compute_top_packages(self, classes):
        """Compute top packages by class count."""
        package_counter = Counter()
        for cls in classes:
            try:
                name = cls.get_name()  # "Lcom/example/foo/Bar;"
                if not name:
                    continue
                parts = name[1:].replace("/", ".").rsplit(".", 1)
                if len(parts) > 1:
                    package = parts[0]
                else:
                    package = "(default)"
                package_counter[package] += 1
            except Exception:
                continue

        return [
            {"package": pkg, "class_count": count}
            for pkg, count in package_counter.most_common(20)
        ]

    def extract(self):
        if not self._is_valid_apk():
            self.log.error(f"Invalid APK for {self.hash.sha256}")
            return None

        from androguard.core.dex import DEX

        try:
            dex_names = list(self.apk.get_dex_names() or [])
        except Exception as e:
            self.log.warning(f"Error getting DEX names for {self.hash.sha256}: {e}")
            dex_names = []

        try:
            dex_buffers = list(self.apk.get_all_dex() or [])
        except Exception as e:
            self.log.error(f"Error getting DEX buffers for {self.hash.sha256}: {e}")
            return None

        if not dex_buffers:
            self.log.debug("No DEX files found in APK")
            return None

        self.dex_files = []
        for i, dex_data in enumerate(dex_buffers):
            dex_name = dex_names[i] if i < len(dex_names) else f"classes{i}.dex"

            dex_sha256 = hashlib.sha256(dex_data).hexdigest()
            dex_tlsh = None
            if len(dex_data) >= 50:
                try:
                    dex_tlsh = tlsh.hash(dex_data) or None
                except Exception:
                    pass

            try:
                d = DEX(dex_data)
            except Exception as e:
                self.log.warning(f"Failed to parse DEX {dex_name}: {e}")
                continue

            try:
                classes = list(d.get_classes() or [])
            except Exception as e:
                self.log.warning(f"Error getting classes from {dex_name}: {e}")
                classes = []
            try:
                methods = list(d.get_methods() or [])
            except Exception as e:
                self.log.warning(f"Error getting methods from {dex_name}: {e}")
                methods = []
            try:
                strings = list(d.get_strings() or [])
            except Exception as e:
                self.log.warning(f"Error getting strings from {dex_name}: {e}")
                strings = []

            try:
                top_packages = self._compute_top_packages(classes)
            except Exception as e:
                self.log.warning(f"Error computing top packages for {dex_name}: {e}")
                top_packages = []
            try:
                api_usage = self._analyze_api_usage(d)
            except Exception as e:
                self.log.warning(f"Error analyzing API usage for {dex_name}: {e}")
                api_usage = {}
            try:
                obfuscation_indicators = self._compute_obfuscation_indicators(classes, methods)
            except Exception as e:
                self.log.warning(f"Error computing obfuscation indicators for {dex_name}: {e}")
                obfuscation_indicators = None

            self.dex_files.append(APKDexFile(
                filename=dex_name,
                sha256=dex_sha256,
                class_count=len(classes),
                method_count=len(methods),
                string_count=len(strings),
                tlsh=dex_tlsh,
                top_packages=top_packages,
                api_usage=api_usage if api_usage else None,
                obfuscation_indicators=obfuscation_indicators,
            ))

        return self.dex_files if self.dex_files else None

    def prepare_export_data(self, exporter_type: str) -> Any:
        if exporter_type == "ClickHouseExporter":
            if not self.dex_files:
                return None

            current_time = datetime.now(timezone.utc)

            # DEX table: one row per DEX file
            dex_data = []
            for dex in self.dex_files:
                dex_data.append([
                    self.sha256,
                    dex.sha256,
                    dex.filename,
                    dex.tlsh,
                    dex.class_count,
                    dex.method_count,
                    dex.string_count,
                    json.dumps(dex.top_packages) if dex.top_packages else None,
                    json.dumps(dex.obfuscation_indicators) if dex.obfuscation_indicators else None,
                    current_time,
                ])

            # API usage table: one row per category per DEX
            api_data = []
            for dex in self.dex_files:
                if dex.api_usage:
                    for category, api_calls in dex.api_usage.items():
                        api_data.append([
                            self.sha256,
                            dex.sha256,
                            category,
                            api_calls,
                            current_time,
                        ])

            return {
                'multi_table': True,
                'dex': {
                    'table': 'redb_apk_dex',
                    'data': dex_data,
                    'column_names': [
                        'sha256', 'dex_sha256', 'dex_filename', 'dex_tlsh',
                        'dex_class_count', 'dex_method_count', 'dex_string_count',
                        'dex_top_packages', 'dex_obfuscation_indicators',
                        'analysis_date',
                    ],
                    'column_type_names': [
                        'FixedString(64)', 'FixedString(64)', 'String', 'Nullable(String)',
                        'UInt32', 'UInt32', 'UInt32',
                        'Nullable(String)', 'Nullable(String)',
                        "DateTime64(3, 'UTC')",
                    ],
                },
                'api_usage': {
                    'table': 'redb_apk_dex_api_usage',
                    'data': api_data,
                    'column_names': [
                        'sha256', 'dex_sha256', 'api_category',
                        'api_calls', 'analysis_date',
                    ],
                    'column_type_names': [
                        'FixedString(64)', 'FixedString(64)', 'LowCardinality(String)',
                        'Array(String)', "DateTime64(3, 'UTC')",
                    ],
                },
            }

    def get_clickhouse_table(self) -> str:
        return "redb_apk_dex"