본문 바로가기

[REVERSING]/▶악성코드분석

[악성코드]BlackEnergy2(svchost.exe DKOM) #3 세번째 프로세스 분석

 

[그림.1]

 

분석전에 SSDT 테이블을 후킹을 하는 악성코드로 판단을 했었는데 다시 상세히 분석하니 이녀석은 SSDT 후킹을 하는 악성코드가 아니었습니다.

IceSword툴을 이용해서 SSDT 테이블에서 변경이된 Native Function이 있는지 확인결과 이상이 없었습니다.

 

 

[그림.2]

 

그런데 Process를 확인 결과 분명 PID 3720을 사용하고있는 svchost.exe는 태스크매니저 또는 ProcessExplorer로 확인했을때 없었는데 IceSword에서는 실행중인 프로세스로 확인이 되네요.

 

[그림.3]

 

올리디버거로 그림.3과 같이 0x151139F0와 0x15114D10함수로 진입하여 분석을 시도합니다.

위의 함수들은 Kernel모드로 진입하여 DKOM을 작업하는 함수들입니다.

DKOM은 간략히 설명하면 프로세스와 프로세스끼리 서로 링크드리스트를 이용하여 서로 포인터 메모리주소로 연결되어있는데 이 각각의 연결링크를 끊어 프로세스를 은닉하는 기법입니다.

 

[그림.4]

 

0x15114D10함수 내부로 진입하고 0x15114C80 함수로 진입후 실행하면 BlueScreen이 발생하여 더 이상 분석이 불가능합니다.

그 이유는 ollydbg는 UserMode 디버거이기 때문에 커널모드로 분석이 불가능 하기 때문입니다.

UserMode디버거는 커널로 진입하여 분석을 할 수 없기 때문에 더 이상 ollydbg로는 해당 악성코드 분석이 불가능했습니다.

그래서 해당 악성코드의 특정 코드 영역만 커널모드 디버거인 windbg를 이용하여 분석을 이어서 진행했습니다.

 

[그림.5]

 

우선 분석하기전에 현재 실행되고 있는 svchost.exe의 PID를 확인하면 3152 이고 이것을 16진수로 변경하면 C50이 됩니다.

16진수로 변경한 이유는 windbg에서 PID는 16진수로 보여주기 때문에 PID를 16진수로 변경 후 확인 해야합니다.

[그림.6]

 

현재 DKOM 코드 영역을 분석하기위해 vmware의 가상OS Windows XP와 windbg를 시리얼포트를 사용하여 리모트로 연결한 상태입니다.

즉 제가 사용하고 있는 로컬컴퓨터 Windows7 64비트에 windbg를 세팅하고, vmware의 가상OS의 Windows XP와 서로 연결해 놓은 상태입니다.

이와 같은 방법은 검색하면 쉽게 알 수 있으니 찾아보시면 금방 확인이 가능합니다.

분석을 위한 세팅이 완료된 상태이기 때문에 분석을 시작하겠습니다.

우선 위의 PrecessExplorer에서 확인했던 svchost.exe의 PID를 windbg에서 확인해 봅니다.

PID가 0c50인 svchost.exe가 존재하는걸로 확인이 됬습니다.

 

[그림.7]

 

그럼 이제 커널모드에서 특정 프로세스를 attach하여 분석을 해야합니다.

즉 커널 모드에서 유저모드디버깅이 가능하게 할 수 있는데 그림.7과같이 명령어를 입력하여 svchost.exe의 EPROCESS주소 0x89C182F8로 attach하면 svchost.exe를 분석 할 수 있게 됩니다.

정상적으로 붙었는지 확인을 !process 명령어로 확인 결과 0x89C182F8 svchost.exe로 세팅된 것을 확인 할 수 있습니다.

 

[그림.8]

 

그리고 svchost.exe는 실행시 은닉이되기 때문에 분석 편의상 제가 svchost.exe의 EP에 자기자신으로 점프하도록 바이너리를 수정해놨었는데요 이렇게되면 EP 0x151130F0 자기자신으로 점프하여 더이상 코드실행이 되지 않게 됩니다.

이상태에서 Attatch하여 분석하면 조금 편리하기 때문에 바이너리를 수정했었습니다.

 

[그림.9]

 

이 수정된 바이너리를 원래의 코드로 다시 수정을 해주고 해당 EP에 브레이크 포인트를 걸고 브레이포 인트까지 실행하여 분석을 이어갑니다.

 

 

[그림.10]

 

여기서 잠시 svchost.exe의 EPROCESS를 확인해봅니다.

DKOM 즉 프로세스와 프로세스간의 연결된 링크드리스트를 변경하려면 EPROCESS의 0x88의 ActiveProcessLinks ListEntry의 주소를 조작해야합니다.

그러나 주의해야 할 점이 현재 그림.10의 보이는 0x89B4DE54-0x89BA670C주소자체를 조작하는 것이아니라 이 주소가 가르키고 있는 주소를 변경해야 합니다.

즉 0x89B4DE54-0x89BA670C 주소는 포인터 역할을 한다고 보시면 됩니다.

 

[그림.11]

 

DKOM영역의 코드내부로 진입하면 sysenter 명령으로 커널로 진입하는 것을 확인 할 수있습니다.

 

[그림.12]

 

그림.12의 코드를 보면 0x89C182F8 svchost.exe의 EPROCESS의 주소를 얻어오고 이 주소값에다가 +0x88 을 더하여 0x89C18380 주소를 얻게 됩니다.

이 주소를 EPROCESS 구조체에서 확인해보면 ActiveProcessLinks ListEntry 주소인것을 확인 할 수 있습니다.

즉 링크드리스트를 조작하기 위한 첫번째 작업으로 ActiveProcessLinks ListEntry의 주소를 얻습니다.

[그림.13]

 

그리고 여기서 0x89B4DE28을 Flink(ForwardLink)라고 하고 0x89BA66E0를 Blink(BackLink)라고 하겠습니다.

그림.13의 0x151139CE코드를 보면 EAX가 ActiveProcessLinks ListEntry 의 Blink 0x89BA66E0를 가르키고 있고 이 가르키는 곳에 Flink 0x89B4DE28 주소로 변경합니다.

정리하면 원래 Blink는 다른 프로세스를 가르키고 있는 주소로 세팅되어 있었는데 이 주소를 자기자신의 Flink 0x89B4DE28 주소로 변경해 버린것 입니다.

 

[그림.14]

 

그리고 이어서 코드를 실행하면 0x151139DD 주소에 MOV DWORD PTR [EAX+4], EDX 코드를 볼 수 있습니다.

이 코드는 ActiveProcessLinks ListEntry Flink 0x89B4DE28 주소가 가르키는 곳에 EDX(0x89EA9E28)주소로 세팅합니다.

 

 

[그림.15]

 

변경된 Flink의주소 0x89EA9E28를 확인해보면 다른 프로세스의 링크드리스트 주소가 아닌 nt!PsActiveProcessHead의 엉뚱한 함수 주소를 가르키는 포인터임을 확인 할 수 있습니다.

이것으로 svchost.exe의 ActiveProcessLinks 의 ForwardLink와 BackLink가 모두 변경이 됬고 이로써 프로세스의 링크드 리스트는 끊어 젔기 때문에 svchost.exe는 은닉이 가능하게 되는 것이고 이 기법을 DKOM기법이라고 합니다.

 

[그림.16]

 

다시 ProcessExplorer로 확인결과 svchost.exe가 사라진 것을 확인 할 수 있습니다.

프로세스 은닉 이후의 행위에 대해 이어서 분석을 진행하겠습니다.

 

[그림.17]

 

windbg는 커널디버깅이 가능하다는 장점이 있고 기능들도 좋지만 유저모드 디버거들에 비해 불편한점이 많기 때문에 DKOM기법을 이용하여 은닉된 이후의 코드는 ollydbg로 분석 하였습니다.

그림.17을 보면 자기자신을 삭제하고 CreateFileA함수로 c:\windows\system32\mssrv32.exe 파일을 오픈합니다.

 

 

[그림.18]

 

그리고 레지스트리를 생성하고 값을 세팅하는데 다음과 같습니다.

 

[그림.19]

 

HKEY_LOCAL_MACHINE - SYSTEM\CurrentControlSet\Services\msupdate 의 레지스트리에 그림19와같이 레지스트리를 등록합니다.

해당 레지스트리는 자기자신의 코드를 복사한 mssrv32.exe를 서비스로 등록시킵니다.

 

[그림.20]

 

서비스로 등록된것을 확인하면 사용자들을 속이기 위해서 microsoft의 보안업데이트로 속이고 있는 것을 확인 할 수 있습니다.

 

[그림.21]

 

레지스트리 등록 과정이 끝나면 C드라이브의 볼륨 시리얼넘버를 구하고, 현재 사용중인 pc의 이름을 구해서 두 데이터를 결합 후 저장합니다.

 

 

[그림.22]

 

이 값을 다시 다음과 같이 만들어서 저장합니다.

id=xDKCOM_241CA3 B5&build_id=165BCFE

URL 파라미터 같네요

 

[그림.23]

 

HTTP Request패킷을 POST형식으로 다음과같이 세팅 하여 전송합니다.

www.crimeware.com/stat.php?id=xDKCOM_241CA3 B5&build_id=165BCFE

원래는 여기서 HttpSendRequestA함수로 URL 을 Requst하고 이에대한 Response응답데이터를 InetrnetReadFile함수로 받게됩니다.

하지만 해당 사이트는 현재 닫힌 상태이기 때문에 정상적인 Response를 받을 수 없는 상태입니다.

 

 [그림.24]

 

받은 데이터가 없을때는 위와같이 특정값 * 특정값 * 3E8와 같이 특정값과 3E8을 곱한 값을 millisecond로 만들어서 시간값을 세팅하고 그 시간동안 Sleep 함수를 호출하여 대기하게됩니다.

여기서 현재코드에서 Sleep을 하기전에 메모리주소 0x151135F2에 보면 CreateThread를 호출하는데 이 스레드의 코드 내용을 보면 아래와 같습니다.

 

[그림.25]

 

생성되는 스레드도 그림.11의 코드와 같이 특정값 * 특정값 * 3E8와 같이 특정값과 3E8을 곱한 값을 millisecond로 만들어서 시간값을 세팅하고 대기하게됩니다.

이렇게 대기한 이후에 코드는 이어서 그림.8부터의 과정을 반복하여 웹서버에 정보를 Request하고 Response받는 행위를 계속 하게됩니다.

여기까지 진행상황을 간략히 정리하면 감염자 대상의 PC정보와 이에해당하는 고유한 값의 정보를 웹서버에 전달하고 Response받은 데이터가 없을때 Sleep하여 감염된 PC의 봇은 잠을 자게됩니다. 그리고 또다시 Sleep함수에서 설정한 시간값만큼의 시간이 지나면 위의 과정을 반복적으로 하게되는 것입니다.

여기서 잠시 쿠쿠샌드박스에서 분석된 결과를 한번 확인해보겠습니다.

 

[그림.26]

 

쿠쿠샌드박스에서도 3개의 프로세스가 탐지되고 분석을 해서 리포트로 만들어 줬는데요

그중 마지막 자식프로세스인 svchost.exe를 분석한 결과를 리포트해줍니다.

쿠쿠의 결과를 봐도 그림.12와같이 각각 메인스레드와 호출된 스레드가 600000, 1800000으로 Sleep까지만 분석을 하고 종료한것을 확인 할 수 있습니다.

더이상의 특별한 과정이 없나봅니다.

SSDT 테이블의 주소값을 건드리길래 멋지게 후킹을 해줄것으로 기대했는데 굉장히 아쉽네요 ㅠ

이부분은 후킹이 됬는지 추후에 확인해보겠습니다.

일단은 분석은 이렇게 종료가 됬습니다.

하지만 위에서 잠시 언급한대로 감염된 PC이름과 고유한 값의 정보를 웹서버에 전달하고 Response받은 데이터가 없을때 Sleep한다고 했습니다.

여기서 잠깐 왜 Response가 없을때 Sleep함수를 호출할까요? 라고 생각해 볼 수 있겠습니다.

왜그럴까? 한번 고민해보면 간단합니다.

만약 이러한 프로그램들로 수백만대의 감염된 PC들이 있다고 생각했을때를 볼 수 있습니다.

수백만대의 컴퓨터가 각자의 정보들을 공격자의 웹서버에 Request를 보냅니다. 여기서 Sleep이 없다면?

Request데이터가 없는 봇들 전부다 공격자 웹서버에 패킷을 보내게됩니다.

역으로 DDOS를 받는 셈이겠네요..(나중에 저러한 봇들 찾아서 이와같이 컨트롤하는 부분들 전부다 찾아서 코드패치후 역으로 공격하고싶은 상상을 하게되네요 ㅋ)

그렇다면 Response받은 데이터가 있다면? 분명 이에 대한 어떤 특정 루틴을 탈것 같은 예감이 듭니다.

이부분은 간단히 웹서버를 만들고 감염된 pc의 호스트주소에서  WWW.CRIMEW***.COM를 내 웹서버로 세팅해놓고 조건에 맞게끔 하나

씩 멋지게 분석 하려고했으나.. 엄청난 삽질이 예상이되네요..

차라리 제대로 동작하는 샘플을 하나더 분석하는게 정신건강에 더 이로울듯 싶다고 생각해서 그냥 끼워맞추기식 코드패치를 해서 몇개의 명령어들을 알아냈습니다.

그럼 간단히 알아보겠습니다.

 

[그림.27]

 

우선 InternetReadFile함수가 호출될때 PUSH ECX 이 부분의 파라미터에 호출이후 데이터가 버퍼의 시작주소가 됩니다.

그래서 InternetReadFile 함수 호출이후 이 버퍼에 제가 임의로 "gogo" 문자열을 입력을 함으로써 Response데이터 있는것 처럼 만든것 입니다.

 

[그림.28]

 

역시 예상대로 Response데이터를 파싱해서 특정위치에있는 데이터와 연산을해서 4바이트짜리 코드를 2바이트로 만들어서 저장합니다.

 

[그림.29]

 

이어서 실행되는 루틴을 따라가보니 특정 명령어(stop/die/open)에 대한 분기를 하여 실행을 하게됩니다.

여기서 die는 자기자신(_bot.exe)을 복사했던 파일 c:\windows\system32\mssrv32.exe을 삭제하도록 하는 명령어입니다.

그리고 open명령어는 iexplorer.exe "? " 와 같은 형식으로 실행을 하는 명령입니다.

즉 공격자가 _bot.exe감염된 pc에서 원하는 주소로 웹브라우저를 실행하는 명령입니다.

 

[그림.30]

 

이어서 루틴을 따라가면 공격자가 실행한 명령어가 맞는지 검증합니다.

검증하는 곳의 주소로 가보니 몇개의 명령어들이 있네요..

 

[그림.31]

 

계속 코드를 따라가보면 "open"에 대한 명령을 위와 같이 실행합니다.

제가 코드를 강제로 패치해서 진행하다보니  iexplorer.exe "비어있는 버퍼" 로 세팅이 됬습니다.

코드에서 비어있는 버퍼부분에 값을 wsprinf함수로 두개의 문자를 결합하는 것으로 보아 빈 버퍼에는 공격자가 입력해서 사용할 URL 주소일거라고 생각이 듭니다.

 

[그림.32]

 

실제 웹브라우저가 실행이 됬는지 확인해보면 정상적으로 실행이 됬네요.. 

 

[그림.33]

 

웹브라우저가 실행이 되고나면 스레드를 실행합니다.

 

[그림.34]

 

스레드  내부로 들어가서 보면 웹브라우저를 실행해놓고 2710(10000ms)의 시간만큼 Sleep을 한 후에 실행시켰던 웹브라우저를 종료합니다.

이와 같은 방식으로 웹브라우저에 있는 문자(명령어)들로 _bot.exe에게 명령을 내리는것 같네요..

이것으로 분석을 마치겠습니다~~