Chang-Soo Han

42 papers A* 5A 5B 4Journal 13Unranked 15
YearRankTypeTitle / Venue / Authors
2020 J jnl
Sensors
Soo-Hoon Noh, Yong-Seok Lee, Sang-Ho Kim, Jae-Sang Cho, Chang-Soo Han, Seung-Yeol Lee, Dong-Eun Lee
2019 J jnl
IEEE Robotics Autom. Lett.
Muhammad Usman, Abdul Manan Khan, Ahmad Ali, Sheraz Yaqub, Khalil Muhammad Zuhaib, Ji Yeong Lee, Chang-Soo Han
2018 J jnl
Robotics Auton. Syst.
Ahmad Ali, Sheraz Yaqub, Muhammad Usman, Khalil Muhammad Zuhaib, Abdul Manan Khan, Ji Yeong Lee, Chang-Soo Han
2017 conf
SII
Yalun Song, Gong Zhang, Zhicheng Hou, Weijun Wang, Zheng Xu, Xing Gu, Chang-Soo Han, Anyi Huang
2017 conf
URAI
Zhicheng Hou, Weijun Wang, Gong Zhang, Chang-Soo Han
2017 conf
URAI
Jimin Liang, Gong Zhang, Weijun Wang, Zhicheng Hou, Jun Li, Xiying Wang, Chang-Soo Han
2017 conf
URAI
Jinfeng Qiu, Zhicheng Hou, Weijun Wang, Gong Zhang, Yafeng Li, Wei Feng, Chang-Soo Han
2016 J jnl
Comput. Aided Des.
Rui-Jun Yan, Jing Wu, Ji Yeong Lee, Abdul Manan Khan, Chang-Soo Han, Erdal Kayacan, I-Ming Chen
2016 J jnl
Adv. Robotics
Seungnam Yu, Hee-Don Lee, WanSoo Kim, Chang-Soo Han
2016 conf
AIM
Abdul Manan Khan, Fatima Khan, Chang-Soo Han
2016 J jnl
Adv. Robotics
Abdul Manan Khan, Muhammad Usman, Ahmad Ali, Fatima Khan, Sheraz Yaqub, Chang-Soo Han
2015 A* conf
ICRA
Abdul Manan Khan, Deok-won Yun, Mian Ashfaq Ali, Jung-Soo Han, Kyoosik Shin, Chang-Soo Han
2015 A conf
IROS
Donghwan Lim, WanSoo Kim, Hee-Don Lee, Hojun Kim, Kyoosik Shin, Taejoon Park, Ji Yeong Lee, Chang-Soo Han
2015 A* conf
ICRA
Dong-Hyung Kim, Youn-Sung Choi, Taejoon Park, Ji Yeong Lee, Chang-Soo Han
2014 J jnl
J. Syst. Control. Eng.
Rui-Jun Yan, Jing Wu, Quan Yuan, Chao Yuan, Lu-Ping Luo, Kyoosik Shin, Ji Yeong Lee, Chang-Soo Han
2014 B conf
RO-MAN
Abdul Manan Khan, Deok-won Yun, Jung-Soo Han, Kyoosik Shin, Chang-Soo Han
2013 conf
ISR
Dong-Hyung Kim, Sung-Jin Lim, Duck-Hyun Lee, Ji Yeong Lee, Chang-Soo Han
2012 conf
SII
Sang-Ho Kim, Dong-Hyung Kim, Chang-Jun Kim, Mian Ashfaq Ali, Sung-Hoon Back, Chang-Soo Han
2012 conf
SII
Lerrel Joseph Pinto, Dong-Hyung Kim, Ji Yeong Lee, Chang-Soo Han
2012 A* conf
ICRA
Byeong-Kyu Lee, Hee-Don Lee, Ji Yeong Lee, Kyoosik Shin, Jung-Soo Han, Chang-Soo Han
2012 conf
CASE
Jae-Sang You, Dong-Hyung Kim, Sung-Jin Lim, Sung-Pil Kang, Ji Yeong Lee, Chang-Soo Han
2012 conf
SII
Dongsu Shin, Minsung Kang, Seunghoon Lee, Chang-Soo Han
2012 conf
CASE
Dong-Hyung Kim, Seunghoon Lee, Minsung Kang, Bo-Ill Chun, Chang-Soo Han
2011 conf
ICAR
Hyeunseok Choi, Dongik Shin, Tae-Yul Tak, Young-Sun Ryuh, Chang-Soo Han
2011 A conf
IROS
Sarmad Shams, Dongik Shin, Jung-Soo Han, Ji Yeong Lee, Kyoosik Shin, Chang-Soo Han
2011 conf
URAI
Dong-Hyung Kim, Youngmyung Lee, Ji Yeong Lee, Gyung-Jin Park, Chang-Soo Han, Sunil K. Agrawal
2011 conf
ROBIO
Hyeunseok Choi, Dongik Shin, Young-Sun Ryuh, Chang-Soo Han
2011 B conf
Intelligent Vehicles Symposium
Dong-Hyung Kim, Chang-Jun Kim, Sang-Ho Kim, Joon-Young Choi, Chang-Soo Han
2011 conf
URAI
Chengjie Li, Chanhun Park, Jin Ho Kyung, Gwang-Jo Chung, Chang-Soo Han
2010 J jnl
Robotica
Seungyeol Lee, Seung Nam Yu, Seokjong Yu, Chang-Soo Han
2010 A conf
IROS
WanSoo Kim, Seunghoon Lee, Minsung Kang, Jung-Soo Han, Chang-Soo Han
2010 B conf
RO-MAN
Seunghoon Lee, WanSoo Kim, Minsung Kang, Jung-Soo Han, Chang-Soo Han
2010 B conf
Intelligent Vehicles Symposium
Changmook Chun, SeungBeum Suh, Chi-won Roh, Yeonsik Kang, Sungchul Kang, Jung-yup Lee, Chang-Soo Han
2010 A conf
IROS
Hyunseop Lim, Soonwoong Hwang, Kyoosik Shin, Chang-Soo Han
2007 J jnl
Auton. Robots
Seung Nam Yu, Seung Yeol Lee, Chang-Soo Han, Kye Young Lee, Sang Heon Lee
2007 J jnl
Auton. Robots
Seung Yeol Lee, Kye Young Lee, Sang Heon Lee, Jin Woo Kim, Chang-Soo Han
2007 J jnl
Auton. Robots
Seung Yeol Lee, Yong Seok Lee, Bum Seok Park, Sang Heon Lee, Chang-Soo Han
2007 J jnl
Auton. Robots
Seung Nam Yu, Seung Yeol Lee, Chang-Soo Han
2006 J jnl
J. Field Robotics
Chang-Soo Han, Seung Yeol Lee, Kye Young Lee, Bum Seok Park
2004 A* conf
ICRA
Tong-Jin Park, Chang-Soo Han, Jung-Soo Han, Hogil Lee
2001 A* conf
ICRA
Tong-Jin Park, Chang-Soo Han
1991 A conf
IROS
Chang-Soo Han, Jeffrey C. Hudgens, Delbert Tesar, Alfred E. Traver
redb/extractors/malcontent.py
← Index redb/extractors/malcontent.py python
import inspect
import json
import subprocess
from typing import Any
from datetime import datetime, timezone

from redb.extractors.enum import Tag
from redb.models.dataclasses import Malcontent
from redb.extractors.extractor import Extractor
from dotenv import load_dotenv
import os

load_dotenv(override=True)


class MalcontentExtractor(Extractor):
    """
    Extractor for malcontent tool from chainguard-dev/malcontent.

    Malcontent discovers supply-chain compromises through context, differential
    analysis, and 14,000+ YARA rules. It analyzes binaries and code to detect
    malicious content and suspicious behavioral patterns.

    Binary can be extracted from Docker image:
        docker cp $(docker create cgr.dev/chainguard/malcontent:latest):/usr/bin/mal /usr/local/bin/mal

    Stores full JSON output for materialized view extraction.
    """

    # Cache version at class level to avoid repeated subprocess calls
    _cached_version = None

    def __init__(
        self,
        filepath,
        log,
        exporters=None,
        index_prefix=None,
        elastic_index=None,
        known_benign=False,
        known_malicious=False,
    ):
        super().__init__(
            filepath,
            log,
            exporters,
            index_prefix,
            elastic_index,
            known_benign,
            known_malicious
        )
        self.malcontent = None

    @classmethod
    def _get_malcontent_version(cls, log) -> str:
        """Get malcontent version, cached at class level."""
        if cls._cached_version is not None:
            return cls._cached_version

        malcontent_path = os.getenv("MALCONTENT_PATH", "/usr/local/bin/mal")
        try:
            result = subprocess.run(
                [malcontent_path, "--version"],
                capture_output=True,
                text=True,
                timeout=10
            )
            version_output = result.stdout.strip()
            if result.returncode == 0 and version_output:
                # Parse "malcontent version v1.21.5" -> "1.21.5"
                if version_output.startswith("malcontent version v"):
                    version_output = version_output[len("malcontent version v"):]
                elif version_output.startswith("malcontent version "):
                    version_output = version_output[len("malcontent version "):]
                cls._cached_version = version_output
            else:
                cls._cached_version = "unknown"
        except Exception as e:
            log.warning(f"Could not get malcontent version: {e}")
            cls._cached_version = "unknown"

        return cls._cached_version

    def _extract_malcontent(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        TIMEOUT = int(os.getenv("MALCONTENT_TIMEOUT", "300"))
        malcontent_path = os.getenv("MALCONTENT_PATH", "/usr/local/bin/mal")

        malcontent_command = [malcontent_path, "analyze", "--format=json", self.filepath]

        import signal

        try:
            process = subprocess.Popen(
                malcontent_command,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                preexec_fn=os.setsid
            )

            try:
                stdout, stderr = process.communicate(timeout=TIMEOUT)
                if process.returncode != 0:
                    self.log.error(f"Error running malcontent, return code: {process.returncode}, stderr: {stderr}")
                    return {}
            except subprocess.TimeoutExpired:
                self.log.warning(f"The malcontent command timed out after {TIMEOUT} seconds, terminating process group")
                try:
                    os.killpg(process.pid, signal.SIGTERM)
                    try:
                        process.wait(timeout=3)
                    except subprocess.TimeoutExpired:
                        self.log.warning("Process didn't terminate with SIGTERM, sending SIGKILL")
                        os.killpg(process.pid, signal.SIGKILL)
                    process.wait()
                except (ProcessLookupError, OSError) as e:
                    self.log.warning(f"Error while killing process: {e}")
                return {}

            try:
                malcontent_output = json.loads(stdout)
            except json.JSONDecodeError as e:
                self.log.error(f"Error parsing malcontent output: {e}")
                return {}

            # Unwrap the Files/<path> structure to get the inner content
            # Structure is: {"Files": {"/path/to/file": {<actual content>}}}
            files_dict = malcontent_output.get("Files", {})
            if not files_dict:
                self.log.warning("Malcontent output has no 'Files' key")
                return {}

            # Get the first (and only) file's content
            file_content = next(iter(files_dict.values()), {})
            if not file_content:
                self.log.warning("Malcontent output has empty file content")
                return {}

            # Extract risk score and level from the unwrapped content
            risk_score = file_content.get("RiskScore", 0)
            risk_level = file_content.get("RiskLevel", "")

            version = self._get_malcontent_version(self.log)

            self.malcontent = Malcontent(
                malcontent_dump=json.dumps(file_content),
                version=version,
                risk_score=risk_score,
                risk_level=risk_level
            )
            self.log.debug(f"Malcontent analysis complete, version={version}, risk={risk_level}({risk_score})")

        except Exception as e:
            self.log.error(f"Unexpected error in malcontent extraction: {str(e)}")
            if 'process' in locals() and process.poll() is None:
                try:
                    os.killpg(process.pid, signal.SIGKILL)
                    process.wait()
                except:
                    pass
            return {}

    def prepare_export_data(self, exporter_type: str) -> Any:
        if exporter_type == "ClickHouseExporter":
            current_time = datetime.now(timezone.utc)

            data = [[
                self.sha256,
                current_time,
                self.malcontent.version,
                self.malcontent.risk_score,
                self.malcontent.risk_level,
                self.malcontent.malcontent_dump
            ]]

            column_names = [
                'sha256', 'analysis_date',
                'malcontent_version', 'malcontent_risk_score', 'malcontent_risk_level',
                'malcontent_json'
            ]

            column_type_names = [
                'FixedString(64)',
                'DateTime64(3, \'UTC\')',
                'LowCardinality(String)', 'UInt8', 'LowCardinality(String)',
                'JSON'
            ]

            return (data, column_names, column_type_names)

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

    def extract(self):
        self.log.debug(inspect.currentframe().f_code.co_name)
        try:
            self._extract_malcontent()
            return self.malcontent
        except Exception as e:
            self.log.error(f"Error extracting malcontent: {e}")
            return None

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