Showing
5 changed files
with
271 additions
and
23 deletions
... | @@ -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 | } |
... | @@ -298,13 +318,173 @@ namespace VulnCrawler | ... | @@ -298,13 +318,173 @@ namespace VulnCrawler |
298 | } | 318 | } |
299 | return string.Empty; | 319 | return string.Empty; |
300 | } | 320 | } |
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 | + } | ||
301 | 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 | ||
... | @@ -178,7 +176,7 @@ namespace VulnCrawler | ... | @@ -178,7 +176,7 @@ namespace VulnCrawler |
178 | catch (Exception e) | 176 | catch (Exception e) |
179 | { | 177 | { |
180 | // Console.WriteLine(entry.Patch); | 178 | // Console.WriteLine(entry.Patch); |
181 | - // Console.WriteLine(e.ToString()); | 179 | + // Console.WriteLine(e.ToString()); |
182 | // Console.ReadLine(); | 180 | // Console.ReadLine(); |
183 | continue; | 181 | continue; |
184 | } | 182 | } | ... | ... |
-
Please register or login to post a comment