Practical Malware Analysis 7-3
실습 7-3
실습 환경 : Vmware (Windows 7 32 bit)
사용한 툴 : IDA Free 5.0, Strings
[01] 이 프로그램은 어떤 방식으로 컴퓨터가 재시작할 때마다 실행(지속 메커니즘)을 보장하는가?
우선 Strings를 사용하여 문자열을 찾아보면
위와 같은 문자열 들을 볼 수 있는데 Kernel32.dll과 Kerne123.dll이 있는 것으로 보아 Kernel32.dll 의 영문자 l을 숫자 1로 바꿔 Kernel32.dll로 보이게끔 할 것이라고 추측할 수 있다.
이제 Import 함수를 살펴보면
CreateFile 함수 CreateFileMapping 함수, MapViewOfFile 함수를 확인할 수 있는데 이를 통해 추측을 해보면 파일을 열고 메모리에 매핑을 하는 것으로 생각할 수 있고
FindFirstFile 함수, FindNextFile 함수 등을 확인할 수 있는데 디렉터리를 탐색하는 것이라고 생각해 볼 수 있고
CopyFile 함수를 사용해 탐색한 파일을 어딘가에 복사한다고 추측해 볼 수 있었다.
그리고 위에서 String으로 확인한 문자열에서 Lab07-03.dll을 확인 하였으므로 이 dll을 사용할 것이라고 생각 했지만 LoadLibrary, GetProcAddress를 임포트 하지 않는 것으로 봐서 런타임에 해당 dll을 로드하지 않고 다른 방식을 사용하고 있음을 생각해 볼 수 있었다.
이제 Lab07-03.dll을 Strings로 살펴보면
위처럼 흥미로운 문자열 들을 확인할 수 있는데 악성코드가 접속하는 IP주소인 127.26.152.13도 확인할 수 있고 이는 네트워크 기반의 시그니처로 활용할 수 있을 것이다. 이제 Import 함수를 살펴보면
WS2_32.dll을 사용하여 네트워크 통신을 수행하는 것을 확인할 수 있고 Mutex를 생성하며 CreateProcess 함수를 사용하여 프로세스를 생성하는 것도 확인할 수 있었다.
이제 IDA를 사용하여 dll을 분석해보면
처음에 _alloca_prove 함수를 사용하여 스택에 공간을 할당하는 것을 확인할 수 있다. 계속 분석해보면
OpenMutex 함수와 CreateMutex 함수를 사용하여 악성코드가 한 번에 하나의 사본만 실행하게 하고 WSAstartup 함수를 사용하여 소켓 라이브러리를 초기화 하고 소켓을 시작한다.
더 살펴보면 socket 함수로 소켓을 생성하고
목적지 IP주소가 담긴 inet_addr을 호출하고 포트를 50h(80)으로 지정하고 connect를 사용하여 연결한다. 이제 어떤한 데이터가 전송되는지 살펴보자
살펴보면 hello문자열을 볼 수 있는데 이 문자열을 토대로 생각을 해보면 악성코드에 감염된 PC가 위에서 확인했던 목적지 IP주소 127.26.152.13에 연결이 되었음을 전달하는 것 같다.
send가 정상적으로 동작하였으면 0을 반환하고 실패했으면 -1을 반환하므로 정상적으로 동작했을 경우를 가정하여 다음을 분석해보면
shutdown을 사용해 소켓의 send를 쪽만 닫은 뒤 성공하면
recv를 사용해 무엇인가 입력 값을 기다리고 있는 것을 확인할 수 있다. 계속 분석을 진행해보면
strncmp 함수를 호출하여 recv를 통해 입력 받은 값이 sleep 이면
60,000ms (60)초 간 중지하는 Sleep 함수를 호출한다. 만약 sleep이 아니면
strncmp 함수를 통해 버퍼가 exec로 시작하는지 확인하고 exec로 시작하면 0을 반환하고 jnz문에 의해 점프하지 않는데 살펴보면
CreateProcess 함수를 호출하는 것을 확인할 수 있는데 어떠한 프로세스가 실행되는지는 모른다. CreateProcess 함수의 두 번째 파라미터인 CommandLine 이 어떠한 값으로 지정 되는지 모르기 때문이다.
위의 분석을 요약하자면 DLL파일은 뮤텍스를 생성하여 중복 실행을 방지하고 winsock을 사용하여 127.26.152.13 주소와 통신하며 소켓을 통해 받은 문자열이 exec일 경우 프로세스를 실행하는데 어떠한 프로세스를 실행하는지는 아직 알 수 없다.
이제 exe파일을 분석해보자
살펴보면 처음에 인자의 값이 2개인지 확인한 후 인자 값이 2개가 아니라면 jnz문을 통해 점프하여 프로그램은 종료된다. 인자 값이 2개라면
위와 같이 argv[1] 값을 eax로 이동시키고 WARNING_THIS_WILL_DESTROY_YOUR_MACHINE 문자열을 esi로 이동시킨다. 그 뒤에
연산을 통해 eax에 저장된 argv[1] 값과 esi에 저장된 문자열이 동일한지 비교한다. 동일하지 않으면 즉시 함수를 반환하는 지점으로 점프하므로 프로그램 실행시 입력해야 될 파라미터가 WARNING_THIS_WILL_DESTROY_YOUR_MACHINE 인 것을 알 수 있었다.
이제 분석을 계속 진행해보면
위와 같이 CreateFileA 함수를 사용하여 C:\Windows\System32\Kernel32.dll을 열고 CreateFileMappingA 함수를 사용해 Kernel32.dll 파일을 매핑 개체로 만든 뒤 핸들을 반환하고
MapViewOfFile 함수를 사용하여 실제 메모리에 연결하여 매핑 파일을 생성하고 그 파일의 첫 번째 주소값을 반환한다. 그리고 CreateFileA 함수를 사용하여 Lab07-03.dll 파일을 열고 캡쳐하진 않았지만 이 파일 역시 CreateFileMappingA 함수를 사용하여 매핑 개체로 만든 뒤에 MapViewOfFile 함수를 사용하여 실제 메모리에 연결하여 매핑 파일을 생성하고 주소값을 반환한다.
이제 분석을 진행해보면 복잡한 소스코드가 보이는데 프로그램의 모든 마지막 오퍼레이션을 확인할 수는 없으므로 일단은 넘기고 다음을 살펴보면
CloseHandle 함수를 호출하여 파일의 편집을 종료하였음을 알 수 있고 그 후에 CopyFile 함수를 호출하여 Lab07-03.dll을 C:\Windows\System32\Kerne132.dll(숫자 1)에 복사하여 kernel32.dll 같이 보이게 한다. 이를 통해서 kerne132.dll(숫자 1)이 kernel32.dll 대신 사용될 것이라고 추측해 볼 수 있다.
이제 main의 끝부분을 살펴보면
C:\* 문자열을 인자로 받는 함수를 호출하는 것을 확인할 수 있다. 이 함수를 살펴보면
FindFirstFile 함수를 C:\* 와 함꼐 호출하는데 많은 산술 연산과 비교를 확인할 수 있다. 이 역시 시간 소모적인 함수로 넘긴뒤에 나중에 필요한 정보가 있으면 되돌아오기로 한다.
분석을 계속 진행해보면 sub_4011e0 함수를 확인할 수 있는데 이는 현재 분석하고 있는 함수이므로 자신을 호출하는 재귀함수 임을 의미한다.
함수를 살펴보면 stricmp 함수를 확인할 수 있는데 문자열 .exe와 비교한 후 일치하면 sub_4010a0 함수를 호출한다.
이를 토대로 추측을 해보면 이 함수는 C 드라이브 에서 .exe 파일을 검색하고 파일 확장자가 .exe 이면 뭔가를 할 것이라고 생각할 수 있다.
재귀호출을 하는 것은 전체 파일 시스템을 탐색한다는 의미일 것이다. 이제 .exe 파일을 탐색하여 무슨 짓을 하는지 알아보기 위해서 함수 sub_4010a0를 분석해봐야한다.
하지만 sub_4010a0 함수는 세부적으로 분석하기에는 오랜 시간이 걸리는 복잡한 함수이기 때문에 함수가 호출될 때만 살펴보면
CreateFile, CreateFileMapping, MapViewOfFile을 호출하는 것을 확인할 수 있고 이를 통해 메모리 공간에 전체 파일을 매핑해 프로그램이 다은 추가 함수 없이 파일을 읽고 쓸 수 있다는 것을 알게되었다. 계속 분석을 진행해보면
stricmp 함수를 볼 수 있는데 여기서 프로그램은 kernel32.dll 문자열 값을 비교하고 값이 같으면
위와 같이 진행되는데 살펴보면 rep movsd를 볼 수 있는데 이는 esi의 값을 edi로 복사하는 역활을 한다. 그러면 edi 값과 esi 값이 무엇인지 살펴보면 mov edi, ebx를 통해 ebx값을 edi로 옮기는 것을 확일할 수 있었고 ebx는 stricmp로 건네주는 값을 로드하고 있음을 알 수 있으니 edi 값은 kernel32.dll 임을 알 수 있다.
즉 함수가 문자열 kernel32.dll을 발견하면 esi의 값으로 치환한다는 것을 의미하는데 esi의 값을 살펴보면 오프셋 dword_403010 값임을 알 수 있고 이를 살펴보면 kerne132.dll(숫자 1) 임을 알 수 있다.
이제 종합해보면 실행 파일이 .exe로 끝나는 모든 파일을 검색하고 kernel32.dll이라는 문자열을 가진 파일의 위치를 찾아 kerne132.dll(숫자 1)로 치환함을 알 수 있다.
이전에 분석에서 Lab07-03.dll을 C:\Windows\\System32 로 복사하고 이름을 kerne132.dll(숫자 1)로 변경함을 알고 있으니 악성코드가 kernel32.dll 대신 kerne132.dll(숫자 1)로 접근하게 파일을 변조하다고 볼 수 있다.
결론은 이 악성코드는 .exe 파일이 실행될때 마다 악의적인 kerne132.dll(숫자 1)을 로드하여 DLLMain에서 코드를 실행하게 한다.
[02] 이 프로그램을 탐지할 때 호스트 기반으로 좋은 시그니처는 무엇인가?
위에서 확인했듯이 kerne132.dll(숫자 1)이라는 파일명으로 하드 코딩되어 있고 뮤텍스 이름도 SADFHUHF로 하드 코딩 되어있다.
[03] 이 프로그램의 목적은 무엇인가?
이 악성코드는 삭제하기 어려운 백도어를 생성하고 두 가지 명령어를 갖는데 하나는 exec로 명령어를 실행시키고 다른 하나는 sleep으로 60초 동안 sleep하는 기능을 가진다.
[04] 일단 악성코드가 설치된다면 어떻게 삭제할 수 있는가?
이 악성코드는 시스템의 모든 .exe 파일을 감염시키므로 삭제하기 매우 어렵다. 백업을 해놓지 않았다면 kerne132.dll(숫자 1) 파일의 악의적인 콘텐츠만 제거하게 수정하거나 kernel32.dll을 복사해 kerne132.dll(숫자 1)로 이름을 변경하는 등의 방법이 있다.
이번 실습은 정말 힘들었던 것 같다. 사실 거의 책을 보고 참고해 분석을 따라서 진행하였다. 공부도 많이 됬지만 그 만큼 내가 많이 부족하구나를 느낀 실습이었다.