Post

syzkaller 환경구축

개요

Linux Kernel Fuzzer 중 syzkaller 퍼저의 설명 및 환경 구축에 대해서 설명드리겠습니다. 해당 Fuzzer는 오픈소스로 아래의 링크에 있습니다.

기본구조

syzkaller 퍼저는 공식문서에 따르면 다음과 같은 구조를 가지고 있다고 합니다.

0syzkaller 구조

  • syz-manager: 여러 VM 인스턴스를 시작하고 모니터링 및 VM 인스턴스가 crash 발생시 다시 시작하고 syz-fuzzer 프로세스를 VM 내부에서 실행합니다. crash 발생시 저장하는 역할도 수행하며 host에서 실행됩니다.
  • syz-fuzzer: 해당 프로세스는 VM 내부에서 실행됩니다. 퍼징 프로세스(nput generation, mutation, minimization등)를 syz-fuzzer에 전달하고 새로운 coverage를 tirgger하는 input을 RPC를 통해 syz-manager 프로세스에 보냅니다. 또한 syz-executor프로세스를 시작합니다.
  • syz-executor: 해당 프로세스는 single input(syscall 시퀀스)을 실행합니다. 프로세스에서 실행할 프로그램을 수락 syz-fuzzer하고 결과를 다시 보냅니다. 또한, 공유 메모리를 사용하여 통신합니다.

💡 다른 유명한 퍼저와 가장 큰 차이점이 syscall을 대상으로 퍼징을 하는 것입니다!

Wi-Fi Fuzzing 구조

Syzkaller에서 Wi-Fi Fuzzing을 위해서 mac80211_hwsim 모듈을 사용하여 Wi-Fi 장치를 에뮬레이션합니다.

  1. 두 개의 가상 Wi-Fi 장치가 생성되고 사전 정의된 MAC 주소(08:02:11:00:00:00 및 08:02:11:00:00:01)가 할당됩니다.
  2. 해당 장치는 IBSS모드로 전환됩니다.
  3. 해당 장치는 IBSS 네트워크를 형성합니다. 네트워크 매개변수는 다음과 같이 정의 되어 있습니다.
    • BSSID(50:50:50:50:50:50)
    • SSID(‘\x10\x10\x10\x10\x10\x10’)
    • 채널(2412MHz)

이러한 단계는 initialize_wifi_devices 함수에서 실행하고 있습니다.

추가적으로 802.11 퍼징을 용이하게 하기 위해 두 개의 의사 syscall도 도입되었습니다.

  1. syz_80211_inject_frame(mac_addr, buf, buf_len)
    • 802.11 프레임 주입을 수행합니다. 해당 프레임은 지정된 네트워크 인터페이스에서 수신된 것으로 나타납니다.
  2. syz_80211_join_ibss(network_interface, ssid, ssid_len, wait_mode)
    • 해당 네트워크 인터페이스를 IBSS 모드로 전환하고 지정된 Ad-hoc 네트워크에 연결합니다.

💡 이렇게 네트워크를 구성하고 syscall을 사용함으로써 Wi-Fi Fuzzing이 가능하다고 합니다!

Linux Kernel Build

우선, Kernel Build를 위해 다음의 패키지를 설치합니다.

1
apt install make gcc flex bison libncurses-dev libelf-dev libssl-dev

그리고 다음의 명령어를 순서대로 입력해서 .config 파일을 설정합니다.

1
2
make defconfig
make kvm_guest.config

이렇게 생성하고 나면 KASAN 같은 기능이 비활성화 되어있기 때문에 아래의 값들을 .config 파일에서 수정합니다.

💡 .config
제가 설정할 때 kernel 버전을 v6.8-rc2를 사용했는데 아래의 값들이 기본적으로 비활성화 되어 있었습니다!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Coverage collection.
CONFIG_KCOV=y

# Debug info for symbolization.
CONFIG_DEBUG_INFO_DWARF4=y

# Memory bug detector
CONFIG_KASAN=y
CONFIG_KASAN_INLINE=y

# Required for Debian Stretch and later
CONFIG_CONFIGFS_FS=y
CONFIG_SECURITYFS=y

# ssh error
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="net.ifnames=0"

마지막으로 아래의 명령어로 build를 합니다.

1
2
make olddefconfig
make -j`nproc`

build 완료 후 생성되는 파일인 $KERNEL/vmlinux 파일과 $KERNEL/arch/x86/boot/bzImage 파일을 적당한 위치에 복사해둡니다.

Image

Kernel Build를 완료했으면 Image 파일을 생성합니다. 우선 아래의 패키지를 설치합니다.

1
apt install debootstrap

이후, 다음의 명령어로 bullseye.img를 생성합니다.

1
2
3
wget https://raw.githubusercontent.com/google/syzkaller/master/tools/create-image.sh -O create-image.sh
chmod +x create-image.sh
./create-image.sh --distribution buster

💡 Error?
syzkaller Readme에 나와 있는 기본 방법으로 create-image.sh 명령어를 실행하면 에러가 발생해서 위의 명령어를 사용해서 Image를 생성했습니다.

Qemu

모든 파일이 준비되었으므로 다음의 명령어로 Linux를 실행합니다. 만약 실행이 안된다면 빌드 과정에서 잘못 빌드된 것이기 때문에 다시 해야됩니다.

1
2
3
4
5
6
7
8
9
10
11
qemu-system-x86_64 \
	-m 2G \
	-smp 2 \
	-kernel ./boot/bzImage \
	-append "console=ttyS0 root=/dev/sda earlyprintk=serial net.ifnames=0" \
	-drive file=./boot/buster.img,format=raw \
	-net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \
	-net nic,model=e1000 \
	-enable-kvm \
	-nographic \
	-pidfile vm.pid

syzkaller

qemu까지 정상 작동한다면 아래와 같이 cfg 파일을 작성합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
	"target": "linux/amd64",
	"http": "127.0.0.1:56741",
	"workdir": "/root/syzkaller/workdir",
	"kernel_obj": "/root/syzkaller/linux-6.8-rc2",
	"image": "/root/syzkaller/qemu/boot/buster.img",
	"sshkey": "/root/syzkaller/qemu/ssh/buster.id_rsa",
	"syzkaller": "/root/syzkaller/syzkaller",
	"procs": 8,
	"type": "qemu",
	"vm": {
		"count": 4,
		"kernel": "/root/syzkaller/qemu/boot/bzImage",
		"cpu": 2,
		"mem": 2048
	}
}

그리고 다음의 명령어를 실행하면 퍼징이 시작되게 됩니다.

1
/root/syzkaller/syzkaller/bin/syz-manager -config=test.cfg

참고사이트

This post is licensed under CC BY 4.0 by the author.