
작성 및 유지관리: Ivan Fratric, [email protected]
저작권 2017 Google Inc. 모든 권리 보유.
Apache License, Version 2.0(이하 "라이선스")에 따라 라이선스가 부여됩니다. 라이선스를 준수하지 않는 한 이 파일을 사용할 수 없습니다. 라이선스 사본은 다음 주소에서 얻을 수 있습니다.
http://www.apache.org/licenses/LICENSE-2.0
관련 법률에 따라 요구되거나 서면으로 동의하지 않는 한, 본 라이선스에 따라 배포되는 소프트웨어는 "있는 그대로" 배포되며, 명시적이거나 묵시적인 어떠한 종류의 보증이나 조건도 없습니다. 본 라이선스에서 명시된 특정 권리와 제한 사항을 확인하려면 라이선스 본문을 참조하세요.
사용법 정보를 보려면 다음 명령을 실행하세요:
python3 generator.py --help
단일 .html 샘플을 생성하려면 다음을 실행하세요:
python generator.py --file <output file>
직접 작성한 템플릿을 사용하여 단일 .html 샘플을 생성하려면 다음을 실행하세요:
python generator.py --file <output file> --template <your custom template file>
단일 호출로 여러 샘플을 생성하려면 다음을 실행하세요:
python generator.py --output_dir <output directory> --no_of_files <number of output files>
생성된 샘플은 지정된 디렉터리에 배치되며 fuzz-<number>.html 형식으로 이름이 지정됩니다(예: fuzz-00001.html, fuzz-00002.html 등). 여러 샘플을 생성하면 입력 문법 파일을 한 번만 로드하고 파싱하면 되므로 더 빠릅니다.
generator.py는 메인 스크립트를 포함합니다. grammar.py를 라이브러리로 사용하며 DOM 퍼징을 위한 추가 헬퍼 코드를 포함합니다.
grammar.py는 대부분 애플리케이션에 독립적인 생성 엔진을 포함하므로 다른(즉, DOM이 아닌) 생성 기반 퍼저에서도 사용할 수 있습니다. 라이브러리로 사용할 수 있으므로 사용법은 아래 별도 섹션에서 설명합니다.
.txt 파일에는 문법 정의가 포함됩니다. 주요 파일은 3개로, html.txt, css.txt, js.txt가 각각 HTML, CSS, JavaScript 문법을 포함합니다. 이러한 루트 문법 파일은 다른 파일의 콘텐츠를 포함할 수 있습니다.
사용자 정의 문법으로 생성 엔진을 사용하려면 다음 Python 코드를 사용할 수 있습니다.
from grammar import Grammar
my_grammar = Grammar()
my_grammar.parse_from_file('input_file.txt')
result_string = my_grammar.generate_symbol('symbol_name')
다음 섹션에서는 문법 파일의 구문을 설명합니다.
Domato는 아래에 지정된 간단한 형식의 문맥 자유 문법(context-free grammar)이 주어지면 해당 문법에서 샘플을 생성하는 엔진을 기반으로 합니다.
문법은 다음 기본 형식의 규칙 집합으로 설명됩니다.
<symbol> = a mix of constants and <other_symbol>s
각 문법 규칙은 등호 문자로 구분된 왼쪽과 오른쪽을 포함합니다. 왼쪽에는 기호(symbol)가 있고, 오른쪽에는 해당 기호가 어떻게 확장될 수 있는지에 대한 세부 정보가 있습니다. 기호를 확장할 때 오른쪽의 모든 기호는 재귀적으로 확장되며, 기호가 아닌 모든 것은 단순히 출력에 복사됩니다. 단일 규칙은 입력 파일의 여러 줄에 걸쳐 있을 수 없습니다.
CSS 문법 일부의 다음 간단한 예를 살펴보세요.
<cssrule> = <selector> { <declaration> }
<selector> = a
<selector> = b
<declaration> = width:100%
문법 엔진이 해당 문법을 파싱하고 'cssrule'을 생성하도록 하면 다음 중 하나가 생성될 수 있습니다.
a { width:100% }
or
b { width:100% }
'selector' 기호에는 두 개의 규칙이 있습니다. 이 경우 생성기가 'selector'를 생성하도록 요청받으면 사용할 규칙을 무작위로 선택합니다. 'p' 속성을 사용하여 규칙의 확률을 지정할 수도 있습니다. 예:
<selector p=0.9> = a
<selector p=0.1> = b
이 경우 문자열 'a'가 'b'보다 더 자주 출력됩니다.
확률 외에도 기호에 적용할 수 있는 다른 속성이 있습니다. 이 속성들은 별도 섹션에 나열되어 있습니다.
HTML 샘플 생성을 위한 또 다른 예를 살펴보세요.
<html> = <lt>html<gt><head><body><lt>/html<gt>
<head> = <lt>head<gt>...<lt>/head<gt>
<body> = <lt>body<gt>...<lt>/body<gt>
'<' 및 '>'는 문법 구문에서 특별한 의미를 가지므로 여기서는 대신 <lt>와 <gt>를 사용합니다. 이러한 기호는 내장되어 있어 사용자가 정의할 필요가 없습니다. 모든 내장 기호 목록은 별도 섹션에서 제공됩니다.
프로그래밍 언어 코드를 생성하려면 유사한 구문을 사용할 수 있지만 몇 가지 차이점이 있습니다. 프로그래밍 언어 문법의 각 줄은 출력의 줄에 해당합니다. 그렇기 때문에 문법 구문은 다양한 프로그래밍 언어의 구문을 표현할 수 있도록 보다 자유로운 형식이 됩니다. 둘째, 줄을 생성할 때 줄을 출력하는 것 외에도 하나 이상의 변수가 생성될 수 있으며 이러한 변수는 다른 줄을 생성할 때 재사용될 수 있습니다. 다시 간단한 예를 살펴보겠습니다.
!varformat fuzzvar%05d
!lineguard try { <line> } catch(e) {}
!begin lines
<new element> = document.getElementById("<string min=97 max=122>");
<element>.doSomething();
!end lines
엔진에 5줄을 생성하도록 지시하면 다음과 같은 결과가 나올 수 있습니다.
try { var00001 = document.getElementById("hw"); } catch(e) {}
try { var00001.doSomething(); } catch(e) {}
try { var00002 = document.getElementById("feezcqbndf"); } catch(e) {}
try { var00002.doSomething(); } catch(e) {}
try { var00001.doSomething(); } catch(e) {}
다음 사항에 유의하세요.
<element> 대신 <new element>를 사용했습니다. 이는 생성기가 'element' 기호를 생성하는 대신 'element' 유형의 새 변수를 생성하도록 지시합니다.<string>은 내장 기호 중 하나이므로 정의할 필요가 없습니다.줄에서 첫 번째 '#' 문자 이후의 모든 내용은 주석으로 간주됩니다. 예를 들면 다음과 같습니다.
#This is a comment
문법 구문에는 어떤 규칙이 비재귀적이며 최대 재귀 수준에 도달했더라도 안전하게 사용할 수 있는지 퍼저에 알려주는 방법이 있습니다. 이는 'nonrecursive' 속성으로 수행됩니다. 아래에 예가 나와 있습니다.
!max_recursion 10
<test root=true> = <foobar>
<foobar> = foo<foobar>
<foobar nonrecursive> = bar
먼저 선택적 '!max_recursion' 문은 최대 재귀 깊이 수준(기본값 50)을 정의합니다. 'foobar'의 두 번째 생성 규칙이 비재귀(non-recursive)로 표시되어 있음을 확인하세요. 최대 재귀 수준에 도달하면 생성기는 'foobar' 기호에 대해 비재귀 규칙을 강제로 사용하므로 무한 재귀를 방지합니다.
Domato에서 문법 포함(including)과 가져오기(importing)는 서로 다른 맥락입니다.
포함(include)은 더 간단합니다. 다음을 사용할 수 있습니다.
!include other.txt
other.txt의 규칙을 현재 파싱 중인 문법에 포함합니다.
가져오기(import)는 약간 다르게 작동합니다.
!import other.txt
파서에게 새 Grammar() 객체를 생성하도록 지시하며, 이 객체는 특수 <import> 기호를 사용하여 현재 문법에서 참조할 수 있습니다. 예를 들면 다음과 같습니다.
<cssrule> = <import from=css.txt symbol=rule>
가져오기와 포함을 네임스페이스 관점에서 생각할 수 있습니다. !include는 포함된 문법을 단일 네임스페이스에 넣는 반면, !import는 새 네임스페이스를 생성하며, 이 네임스페이스는 <import> 기호와 'from' 속성으로 지정된 네임스페이스를 통해 액세스할 수 있습니다.
때로는 문법에서 사용자 정의 Python 코드를 호출하고 싶을 수 있습니다. 예를 들어 엔진을 사용하여 HTTP 응답을 생성하고 본문 길이가 'Size' 헤더와 일치하도록 하려고 한다고 가정해 보겠습니다. 이는 일반 문법 규칙으로는 불가능하므로 다음과 같이 사용자 정의 Python 코드를 포함하여 수행할 수 있습니다.
!begin function savesize
context['size'] = ret_val
!end function
!begin function createbody
n = int(context['size'])
ret_val = 'a' * n
!end function
<foo root> = <header><cr><lf><body>
<header> = Size: <int min=1 max=20 beforeoutput=savesize>
<body> = <call function=createbody>
Python 함수는 '!begin function <function_name>'와 '!end function' 명령 사이에 정의됩니다. 함수는 'beforeoutput' 속성을 사용하거나 <call> 기호를 사용하는 두 가지 방식으로 호출할 수 있습니다.
일부 기호에 'beforeoutput' 속성을 지정하면 해당 기호가 확장될 때 확장 결과가 샘플로 출력되기 직전에 해당 함수가 호출됩니다. 확장 결과는 ret_val 변수에 담겨 함수에 전달됩니다. 그러면 함수는 ret_val을 수정하거나, 나중에 사용하기 위해 저장하거나, 다른 작업을 수행할 수 있습니다.
특수 <call> 기호를 사용하면 언어 생성 중에 해당 기호가 발견될 때 함수('function' 속성에 지정됨)가 호출됩니다. 함수가 ret_val에 저장한 값은 확장 결과로 간주됩니다(ret_val이 샘플에 포함됩니다).
Python 코드는 다음 변수에 액세스할 수 있습니다.
context - 전체 샘플 생성 과정에서 전달되는 사전(dictionary)입니다. 값을 저장하고(위 예에서 크기를 저장하는 것처럼) 이후에 실행되는 규칙에서 해당 값을 검색하는 데 사용할 수 있습니다.attributes - 현재 처리 중인 기호에 해당하는 사전입니다. 함수에 매개변수를 전달하는 데 사용할 수 있습니다. 예를 들어 <call function=func foo=bar>와 같은 방식으로 함수를 호출하면 attributes[‘foo’]가 ‘bar’로 설정됩니다.ret_val - 함수 호출 결과로 출력될 값입니다. <call> 기호로 함수를 호출하면 빈 값으로 초기화되고, 그렇지 않으면 기호에서 생성된 값으로 초기화됩니다.다음 기호는 특별한 의미를 가지며 사용자가 재정의해서는 안 됩니다.
<lt> - ‘<’ 문자<gt> - ‘>’ 문자<hash> - ‘#’ 문자<cr> - CR 문자<lf> - LF 문자<space> - 공백 문자<tab> - 탭 문자<ex> - ‘!’ 문자<char> - ‘code’ 속성을 사용하여 임의의 ASCII 문자를 생성하는 데 사용할 수 있습니다. 예를 들어 <char code=97>은 ‘a’에 해당합니다. 지정하지 않으면 임의의 문자를 생성합니다. ‘min’ 및 ‘max’ 속성을 지원합니다.<hex> - 임의의 16진수 숫자를 생성합니다.<int>, <int 8>, <uint8>, , , , , , - 임의의 정수를 생성하는 데 사용할 수 있습니다. 생성될 정수 범위를 제한하는 데 사용할 수 있는 ‘min’ 및 ‘max’ 속성을 지원합니다. 출력을 텍스트 대신 리틀/빅 엔디언 형식의 바이너리로 만드는 ‘b’ 및 ‘be’ 속성을 지원합니다.다음 속성이 지원됩니다.
‘doSomething(<int id=1>, <int id=1>)’ 규칙에서 두 int는 결국 동일한 값을 가지게 됩니다. 첫 번째 인스턴스만 실제로 확장되고 두 번째는 첫 번째에서 복사됩니다.<call> 기호에서 사용됩니다. 자세한 내용은 ‘Python 코드 포함’ 섹션을 참조하세요.Domato로 발견된 일부 버그는 다음과 같습니다.
이 제품은 공식 Google 제품이 아닙니다.
<int16><uint16><int32><uint32><int64><uint64><float>, <double> - 임의의 부동 소수점 숫자를 생성합니다. ‘min’ 및 ‘max’ 속성(지정하지 않으면 0과 1)을 지원합니다. 출력을 바이너리로 만드는 ‘b’ 속성을 지원합니다.<string> - 임의의 문자열을 생성합니다. 생성되는 최소 및 최대 문자 코드를 제어하는 ‘min’ 및 ‘max’ 속성과 문자열 길이를 제어하는 ‘minlength’ 및 ‘maxlength’ 속성을 지원합니다.<htmlsafestring> - HTML 메타 문자를 이스케이프한다는 점을 제외하면 <string>과 동일하므로 문자열을 HTML 텍스트 또는 속성 값의 일부로 안전하게 포함할 수 있습니다.<lines> - 주어진 개수(‘count’ 속성)의 코드 줄을 출력합니다. 예시는 프로그래밍 언어 코드 생성 섹션을 참조하세요.<import> - 다른 문법에서 기호를 가져옵니다. 자세한 내용은 외부 문법 포함 섹션을 참조하세요.<call> - function 속성에 해당하는 사용자 정의 함수를 호출합니다. 자세한 내용은 문법에 Python 코드 포함 섹션을 참조하세요.