반응형

컨테이너 이미지의 기본 개념

컨테이너 이미지는 애플리케이션을 실행하는 데 필요한 모든 요소를 포함한

표준화된 실행 패키지 또는 "실행 환경"입니다.

컨테이너 이미지는 애플리케이션을 실행하는 데 필요한 모든 파일과 설정을 담고 있으며,

호스트 OS의 커널을 공유하면서 독립적으로 실행됩니다.

이미지는 일종의 '스냅샷'으로, 생성 후에는 변경되지 않습니다.

 

조금 더 쉽게 풀어보겠습니다.

컨테이너 이미지는 마치 여행을 위해 필요한 모든 짐을 가지고 있는 완벽하게 준비된 여행 가방과 같습니다.

이 가방에는 여행지에서 필요한 모든 것들이 들어있어 어디든지 떠날  준비가 되어 있습니다.

컨테이너 이미지는 애플리케이션을 실행하는 데 필요한 모든 파일과 설정을 담고 있으며,

마치 여행 가방이 다른 집의 침대 위에 놓여도 그 안의 내용물이 변하지 않는 것처럼,

컨테이너 이미지도 다른 컴퓨터 환경에 배치되어도 동일하게 작동합니다.

컨테이너 이미지는 컴퓨터의 '호스트 OS 커널'을 공유하며,

이는 여러 여행 가방들이 같은 항공기를 공유하는 것과 비슷하다고 볼 수 있습니다.

마지막으로,

컨테이너 이미지는 '스냅샷'으로, 여행 가방이 완벽하게 포장되어 잠겨진 후 변하지 않는 것과 같습니다.

이 이미지는 생성된 후에는 변경되지 않으며, 필요할 때마다 원본 상태 그대로 사용할 수 있습니다.

즉,

컨테이너는 소프트웨어를 효율적으로 실행하기 위해 필요한

코드, 런타임 환경, 시스템 도구, 시스템 라이브러리와 같은 모든 종속성을 포함하는 경량화된 가상화 기술입니다.

컨테이너는 애플리케이션을 격리하고 그 환경을 다른 시스템에 쉽게 이식할 수 있게 해 줍니다.

컨테이너는 전통적인 가상 머신(VM)과 비교하여 더 가벼운 가상화 형태로 간주됩니다.

가상 머신은 각각의 VM이 전체 운영 시스템을 실행하므로

상대적으로 많은 자원을 소모합니다.

반면,

컨테이너는 호스트 OS의 커널을 공유하며,

오직 애플리케이션과 그 종속성만을 포함하기 때문에

더 빠르게 시작되고, 더 적은 자원을 사용합니다.

 

VM에 대해서 아직 모르신다면 아래 글을 읽고 와주세요!

(작성 중)


컨테이너의 장점
  1. 이식성: 컨테이너는 도커와 같은 컨테이너 플랫폼에 의해 지원되며, 이로 인해 어떤 컴퓨터나 클라우드 환경에서도 동일하게 실행될 수 있습니다.
  2. 경량성: 컨테이너는 필요한 리소스만 포함하고 있기 때문에 작고, 빠르며, 효율적입니다.
  3. 격리성: 각 컨테이너는 서로 독립적으로 작동하며, 이는 서로 다른 컨테이너 간의 충돌을 방지합니다.
  4. 스케일링과 관리의 용이성: 컨테이너는 쉽게 생성, 배포, 복제, 및 삭제가 가능하여 대규모 애플리케이션과 서비스의 관리가 용이합니다.

컨테이너의 사용 사례
  • 개발 및 테스트: 개발자는 로컬 환경에서 컨테이너를 사용하여 애플리케이션을 개발하고 테스트할 수 있으며, 생산 환경과 동일한 설정을 유지할 수 있습니다.
  • 마이크로서비스 아키텍처: 컨테이너는 마이크로서비스 아키텍처의 기본 구성 요소로, 각 마이크로서비스를 독립적인 컨테이너로 배포하여 서비스의 확장성과 유지보수성을 향상시킬 수 있습니다.
  • 지속적 통합 및 지속적 배포 (CI/CD): 컨테이너는 CI/CD 파이프라인을 통해 코드 변경 사항을 쉽게 통합하고 자동으로 배포하는 데 이상적입니다.

컨테이너 기술은 현대 IT 환경에서 중요한 역할을 하며,

애플리케이션의 배포와 관리를 더욱 간편하고 효율적으로 만들어 줍니다.

특히, 도커 이미지는 컨테이너 이미지의 특별한 형태로,

도커 플랫폼에서 사용되며 표준화된 형식을 따릅니다.

도커 이미지는 이미지 레이어의 개념을 활용하여,

각 레이어가 변경 사항을 포함하므로 이미지의 효율적인 관리와 업데이트가 가능합니다.

이는 저장 공간과 데이터 전송을 최적화하며,

도커 레지스트리를 통한 이미지의 공유와 배포를 용이하게 합니다.

 

도커 이미지에 대해 더 알고 싶으시다면,

아래 링크를 참조해 주세요. 

https://jdcyber.tistory.com/68

 

도커(Docker)란 무엇인가?

도커(Docker)란 무엇인가? 도커는 컨테이너 가상화 기술을 이용해 개발자들이 프로그램을 효과적으로 배포하고관리할 수 있도록 해주는 오픈 소스 프로젝트입니다.이 기술은 각각의 애플리케이

jdcyber.tistory.com


오늘은 컨테이너 이미지에 대해 알아보며,

이 독특한 기술이 어떻게 소프트웨어 개발과 배포를 혁신적으로 변화시켰는지를 살펴보았습니다.

컨테이너 이미지는 개발자들이 어떤 환경에서도 일관된 결과를 보장하며

애플리케이션을 빠르고 효율적으로 배포할 수 있게 해 줍니다.

이러한 표준화된 실행 패키지는 앞으로도 계속해서

IT 산업에서 중요한 역할을 할 것입니다.

다음 시간에는 또 다른 흥미로운 기술 주제로 여러분을 만나 뵙겠습니다.

감사합니다!


궁금하신 사항은 댓글에 남겨주세요

댓글에 남겨주신 내용

추후 정리해서 올려드리겠습니다

구독 신청하시면 업로드 시 알려드릴게요!

-

조금이라도 도움이 되셨다면

공감&댓글 부탁드리겠습니다

감사합니다!

반응형
반응형

 

오늘은 Windows 운영 체제에서 가장 중요한

파일 형식인 Portable Executable(PE)에 대해 이야기하려 합니다.

PE 파일은 .exe, .dll, .sys 등과 같이 실행 가능한 파일들을 가리키며,

이 파일들 간의 복잡한 의존성을 분석하는 것은 소프트웨어 개발과 보안 분석에 있어 매우 중요합니다.

이번 포스팅에서는 PE 파일의 Import Table, Export Table, 그리고 Import Address Table(IAT)을 이용해서

의존성을 분석하고, 이를 그래프로 시각화하는 방법을 소개하겠습니다.


Import table과 export table 그리고 iat의 차이점

 

Import Table, Export Table,

그리고 Import Address Table (IAT)은

모두 Portable Executable (PE) 파일 형식의 구성요소입니다.

테이블이 나타내는 정보가 다르므로 각각의 목적과 기능을 이해하는 것이 중요합니다.


Import Table이란?

이 테이블은 PE 파일이 실행되기 위해 필요한

외부 라이브러리(DLL 파일)들의 정보를 담고 있습니다.

Import Table에는 각 DLL 파일의 이름과 해당 DLL에서 호출할 함수들의 목록이 포함되어 있습니다.

즉, 이 PE 파일이 실행되기 위해 어떤 외부 DLL에 의존하는지,

그리고 그 DLL에서 어떤 함수들을 사용하는지를 알려주는 테이블입니다.


Export Table이란?

이 테이블은 DLL 파일이 외부에 제공하는 함수나

변수의 정보를 담고 있습니다.

DLL 파일은 여러 개의 PE 파일에서 공유하여

사용할 수 있는 라이브러리로서,

그 안에 정의된 여러 함수들을 외부에 제공합니다.

Export Table은 이러한 함수들의 목록과

그 함수들의 주소 정보를 제공합니다.

따라서, 다른 PE 파일들이 이 DLL 파일을 어떻게

활용할 있는지를 알려주는 테이블입니다.


Import Address Table (IAT)이란?

 

이 테이블은 PE 파일이 Import Table을 통해 가져온 외부 함수들의 주소를 저장하는 곳입니다.

즉, Import Table에서 나열한 각 함수에 대한 실제 메모리 주소를 가지고 있습니다.

PE 파일이 실행되면, 로더는 이 IAT를 채워 넣어서, PE 파일이 각 함수를 호출할 때 메모리에서 바로 찾을 있도록 합니다.


Import Table은 '무엇'이 필요한지(어떤 DLL과 함수들이 필요한지),

Export Table은 '무엇'을 제공하는지(어떤 함수와 변수들을 제공하는지),

IAT는 '어디에' 있는지(각 함수의 메모리 주소는 어디인지)를 나타냅니다.

이 세 가지 테이블은 PE 파일이 외부 라이브러리와 어떻게 상호작용하는지를 이해하는데 중요한 역할을 합니다.

PE 파일 의존성 그래프 생성

 

필요한 라이브러리 작업을 수행하기 위해 pefile networkx라는 가지 파이썬 라이브러리를 사용하겠습니다.

pefile은 PE 파일을 분석하고 파싱하는데 필요한 라이브러리이며,

networkx는 그래프를 생성하고 시각화하는데 사용됩니다.

먼저, 주어진 디렉토리에서 모든 PE 파일을 찾고 이들을 파싱하여 그래프의 노드로 추가합니다.

그런 다음 각 PE 파일의 Import Table을 분석하여 필요한 DLL을 그래프에 추가하고,

이들 사이의 의존성을 간선으로 표현합니다.

PE 파일 의존성 그래프 업데이트 그 다음 단계에서는 모든 PE 파일의 Export Table을 분석합니다.

이를 통해 각 DLL이 제공하는 함수를 알 수 있습니다.

이 함수들을 사용하는 다른 PE 파일을 찾아 그래프에 의존성을 추가합니다.

IAT 정보 출력 마지막으로, 각 PE 파일의 Import Address Table(IAT)를 분석하여

각 함수가 실제로 어떤 메모리 주소에서 호출되는지를 출력합니다.

그래프 시각화 모든 정보를 바탕으로 그래프를 생성한 후에는

networkx와 matplotlib를 이용해서 그래프를 시각화합니다.

이를 통해 각 PE 파일 간의 복잡한 의존성을 한눈에 확인할 수 있습니다.

 

(아래는 예시 코드입니다)

import os
import pefile
import networkx as nx
import matplotlib.pyplot as plt

def create_dependency_graph(directory):
    G = nx.DiGraph()

    pe_files = {}

    # 모든 PE 파일을 파싱한다.
    for filename in os.listdir(directory):
        filepath = os.path.join(directory, filename)

        # PE 파일이 아닌 경우 건너뛴다.
        if not pefile.isPE(filepath):
            continue

        pe = pefile.PE(filepath)

        # 파싱한 PE 파일을 저장한다.
        pe_files[filename] = pe

        # 현재 파일 노드를 그래프에 추가
        G.add_node(filename)

    # 모든 PE 파일의 Import 정보를 통해 그래프를 만든다.
    for filename, pe in pe_files.items():
        if hasattr(pe, "DIRECTORY_ENTRY_IMPORT"):
            for entry in pe.DIRECTORY_ENTRY_IMPORT:
                dll_name = entry.dll.decode('utf-8')

                G.add_node(dll_name)
                G.add_edge(filename, dll_name)  # 현재 파일에서 DLL로 의존성 표시

                # IAT 정보를 출력한다.
                for imp in entry.imports:
                    print(f'{filename} imports function {imp.name} from {dll_name} at address {hex(imp.address)}')

    # 모든 PE 파일의 Export 정보를 통해 그래프를 업데이트한다.
    for filename, pe in pe_files.items():
        if hasattr(pe, "DIRECTORY_ENTRY_EXPORT"):
            for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols:
                # 해당 PE 파일이 export하는 함수를 사용하는 다른 PE 파일을 찾는다.
                for user_filename, user_pe in pe_files.items():
                    if hasattr(user_pe, "DIRECTORY_ENTRY_IMPORT"):
                        for entry in user_pe.DIRECTORY_ENTRY_IMPORT:
                            if entry.dll.decode('utf-8') == filename:
                                for imp in entry.imports:
                                    if imp.name == exp.name:
                                        G.add_edge(user_filename, filename)  # 다른 파일에서 현재 파일로 의존성 표시

    return G

# 디렉토리 지정 (PE 파일들이 위치한 디렉토리를 지정해야 함)
directory = './PE_files_directory'  
G = create_dependency_graph(directory)

# 그래프를 그림
nx.draw(G, with_labels=True)
plt.show()

 

정리

 

이 포스트에서는 PE 파일의 Import Table, Export Table,

그리고 IAT를 이용해 PE 파일 간의 의존성을 분석하고 시각화하는 방법을 살펴봤습니다.

 

다시 한번 정리해보면,

Import Table: PE 파일이 실행되기 위해 필요한 외부 라이브러리(DLL 파일)들의 정보
Export Table: DLL 파일이 외부에 제공하는 함수나 변수의 정보
(다른 PE 파일들이 이 DLL 파일을 어떻게 활용할 수 있는지를 알려주는 테이블)
Import Address Table (IAT): PE 파일이 Import Table을 통해 가져온 외부 함수들의 주소를 저장하는 곳

 

Import Table은 '무엇'이 필요한지

(어떤 DLL과 함수들이 필요한지)

 

Export Table은 '무엇'을 제공하는지

(어떤 함수와 변수들을 제공하는지),

 

IAT는 '어디에' 있는지

(각 함수의 메모리 주소는 어디인지)

 

이 방법을 통해 복잡한 소프트웨어 시스템의 구조를 이해하고, 문제를 분석하고, 솔루션을 찾는 데 도움이 될 수 있습니다.

다음 포스팅에서는 더 심화된 분석 기법을 적용해보겠습니다.

 

그럼, 즐겁게 코딩하시길 바랍니다!


궁금하신 사항은 댓글에 남겨주세요

댓글에 남겨주신 내용

추후 정리해서 올려드리겠습니다

구독 신청하시면 업로드 시 알려드릴게요!

-

조금이라도 도움이 되셨다면

공감&댓글 부탁드리겠습니다

감사합니다!

반응형

+ Recent posts