/
Ransomware Containment

.Net 어셈블리를 사용하는 랜섬웨어 기법 이해하기: EXE 어셈블리 대 DLL 어셈블리

이 시리즈의 1부에서는 멀웨어, 특히 랜섬웨어가 사용하는 몇 가지 기법에 대해 살펴보았습니다. 앞서 살펴본 것처럼 다운로더, 드로퍼, 로더, 인코딩 및 암호화와 같은 개별 기술은 모두 .Net (닷넷) 소프트웨어 프레임워크 및 기타 여러 프로그래밍 프레임워크와 코드 언어에서 제공하는 합법적이고 프로그래밍 가능한 기능입니다. 아래는 이전 글에서 설명한 몇 가지 기법을 모아놓은 것입니다.

이 두 번째 기사에서는 Microsoft .Net의 프레임워크를 통해 어셈블리의 기본 사항을 살펴봅니다. C# 프로그래밍 코드와 같은 초기 하이레벨 코드에서 이러한 기능이 최종적으로 실행되는 방식을 가능하게 하는 어셈블리(EXE와 DLL)와 그 관계의 차이점에 대해 자세히 살펴보겠습니다. 이전 글에서 소개한 코드를 사용하여 이러한 차이점과 관계를살펴보겠습니다‍.

Microsoft .Net이란 무엇인가요?

Microsoft .Net은 여러 프로그래밍 언어를 지원하고 다양한 운영 체제를 대상으로 하도록 설계된 소프트웨어 개발 프레임워크입니다. C#(C 샤프 발음)과 같은 지원되는 프로그래밍 언어는 관리 코드(관리되지 않는 코드 또는 네이티브 코드와 반대되는 개념)로 컴파일되고 실행됩니다. 이를 위해 .Net은 대상 플랫폼에 직접 코드를 실행하지 않고 전용 가상 머신에서 코드를 실행합니다. 이 가상 머신을 .Net 공용 언어 런타임(CLR)이라고 합니다. .Net이 지원하는 C#, VB.Net, F#과 같은 모든 다른 프로그래밍 언어에서 컴파일되거나 어셈블된 코드를 최종적으로 실행하는 공통 중개자라고 생각할 수 있습니다. 아래 예시는 이전 글의 C# 프로그래밍 언어 코드를 보여줍니다.

관리 코드란 위의 상위 레벨 C# 프로그래밍 언어 코드와 F#, VB.Net과 같은 다른 언어 코드가 먼저 중간 언어(IL)로 컴파일되는 것을 의미합니다. 위에 표시된 C# 고급 코드는 아래 이미지에 표시된 중급 언어 지침으로 컴파일됩니다. 이 코드는 저수준 어셈블리 프로그래밍 구문과 유사합니다.

그런 다음 이 중간 언어(IL)는 해당 머신 플랫폼을 대상으로 하는 네이티브 또는 머신 코드로 추가 컴파일됩니다. 이 컴파일은 JIT(Just-in-Time) 컴파일러라는 또 다른 .Net 컴포넌트에 의해 수행됩니다.

네이티브 또는 머신 코드는 특정 컴퓨터의 프로세서(CPU)가 이해하는 명령어(0과 1)의 집합입니다. 이 마지막 단계는 JIT를 포함하는 CLR(공용 언어 런타임)에서 관리합니다. CLR은 .Net 런타임 환경 또는 가상 머신입니다. Java는 중개 런타임이라는 개념을 사용하는 또 다른 소프트웨어 프레임워크입니다. Java 가상 머신과 마찬가지로 .Net 플랫폼을 독립적으로 만드는 주요 부분입니다. .Net  코드를 관리 코드라고 부르는 이유는 프로그래밍 코드가 컴퓨터의 CPU에서 직접 실행되는 것이 아니라 중개자 CLR에 의해 관리되기 때문입니다.

.Net에서 관리되는 코드의 장점은 자동 메모리 관리 및 가비지 컬렉션입니다. 즉, 개발자는 C 또는 C++ 코드의 경우처럼 시스템 리소스를 절약하기 위해 코드에서 컴퓨터 메모리를 할당하고 할당 해제하는 것에 대해 걱정할 필요가 없습니다. .Net에는 할당 해제된 메모리를 처리하기 위해 주기적으로 실행되는 가비지 수집기가 있습니다. 필요할 때 프로그래머가 호출할 수도 있습니다. 아래 다이어그램은 .Net 애플리케이션의 아키텍처를 보여줍니다.

이와 달리 VB6, C, C++와 같은 비.Net 컴파일러는 하이레벨 코드를 대상 플랫폼(OS 및 CPU)의 머신 코드로 직접 컴파일합니다. 따라서 결과 실행 파일 또는 코드 어셈블리는 컴파일러의 대상 머신 플랫폼에 연결됩니다. 관리되지 않는 코드 또는 네이티브 코드라고도 합니다. 구조적으로 다르지만, 어셈블리의 코드, 특히 네이티브 코드로 개발된 DLL을 Interop Marshalling(플랫폼 호출)이라는 기능을 사용하여.Net 관리형 애플리케이션에서 사용할 수 있습니다. 예를 들어 네이티브 Windows 운영 체제 DLL을 사용하거나 일부 하위 수준의 운영 체제 기능을 활성화하기 위해 관리되는 .Net 애플리케이션에서 참조되는 C++로 작성된 코드와 같은 외부 라이브러리를 사용하는 경우가 이에 해당합니다. 이 경우 .Net 자체는 Windows 운영 체제가 의존하는 네이티브 DLL을 안전하게 감싸는 래퍼로 생각할 수 있으며, 그 대부분은 실제로 C++로 작성됩니다.↪CF_200D↩

.Net 어셈블리란 무엇인가요?

Microsoft는 .Net 어셈블리를 단일 배포 단위로 설명합니다. 즉, 어셈블리는 호환되는 모든 .Net 대상 플랫폼에서 실행할 수 있는 형태로 컴파일(조립)된 다양한 유형의 코드 및 관련 파일의 모음입니다. 실행은 .Net의 공용 언어 런타임에 의해 수행됩니다. Windows 운영 체제에서 어셈블리의 예로는 실행 파일(.exe)과 클래스 라이브러리 또는 동적 링크 라이브러리(.dll) 파일이 있습니다.  

아래 예제 코드 이미지를 자세히 살펴보면 왼쪽에 C# 실행 어셈블리가 있고 오른쪽에 또 다른 C# DLL(클래스 라이브러리라고도 함) 어셈블리 코드가 있습니다. 실행 코드는 DLL 파일을 참조한 다음 실행 중에 DLL 코드에서 특정 메서드(함수)를 호출합니다. 이러한 참조 및 호출은 아래 이미지에 강조 표시되어 있습니다. 이 글의 뒷부분에서 두 코드에 대한 자세한 내용을 설명하겠습니다. 또한 이 시리즈에서는 이 조합이 악의적인 목적으로 어떻게 사용될 수 있는지 보여드리겠습니다.

다음 예제에서는 실행 코드에서 DLL 파일을 수동으로 참조합니다. 즉, 실행 코드의 컴파일 시간 동안 코드(모듈, 클래스 및 메서드로 구성)뿐만 아니라 DLL 및 해당 메타데이터에 대한 관련 정보가 참조됩니다.

공유 라이브러리인 DLL 코드는 자체적으로 직접 실행할 수 없습니다. 코드 관점에서 볼 때 DLL에는 실행할 기본 시작점 기능이 없기 때문에 실행 파일(.exe) 코드가 설정된 방식으로 독립 실행형 코드로 실행할 수 없기 때문입니다. 예를 들어, 아래 오류 메시지는 컴파일러에서 클래스 라이브러리 또는 DLL 파일을 직접 실행하려고 할 때 발생하는 결과를 보여줍니다.

반면 실행 코드는 실행이 시작되는 주요 진입점 함수 또는 메서드가 있지만, DLL은 주로 다른 어셈블리에서 참조하는 코드 블록의 라이브러리이므로 주요 진입점 함수가 실제로 필요하지 않습니다.

참조가 완료되면 관심 있는 DLL 파일의 특정 코드를 호출하여 실행할 수 있습니다. 이전 글에서 살펴본 것처럼 아래의 코드 예제(EXE 및 DLL)는 이 점을 반복적으로 설명합니다.  

실행 가능한 애플리케이션이 실행되고 참조한 DLL의 코드를 호출하여 다음 이미지와 같은 출력을 생성합니다.

이 간단한 프로그램은 EXE 및 DLL과 같은 .Net 어셈블리를 함께 사용할 수 있는 방법을 보여줍니다.

위에서 참조한 DLL 코드에는 입력당 두 개의 매개 변수(이름과 나이)를 받은 다음 이 정보를 사용하여 인사말 메시지를 표시하는 메서드(함수)가 있습니다. 반면 실행 코드는 명령줄에서 이름과 나이에 대한 사용자 입력 정보를 받은 다음 해당 정보를 DLL 메서드에 인수 또는 입력으로 전달하는 코드를 실행합니다. 그런 다음 EXE 애플리케이션이 사용자로부터 수집한 정보를 사용하여 DLL 코드의 메시지를 콘솔 화면에 다시 표시합니다.

.Net 어셈블리 분석

실행 파일에 대한 정적 분석을 수행하면실행을 위해 가져온 DLL 및 기타 구성 요소의 다양한 참조가 표시됩니다. 실행 어셈블리는 자체 사용자 지정 DLL 외에도 기본 코드(클래스, 유형 등)가 포함되어 있고 프로그램이 원활하게 실행되는 데 필요한 DLL인 mscorlib와 같은.Net 자체와 관련된 추가 DLL을 가져옵니다.

코드 개발 환경인 Visual Studio에서는 데이터 유형 중 하나(이 경우.Net의  System.String에서 문자열 )에서 그 출처를 역추적하여 mscorlib의 사용을 확인할 수 있습니다. 그러면 아래와 같이 해당 유형이 발생한 기본 제공 .Net 어셈블리( mscorlib )가 표시됩니다.

문자열은 프로그래밍 용어로 사용자가 입력한 후 다시 표시되는 텍스트가 저장되는 데이터 유형입니다. 또한 정적 분석을 통해 "DLL_dontNet_Assembly"라는 DLL을 확인할 수 있습니다. 사용자가 세부 정보를 입력한 후 메시지를 표시하는 "DisplayMsgMethod" 메서드가 포함된 사용자 지정 DLL입니다.

이 예제에서는 프로그램이 실행되기 전에 모든 코드를 컴파일하는 동안 사용자 지정 DLL을 수동으로 참조하고 로드했습니다. 실행 파일을 실행하는 동안 DLL을 참조할 수도 있습니다. 이는 코드를 컴파일하는 동안 원하는 DLL에 액세스할 수 없는 경우에 특히 유용할 수 있습니다. 이 프로세스를 리플렉션이라고 하며, 이를 통해 프로그램 실행 중에 .Net 어셈블리(메타데이터 및 속성)를 검사하고 그 안에 포함된 코드(모듈, 클래스, 메서드 및 속성)를 사용할 수 있습니다. 이 기법은 반사적 DLL 인젝션 공격으로 알려진 악의적인 의도를 위해 조정될 수도 있습니다.↪cf_200D↩

또한.Net 어셈블리(실행 파일 및 클래스 라이브러리)는 어셈블리에 대한 메타데이터가 포함된 매니페스트 파일과 공통 언어 런타임이.Net을 실행할 수 있는 모든 호환 플랫폼에서 어셈블리를 실행할 수 있도록 하는 IL(중간 언어) 코드로 구성됩니다. 아래 이미지는 두 가지 어셈블리(EXE 및 DLL)의 IL 어셈블리 지침과 매니페스트 구조를 보여줍니다. 매니페스트 파일에는 버전 번호, 설명 등과 같은 .Net 어셈블리에 대한 메타데이터가 포함되어 있습니다.

이제 .Net 소프트웨어 프레임워크와 관련 어셈블리, 그리고 이들이 서로 어떻게 상호 작용할 수 있는지에 대한 기본적인 이해가 있어야 합니다.

다음 글에서는 지금까지 논의하고 배운 기술과 기능을 하나의 악성 랜섬웨어 실행 파일에 적용해보겠습니다.

일루미오 제로 트러스트 세분화가 랜섬웨어 침해를 차단하는 데 어떻게 도움이 되는지 자세히 알아보세요.

관련 주제

No items found.

관련 문서

전 세계 랜섬웨어 비용 연구: 숫자가 알려주는 것
Ransomware Containment

전 세계 랜섬웨어 비용 연구: 숫자가 알려주는 것

공격자들이 어떻게 운영 중단으로 전환하고 있는지, 예방만으로는 충분하지 않은 이유, 제로 트러스트와 마이크로세그멘테이션이 랜섬웨어의 영향을 억제하는 방법에 대해 알아보세요.

방화벽만으로는 랜섬웨어 차단에 충분하지 않은 이유
Ransomware Containment

방화벽만으로는 랜섬웨어 차단에 충분하지 않은 이유

방화벽이 위협을 따라잡기에는 너무 느린 이유와 랜섬웨어 차단을 위해 마이크로세그멘테이션이 중요한 이유에 대해 알아보세요.

일루미오로 Clop 랜섬웨어 공격을 막는 방법
Ransomware Containment

일루미오로 Clop 랜섬웨어 공격을 막는 방법

클롭 랜섬웨어 변종이 어떻게 작동하는지, 조직이 마이크로세그멘테이션을 통해 공격을 차단하는 데 Illumio가 어떻게 도움이 되는지 알아보세요.

.Net 어셈블리를 사용한 랜섬웨어 기법 이해하기: 5가지 주요 기법
Ransomware Containment

.Net 어셈블리를 사용한 랜섬웨어 기법 이해하기: 5가지 주요 기법

.Net 소프트웨어 프레임워크를 사용하는 5가지 랜섬웨어 기법에 대해 알아보세요.

일루미오로 LockBit 랜섬웨어 공격을 차단하는 방법
Ransomware Containment

일루미오로 LockBit 랜섬웨어 공격을 차단하는 방법

록빗 랜섬웨어의 작동 방식과 2022년 여름, 일루미오 제로 트러스트 세분화가 록빗 랜섬웨어 공격을 차단한 방법을 알아보세요.

위반 가정.
영향 최소화.
복원력 향상.

제로 트러스트 세분화에 대해 자세히 알아볼 준비가 되셨나요?