노현종

ExtractGitCriticalMethodTable 추가

변경된 메서드와 변경된 코드 라인 그리고 각 라인에서 메서드-크리티컬 변수 딕셔너리 맵핑
......@@ -67,6 +67,7 @@ namespace VulnCrawler
public static void Run() {
// Repository 폴더들이 있는 주소를 지정하면 하위 폴더 목록을 가져옴(Repository 목록)
// var fields = VulnWorker.GetCriticalVariant(@"return _is_safe_url(url, host) and _is_safe_url(url.replace('\\', '/'), host)");
var c = new VulnC();
var fields = c.ExtractCriticalVariant(@"if (s->session->peer != s->session->sess_cert->peer_key->x509)");
......
......@@ -13,11 +13,10 @@ namespace VulnCrawler
// 추상 클래스
public abstract class VulnAbstractCrawler
{
protected Regex extractMethodLine;
protected HashSet<string> ReservedList { get; }
protected abstract string ReservedFileName { get; }
// = { "if", "return", "break", "while", "typedef" };
/// <summary>
/// 생성자
/// 경로를 입력받아서(path)
......@@ -25,20 +24,16 @@ namespace VulnCrawler
/// 커밋 목록을 검색함
/// </summary>
/// <param name="path"></param>
public VulnAbstractCrawler() {
public VulnAbstractCrawler()
{
extractMethodLine = new Regex(RegexFuncPattern);
ReservedList = new HashSet<string>();
LoadReservedList();
}
// 소멸자
~VulnAbstractCrawler() {
Repository?.Dispose();
}
private void LoadReservedList()
{
try
......@@ -46,13 +41,11 @@ namespace VulnCrawler
var lines = File.ReadLines(ReservedFileName, Encoding.Default);
foreach (var item in lines)
{
if (string.IsNullOrWhiteSpace(item))
{
continue;
}
ReservedList.Add(item);
}
}
catch(FileNotFoundException)
......@@ -61,7 +54,6 @@ namespace VulnCrawler
}
}
protected virtual Regex MethodExtractor => new Regex(RegexFuncPattern);
#region 메서드 패턴 정규식 그룹
// 정규식 그룹화
// @@ -oldStart,oldLines +newStart,newLines @@ MethodName():
......@@ -114,7 +106,10 @@ namespace VulnCrawler
/// <returns>함수 문자열</returns>
protected abstract string GetOriginalFunc(Stream oldStream, string methodName);
// 테스트용 함수 곧 삭제될 운명
/// <summary>
/// 성능 개선을 위한
/// 코드 라인 위치 기반 취약 원본 함수 추출 테스트용 함수 곧 삭제 예정
/// </summary>
public string GetOriginalFuncTest(Stream oldStream, string methodName, int start)
{
StringBuilder oldBuilder = new StringBuilder();
......@@ -227,6 +222,9 @@ namespace VulnCrawler
return oldBuilder.ToString();
}
public abstract IDictionary<string, IEnumerable<string>> ExtractGitCriticalMethodTable(string srcCode);
/// <summary>
/// 실제 프로세스
/// </summary>
......@@ -237,9 +235,10 @@ namespace VulnCrawler
// 패치 전 원본 함수 구하고
string func = GetOriginalFunc(oldStream, methodName);
// 주석 제거하고
// func = RemoveComment(func);
//func = RemoveComment(func);
// 해쉬하고
string md5 = MD5HashFunc(func);
// 튜플로 반환
return (func, md5);
}
/// <summary>
......@@ -332,11 +331,11 @@ namespace VulnCrawler
var method = met as Match;
if (method.Success)
{
Console.WriteLine(method.Groups[1].Value);
// Console.WriteLine(method.Groups[1].Value);
methodSets.Add(method.Groups[1].Value); // aaaa
}
}
Console.WriteLine("----");
// Console.WriteLine("----");
var vars = Regex.Matches(line, fieldPattern)
.Cast<Match>()
.Where(m => {
......@@ -359,6 +358,12 @@ namespace VulnCrawler
{
return false;
}
/* 알파벳이 하나도 없으면 넘어감 */
if(!m.Value.Any(c => char.IsLetter(c)))
{
return false;
}
return true;
})
.Distinct(new MatchComparer());
......
......@@ -10,7 +10,8 @@ namespace VulnCrawler
{
public class VulnC : VulnAbstractCrawler
{
protected override string RegexFuncPattern => $@"@@ \-(?<{OldStart}>\d+),(?<{OldLines}>\d+) \+(?<{NewStart}>\d+),(?<{NewLines}>\d+) @@ (?<{MethodName}>(static)?( const )? [\w]+ [\w]+\([\w \*\,\t\n]*[\)\,])";
// protected override string RegexFuncPattern => $@"@@ \-(?<{OldStart}>\d+),(?<{OldLines}>\d+) \+(?<{NewStart}>\d+),(?<{NewLines}>\d+) @@ (?<{MethodName}>(static)?( const )? [\w]+ [\w]+\([\w \*\,\t\n]*[\)\,])";
protected override string RegexFuncPattern => $@"(?<{MethodName}>(unsigned|static)?( const )? [\w]+ [\w]+\(([\w \*\,\t\n])*[\)\,])";
protected override string Extension => ".c";
protected override string ReservedFileName => "CReserved.txt";
public override MatchCollection GetMatches(string patchCode) {
......@@ -31,13 +32,79 @@ namespace VulnCrawler
return replace;
}
public override IDictionary<string, IEnumerable<string>> ExtractGitCriticalMethodTable(string srcCode)
{
var table = new Dictionary<string, IEnumerable<string>>();
string prevMethodName = string.Empty;
StringBuilder builder = new StringBuilder();
// 라인으로 나누고 @@가 시작하는 곳까지 생략
var split = Regex.Split(srcCode, "\n").SkipWhile(s => !s.StartsWith("@@")).ToArray();
for(int i = 0; i < split.Length; i++)
{
string line = split[i].Trim();
// 문자열 제거
line = Regex.Replace(line, @""".+""", "");
var methodMatch = extractMethodLine.Match(line);
string methodName = methodMatch.Groups[MethodName].Value.Trim();
// 추가된, 제거된 라인인지 확인
if (Regex.IsMatch(line, @"^[+-]\s"))
{
// 주석문인지 확인
if (Regex.IsMatch(line, @"^[+-]\s*(\*|\/\*|\*\/)"))
{
continue;
}
Console.WriteLine(line);
builder.AppendLine(line);
continue;
}
// 메서드 매칭이 성공했거나 마지막 문단일 경우
if (methodMatch.Success || i == split.Length - 1)
{
if (string.IsNullOrWhiteSpace(prevMethodName))
{
builder.Clear();
prevMethodName = methodName;
continue;
}
if (methodName.Contains("return"))
{
continue;
}
if (methodName.Contains("="))
{
continue;
}
if (!table.ContainsKey(prevMethodName))
{
table[prevMethodName] = new HashSet<string>();
}
var list = table[prevMethodName] as HashSet<string>;
foreach (var b in Regex.Split(builder.ToString(), "\n"))
{
// 각 수집된 라인 별로 크리티컬 변수 선정
foreach (var var in ExtractCriticalVariant(b))
{
if (string.IsNullOrWhiteSpace(var))
{
continue;
}
list.Add(var);
}
}
prevMethodName = methodName;
builder.Clear();
}
}
return table;
}
protected override string GetOriginalFunc(Stream oldStream, string methodName) {
StringBuilder oldBuilder = new StringBuilder();
methodName = Regex.Escape(methodName);
using (var reader = new StreamReader(oldStream)) {
Console.WriteLine(methodName);
string method = Regex.Escape(methodName);
using (var reader = new StreamReader(oldStream)) {
bool found = false;
bool found2 = false;
bool commentLine = false;
......@@ -131,7 +198,7 @@ namespace VulnCrawler
else
{
// 메서드 찾았는지 확인
if (Regex.Match(line, $"{methodName}").Success)
if (Regex.Match(line, $"{method}").Success)
{
string trim = line.Trim();
// 주석으로 시작했다면 넘어감
......@@ -146,13 +213,13 @@ namespace VulnCrawler
}
// 혹시 메서드가 문자열 사이에 있다면 넘어감..
if (Regex.Match(trim, $@"""[.]*({methodName})").Success)
if (Regex.Match(trim, $@"""[.]*({method})").Success)
{
continue;
}
// 만약 찾은 메서드 라인에서 중괄호 {가 시작된 경우
if (Regex.Match(trim, $@"{methodName}\s*" + @"\{").Success)
if (Regex.Match(trim, $@"{method}\s*" + @"\{").Success)
{
// 동시에 } 닫히기까지 한 경우 드물겠지만..
if (trim.EndsWith("}"))
......@@ -170,8 +237,8 @@ namespace VulnCrawler
}
}
Console.WriteLine(oldBuilder.ToString());
Console.ReadLine();
//Console.WriteLine(oldBuilder.ToString());
//Console.ReadLine();
return oldBuilder.ToString();
}
......
......@@ -65,5 +65,10 @@ namespace VulnCrawler
}
return replace;
}
public override IDictionary<string, IEnumerable<string>> ExtractGitCriticalMethodTable(string srcCode)
{
throw new NotImplementedException();
}
}
}
......
......@@ -84,17 +84,24 @@ namespace VulnCrawler
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"Commit Message: {commitMsg}");
Console.ResetColor();
Console.BackgroundColor = ConsoleColor.DarkRed;
Console.WriteLine($"Patched: \n{entry.Patch}");
Console.ResetColor();
// Console.WriteLine("-----------");
var table = self.ExtractGitCriticalMethodTable(entry.Patch);
foreach (var item in table)
{
Console.WriteLine($"Method : {item.Key}");
foreach (var b in item.Value)
{
Console.WriteLine($"--{b}");
}
}
Console.ReadLine();
}
else
{
continue;
}
......@@ -106,10 +113,11 @@ namespace VulnCrawler
foreach (var reg in regs)
{
var match = reg as Match;
string methodName = match.Groups[VulnAbstractCrawler.MethodName].Value.Trim();
int start = int.Parse(match.Groups[VulnAbstractCrawler.OldStart].Value);
Console.WriteLine("methodName = " + methodName);
int start = 0; //int.Parse(match.Groups[VulnAbstractCrawler.OldStart].Value);
// Console.WriteLine("methodName = " + methodName);
string originalFunc, md5;
(originalFunc, md5) = self.Process(oldBlob.GetContentStream(),
methodName, start);
......@@ -127,14 +135,17 @@ namespace VulnCrawler
//Console.WriteLine($"Patched: \n{entry.Patch}");
Console.ResetColor();
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("==============================");
Console.ResetColor();
#endregion
}
Console.ReadLine();
}
catch (Exception e)
{
Console.WriteLine(entry.Patch);
Console.WriteLine(e.ToString());
Console.ReadLine();
continue;
......