노현종

Merge

...@@ -219,26 +219,12 @@ namespace VulnUserCodeAnalyzer ...@@ -219,26 +219,12 @@ namespace VulnUserCodeAnalyzer
219 var repoBytes = Encoding.Unicode.GetBytes(repository); 219 var repoBytes = Encoding.Unicode.GetBytes(repository);
220 var repoBase64 = Convert.ToBase64String(repoBytes); 220 var repoBase64 = Convert.ToBase64String(repoBytes);
221 221
222 - var repoDir = new DirectoryInfo($@"C:\Repo\{repoBase64}"); 222 + foreach (var (userName, repository) in reposits)
223 - if (repoDir.Exists) 223 + {
224 - { 224 + Console.WriteLine($"{userName}, {repository}");
225 - continue; 225 + }
226 - }
227 - repoDir.Create();
228 - Console.WriteLine($"Clone... Path : {repoDir.FullName}, Url : {repository}");
229 - Clone(repoDir.FullName, repository);
230 226
231 - repoPath = repoDir.FullName; 227 + Console.ReadLine();
232 - userId = userName;
233 - }
234 - if (!string.IsNullOrWhiteSpace(repoPath) && !string.IsNullOrWhiteSpace(userId))
235 - {
236 - break;
237 - }
238 - repoWatch.Restart();
239 - }
240 - //Console.WriteLine("엔터를 누르세요");
241 - //Console.ReadLine();
242 228
243 /* hashDict = 사용된 사용자 함수 정보 */ 229 /* hashDict = 사용된 사용자 함수 정보 */
244 var hashDict = new Dictionary<int, HashSet<VulnAbstractCrawler.UserBlock>>(); 230 var hashDict = new Dictionary<int, HashSet<VulnAbstractCrawler.UserBlock>>();
...@@ -247,205 +233,197 @@ namespace VulnUserCodeAnalyzer ...@@ -247,205 +233,197 @@ namespace VulnUserCodeAnalyzer
247 stopwatch.Start(); 233 stopwatch.Start();
248 DirectoryInfo dirInfo = new DirectoryInfo(repoPath); 234 DirectoryInfo dirInfo = new DirectoryInfo(repoPath);
249 235
250 - /* 모든 .c 파일 탐색 */ 236 + /* 모든 .c 파일 탐색 */
251 - var codeFiles = dirInfo.EnumerateFiles("*.c", SearchOption.AllDirectories); 237 + var codeFiles = dirInfo.EnumerateFiles("*.c", SearchOption.AllDirectories);
252 - int totalFileCount = codeFiles.Count(); 238 + int totalFileCount = codeFiles.Count();
253 - int count = 0; 239 + int count = 0;
254 - foreach (var codeFile in codeFiles) 240 + foreach (var codeFile in codeFiles)
241 + {
242 + Console.WriteLine(codeFile.FullName);
243 + using (var reader = codeFile.OpenText())
255 { 244 {
256 - Console.WriteLine(codeFile.FullName); 245 + /* 사용자 코드를 함수별로 나눔 */
257 - using (var reader = codeFile.OpenText()) 246 + var dict = crawler.CrawlUserCode(reader);
247 + foreach (var item in dict)
258 { 248 {
259 - /* 사용자 코드를 함수별로 나눔 */ 249 + /* hashDict의 키와 item.key는 함수 블록의 코드 길이 */
260 - var dict = crawler.CrawlUserCode(reader); 250 + if (!hashDict.ContainsKey(item.Key))
261 - foreach (var item in dict)
262 { 251 {
263 - /* hashDict의 키와 item.key는 함수 블록의 코드 길이 */ 252 + hashDict[item.Key] = new HashSet<VulnAbstractCrawler.UserBlock>();
264 - if (!hashDict.ContainsKey(item.Key)) 253 + }
265 - { 254 + /* item.Value는 각 코드 길이 마다의 블록 정보
266 - hashDict[item.Key] = new HashSet<VulnAbstractCrawler.UserBlock>(); 255 + * Bloom Filter에 코드 블록 해쉬값 기록
267 - } 256 + */
268 - /* item.Value는 각 코드 길이 마다의 블록 정보 257 + foreach (var hash in item.Value)
269 - * Bloom Filter에 코드 블록 해쉬값 기록 258 + {
270 - */ 259 + hash.Path = codeFile.FullName;
271 - foreach (var hash in item.Value) 260 + hashDict[item.Key].Add(hash);
272 - { 261 + filter.Add(hash.Hash);
273 - hash.Path = codeFile.FullName;
274 - hashDict[item.Key].Add(hash);
275 - filter.Add(hash.Hash);
276 - }
277 } 262 }
278 - count++;
279 - double per = ((double)count / (double)totalFileCount) * 100;
280 - Console.WriteLine($"{count} / {totalFileCount} :: {per.ToString("#0.0")}%, 개체 수 : {hashDict.Count}");
281 } 263 }
264 + count++;
265 + double per = ((double)count / (double)totalFileCount) * 100;
266 + Console.WriteLine($"{count} / {totalFileCount} :: {per.ToString("#0.0")}%, 개체 수 : {hashDict.Count}");
282 } 267 }
283 - var findBlocks = new Queue<VulnAbstractCrawler.UserBlock>(); 268 + }
284 - var vulnDict = new Dictionary<string, IEnumerable<VulnRDS._Vuln>>(); 269 + var findBlocks = new Queue<VulnAbstractCrawler.UserBlock>();
285 - foreach (var set in hashDict) 270 + var vulnDict = new Dictionary<string, IEnumerable<VulnRDS._Vuln>>();
271 + foreach (var set in hashDict)
272 + {
273 + /* 사용자 코드의 길이 마다 DB로 부터 같은 길이의 CVE 레코드 목록 가져옴 */
274 + var cveList = VulnRDS.SelectVulnbyLen(set.Key).Select(v => v.Cve).Distinct();
275 + foreach (var cve in cveList)
286 { 276 {
287 - /* 사용자 코드의 길이 마다 DB로 부터 같은 길이의 CVE 레코드 목록 가져옴 */ 277 + if (!vulnDict.ContainsKey(cve))
288 - var cveList = VulnRDS.SelectVulnbyLen(set.Key).Select(v => v.Cve).Distinct();
289 - foreach (var cve in cveList)
290 { 278 {
291 - if (!vulnDict.ContainsKey(cve)) 279 + vulnDict[cve] = new HashSet<VulnRDS._Vuln>();
280 + var vulnHashSet = vulnDict[cve] as HashSet<VulnRDS._Vuln>;
281 + /* 같은 길이의 CVE에서 또 같은 종류의 CVE 레코드 목록 가져옴
282 + * 같은 종류의 CVE 레코드들이 사용자 코드에서 모두 포함되어야
283 + * CVE를 가지고 있다고 인정하는 프로그램 정책 때문
284 + */
285 + var searchedCveHashList = VulnRDS.SelectVulnbyCve(cve);
286 + Console.WriteLine($"cve:{cve}, {searchedCveHashList.Count()}개 가져옴");
287 + foreach (var s in searchedCveHashList)
292 { 288 {
293 - vulnDict[cve] = new HashSet<VulnRDS._Vuln>(); 289 + vulnHashSet.Add(s);
294 - var vulnHashSet = vulnDict[cve] as HashSet<VulnRDS._Vuln>;
295 - /* 같은 길이의 CVE에서 또 같은 종류의 CVE 레코드 목록 가져옴
296 - * 같은 종류의 CVE 레코드들이 사용자 코드에서 모두 포함되어야
297 - * CVE를 가지고 있다고 인정하는 프로그램 정책 때문
298 - */
299 - var searchedCveHashList = VulnRDS.SelectVulnbyCve(cve);
300 - Console.WriteLine($"CVE:{cve}, Received Count : {searchedCveHashList.Count()}");
301 - foreach (var s in searchedCveHashList)
302 - {
303 - vulnHashSet.Add(s);
304 - }
305 -
306 } 290 }
291 +
307 } 292 }
308 } 293 }
309 - var findCveDict = new Dictionary<string, List<VulnAbstractCrawler.UserBlock>>(); 294 + }
310 - var findCveList = new HashSet<string>(); 295 + var findCveDict = new Dictionary<string, List<VulnAbstractCrawler.UserBlock>>();
311 - /* 본격적인 취약점 매칭 부분 */ 296 + var findCveList = new HashSet<string>();
312 - foreach (var vulnSet in vulnDict) 297 + /* 본격적인 취약점 매칭 부분 */
298 + foreach (var vulnSet in vulnDict)
299 + {
300 + //Console.WriteLine($"-----cve:{vulnSet.Key}");
301 + bool match = false;
302 + foreach (var vuln in vulnSet.Value)
313 { 303 {
314 - Console.WriteLine($"-----cve:{vulnSet.Key}"); 304 + /* 사용자 코드 해쉬 저장해논 bloom filter에 취약점 레코드 해쉬값들이 포함되는지 확인
315 - bool match = false; 305 + * 포함이 된다는 건 해당 취약점 레코드가 사용자 코드에도 있다는 뜻(취약점)
316 - foreach (var vuln in vulnSet.Value) 306 + * 같은 종류의 CVE 레코드가 전부 필터에 포함된다면 취약점으로 판단한다.
307 + */
308 + if (filter.Contains(vuln.BlockHash))
317 { 309 {
318 - /* 사용자 코드 해쉬 저장해논 bloom filter에 취약점 레코드 해쉬값들이 포함되는지 확인 310 + if (hashDict.ContainsKey(vuln.LenFunc))
319 - * 포함이 된다는 건 해당 취약점 레코드가 사용자 코드에도 있다는 뜻(취약점)
320 - * 같은 종류의 CVE 레코드가 전부 필터에 포함된다면 취약점으로 판단한다.
321 - */
322 - if (filter.Contains(vuln.BlockHash))
323 { 311 {
324 - if (hashDict.ContainsKey(vuln.LenFunc)) 312 + /* Bloom Filter는 아쉽게도 포함 여부만 알 수 있기에
313 + * 포함되었음을 알았다면 검색해서 정보를 구한다. */
314 + var userBlock = hashDict[vuln.LenFunc].FirstOrDefault(b => b.Hash == vuln.BlockHash);
315 + if (userBlock == null)
325 { 316 {
326 - //Console.WriteLine("찾음"); 317 + continue;
327 - /* Bloom Filter는 아쉽게도 포함 여부만 알 수 있기에
328 - * 포함되었음을 알았다면 검색해서 정보를 구한다. */
329 - var userBlock = hashDict[vuln.LenFunc].FirstOrDefault(b => b.Hash == vuln.BlockHash);
330 - if (userBlock == null)
331 - {
332 - continue;
333 - }
334 - /* 해당 유저 블록을 임시 저장한다.
335 - * 밑에서 블록 정보를 DB로 전송하기 위해서다.
336 - */
337 - if (!findCveDict.ContainsKey(vuln.Cve))
338 - {
339 - findCveDict[vuln.Cve] = new List<VulnAbstractCrawler.UserBlock>();
340 - }
341 - userBlock.Url = vuln.Url;
342 - findCveDict[vuln.Cve].Add(userBlock);
343 - match = true;
344 } 318 }
319 + /* 해당 유저 블록을 임시 저장한다.
320 + * 밑에서 블록 정보를 DB로 전송하기 위해서다.
321 + */
322 + if (!findCveDict.ContainsKey(vuln.Cve))
323 + {
324 + findCveDict[vuln.Cve] = new List<VulnAbstractCrawler.UserBlock>();
325 + }
326 + userBlock.Url = vuln.Url;
327 + findCveDict[vuln.Cve].Add(userBlock);
328 + match = true;
345 } 329 }
346 - else
347 - {
348 - match = false;
349 - break;
350 - }
351 - }
352 - /* 취약점 레코드가 전부 있어야 CVE 찾음 인정 */
353 - if (match)
354 - {
355 - Console.WriteLine($"Matched CVE : {vulnSet.Key}");
356 - /* 찾았으면 cve값을 기록함 밑에서 찾은 cve 정보 전송하기 위해 */
357 - findCveList.Add(vulnSet.Key);
358 } 330 }
359 else 331 else
360 { 332 {
361 - Console.WriteLine("Not"); 333 + match = false;
334 + break;
362 } 335 }
363 } 336 }
364 - stopwatch.Stop(); 337 + /* 취약점 레코드가 전부 있어야 CVE 찾음 인정 */
365 - /* 매칭 끝 후처리 (출력, DB 전송 등) */ 338 + if (match)
366 - var hours = stopwatch.Elapsed.Hours;
367 - var minutes = stopwatch.Elapsed.Minutes;
368 - var seconds = stopwatch.Elapsed.Seconds;
369 - Console.WriteLine($"Elapsed Time : {hours.ToString("00")}:{minutes.ToString("00")}:{seconds.ToString("00")}");
370 - Console.WriteLine($"Matched CVE Count : {findCveList.Count}");
371 - //Console.ReadLine();
372 -
373 - var yearMatch = new Regex(@"CVE-(\d{4})-(\d+)");
374 - foreach (var cve in findCveList)
375 { 339 {
376 - Console.WriteLine(cve); 340 + Console.WriteLine($"CVE 찾음 {vulnSet.Key}");
377 - var c = yearMatch.Match(cve); 341 + /* 찾았으면 cve값을 기록함 밑에서 찾은 cve 정보 전송하기 위해 */
378 - int year = int.Parse(c.Groups[1].Value); 342 + findCveList.Add(vulnSet.Key);
379 - if (!CVE_JSON.CveDict.ContainsKey(year)) 343 + }
380 - { 344 + else
381 - continue; 345 + {
382 - } 346 + Console.WriteLine("없음");
383 - if (!CVE_JSON.CveDict[year].ContainsKey(cve)) 347 + }
384 - { 348 + }
385 - continue; 349 + stopwatch.Stop();
386 - } 350 + /* 매칭 끝 후처리 (출력, DB 전송 등) */
387 - var data = CVE_JSON.CveDict[year][cve]; 351 + var hours = stopwatch.Elapsed.Hours;
388 - 352 + var minutes = stopwatch.Elapsed.Minutes;
389 - /* 취약점 타입 분류 */ 353 + var seconds = stopwatch.Elapsed.Seconds;
390 - string type = "NORMAL"; 354 + Console.WriteLine($"경과 시간 {hours.ToString("00")}:{minutes.ToString("00")}:{seconds.ToString("00")}");
391 - if (data.Detail.IndexOf("overflow", StringComparison.CurrentCultureIgnoreCase) > 0) 355 + Console.WriteLine($"찾은 CVE 개수 : {findCveList.Count}");
392 - { 356 + var yearMatch = new Regex(@"CVE-(\d{4})-(\d+)");
393 - type = "OVERFLOW"; 357 + foreach (var cve in findCveList)
394 - } 358 + {
395 - else if (data.Detail.IndexOf("xss", StringComparison.CurrentCultureIgnoreCase) > 0) 359 + Console.WriteLine(cve);
396 - { 360 + var c = yearMatch.Match(cve);
397 - type = "XSS"; 361 + int year = int.Parse(c.Groups[1].Value);
398 - } 362 + if (!CVE_JSON.CveDict.ContainsKey(year))
399 - else if (data.Detail.IndexOf("injection", StringComparison.CurrentCultureIgnoreCase) > 0) 363 + {
400 - { 364 + continue;
401 - type = "SQLINJECTION"; 365 + }
402 - } 366 + if (!CVE_JSON.CveDict[year].ContainsKey(cve))
403 - else if (data.Detail.IndexOf("dos", StringComparison.CurrentCultureIgnoreCase) > 0) 367 + {
404 - { 368 + continue;
405 - type = "DOS"; 369 + }
406 - } 370 + var data = CVE_JSON.CveDict[year][cve];
407 - else if (data.Detail.IndexOf("Memory", StringComparison.CurrentCultureIgnoreCase) > 0)
408 - {
409 - type = "MEMORY";
410 - }
411 - else if (data.Detail.IndexOf("CSRF", StringComparison.CurrentCultureIgnoreCase) > 0)
412 - {
413 - type = "CSRF";
414 - }
415 - else if (data.Detail.IndexOf("inclusion", StringComparison.CurrentCultureIgnoreCase) > 0)
416 - {
417 - type = "FILEINCLUSION";
418 - }
419 - else if (data.Detail.IndexOf("EXCUTE", StringComparison.CurrentCultureIgnoreCase) > 0)
420 - {
421 - type = "EXCUTE";
422 - }
423 -
424 - var urlBytes = Convert.FromBase64String(findCveDict[cve].FirstOrDefault().Url);
425 - string url = Encoding.Unicode.GetString(urlBytes);
426 - //Console.WriteLine(findCveDict[cve].FirstOrDefault().Path.Replace(repoPath, ""));
427 -
428 - var vulnDetail = new VulnRDS.Vuln_detail
429 - {
430 - CveName = data.Code,
431 - Type = type,
432 - Level = data.Level.ToString(),
433 - Year = data.Year.ToString(),
434 - CveDetail = data.Detail,
435 - Publish_date = data.Publish_Date.ToString("yyyy-MM-dd"),
436 - Update_date = data.Update_Date.ToString("yyyy-MM-dd"),
437 - UserName = userId,
438 - Url = url,
439 - FileName = findCveDict[cve].FirstOrDefault().Path.Replace(repoPath, ""),
440 - FuncName = findCveDict[cve].FirstOrDefault().FuncName,
441 - Product = data.Type,
442 - };
443 -
444 - /* DB 전송 */
445 - VulnRDS.InsertVulnDetail(vulnDetail);
446 371
447 - Console.WriteLine($"Added CVE: {vulnDetail.CveName}, Type: {vulnDetail.Type}, CVSS: {vulnDetail.Level}"); 372 + /* 취약점 타입 분류 */
373 + string type = "NORMAL";
374 + if (data.Detail.IndexOf("overflow", StringComparison.CurrentCultureIgnoreCase) > 0)
375 + {
376 + type = "OVERFLOW";
377 + }
378 + else if (data.Detail.IndexOf("xss", StringComparison.CurrentCultureIgnoreCase) > 0)
379 + {
380 + type = "XSS";
448 } 381 }
382 + else if (data.Detail.IndexOf("injection", StringComparison.CurrentCultureIgnoreCase) > 0)
383 + {
384 + type = "SQLINJECTION";
385 + }
386 + else if (data.Detail.IndexOf("dos", StringComparison.CurrentCultureIgnoreCase) > 0)
387 + {
388 + type = "DOS";
389 + }
390 + else if (data.Detail.IndexOf("Memory", StringComparison.CurrentCultureIgnoreCase) > 0)
391 + {
392 + type = "MEMORY";
393 + }
394 + else if (data.Detail.IndexOf("CSRF", StringComparison.CurrentCultureIgnoreCase) > 0)
395 + {
396 + type = "CSRF";
397 + }
398 + else if (data.Detail.IndexOf("inclusion", StringComparison.CurrentCultureIgnoreCase) > 0)
399 + {
400 + type = "FILEINCLUSION";
401 + }
402 + else if (data.Detail.IndexOf("EXCUTE", StringComparison.CurrentCultureIgnoreCase) > 0)
403 + {
404 + type = "EXCUTE";
405 + }
406 +
407 + var urlBytes = Convert.FromBase64String(findCveDict[cve].FirstOrDefault().Url);
408 + string url = Encoding.Unicode.GetString(urlBytes);
409 +
410 + /* DB 전송 */
411 + VulnRDS.InsertVulnDetail(new VulnRDS.Vuln_detail
412 + {
413 + CveName = data.Code,
414 + Type = type,
415 + Level = data.Level.ToString(),
416 + Year = data.Year.ToString(),
417 + CveDetail = data.Detail,
418 + Publish_date = data.Publish_Date.ToString("yyyy-MM-dd"),
419 + Update_date = data.Update_Date.ToString("yyyy-MM-dd"),
420 + UserName = "samsung",
421 + Url = url,
422 + FileName = findCveDict[cve].FirstOrDefault().Path.Replace(@"C:\code", ""),
423 + FuncName = findCveDict[cve].FirstOrDefault().FuncName,
424 + Product = data.Type,
425 + });
426 + Console.WriteLine("추가 완료");
449 } 427 }
450 } 428 }
451 } 429 }
......