정보보안/fuzzing
[TheFuzzingBook] Breaking Things with Random Inputs
meanjung
2022. 1. 28. 14:44
Runner 클래스
- PUT 자체라고 볼 수 있음.
- 어떤 랜덤값을 실행하기 위해 임의로 뭔가 동작을 하는 프로그램
Fuzzer 클래스
- 랜덤한 문자열을 생성해서 fuzz()
- Runner 클래스에서 실행시키기
from typing import Dict, Tuple, Union, List, Any
import random, os, tempfile, subprocess
Outcome = str
#################################################
### Runner ######################################
#################################################
class Runner:
PASS = "PASS"
FAIL = "FAIL"
UNRESOLVED = "UNRESOLVED"
def __init__(self) -> None:
pass
def run(self, inp: str) -> Any:
return (inp, Runner.UNRESOLVED)
class PrintRunner(Runner):
def run(self, inp) -> Any:
print(inp)
return (inp, Runner.UNRESOLVED)
class ProgramRunner(Runner):
def __init__(self, program: Union[str, List[str]]) -> None:
self.program = program
def run_process(self, inp: str = "") -> subprocess.CompletedProcess:
return subprocess.run(self.program,
input=inp,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
def run(self, inp: str = "") -> Tuple[subprocess.CompletedProcess, Outcome]:
result = self.run_process(inp)
if result.returncode == 0:
outcome = self.PASS
elif result.returncode < 0:
outcome = self.FAIL
else:
outcome = self.UNRESOLVED
return (result, outcome)
class BinaryProgramRunner(ProgramRunner):
def run_process(self, inp: str = "") -> subprocess.CompletedProcess:
return subprocess.run(self.program,
input=inp.encode(),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
cat = ProgramRunner(program="cat")
#################################################
### Fuzzer ######################################
#################################################
class Fuzzer:
def __init__(self) -> None:
pass
# 랜덤한 문자열 생성
def fuzz(self) -> str:
return ""
# fuzz()에서 생성한 랜덤한 문자열 Runner에서 실행
def run(self, runner: Runner = Runner()) -> Tuple[subprocess.CompletedProcess, Outcome]:
return runner.run(self.fuzz())
def runs(self, runner: Runner = PrintRunner(), trials: int = 10)-> List[Tuple[subprocess.CompletedProcess, Outcome]]:
outcomes = []
for i in range(trials):
outcomes.append(self.run(runner))
return outcomes
class RandomFuzzer(Fuzzer):
def __init__(self, min_length: int = 10, max_length: int = 100,
char_start: int = 32, char_range: int = 32) -> None:
self.min_length = min_length
self.max_length = max_length
self.char_start = char_start
self.char_range = char_range
def fuzz(self) -> str:
string_length = random.randrange(self.min_length, self.max_length + 1)
out = ""
for i in range(0, string_length):
out += chr(random.randrange(self.char_start,
self.char_start + self.char_range))
return out
random_fuzzer = RandomFuzzer(min_length=20, max_length=20)
# for i in range(10):
# inp = random_fuzzer.fuzz()
# result, outcome = cat.run(inp)
# assert result.stdout == inp
# assert outcome == Runner.PASS
random_fuzzer.runs(cat, 10)