Showing
3 changed files
with
81 additions
and
54 deletions
... | @@ -65,10 +65,6 @@ namespace VulnCrawler | ... | @@ -65,10 +65,6 @@ namespace VulnCrawler |
65 | 65 | ||
66 | /* 메인 동작 함수 */ | 66 | /* 메인 동작 함수 */ |
67 | public static void Run() { | 67 | public static void Run() { |
68 | - | ||
69 | - | ||
70 | - | ||
71 | - | ||
72 | // Repository 폴더들이 있는 주소를 지정하면 하위 폴더 목록을 가져옴(Repository 목록) | 68 | // Repository 폴더들이 있는 주소를 지정하면 하위 폴더 목록을 가져옴(Repository 목록) |
73 | Regex.CacheSize = 50; | 69 | Regex.CacheSize = 50; |
74 | 70 | ||
... | @@ -88,35 +84,6 @@ namespace VulnCrawler | ... | @@ -88,35 +84,6 @@ namespace VulnCrawler |
88 | { | 84 | { |
89 | continue; | 85 | continue; |
90 | } | 86 | } |
91 | - //var crawler = new VulnC(); | ||
92 | - //crawler.Init(directory); | ||
93 | - | ||
94 | - //Tree commitTree1 = crawler.Repository.Lookup<Commit>("e589db7a6a9c8f1557007f2cc765ee28ad7a1edd").Tree; | ||
95 | - ////Tree parentTree1 = crawler.Repository.Lookup<Commit>("344ba37bdc299660e1b1693b6999e5fe116893e1").Tree; | ||
96 | - | ||
97 | - //Commit commit = crawler.Repository.Lookup<Commit>("e589db7a6a9c8f1557007f2cc765ee28ad7a1edd"); | ||
98 | - | ||
99 | - //foreach (var parent in commit.Parents) | ||
100 | - //{ | ||
101 | - // Console.WriteLine($"Parent ID:{parent.Sha}"); | ||
102 | - // Tree commitTree = commit.Tree; | ||
103 | - // Tree parentTree = parent.Tree; | ||
104 | - // var patch = crawler.Repository.Diff.Compare<Patch>(commitTree, parentTree.); | ||
105 | - // foreach (var item in patch.Where(p => p.OldPath.EndsWith(".c"))) | ||
106 | - // { | ||
107 | - | ||
108 | - // Console.WriteLine(item.Status); | ||
109 | - // Console.WriteLine(item.Path); | ||
110 | - // Console.WriteLine(item.Patch); | ||
111 | - // } | ||
112 | - // Console.ReadLine(); | ||
113 | - | ||
114 | - //} | ||
115 | - | ||
116 | - | ||
117 | - ////Console.WriteLine(patch.Content); | ||
118 | - //Console.ReadLine(); | ||
119 | - | ||
120 | // 템플릿 패턴화 T : VulnAbstractCrawler | 87 | // 템플릿 패턴화 T : VulnAbstractCrawler |
121 | VulnWorker.Run<VulnC>(directory); | 88 | VulnWorker.Run<VulnC>(directory); |
122 | } | 89 | } | ... | ... |
... | @@ -67,6 +67,7 @@ namespace VulnCrawler | ... | @@ -67,6 +67,7 @@ namespace VulnCrawler |
67 | public string FileName { get; set; } = "NULL"; /* FileName */ | 67 | public string FileName { get; set; } = "NULL"; /* FileName */ |
68 | public string FuncName { get; set; } = "NULL"; /* funcName */ | 68 | public string FuncName { get; set; } = "NULL"; /* funcName */ |
69 | public string Url { get; set; } = "NULL"; /* Url */ | 69 | public string Url { get; set; } = "NULL"; /* Url */ |
70 | + public string Product { get; set; } | ||
70 | 71 | ||
71 | } | 72 | } |
72 | //connect | 73 | //connect |
... | @@ -242,7 +243,7 @@ namespace VulnCrawler | ... | @@ -242,7 +243,7 @@ namespace VulnCrawler |
242 | { | 243 | { |
243 | Connection = Conn, | 244 | Connection = Conn, |
244 | //db에 추가 | 245 | //db에 추가 |
245 | - CommandText = "INSERT INTO vulnDetail(type, year, level, userName, cveName, publish_date,update_date, cveDetail,fileName, funcName, url) VALUES(@type, @year, @level, @userName, @cveName, @publish_date,@update_date, @cveDetail,@fileName, @funcName,@url)" | 246 | + CommandText = "INSERT INTO vulnDetail(type, year, level, userName, cveName, publish_date,update_date, cveDetail,fileName, funcName, url, product) VALUES(@type, @year, @level, @userName, @cveName, @publish_date,@update_date, @cveDetail,@fileName, @funcName,@url,@product)" |
246 | }; | 247 | }; |
247 | cmd.Parameters.AddWithValue("@type", $"{vuln.Type}"); | 248 | cmd.Parameters.AddWithValue("@type", $"{vuln.Type}"); |
248 | cmd.Parameters.AddWithValue("@year", $"{vuln.Year}"); | 249 | cmd.Parameters.AddWithValue("@year", $"{vuln.Year}"); |
... | @@ -255,16 +256,16 @@ namespace VulnCrawler | ... | @@ -255,16 +256,16 @@ namespace VulnCrawler |
255 | cmd.Parameters.AddWithValue("@fileName", $"{vuln.FileName}"); | 256 | cmd.Parameters.AddWithValue("@fileName", $"{vuln.FileName}"); |
256 | cmd.Parameters.AddWithValue("@funcName", $"{vuln.FuncName}"); | 257 | cmd.Parameters.AddWithValue("@funcName", $"{vuln.FuncName}"); |
257 | cmd.Parameters.AddWithValue("@url", $"{vuln.Url}"); | 258 | cmd.Parameters.AddWithValue("@url", $"{vuln.Url}"); |
258 | - | 259 | + cmd.Parameters.AddWithValue("@product", $"{vuln.Product}"); |
259 | cmd.ExecuteNonQuery(); | 260 | cmd.ExecuteNonQuery(); |
260 | //콘솔출력용 | 261 | //콘솔출력용 |
261 | sql = "INSERT INTO vulnDetail(type, year, level, userName, cveName, publish_date,update_date, cveDetail,fileName, funcName, url) " + | 262 | sql = "INSERT INTO vulnDetail(type, year, level, userName, cveName, publish_date,update_date, cveDetail,fileName, funcName, url) " + |
262 | $"VALUES({vuln.Type}, {vuln.Year}, {vuln.Level}, {vuln.UserName}, {vuln.CveName},{vuln.Publish_date}, {vuln.Update_date}, {vuln.CveDetail}, {vuln.FileName}, {vuln.FuncName}, {vuln.Url})"; | 263 | $"VALUES({vuln.Type}, {vuln.Year}, {vuln.Level}, {vuln.UserName}, {vuln.CveName},{vuln.Publish_date}, {vuln.Update_date}, {vuln.CveDetail}, {vuln.FileName}, {vuln.FuncName}, {vuln.Url})"; |
263 | - Console.WriteLine(sql); | 264 | + // Console.WriteLine(sql); |
264 | } | 265 | } |
265 | catch (Exception e) | 266 | catch (Exception e) |
266 | { | 267 | { |
267 | - Console.WriteLine(e.ToString()); | 268 | + // Console.WriteLine(e.ToString()); |
268 | string es = e.ToString(); | 269 | string es = e.ToString(); |
269 | if (es.Contains("Connection must be valid and open")) | 270 | if (es.Contains("Connection must be valid and open")) |
270 | { | 271 | { | ... | ... |
... | @@ -111,10 +111,13 @@ namespace VulnUserCodeAnalyzer | ... | @@ -111,10 +111,13 @@ namespace VulnUserCodeAnalyzer |
111 | { | 111 | { |
112 | static void Main(string[] args) | 112 | static void Main(string[] args) |
113 | { | 113 | { |
114 | + /* 연도별 CVE JSON 파일 로드 */ | ||
114 | CVE_JSON.AutoLoad(); | 115 | CVE_JSON.AutoLoad(); |
115 | 116 | ||
117 | + /* 크롤러 타입 */ | ||
116 | var crawler = new VulnC(); | 118 | var crawler = new VulnC(); |
117 | 119 | ||
120 | + /* 매칭을 위한 자료구조 Bloom Filter */ | ||
118 | int capacity = 50000000; | 121 | int capacity = 50000000; |
119 | var filter = new Filter<string>(capacity); | 122 | var filter = new Filter<string>(capacity); |
120 | 123 | ||
... | @@ -146,10 +149,15 @@ namespace VulnUserCodeAnalyzer | ... | @@ -146,10 +149,15 @@ namespace VulnUserCodeAnalyzer |
146 | Console.WriteLine("연결 실패"); | 149 | Console.WriteLine("연결 실패"); |
147 | return; | 150 | return; |
148 | } | 151 | } |
152 | + | ||
153 | + /* hashDict = 사용된 사용자 함수 정보 */ | ||
149 | var hashDict = new Dictionary<int, HashSet<VulnAbstractCrawler.UserBlock>>(); | 154 | var hashDict = new Dictionary<int, HashSet<VulnAbstractCrawler.UserBlock>>(); |
155 | + /* 경과 시간 체크 */ | ||
150 | Stopwatch stopwatch = new Stopwatch(); | 156 | Stopwatch stopwatch = new Stopwatch(); |
151 | stopwatch.Start(); | 157 | stopwatch.Start(); |
152 | DirectoryInfo dirInfo = new DirectoryInfo(@"C:\code"); | 158 | DirectoryInfo dirInfo = new DirectoryInfo(@"C:\code"); |
159 | + | ||
160 | + /* 모든 .c 파일 탐색 */ | ||
153 | var codeFiles = dirInfo.EnumerateFiles("*.c", SearchOption.AllDirectories); | 161 | var codeFiles = dirInfo.EnumerateFiles("*.c", SearchOption.AllDirectories); |
154 | int totalFileCount = codeFiles.Count(); | 162 | int totalFileCount = codeFiles.Count(); |
155 | int count = 0; | 163 | int count = 0; |
... | @@ -158,17 +166,21 @@ namespace VulnUserCodeAnalyzer | ... | @@ -158,17 +166,21 @@ namespace VulnUserCodeAnalyzer |
158 | Console.WriteLine(codeFile.FullName); | 166 | Console.WriteLine(codeFile.FullName); |
159 | using (var reader = codeFile.OpenText()) | 167 | using (var reader = codeFile.OpenText()) |
160 | { | 168 | { |
169 | + /* 사용자 코드를 함수별로 나눔 */ | ||
161 | var dict = crawler.CrawlUserCode(reader); | 170 | var dict = crawler.CrawlUserCode(reader); |
162 | foreach (var item in dict) | 171 | foreach (var item in dict) |
163 | { | 172 | { |
173 | + /* hashDict의 키와 item.key는 함수 블록의 코드 길이 */ | ||
164 | if (!hashDict.ContainsKey(item.Key)) | 174 | if (!hashDict.ContainsKey(item.Key)) |
165 | { | 175 | { |
166 | hashDict[item.Key] = new HashSet<VulnAbstractCrawler.UserBlock>(); | 176 | hashDict[item.Key] = new HashSet<VulnAbstractCrawler.UserBlock>(); |
167 | } | 177 | } |
178 | + /* item.Value는 각 코드 길이 마다의 블록 정보 | ||
179 | + * Bloom Filter에 코드 블록 해쉬값 기록 | ||
180 | + */ | ||
168 | foreach (var hash in item.Value) | 181 | foreach (var hash in item.Value) |
169 | { | 182 | { |
170 | hash.Path = codeFile.FullName; | 183 | hash.Path = codeFile.FullName; |
171 | - | ||
172 | hashDict[item.Key].Add(hash); | 184 | hashDict[item.Key].Add(hash); |
173 | filter.Add(hash.Hash); | 185 | filter.Add(hash.Hash); |
174 | } | 186 | } |
... | @@ -178,12 +190,11 @@ namespace VulnUserCodeAnalyzer | ... | @@ -178,12 +190,11 @@ namespace VulnUserCodeAnalyzer |
178 | Console.WriteLine($"{count} / {totalFileCount} :: {per.ToString("#0.0")}%, 개체 수 : {hashDict.Count}"); | 190 | Console.WriteLine($"{count} / {totalFileCount} :: {per.ToString("#0.0")}%, 개체 수 : {hashDict.Count}"); |
179 | } | 191 | } |
180 | } | 192 | } |
181 | - //Console.ReadLine(); | ||
182 | - | ||
183 | var findBlocks = new Queue<VulnAbstractCrawler.UserBlock>(); | 193 | var findBlocks = new Queue<VulnAbstractCrawler.UserBlock>(); |
184 | var vulnDict = new Dictionary<string, IEnumerable<VulnRDS._Vuln>>(); | 194 | var vulnDict = new Dictionary<string, IEnumerable<VulnRDS._Vuln>>(); |
185 | foreach (var set in hashDict) | 195 | foreach (var set in hashDict) |
186 | { | 196 | { |
197 | + /* 사용자 코드의 길이 마다 DB로 부터 같은 길이의 CVE 레코드 목록 가져옴 */ | ||
187 | var cveList = VulnRDS.SelectVulnbyLen(set.Key).Select(v => v.Cve).Distinct(); | 198 | var cveList = VulnRDS.SelectVulnbyLen(set.Key).Select(v => v.Cve).Distinct(); |
188 | foreach (var cve in cveList) | 199 | foreach (var cve in cveList) |
189 | { | 200 | { |
... | @@ -191,6 +202,10 @@ namespace VulnUserCodeAnalyzer | ... | @@ -191,6 +202,10 @@ namespace VulnUserCodeAnalyzer |
191 | { | 202 | { |
192 | vulnDict[cve] = new HashSet<VulnRDS._Vuln>(); | 203 | vulnDict[cve] = new HashSet<VulnRDS._Vuln>(); |
193 | var vulnHashSet = vulnDict[cve] as HashSet<VulnRDS._Vuln>; | 204 | var vulnHashSet = vulnDict[cve] as HashSet<VulnRDS._Vuln>; |
205 | + /* 같은 길이의 CVE에서 또 같은 종류의 CVE 레코드 목록 가져옴 | ||
206 | + * 같은 종류의 CVE 레코드들이 사용자 코드에서 모두 포함되어야 | ||
207 | + * CVE를 가지고 있다고 인정하는 프로그램 정책 때문 | ||
208 | + */ | ||
194 | var searchedCveHashList = VulnRDS.SelectVulnbyCve(cve); | 209 | var searchedCveHashList = VulnRDS.SelectVulnbyCve(cve); |
195 | Console.WriteLine($"cve:{cve}, {searchedCveHashList.Count()}개 가져옴"); | 210 | Console.WriteLine($"cve:{cve}, {searchedCveHashList.Count()}개 가져옴"); |
196 | foreach (var s in searchedCveHashList) | 211 | foreach (var s in searchedCveHashList) |
... | @@ -203,30 +218,37 @@ namespace VulnUserCodeAnalyzer | ... | @@ -203,30 +218,37 @@ namespace VulnUserCodeAnalyzer |
203 | } | 218 | } |
204 | var findCveDict = new Dictionary<string, List<VulnAbstractCrawler.UserBlock>>(); | 219 | var findCveDict = new Dictionary<string, List<VulnAbstractCrawler.UserBlock>>(); |
205 | var findCveList = new HashSet<string>(); | 220 | var findCveList = new HashSet<string>(); |
221 | + /* 본격적인 취약점 매칭 부분 */ | ||
206 | foreach (var vulnSet in vulnDict) | 222 | foreach (var vulnSet in vulnDict) |
207 | { | 223 | { |
208 | //Console.WriteLine($"-----cve:{vulnSet.Key}"); | 224 | //Console.WriteLine($"-----cve:{vulnSet.Key}"); |
209 | bool match = false; | 225 | bool match = false; |
210 | foreach (var vuln in vulnSet.Value) | 226 | foreach (var vuln in vulnSet.Value) |
211 | { | 227 | { |
228 | + /* 사용자 코드 해쉬 저장해논 bloom filter에 취약점 레코드 해쉬값들이 포함되는지 확인 | ||
229 | + * 포함이 된다는 건 해당 취약점 레코드가 사용자 코드에도 있다는 뜻(취약점) | ||
230 | + * 같은 종류의 CVE 레코드가 전부 필터에 포함된다면 취약점으로 판단한다. | ||
231 | + */ | ||
212 | if (filter.Contains(vuln.BlockHash)) | 232 | if (filter.Contains(vuln.BlockHash)) |
213 | { | 233 | { |
214 | - // Console.WriteLine($"필터 확인 : {vuln.BlockHash}"); | ||
215 | if (hashDict.ContainsKey(vuln.LenFunc)) | 234 | if (hashDict.ContainsKey(vuln.LenFunc)) |
216 | { | 235 | { |
236 | + /* Bloom Filter는 아쉽게도 포함 여부만 알 수 있기에 | ||
237 | + * 포함되었음을 알았다면 검색해서 정보를 구한다. */ | ||
217 | var userBlock = hashDict[vuln.LenFunc].FirstOrDefault(b => b.Hash == vuln.BlockHash); | 238 | var userBlock = hashDict[vuln.LenFunc].FirstOrDefault(b => b.Hash == vuln.BlockHash); |
218 | if (userBlock == null) | 239 | if (userBlock == null) |
219 | { | 240 | { |
220 | - //Console.WriteLine("userBlock이 비어있습니다."); | ||
221 | continue; | 241 | continue; |
222 | } | 242 | } |
243 | + /* 해당 유저 블록을 임시 저장한다. | ||
244 | + * 밑에서 블록 정보를 DB로 전송하기 위해서다. | ||
245 | + */ | ||
223 | if (!findCveDict.ContainsKey(vuln.Cve)) | 246 | if (!findCveDict.ContainsKey(vuln.Cve)) |
224 | { | 247 | { |
225 | findCveDict[vuln.Cve] = new List<VulnAbstractCrawler.UserBlock>(); | 248 | findCveDict[vuln.Cve] = new List<VulnAbstractCrawler.UserBlock>(); |
226 | } | 249 | } |
227 | userBlock.Url = vuln.Url; | 250 | userBlock.Url = vuln.Url; |
228 | findCveDict[vuln.Cve].Add(userBlock); | 251 | findCveDict[vuln.Cve].Add(userBlock); |
229 | - //Console.WriteLine($"CVE:{vuln.Cve}, {userBlock.FuncName}, 블록 확인 : DB : {vuln.BlockHash}, User : {userBlock.Hash}"); | ||
230 | match = true; | 252 | match = true; |
231 | } | 253 | } |
232 | } | 254 | } |
... | @@ -236,10 +258,11 @@ namespace VulnUserCodeAnalyzer | ... | @@ -236,10 +258,11 @@ namespace VulnUserCodeAnalyzer |
236 | break; | 258 | break; |
237 | } | 259 | } |
238 | } | 260 | } |
261 | + /* 취약점 레코드가 전부 있어야 CVE 찾음 인정 */ | ||
239 | if (match) | 262 | if (match) |
240 | { | 263 | { |
241 | Console.WriteLine($"CVE 찾음 {vulnSet.Key}"); | 264 | Console.WriteLine($"CVE 찾음 {vulnSet.Key}"); |
242 | - | 265 | + /* 찾았으면 cve값을 기록함 밑에서 찾은 cve 정보 전송하기 위해 */ |
243 | findCveList.Add(vulnSet.Key); | 266 | findCveList.Add(vulnSet.Key); |
244 | } | 267 | } |
245 | else | 268 | else |
... | @@ -248,22 +271,18 @@ namespace VulnUserCodeAnalyzer | ... | @@ -248,22 +271,18 @@ namespace VulnUserCodeAnalyzer |
248 | } | 271 | } |
249 | } | 272 | } |
250 | stopwatch.Stop(); | 273 | stopwatch.Stop(); |
274 | + /* 매칭 끝 후처리 (출력, DB 전송 등) */ | ||
251 | var hours = stopwatch.Elapsed.Hours; | 275 | var hours = stopwatch.Elapsed.Hours; |
252 | var minutes = stopwatch.Elapsed.Minutes; | 276 | var minutes = stopwatch.Elapsed.Minutes; |
253 | var seconds = stopwatch.Elapsed.Seconds; | 277 | var seconds = stopwatch.Elapsed.Seconds; |
254 | Console.WriteLine($"경과 시간 {hours.ToString("00")}:{minutes.ToString("00")}:{seconds.ToString("00")}"); | 278 | Console.WriteLine($"경과 시간 {hours.ToString("00")}:{minutes.ToString("00")}:{seconds.ToString("00")}"); |
255 | - // CVE JSON 검색 | ||
256 | Console.WriteLine($"찾은 CVE 개수 : {findCveList.Count}"); | 279 | Console.WriteLine($"찾은 CVE 개수 : {findCveList.Count}"); |
257 | - | ||
258 | var yearMatch = new Regex(@"CVE-(\d{4})-(\d+)"); | 280 | var yearMatch = new Regex(@"CVE-(\d{4})-(\d+)"); |
259 | foreach (var cve in findCveList) | 281 | foreach (var cve in findCveList) |
260 | { | 282 | { |
261 | Console.WriteLine(cve); | 283 | Console.WriteLine(cve); |
262 | - | ||
263 | var c = yearMatch.Match(cve); | 284 | var c = yearMatch.Match(cve); |
264 | - | ||
265 | int year = int.Parse(c.Groups[1].Value); | 285 | int year = int.Parse(c.Groups[1].Value); |
266 | - | ||
267 | if (!CVE_JSON.CveDict.ContainsKey(year)) | 286 | if (!CVE_JSON.CveDict.ContainsKey(year)) |
268 | { | 287 | { |
269 | continue; | 288 | continue; |
... | @@ -273,19 +292,59 @@ namespace VulnUserCodeAnalyzer | ... | @@ -273,19 +292,59 @@ namespace VulnUserCodeAnalyzer |
273 | continue; | 292 | continue; |
274 | } | 293 | } |
275 | var data = CVE_JSON.CveDict[year][cve]; | 294 | var data = CVE_JSON.CveDict[year][cve]; |
295 | + | ||
296 | + /* 취약점 타입 분류 */ | ||
297 | + string type = "NORMAL"; | ||
298 | + if (data.Detail.IndexOf("overflow", StringComparison.CurrentCultureIgnoreCase) > 0) | ||
299 | + { | ||
300 | + type = "OVERFLOW"; | ||
301 | + } | ||
302 | + else if (data.Detail.IndexOf("xss", StringComparison.CurrentCultureIgnoreCase) > 0) | ||
303 | + { | ||
304 | + type = "XSS"; | ||
305 | + } | ||
306 | + else if (data.Detail.IndexOf("injection", StringComparison.CurrentCultureIgnoreCase) > 0) | ||
307 | + { | ||
308 | + type = "SQLINJECTION"; | ||
309 | + } | ||
310 | + else if (data.Detail.IndexOf("dos", StringComparison.CurrentCultureIgnoreCase) > 0) | ||
311 | + { | ||
312 | + type = "DOS"; | ||
313 | + } | ||
314 | + else if (data.Detail.IndexOf("Memory", StringComparison.CurrentCultureIgnoreCase) > 0) | ||
315 | + { | ||
316 | + type = "MEMORY"; | ||
317 | + } | ||
318 | + else if (data.Detail.IndexOf("CSRF", StringComparison.CurrentCultureIgnoreCase) > 0) | ||
319 | + { | ||
320 | + type = "CSRF"; | ||
321 | + } | ||
322 | + else if (data.Detail.IndexOf("inclusion", StringComparison.CurrentCultureIgnoreCase) > 0) | ||
323 | + { | ||
324 | + type = "FILEINCLUSION"; | ||
325 | + } | ||
326 | + else if (data.Detail.IndexOf("EXCUTE", StringComparison.CurrentCultureIgnoreCase) > 0) | ||
327 | + { | ||
328 | + type = "EXCUTE"; | ||
329 | + } | ||
330 | + var urlBytes = Convert.FromBase64String(findCveDict[cve].FirstOrDefault().Url); | ||
331 | + string url = Encoding.Unicode.GetString(urlBytes); | ||
332 | + | ||
333 | + /* DB 전송 */ | ||
276 | VulnRDS.InsertVulnDetail(new VulnRDS.Vuln_detail | 334 | VulnRDS.InsertVulnDetail(new VulnRDS.Vuln_detail |
277 | { | 335 | { |
278 | CveName = data.Code, | 336 | CveName = data.Code, |
279 | - Type = data.Type, | 337 | + Type = type, |
280 | Level = data.Level.ToString(), | 338 | Level = data.Level.ToString(), |
281 | Year = data.Year.ToString(), | 339 | Year = data.Year.ToString(), |
282 | CveDetail = data.Detail, | 340 | CveDetail = data.Detail, |
283 | - Publish_date = data.Publish_Date.ToString(), | 341 | + Publish_date = data.Publish_Date.ToString("yyyy-MM-dd"), |
284 | - Update_date = data.Update_Date.ToString(), | 342 | + Update_date = data.Update_Date.ToString("yyyy-MM-dd"), |
285 | UserName = "samsung", | 343 | UserName = "samsung", |
286 | - Url = findCveDict[cve].FirstOrDefault().Url, | 344 | + Url = url, |
287 | - FileName = findCveDict[cve].FirstOrDefault().Path, | 345 | + FileName = findCveDict[cve].FirstOrDefault().Path.Replace(@"C:\code", ""), |
288 | FuncName = findCveDict[cve].FirstOrDefault().FuncName, | 346 | FuncName = findCveDict[cve].FirstOrDefault().FuncName, |
347 | + Product = data.Type, | ||
289 | }); | 348 | }); |
290 | Console.WriteLine("추가 완료"); | 349 | Console.WriteLine("추가 완료"); |
291 | } | 350 | } | ... | ... |
-
Please register or login to post a comment