실전 악성코드와 멀웨어 분석 실습 7-3
이 실습에서 실행 전에 악성코드 실행 파일인 Lab07-03.exe과 DLL인 Lab07-03.dll을 입수했다. 이는 실행할 때마다 악성코드가 변경될 수 있기 때문에 중요하다. 두 파일 모두 피해자 시스템의 동일한 디렉토리에서 발견됐다. 프로그램을 실행한다면 두 파일이 분석 장비의 동일한 디렉토리에 위치하게 해야 한다. 127로 시작하는(루프백 주소) IP 문자열이 로컬 장비로 접속한다(실제 악성코드 버전은 이 주소가 외부 장비로 연결되겠지만 여기서는 안전하게 localhost로 접속하게 설정했다.)
Lab07-03.exe의 문자열을 확인하였다. kernel32.dll과 비슷해보이는 이름인 kerne132.dll 문자열이 존재한다.
또한 Lab07-03.dll라는 문자열도 존재한다. 따라서 이러한 dll에 접근하고 있다고 추측할 수 있다.
Lab07-03.exe의 임포트 목록이다.
MapViewOfFile, CreateFileMappingA, CreateFileA 함수를 임포트하는 것으로 보아, 파일을 생성하여 메모리에 매핑하는 것을 알 수 있다.
FIndNextFileA와 FIndFirstFileA는 이 프로그램이 파일을 탐색하여 CopyFileA를 통해 복사하는 것으로 추측할 수 있다.
IsBadReadPtr은 인자로 전달된 포인터가 가리키는 메모리 공간이 유효한지 확인하는 함수이다. 하지만 현재에는 이 함수의 안정성이 보장되지 않았으므로 SEH 사용을 권장한다고 한다.
위에서 확인한 strings의 결과로 미루어 보아 이 프로그램은 Lab07-03.dll을 임포트 할 것이라고 추측할 수 있으나, 임포트 함수로 LoadLibrary, GetProcAddress가 존재하지 않는다. 이는 런타임에 해당 DLL을 로드하지 않는다는 의미이므로 분석할때 확인해야 한다.
Lab07-03.dll의 strings 결과이다.
127로 시작하는 IP 주소와, hello, exec, sleep이라는 문자열이 보인다. 이들이 어떤식으로 사용되는지 확인해 보아야 한다.
Lab07-03.dll의 임포트 목록이다.
CreateProcessA 함수를 임포트 하는 것으로 보아, 다른 프로세스를 생성시킬 수 있다. 또한, 뮤텍스를 생성한다.
WS2_32.dll의 임포트 함수들이다. 소켓통신을 하는 것으로 보인다.
Lab07-03.dll의 익스포트를 확인하려 했으나 존재하지 않았다.
익스포트가 없으면 다른 프로그램이 임포트할 수는 없지만, 프로그램은 익스포트 없이 DLL 상의 LoadLibrary를 호출할 수 있다. 그리고 익스포트가 없기 때문에 rundll32로 실행이 불가능하다.
IDA로 분석하기
dll의 구조가 복잡하기 때문에 함수 호출 중심으로 확인할 것이다.
Lab07-03.dll이 호출하는 함수 목록이다.
뮤텍스를 생성하고 소켓 통신으로 데이터를 송수신 한 뒤, 프로세스를 생성한다.
그 후, 100011C5의 call Sleep 이후로 종료되는 모습이다.
SADFHUMF라는 이름의 뮤텍스를 생성하고 있다.
127.26.152.13이라는 ip주소와, 80번 포트를 사용한다.
send 함수의 인자를 보면, "hello"라는 문자열을 전달하는 것을 확인할 수 있다.
buf 공간에 수신한 정보를 저장한다.
buf에 있는 처음 다섯 개의 문자가 sleep이라는 문자열인지 strncmp로 비교한다,
그리고 0이 반환되면(같을 경우) 60초 동안 Sleep 한다.
즉, sleep이라는 문자열을 서버로부터 수신하면 60초동안 sleep하기 위해 Sleep 함수를 호출한다.
만약 sleep이 아닐 경우에, exec라는 문자열을 buf에 수신된 문자열과 strncmp로 비교하여 같다면 CreateProcessA가 호출된다.
CreateProcessA의 두 번째 인자로 edx의 주소가 전달되었다. 이 두 번째 인자의 역할은 아래와 같다.
새로 생성하는 프로세스에 인자를 전달할 때 사용한다. 첫 번째 인자에 NULL을 전달하고, 두 번째 인자에 실행파일의 이름을 더불어 전달할 수 있다.
이 경우 실행파일 이름은 표준 검색경로를 기준으로 찾는다.
따라서 CommandLine에 생성될 프로세스에 대한 정보를 담고 있다는 것을 알 수 있다.
해당 데이터는 올리디버거로 확인한 결과 아래와 같다.
Lab07-03.dll의 경로인 것을 확인할 수 있다.
exe 분석
Lab07-03.exe가 호출하는 함수 목록이다.
main함수에서는 입력한 인자 수가 2개인지 확인하여 같다면,
eax에 두 번째 인자의 주소를 넣고, esi에 특정 문자열의 주소를 넣어 반복문을 통해 비교하여 문자열이 다르면 프로그램이 종료되고, 같으면 다음 명령어가 실행된다.
여기서 알 수 있는 사실은, WARNING_THIS_WILL_DESTORY_YOUR_MACHINE이라는 커맨드라인 인자를 전달해야 프로그램이 제대로 실행된다는 점이다.
System32 폴더에 Kernel32.dll파일의 핸들을 얻어, 메모리에 매핑한다.
그리고, Lab07-03.dll의 핸들을 얻은 뒤,
역시 메모리에 매핑한다.
만약, 작업이 실패한 경우 프로그램이 종료된다.
핸들을 반환하고, Lab07-03.dll을 system32폴더에 kerne132.dll이라는 이름의 파일로 복사한다. 이는 kernel32.dll과 유사한 파일명이므로 악의적으로 이용될 여지가 있어 주의 깊게 살펴보아야 한다.
그리고 4011E0의 함수를 호출한다. 인자로는 C:\\*가 들어간다.
4011E0 함수가 호출하는 API의 목록이다.
이 함수는 인자로 들어온 C:\\*를 찾아서 해당 파일에 대한 정보를 FindFileData 인자를 통해 저장하고 있다.
위에서 찾은 파일 정보 구조체에서 fwFileAttributes 멤버와 10h를 비교하여 같을 경우에 esi에 "."문자를 저장하고, eax에 파일 이름의 주소를 저장한다.
이때 10h는 파일이 디렉터리에 해당한다는 의미이다.
파일 이름의 주소와 "." 문자를 비교하는 과정이다. 같을 경우에 아래의 코드가 있는 부분으로 분기한다.
.exe와 ebx에 있는 내용을 비교하는 stricmp 함수를 호출하는 부분이다. 만약 두 인자가 같을 경우에는 아래와 같이 파일을 메모리에 매핑하고 검증하는 과정을 거친다.
이러한 과정을 거치고 나면
이름이 kernel32.dll인 파일에 대해서 repne scasb 명령(strlen의 기능)과, rep movsd 명령(memcpy)을 호출한다.
kernel32.dll을 dword_403010으로 덮어씌우는 작업을 한다.
403010의 문자열은 kerne132.dll이다. 따라서 kernel32.dll을 kerne132.dll로 덮어 씌우는 명령을 수행한다.
FindNextFileA 함수로 다음 파일에 대해서도 위와 같은 과정을 거친다. 이 절차는 반복문으로 진행한다.
정리하면, C드라이브 아래에 있는 모든 파일에 대해서 확장자가 exe 파일인 경우를 검색하고, kenel32.dll 파일을 찾아 kerne132.dll로 바꾸어준다. Lab07-03.dll을 System32 위치에 kerne132.dll이라는 이름의 파일로 복사해준다.
동적 분석
Lab07-03.exe에 인자를 주어 실행시킨 결과 정적 분석에서 확인했던 것과 같이 Lab07-03.dll을 system32\kerne132.dll로 복사하는 것을 확인할 수 있다.
저장된 exe 파일을 CreateFileA로 조작하는 것을 확인할 수 있다.
해당하는 exe 파일의 IAT 목록의 일부이다. kernel32.dll 대신 kerne132.dll을 임포트하는 것을 확인하였다.
따라서 이 악성코드는 exe 파일에서 임포트하는 kernel32.dll 대신하여 kerne132.dll을 임포트하게 한다.
Lab07-03.dll의 익스포트 함수들이다. 이는 kernel32.dll의 익스포트 함수 목록과 일치한다. 이를 통해 실제 kernel32.dll의 기능의 동작을 대신하기 위해 DLL 포워딩을 사용한 것을 알 수 있다. 따라서 기능에는 이상이 없으므로 사용자의 입장에서는 문제가 없어보일 수 있다.