작년에 분석한건데 공유(&관리) 차원에서 포스팅해 보아요.
1) 드라이버의 설치
최초 웹을 통해 실행되는 Agent 파일에
의해 드라이버가 설치된다.
이후 Agent는 생성한 파일을
서비스에 등록하여 실행시키고 DeviceIoControl 함수를 통해 직접 통신을 한다.
이때 드라이버는 Parameter로
보내지는 Control Code를 기준으로 각각의 명령을 처리한다.
각 Control Code에 대한
분석은 밑에서 다시 자세히 보도록 하자.
2) Driver Entry 분석
먼저 Control Code 명령을
받기 위한 IRP_MJ_DEVICE_CONTROL Object를 생성한다.
이후 IoCreateFile 함수에
대한 SSDT 후킹을 한다. (SSDT Hook같은 경우
이미 많이 보아온 기법이라 자세하게 보지는 않았다.)
후킹이 완료되면 atapi의 DriverObject를 찾아서 DeviceType가
“FILE_DEVICE_DISK”인 DeviceObject를 찾고 Attach된 Device가 "\\Device\\Harddisk0\\DR0"인
경우 그 값을 전역변수로 저장한다.
즉, “\Driver\atapi”를 통해 Attached Device가 “\\Device\\Harddisk0\\DR0”이고 DeviceType이 “FILE_DEVICE_DISK”인 조건의 atapi의 DeviceObject를 찾는 것이다. 이는 Disk에 ReadWrite시 필요한 조건임을 추측 할 수 있다.
3) Read/Write Disk Control Code 분석
위에서 언급했듯 Control Code로
넘어온 값들은 다음과 같이 일정한 조건을 통해 다양한 명령을 수행하게 된다.
Parameter가 222008, 222000인
경우 파일명을 버퍼에 저장하여 로컬에서 접근을 막도록 한다. SSDT와 관련된 내용으로 자세한 분석은
생략한다.
222014의 경우 실제 하드디스크의 특정 Sector에
Write를 수행한다.
넘어오는 Parameter는 Agent에서 보낸 Data로
I/O manager를 통해 SystemBuffer에 포함된다. IRP 데이터의 입출력 처리 방식은 따로 언급하지 않겠다. 다만, SystemBuffer를 사용하는 방식은
IRP_BUFFERED_IO(0X10)이고 IRP + 8 byte offset에 위치한 Flags값으로 확인 가능하다.
위의 그림에서 볼 수 있듯이 SystemBuffer(밑의 80D50DF8)의 + 8 byte offset 위치에 있는 값이
악성코드가 디스크에 쓰는 값이고(밑의 빨간 네모 박스), Sector
번호 및 Sector Counter값이 같이 인자로 넘어온다.
그렇다면 해당 인자를 통해 어떠한 방식으로 물리 디스크에 데이터를 삽입할까?
악성코드가 물리 디스크에 데이터를 Read/Write하는
방식은 다음과 같다.
(1) 임의 메모리에 ScsiRequestBlock(이하 SRB) 구조체를 생성 및 셋팅
(2) ATAPI의 DeviceObject Index를
통해 해당 Device의 비동기적 IRP 생성
(3) 생성한 IRP 셋팅 – Stack에 MajorFunction, SRB 포인터 등을 설정
(4) ATAPI Device에 붙은 Atapi.sys (Driver)의
IRP_MJ_INTERNAL_DEVICE_CONTROL를 호출하여 디스크 접근
다음은 소스코드이다.
위의 코드 중 특별히 확인해야 할 부분은
IRP Stack에 들어가는 MajorFunction이
3(IRP_MJ_READ)인경우 Command Descriptor Block(CDB) 구조체의 OpCode가 Read이고 아닐 경우 Write라는 것이다.
CDB에는 실제 물리 디스크에 어느 위치를 사용할 지 정의할 수 있고 따라서 SRB구조체의 CDB는 디스크 위치를 찾아가는 중요 포인트가 된다.
다음은 MBR Sector를 수정하는 SRB이다.
노란색으로 나타낸 부분이 CDB 부분이며
주황색으로 표시된 부분이 CDB[5]으로 Logical Block
Address(LBA)을 나타낸다. LBA는 Sector를
나타내는 번호이고 위의 그림상으로 00 이므로 0번째 Sector가 된다. 0번째
Sector는 Disk의 MBR이 위치하는 곳이다. CDB[7]은 Sector Counter로 몇 개의 Sector를 사용할지 나타낸다. 위의 그림상에서는 01이므로 한 개의 Sector를 사용한다는 뜻이다. (보통의 경우 1개 Sector가 512byte로 만약 쓰고자 하는 데이터가 그 이상이 될 때는 사용할
Sector를 더 많이 지정해 줘야한다.)
CDB는 사용하는 목적에 따라서 여러가지 구조로 정의 할 수 있는데 악성코드에
의해 만들어지는 것은 10 Size 2A(write)로 정의되었다.
CDB(10) Write의 구조
SRB가 셋팅되면 IRP를 생성하고, Stack에 SRB의 구조체를
Parameter로 설정한다.
Stack의 첫번째 0F는 IRP_MJ_INTERNAL_DEVICE_CONTROL(Major Function)을 나타내며 80D7A858은 SRB의 포인터가 된다. IRP_MJ_INTERNAL_DEVICE_CONTROL는 SCSI
Request를 요청할 때 SRB 포인터를
Parameter로 설정한다.
이후 IofCallDriver 함수를
통해 atapi driver에게 IRP를 넘기게 되고 Stack에 담겨진 SRB 데이터를 읽어 물리 디스크에 직접 접근하게
된다.
디스크에 Write를 완료하면 Agent는 222020 ControlCode를 호출하게 되는데 이는
atapi driver에 IRP_MJ_INTERNAL_DEVICE_CONTROL함수를
후킹하게 된다.
더 이상 해당 SCSI I/O
Request를 수행 할 수 없게 되는 것이다.
디스크에 삽입된 데이터를 분석하면 Anti
AV, OnlinegameHack Tool, DownLoader 등이 있으며, 부팅시 변조된 MBR 코드에 의해 자동으로 실행되어 진다.