노현종

추상화 정규화 추가

...@@ -66,7 +66,7 @@ namespace VulnCrawler ...@@ -66,7 +66,7 @@ namespace VulnCrawler
66 } 66 }
67 public static void Run() { 67 public static void Run() {
68 // Repository 폴더들이 있는 주소를 지정하면 하위 폴더 목록을 가져옴(Repository 목록) 68 // Repository 폴더들이 있는 주소를 지정하면 하위 폴더 목록을 가져옴(Repository 목록)
69 - 69 + Regex.CacheSize = 50;
70 70
71 // var fields = VulnWorker.GetCriticalVariant(@"return _is_safe_url(url, host) and _is_safe_url(url.replace('\\', '/'), host)"); 71 // var fields = VulnWorker.GetCriticalVariant(@"return _is_safe_url(url, host) and _is_safe_url(url.replace('\\', '/'), host)");
72 var c = new VulnC(); 72 var c = new VulnC();
......
...@@ -20,6 +20,7 @@ namespace VulnCrawler ...@@ -20,6 +20,7 @@ namespace VulnCrawler
20 public bool HasCritical { get; set; } 20 public bool HasCritical { get; set; }
21 public string Code { get; set; } 21 public string Code { get; set; }
22 public string Hash { get; set; } 22 public string Hash { get; set; }
23 + public string AbsCode { get; set; }
23 public IEnumerable<string> CriticalList { get; set; } 24 public IEnumerable<string> CriticalList { get; set; }
24 25
25 } 26 }
...@@ -219,6 +220,7 @@ namespace VulnCrawler ...@@ -219,6 +220,7 @@ namespace VulnCrawler
219 } 220 }
220 public abstract IDictionary<string, IEnumerable<string>> ExtractGitCriticalMethodTable(string srcCode); 221 public abstract IDictionary<string, IEnumerable<string>> ExtractGitCriticalMethodTable(string srcCode);
221 222
223 + public abstract string Abstract(string blockCode, IDictionary<string, string> dict, IDictionary<string, string> methodDict);
222 /// <summary> 224 /// <summary>
223 /// 패치 전 코드 파일과 크리티컬 메서드 테이블로 부터 크리티컬 블록 추출 225 /// 패치 전 코드 파일과 크리티컬 메서드 테이블로 부터 크리티컬 블록 추출
224 /// </summary> 226 /// </summary>
...@@ -228,6 +230,8 @@ namespace VulnCrawler ...@@ -228,6 +230,8 @@ namespace VulnCrawler
228 public virtual IEnumerable<(string methodName, IList<Block> blocks)> Process(Blob oldBlob, IDictionary<string, IEnumerable<string>> table) { 230 public virtual IEnumerable<(string methodName, IList<Block> blocks)> Process(Blob oldBlob, IDictionary<string, IEnumerable<string>> table) {
229 foreach (var item in table) 231 foreach (var item in table)
230 { 232 {
233 + var methodTable = new Dictionary<string, string>();
234 + var varTable = new Dictionary<string, string>();
231 // 메서드 이름 235 // 메서드 이름
232 string methodName = item.Key; 236 string methodName = item.Key;
233 // 패치 전 원본 파일 스트림 237 // 패치 전 원본 파일 스트림
...@@ -255,8 +259,24 @@ namespace VulnCrawler ...@@ -255,8 +259,24 @@ namespace VulnCrawler
255 } 259 }
256 foreach (var block in blocks) 260 foreach (var block in blocks)
257 { 261 {
258 - block.Hash = MD5HashFunc(block.Code); 262 +
259 block.CriticalList = item.Value; 263 block.CriticalList = item.Value;
264 + block.AbsCode = Abstract(block.Code, varTable, methodTable);
265 + block.Hash = MD5HashFunc(block.AbsCode);
266 +
267 + }
268 +
269 + /* 추상화 및 정규화 */
270 + foreach (var block in blocks)
271 + {
272 + string code = block.Code;
273 +
274 + }
275 +
276 +
277 + foreach (var var in varTable)
278 + {
279 + Console.WriteLine($"{var.Key}, {var.Value}");
260 } 280 }
261 yield return (methodName, blocks); 281 yield return (methodName, blocks);
262 } 282 }
...@@ -299,12 +319,172 @@ namespace VulnCrawler ...@@ -299,12 +319,172 @@ namespace VulnCrawler
299 return string.Empty; 319 return string.Empty;
300 } 320 }
301 321
322 +
323 + public MethodVarList ExtractMethodVariantList(string line, bool skipDefine=true)
324 + {
325 + line = line.Trim();
326 + if (string.IsNullOrWhiteSpace(line))
327 + {
328 + return null;
329 + }
330 + if (line.StartsWith("//"))
331 + {
332 + return null;
333 + }
334 + var methodVarList = new MethodVarList() { Methods = new List<string>(), Vars = new List<string>() };
335 + string declarePattern = @"(?<Declare>[a-zA-Z0-9_\.]+)\s+[a-zA-Z0-9_\.]+\s*(=|;|,)";
336 + // 메서드 정규식 패턴
337 + string methodPattern = @"([a-zA-Z0-9_\.]+)\s*\(";
338 + // 변수 정규식 패턴
339 + string fieldPattern = @"\*?(?<Field>[a-zA-Z0-9_\.\[\]\-\>]+)";
340 + string fieldArrayPattern = @"(?<ArrayName>[a-zA-Z0-9_\.]+)\[.+\]";
341 + string invalidPattern = @"^[\d\.]+";
342 +
343 + string commentPattern = @"[""].*[""]";
344 +
345 + string commentPattern2 = @"\/\/.*";
346 + string commentPattern3 = @"\/\*.+\*\/";
347 +
348 + line = Regex.Replace(line, commentPattern, "");
349 + line = Regex.Replace(line, commentPattern2, "");
350 + line = Regex.Replace(line, commentPattern3, "");
351 + // 메서드 목록
352 + var methodSets = new HashSet<string>();
353 +
354 + // 선언 타입명 추출
355 + var declareMatch = Regex.Match(line, Regex.Escape(declarePattern));
356 + string declareName = string.Empty;
357 + if (declareMatch.Success)
358 + {
359 + declareName = declareMatch.Groups["Declare"]?.Value ?? string.Empty;
360 +
361 + }
362 + var methods = Regex.Matches(line, methodPattern);
363 + // 현재 코드 라인에서 메서드 목록 추가
364 + foreach (var met in methods)
365 + {
366 + var method = met as Match;
367 + if (method.Success)
368 + {
369 + if (ReservedList.Contains(method.Groups[1].Value))
370 + {
371 + continue;
372 + }
373 + methodSets.Add(method.Groups[1].Value);
374 + }
375 + }
376 + // Console.WriteLine("----");
377 + var arrayNames = Regex.Matches(line, fieldArrayPattern)
378 + .Cast<Match>()
379 + .Where(m => {
380 + if (m.Value.Equals(declareName))
381 + {
382 + return false;
383 + }
384 +
385 + /* 제일 앞자리가 숫자로 시작하면 넘어감 */
386 + if (Regex.IsMatch(m.Value, invalidPattern))
387 + {
388 + return false;
389 + }
390 +
391 + /* 전 단계에서 구한 메서드 목록에 있으면 넘어감 */
392 + if (methodSets.Contains(m.Value))
393 + {
394 + return false;
395 + }
396 + /* 예약어 목록에 있으면 넘어감 */
397 + if (ReservedList.Contains(m.Value))
398 + {
399 + return false;
400 + }
401 +
402 + /* 알파벳이 하나도 없으면 넘어감 */
403 + if (!m.Value.Any(c => char.IsLetter(c)))
404 + {
405 + return false;
406 + }
407 +
408 + /* 대문자로 구성된 변수면 넘어감 */
409 + if (skipDefine && m.Value.All(c => char.IsUpper(c) || !char.IsLetter(c)))
410 + {
411 + return false;
412 + }
413 +
414 + return true;
415 + })
416 + .Distinct(new MatchComparer());
417 +
418 + var arrays = arrayNames.Select(m => m.Groups["ArrayName"].Value);
419 +
420 + var vars = Regex.Matches(line, fieldPattern)
421 + .Cast<Match>()
422 + .Where(m => {
423 + if (m.Value.Equals(declareName))
424 + {
425 + return false;
426 + }
427 +
428 + /* 제일 앞자리가 숫자로 시작하면 넘어감 */
429 + if (Regex.IsMatch(m.Value, invalidPattern))
430 + {
431 + return false;
432 + }
433 +
434 + /* 전 단계에서 구한 메서드 목록에 있으면 넘어감 */
435 + if (methodSets.Contains(m.Value))
436 + {
437 + return false;
438 + }
439 + /* 예약어 목록에 있으면 넘어감 */
440 + if (ReservedList.Contains(m.Value))
441 + {
442 + return false;
443 + }
444 +
445 + /* 알파벳이 하나도 없으면 넘어감 */
446 + if(!m.Value.Any(c => char.IsLetter(c)))
447 + {
448 + return false;
449 + }
450 +
451 + /* 대문자로 구성된 변수면 넘어감 */
452 + if (skipDefine && m.Value.All(c => char.IsUpper(c) || !char.IsLetter(c)))
453 + {
454 + return false;
455 + }
456 +
457 + return true;
458 + })
459 + .Distinct(new MatchComparer());
460 +
461 + foreach (var x in vars)
462 + {
463 + if (x.Success)
464 + {
465 + methodVarList.Vars.Add(x.Groups["Field"].Value);
466 + }
467 + }
468 +
469 + foreach (var x in arrays)
470 + {
471 + methodVarList.Vars.Add(x);
472 + }
473 +
474 +
475 + foreach (var m in methodSets)
476 + {
477 + methodVarList.Methods.Add(m);
478 + }
479 + return methodVarList;
480 + }
481 +
302 /// <summary> 482 /// <summary>
303 /// 크리티컬 변수 목록 추출 483 /// 크리티컬 변수 목록 추출
304 /// </summary> 484 /// </summary>
305 /// <param name="line">현재 코드줄</param> 485 /// <param name="line">현재 코드줄</param>
306 /// <returns></returns> 486 /// <returns></returns>
307 - public IEnumerable<string> ExtractCriticalVariant(string line) 487 + public IEnumerable<string> ExtractCriticalVariant(string line, bool skipDefine=true)
308 { 488 {
309 line = line.Trim(); 489 line = line.Trim();
310 if (string.IsNullOrWhiteSpace(line)) 490 if (string.IsNullOrWhiteSpace(line))
...@@ -364,18 +544,11 @@ namespace VulnCrawler ...@@ -364,18 +544,11 @@ namespace VulnCrawler
364 { 544 {
365 return false; 545 return false;
366 } 546 }
367 -
368 - /* 대문자로 구성된 변수면 넘어감 */
369 - if (m.Value.All(c => char.IsUpper(c) || !char.IsLetter(c)))
370 - {
371 - return false;
372 - }
373 /* 제일 앞자리가 숫자로 시작하면 넘어감 */ 547 /* 제일 앞자리가 숫자로 시작하면 넘어감 */
374 if (Regex.IsMatch(m.Value, invalidPattern)) 548 if (Regex.IsMatch(m.Value, invalidPattern))
375 { 549 {
376 return false; 550 return false;
377 } 551 }
378 -
379 /* 전 단계에서 구한 메서드 목록에 있으면 넘어감 */ 552 /* 전 단계에서 구한 메서드 목록에 있으면 넘어감 */
380 if (methodSets.Contains(m.Value)) 553 if (methodSets.Contains(m.Value))
381 { 554 {
...@@ -386,14 +559,16 @@ namespace VulnCrawler ...@@ -386,14 +559,16 @@ namespace VulnCrawler
386 { 559 {
387 return false; 560 return false;
388 } 561 }
389 -
390 /* 알파벳이 하나도 없으면 넘어감 */ 562 /* 알파벳이 하나도 없으면 넘어감 */
391 if(!m.Value.Any(c => char.IsLetter(c))) 563 if(!m.Value.Any(c => char.IsLetter(c)))
392 { 564 {
393 return false; 565 return false;
394 } 566 }
395 - 567 + /* 대문자로 구성된 변수면 넘어감 */
396 - 568 + if (skipDefine && m.Value.All(c => char.IsUpper(c) || !char.IsLetter(c)))
569 + {
570 + return false;
571 + }
397 return true; 572 return true;
398 }) 573 })
399 .Distinct(new MatchComparer()); 574 .Distinct(new MatchComparer());
...@@ -437,4 +612,10 @@ namespace VulnCrawler ...@@ -437,4 +612,10 @@ namespace VulnCrawler
437 return obj.Value.GetHashCode(); 612 return obj.Value.GetHashCode();
438 } 613 }
439 } 614 }
615 +
616 + public class MethodVarList
617 + {
618 + public IList<string> Vars { get; set; }
619 + public IList<string> Methods { get; set; }
620 + }
440 } 621 }
......
...@@ -359,7 +359,6 @@ namespace VulnCrawler ...@@ -359,7 +359,6 @@ namespace VulnCrawler
359 { 359 {
360 continue; 360 continue;
361 } 361 }
362 -
363 if (!(trimLine.EndsWith("}") || trimLine.EndsWith(";"))) 362 if (!(trimLine.EndsWith("}") || trimLine.EndsWith(";")))
364 { 363 {
365 continue; 364 continue;
...@@ -370,7 +369,6 @@ namespace VulnCrawler ...@@ -370,7 +369,6 @@ namespace VulnCrawler
370 prevStartBlock = true; 369 prevStartBlock = true;
371 continue; 370 continue;
372 } 371 }
373 -
374 mainLine = true; 372 mainLine = true;
375 } 373 }
376 374
...@@ -398,11 +396,7 @@ namespace VulnCrawler ...@@ -398,11 +396,7 @@ namespace VulnCrawler
398 { 396 {
399 blockList.Add(new Block { Code = mains, HasCritical = criticalBlock, Num = crNum++ }); 397 blockList.Add(new Block { Code = mains, HasCritical = criticalBlock, Num = crNum++ });
400 } 398 }
401 -
402 -
403 } 399 }
404 -
405 -
406 } 400 }
407 401
408 bool cb = false; 402 bool cb = false;
...@@ -459,5 +453,75 @@ namespace VulnCrawler ...@@ -459,5 +453,75 @@ namespace VulnCrawler
459 453
460 return blockList; 454 return blockList;
461 } 455 }
456 +
457 + public override string Abstract(string blockCode, IDictionary<string, string> dict, IDictionary<string, string> methodDict)
458 + {
459 + var split = blockCode.Split('\n');
460 + var varName = "VAL";
461 + var methodName = "FUNC";
462 + int varIdx = dict.Count();
463 + int methodIdx = methodDict.Count();
464 +
465 + var removes = Regex.Split(blockCode, Environment.NewLine, RegexOptions.Multiline);
466 + StringBuilder builder = new StringBuilder();
467 + Console.ForegroundColor = ConsoleColor.DarkYellow;
468 + foreach (var item in removes)
469 + {
470 + if (string.IsNullOrWhiteSpace(item))
471 + {
472 + continue;
473 + }
474 + Console.Write(item);
475 + builder.Append(item);
476 + // Console.ReadLine();
477 + }
478 +// Console.WriteLine(builder.ToString());
479 + Console.ResetColor();
480 + foreach (var line in split)
481 + {
482 + var varList = ExtractMethodVariantList(line, skipDefine: false);
483 + if (varList == null)
484 + {
485 + continue;
486 + }
487 + foreach (var var in varList.Vars)
488 + {
489 + if (!dict.ContainsKey(var))
490 + {
491 + dict[var] = varName + varIdx++;
492 + }
493 + }
494 +
495 + foreach (var m in varList.Methods)
496 + {
497 + if (!methodDict.ContainsKey(m))
498 + {
499 + methodDict[m] = methodName + methodIdx++;
500 + }
501 + }
502 +
503 + }
504 +
505 + var sortVarDict = dict.OrderByDescending(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
506 + var sortMethodDict = methodDict.OrderByDescending(p => p.Key).ToDictionary(p => p.Key, p => p.Value);
507 +
508 + string temp = blockCode;
509 + foreach (var pair in sortVarDict)
510 + {
511 + temp = Regex.Replace(temp, $@"\b{pair.Key}\b", pair.Value);
512 + }
513 +
514 + foreach (var pair in sortMethodDict)
515 + {
516 + temp = Regex.Replace(temp, $@"\b{pair.Key}\b", pair.Value);
517 +
518 + }
519 + temp = Regex.Replace(temp, @"\s", "", RegexOptions.Multiline);
520 + temp = Regex.Replace(temp, @"{|}|;|\)|\(", "");
521 + temp = temp.ToUpper();
522 +
523 +
524 + return temp;
525 + }
462 } 526 }
463 } 527 }
......
...@@ -75,5 +75,10 @@ namespace VulnCrawler ...@@ -75,5 +75,10 @@ namespace VulnCrawler
75 { 75 {
76 throw new NotImplementedException(); 76 throw new NotImplementedException();
77 } 77 }
78 +
79 + public override string Abstract(string blockCode, IDictionary<string, string> dict, IDictionary<string, string> methodDict)
80 + {
81 + throw new NotImplementedException();
82 + }
78 } 83 }
79 } 84 }
......
...@@ -41,16 +41,13 @@ namespace VulnCrawler ...@@ -41,16 +41,13 @@ namespace VulnCrawler
41 41
42 42
43 private static void PrintPatchEntrys(IEnumerable<PatchEntryChanges> entrys, VulnAbstractCrawler self, string commitMsg, string cve) { 43 private static void PrintPatchEntrys(IEnumerable<PatchEntryChanges> entrys, VulnAbstractCrawler self, string commitMsg, string cve) {
44 -
45 foreach (var entry in entrys) { 44 foreach (var entry in entrys) {
46 // 기존 소스코드 45 // 기존 소스코드
47 var oldOid = entry.OldOid; 46 var oldOid = entry.OldOid;
48 -
49 try 47 try
50 { 48 {
51 Blob oldBlob = self.Repository.Lookup<Blob>(oldOid); 49 Blob oldBlob = self.Repository.Lookup<Blob>(oldOid);
52 string oldContent = oldBlob.GetContentText(); 50 string oldContent = oldBlob.GetContentText();
53 -
54 // 변경된 소스코드 51 // 변경된 소스코드
55 var newOid = entry.Oid; 52 var newOid = entry.Oid;
56 Blob newBlob = self.Repository.Lookup<Blob>(newOid); 53 Blob newBlob = self.Repository.Lookup<Blob>(newOid);
...@@ -116,6 +113,7 @@ namespace VulnCrawler ...@@ -116,6 +113,7 @@ namespace VulnCrawler
116 Console.WriteLine($"=====block({block.Num}, {block.HasCritical.ToString()})"); 113 Console.WriteLine($"=====block({block.Num}, {block.HasCritical.ToString()})");
117 Console.WriteLine(block.Code); 114 Console.WriteLine(block.Code);
118 Console.ResetColor(); 115 Console.ResetColor();
116 + Console.WriteLine($"AbsCode = \n{block.AbsCode}");
119 Console.WriteLine($"MD5 = {block.Hash}"); 117 Console.WriteLine($"MD5 = {block.Hash}");
120 } 118 }
121 119
......