Home
System Hacking
🗑️

Dumb Fuzzing (With Linux)

Type
Fuzzing
TIME
2022/01/20 17:54
종류
Linux
1 more property

Dumb Fuzzing

이번 시간에는 Dumb Fuzzing이 무엇인지 Dumb Fuzzer을 이용하여 Target ProgramFuzzing하고 Crash를 찾아보겠습니다.
간단한 Fuzzer를 작성하고 간단한 Mutation을 통해서 데이터를 변조하고 자동으로 테스트할 수 있도록 코드를 Dumb Fuzzer를 만들어 봅시다.
Dumb Fuzzing을 시작하기 전 먼저 대상을 정해야합니다.

Fuzzing Target

저는 퍼징 대상을 unzip이라는 압축 유틸리티로 설정하였습니다.
apt-get update && apt-get install unzip
Bash
복사

Seed File

unzipzip file을 입력으로 받아 압축을 해제하는 바이너리임으로 zip 파일을 Seed File 사용해 Fuzzing을 진행하겠습니다.

Fuzzer

해당 글은 Dumb Fuzzing임으로 효울적인 Seed Fil, Smart 한 Fuzzer에 대해서는 이야기 하지 않고 간단하게 Fuzzer를 작성하고 돌려보는 것에 의미를 두겠습니다.
일단 먼저 시작하기 전 아래와 같이 crash, sample, tmp 폴더를 생성한 뒤 sample 폴더에 zip 파일을 넣어줍니다.

Fuzzing Ready

Fuzzing 준비 단계에서는 우리가 사용할 sample 파일 데이터를 불러오며 어떤 파일을 사용할지 선택해야합니다.
아래의 코드의 Ready 함수를 통해서 sample 파일을 랜덤으로 선택하여 데이터를 불러오겠습니다.
import random import glob def Ready(sample_path): file_list = glob.glob(sample_path+'/*') temp_file = random.choice(file_list) f = open(temp_file, 'rb').read() return bytearray(f)
Python
복사
sample_path : sample 파일이 존재하는 폴더 경로
해당 함수는 아래의 코드를 추가하여 실제 데이터를 확인할 수 있습니다.
print(Ready('sample')[:10])
Python
복사

Fuzzing Mutator

랜덤한 Seed 파일을 선택했다면 이제 Seed 파일을 기반으로 Mutation을 진행해야합니다.
아래의 코드의 Mutator 함수를 통해서 랜덤한 데이터를 생성한 뒤 파일로 저장하겠습니다.
import time def Mutator(flips_pro, tmp, file_format): byte_data = Ready('sample') flips_count = int(len(byte_data) * flips_pro) + 1 range_byte_data = range(len(byte_data)) flips_index = [] index = 0 while index < flips_count: flips_index.append(random.choice(range_byte_data)) index += 1 for i in flips_index: byte_data[i] = random.getrandbits(8) input_path = tmp +'/'+str(int(time.time()))+ file_format f = open(input_path, 'wb') f.write(byte_data) f.close() return input_path
Python
복사
flips_pro : 데이터의 얼마만큼을 Mutation 할 지
tmp : tmp 폴더 경로
file_format : Fuzzing을 진행하는 파일 포맷
위 코드에서 실제 파일을 생성하고 싶다면 아래의 코드를 추가하여 확인할 수 있습니다.
Mutator(0.1, 'tmp', '.zip')
Python
복사
전체적인 코드는 아래와 동일합니다.
import random import glob import time def Ready(sample_path): file_list = glob.glob(sample_path+'/*') temp_file = random.choice(file_list) f = open(temp_file, 'rb').read() return bytearray(f) def Mutator(flips_pro, tmp, file_format): byte_data = Ready('sample') flips_count = int(len(byte_data) * flips_pro) + 1 range_byte_data = range(len(byte_data)) flips_index = [] index = 0 while index < flips_count: flips_index.append(random.choice(range_byte_data)) index += 1 for i in flips_index: byte_data[i] = random.getrandbits(8) input_path = tmp +'/'+str(int(time.time()))+ file_format f = open(input_path, 'wb') f.write(byte_data) f.close() return input_path
Python
복사

Fuzzing Runner

실제 Target Binary를 실행할 Runner를 구현해 줍니다.
from pexpect import run def Runner(flips_pro, tmp, file_format): input_path = Mutator(flips_pro, tmp, file_format) command = "unzip -e ./{} -d ./tmp/".format(input_path) out, returncode = run('{}'.format(command), withexitstatus=1, timeout=3) if b"Segmentation" in out: print("FIND CRASH!") run('cp ./{} ./crash/{}.zip'.format(input_path, str(int(time.time())))) run('sh -c \'rm -rf ./tmp/*\'')
Python
복사
pexpect 라이브러리의 run 함수를 이용하여 바이너리를 실행하고 stdoutreturncode를 받아 Segmentation Fault를 탐지하고 Crash 파일을 저장합니다.

Fuzzing Fuzzing

이제 실제 Fuzzing을 연속해서 진행하는 함수를 구현하여 마무리합니다.
전체적인 코드는 아래와 같습니다.
import random import glob import time from pexpect import run def Ready(sample_path='sample'): file_list = glob.glob(sample_path+'/*') temp_file = random.choice(file_list) f = open(temp_file, 'rb').read() return bytearray(f) def Mutator(flips_pro, tmp, file_format): byte_data = Ready('sample') flips_count = int(len(byte_data) * flips_pro) + 1 range_byte_data = range(len(byte_data)) flips_index = [] index = 0 while index < flips_count: flips_index.append(random.choice(range_byte_data)) index += 1 for i in flips_index: byte_data[i] = random.getrandbits(8) input_path = tmp +'/'+str(int(time.time()))+ file_format f = open(input_path, 'wb') f.write(byte_data) f.close() return input_path def Runner(flips_pro, tmp, file_format): input_path = Mutator(flips_pro, tmp, file_format) command = "unzip -e ./{} -d ./tmp/".format(input_path) out, returncode = run('{}'.format(command), withexitstatus=1, timeout=3) if b"Segmentation" in out: print("FIND CRASH!") run('cp ./{} ./crash/{}.zip'.format(input_path, str(int(time.time())))) run('sh -c \'rm -rf ./tmp/*\'') def Fuzzing(count ,flips_pro, tmp, file_format): index = 0 while index < count: if index % 10 == 0: print(index) Runner(flips_pro, tmp, file_format) index+=1 Fuzzing(100, 0.01, 'tmp', '.zip')
Python
복사
이상으로 Dumb Fuzzer 만들기를 성공하셨습니다.
아직은 Dumb FuzzerCrash를 발견하지 못 할수 있습니다.
다음시간에는 Smart Fuzzer에 대해서 알아보고 직접 코드를 작성해 보겠습니다.

Reference