KOROMOON

착한 사마리아인이 되고 싶습니다.

1/18/2021

악성코드 분석가 관점에서 학습하는 데 필요한 프로그래밍 개념



악성코드 분석 교육 및 컨설팅 서비스를 제공하는 컴퓨터 보안 회사인 AGDC 서비스 사의 블로그 게시물을 번역하였으며 해당 게시물 기재일은 2020년 12월 20일 임.

링크 : 

https://agdcservices.com/blog/required-programming-concepts-to-learn-for-malware-analysts/


악성코드 분석 기술을 향상시키기 위해 프로그래밍하는 방법을 배워야 하지만 어디서부터 시작해야 할지 모름.

본 게시물에서는 악성코드 분석하는 데 시간 낭비하지 않도록 효율적인 측면에서 기재하고자 함.




( 1 ) 핵심 프로그래밍 언어


3 가지 핵심 언어를 식별하였으며 집중할 개념에 대해서 설명함.


C

x86_64 assembly

Python




( 2 ) 최종 목표


배울 실제 개념에 대해 이야기하기 전에 최종 목표가 무엇인지 파악해야 함.

목표를 모르면 언제 멈춰야 할 지 알 수 없으며 불필요한 시간을 보낼 수 있음.


악성코드 분석을 위해서는 주로 프로그래밍 코드를 읽는 방법을 배워야 함.

코드를 작성하는 것과 읽는 데 필요한 기술에는 상당한 차이가 있음.

코드를 작성하려면 API 동작 방식, 다양한 옵션 사용의 성능 영향, 효율적인 코딩 방법 등을 정확히 알아야 함.

프로그래밍을 사용하여 문제를 해결하는 방법도 알아야 함.


그러나 분석가는 악성코드를 작성하지 않음.

기능을 확인하고 침해 지표(IOC)를 식별하기 위해 이를 분석하면 됨.

코드 작성에 언급된 위 결정 사항은 악성코드 개발자가 결정함.

그러나 분석가는 코드에서 찾은 API 가 수행하는 작업을 인식하고 그 중요성을 결정하기만 하면 됨.


악성코드 바이러리를 읽는 것 외에도 악성코드 기능이 어떤 동작하는지 이해할려면 예제 소스 코드도 읽어야 함.

악성코드 분석은 주로 패턴 인식임.

일반 조건부 논리와 함께 사용되는 API 를 보기 위해 악성 어셈블리 코드를 읽음.

그런 다음 알고 있는 모든 프로그래밍 패턴과 비교하여 보고 가능성이 높은 기능을 결정함.

특정 기능을 모르면 악성코드 븐석하는 데 어려움이 있음.


그러나 작성하는 데 예외는 Python 임.

여기에서 실제로 코드를 읽는 것 외에도 Python 으로 프로그래밍하는 방법을 배워야 함.

Python 을 배우는 주된 이유 중 하나는 악성코드 분석에 도움이 되는 분석 스크립트를 작성하기 때문임.

또한, 수동으로 수행하기 어렵거나 시간이 많이 걸리는 작업을 수행하기 위해 코드를 작성하는 추가 목표가 있음.




( 3 ) 얼마나 배울 것인가?


해당 게시물에서는 배워야 할 내용에 대한 세부 사항을 나열하지만 각 주제에 대해 얼마나 배워야 하는지에 대한 질문이 남음.

이것을 정의하는데 쉬운 방법은 없음.

궁극적으로 이해 수준은 악성코드 분석 전문 지식 수준과 밀접한 관련이 있음.

프로그래밍에 대한 기본적인 이해만 가지고 있다면 최고의 리버스 엔지니어링 레벨에 도달하기가 매우 어려울 것임.

그러나 악성코드를 분석하기 전에 프로그래밍 개념을 숙달하는 데 모든 시간을 소비한다면 여전히 초보자 악성코드 분석가가 될 것임.

당신의 노력을 최적화하는 데 도움이 되는 제안을 제공할 것이지만 이는 단지 제안일 뿐임을 기억하십시오.


결국 각 주제 영역에 대해 프로그래밍 입문 책에 나열된 개념을 보다 깊이 있게 학습하는 것이 좋음.

충분한 배경 지식을 습득 한 후 새로운 질문에 대한 주제를 깊이 파헤져 나가야 함.

새로운 질문이 나오지 않을 만큼 충분히 배우길 권함.

단, 불필요한 주제가 아닌 악성코드 분석에 필요한 주제에 한에서만 학습하길 바람.




( 4 ) 모든 언어에 대한 핵심 개념


각 프로그래밍 언어에는 집중해야 할 고유한 측면이 있지만 모든 언어에 걸쳐 알아야 할 몇 가지 기본 사항이 있음.


변수

비교 연산자 (같음/작음/보다 큼)

조건부 논리 (If, If-Else 문, For/While 루프, Switch 문)

비트 연산 (and, or, xor, 오른쪽 시프트, 왼쪽 시프트,)

함수 인수 : 값으로 전달 vs 참조로 전달




( 5 ) C 프로그래밍 언어 핵심 개념


C 프로그래밍에는 이해하고 싶은 추가 개념이 있음.


포인터

구조체

특정 API


API 경우 일반적으로 악성코드에서 발견되는 기능을 수행하는 데 사용되는 API 를 배워야 함.

검색해야 하는 알려지지 않은 기능도 있지만 악성코드에서 가장 많이 사용되는 API 기본 기능을 이해해야 함.

이러한 공통 API 는 사용되는 라이브러리 호출의 80% ~ 90% 가 될 것이므로 이해하면 라이브러리 함수를 조사할 필요성을 극적으로 줄여 분석 속도를 크게 높일 수 있음.


악성코드가 수행하는 일반적인 기능 목록은 다음과 같음.

이러한 기능을 수행하는 데 사용할 수 있는 다양한 API 를 모두 알고 있어야 함.

Windows 라이브러리 API 에 집중해야 하지만 표준 C 라이브러리 API(ex. WriteFile vs fwrite)에도 익숙해야 함.

이러한 기능을 프로그래밍하는 방법에 대해 인터넷 검색하면 사용된 모든 관련 라이브러리 기능을 배울 수 있도록 다양한 프로그래밍 예제를 찾을 수 있음.


파일 작업 (검색, 읽기, 쓰기, 삭제)

레지스트리 작업 (검색, 읽기, 쓰기, 삭제)

프로세스 조작 (검색, 생성, 읽기, 쓰기, 종료)

서비스 조작 (생성, 시작, 쿼리)

네트워크 작업 (소켓 구축, 서버에 연결, 패킷 읽기/쓰기)

문자열 조작 (문자열 길이 가져오기, 하위 문자열 찾기, 문자열 복사, 형식화된 문자열 작성)

기타 작업 (메모리 할당, 메모리 비우기, Sleeping, 스레드 시작, DLL 로드, 내보내기 해결)


이 게시물 끝 부록에 이러한 기능이 사용되는 많은 공통 API 목록을 참조로 포함함.

그러나 부록은 목록일 뿐이지 API 사용 밥법과 대체 API 를 확인하려면 프로그래밍 기능을 계속 조사해야 함.




( 6 ) x86_64 assembly 핵심 개념


어셈블리를 읽을 수 있는 것은 악성코드 리버스 엔지니어링의 핵심임.

디컴파일러는 어셈블리의 C 와 유사한 표현을 제공할 수 있지만 항상 사용 가능하거나 정확하지는 않음.

분석하는 데 어셈블리를 항상 사용할 수 있으므로 어셈블리를 읽을 수 있는 것은 악성코드 리버스 엔지니어링을 할 수 있다는 것을 의미함.


먼저 레지스터에 대해 배우십시오. 다음에 대해 알아야 함.


범용 레지스터 (General Purpose Registers)

플래그 레지스터 (Flags Register)

명령 포인터 레지스터 (Instruction Pointer Register)


레지스터의 특정 바이트 참조(al vs ah vs ax vs eax vs rax)와 같은 다양한 액세스 방법을 배우십시오.


다음으로 필수 지침을 배워야 함.

x86_64 명령어 세트에는 수백 개의 명령어가 있지만 다행히 악성코드에 사용되는 명령어의 95% 는 특정 명령어에서 나옴.

이러한 각 핵심 명령어가 수행하는 작업을 정확히 기억하는 게 좋음.


학습할 핵심 명령어는 다음과 같음.


push / pop

call / ret

mov / lea / brackets operator ([])

cmp / test

and

xor 

inc / dec

add / sub

div / idiv / mul / imul

shr /sar / shl / sal

nop

jmp

jcc (jz / jnz / je / jne / ja / jae / jb / jbe / jg / jge / jl / jle)


그런 다음 호출 규칙을 검토해야 함.

규칙의 모든 측면을 알 필요는 없지만 인수가 함수에 전달되는 방법과 휘발성/비휘발성 레지스터가 무엇인지 잘 알고 있어야 함.

다음 호출 규칙에 중점을 둠.


cdecl

standard calling convention

fastcall

x64 convention


마지막으로 C 프로그램의 다음 분기문이 어셈블리에서 어떻게 보이지는 검토해야 함.




( 7 ) Python 핵심 개념


Python 은 프로그밍을 읽는 것 외에도 작성할 수 있기를 바람.

핵심 개념 외에도 다음과 같은 개념을을 배워야 함.


컬렉션 (리스트, 사전, 세트)

리스트 이해

문자열과 바이트 배열 간 변환


기본 개념을 알고 나면 분석 스크립트에서 자주 사용되는 여러 일반 작업을 코딩하는 방법도 알아야 함.


텍스트 및 이진 데이터로 파일 읽기

텍스트 및 이진 데이터로 파일에 데이터 쓰기

리스트/사전/세트에 문자열이 포함되어 있는지 확인

하드 코딩된 문자열과 변수의 조합으로 구성된 형식화된 문자열 작성

정규식 사용

간단한 암호화 작업 수행, 비트 연산자 작업 수행 (and, or, xor, 빼기, 더하기, 오른쪽 이동, 왼쪽 이동)

PyCryptoDome 과 같은 외부 라이브러리를 사용하여 RC4, ACE, RSA 암호화 수행




( 8 ) 마지막 생각들


여기에서 언급한 핵심 개념에 대한 기본적인 이해가 끝나면 이러한 개념을 사용할 수 있는 모든 다양한 방법을 배우는 데 초점을 맞춰야 함.

우리는 악성코드를 작성하는 것이 아니라 읽는다는 것을 기억하십시오.

즉, 악성코드에서 인식할 수 있도록 이러한 개념을 사용할 수 있는 다양한 방법을 가능한 한 많이 알아야 함.

이러한 개념이 어떻게 사용되는 지에 대한 모든 변형을 보려면 다양한 프로그래밍 예제를 조사하는 데 상당한 시간을 투자해야 함.

지식 기반을 넓을 수록 악성코드를 더 빨리 분석할 수 있음.




( 9 ) 부록 - 공통 기능 API 목록



파일 조작 API


CreateFile

WriteFile

ReadFile

MoveFile

DeleteFile

CopyFile

FindFirstFile

FindNextFile

fopen

fread

fscan

fgetc

fgets

fwrite

fputc

fputs

fprintf



레지스트리 조작 API


RegCreateKey

RegQueryValueEx

RegGetValue

RegEnumValue

RegSetValue

RegSetKeyValue

RegDeleteValue

RegDeleteKey

RegDeleteKeyValue



프로세스 조작 API


OpenProcess

CreateProcess

CreateProcessAsUser

CreateToolhelp32Snapshot

Process32First

Process32Next

ReadProcessMemory

WriteProcessMemory

TerminateProcess

ExitProcess



서비스 조작 API


StartServiceCtrlDispatcher

RegisterServiceCtrlHandler

SetServiceStatus

OpenSCManager

CreateService

StartService

OpenService

QueryServiceConfig

ChangeServiceConfig



네트워크 조작 API


WSAStartup

socket

connect

bind

listen

accept

send

recv

inet_addr

htons

ntohs

closesocket

shutdown

gethostname

gethostbyname

InternetOpen

InternetOpenURL

InternetConnect

InternetReadFile

InternetWriteFile

HttpOpenRequest

HttpQueryInfo

HttpSendRequest

HttpAddRequestHeader

WinHttpOpen

WinHttpAddRequestHeaders

WinHttpOpenRequest

WinHttpQueryDataAvailable

WinHttpConnect

WinHttpQueryHeaders

WinHttpSendRequest

WinHttpReceiveResponse

WinHttpReadData

WinHttpWriteData



문자열 조작 API


sprintf

strstr

strcpy

strcat

strlen



기타 API


VirtualAlloc / malloc

memset

memcpy

LoadLibrary

GetProcAddress

CreateThread

WaitForSingleObject

Slttp

GetTickCount


댓글 없음:

댓글 쓰기