노현종

UserCodeAnalyzer 구현

......@@ -81,7 +81,7 @@ namespace VulnCrawler
/* 폴더 중에 linux가 있으면 잠깐 넘어감 (너무 커서 테스트 힘듦) */
if (directory.Contains("linux"))
{
// continue;
continue;
}
// 템플릿 패턴화 T : VulnAbstractCrawler
VulnWorker.Run<VulnC>(directory);
......
......@@ -45,6 +45,7 @@ namespace VulnCrawler
~VulnAbstractCrawler() {
Repository?.Dispose();
}
private void LoadReservedList()
{
try
......@@ -120,6 +121,8 @@ namespace VulnCrawler
/// <returns>함수 문자열</returns>
protected abstract string GetOriginalFunc(Stream oldStream, string methodName);
public abstract IDictionary<int, List<string>> CrawlUserCode(StreamReader reader);
protected abstract IList<Block> GetCriticalBlocks(string srcCode, IEnumerable<string> criticalList);
/// <summary>
/// 성능 개선을 위한
......@@ -401,11 +404,11 @@ namespace VulnCrawler
return false;
}
/* 대문자로 구성된 변수면 넘어감 */
if (skipDefine && m.Value.All(c => char.IsUpper(c) || !char.IsLetter(c)))
{
return false;
}
///* 대문자로 구성된 변수면 넘어감 */
//if (skipDefine && m.Value.All(c => char.IsUpper(c) || !char.IsLetter(c)))
//{
// return false;
//}
return true;
})
......@@ -447,11 +450,11 @@ namespace VulnCrawler
return false;
}
/* 대문자로 구성된 변수면 넘어감 */
if (skipDefine && m.Value.All(c => char.IsUpper(c) || !char.IsLetter(c)))
{
return false;
}
///* 대문자로 구성된 변수면 넘어감 */
//if (skipDefine && m.Value.All(c => char.IsUpper(c) || !char.IsLetter(c)))
//{
// return false;
//}
return true;
})
......
......@@ -12,11 +12,14 @@ namespace VulnCrawler
{
// 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 RegexFuncPattern => $@"^[\w \*]*(?<{MethodName}>[\w\*]+ [\w\*]+\(([\w \*\,\t\n])*[\)\,])";
/* 검색 파일 타입 */
protected override string Extension => ".c";
/* 예약어 파일명 */
protected override string ReservedFileName => "CReserved.txt";
/// <summary>
/// 패치 코드에서 함수 목록 뽑는 정규식
/// </summary>
......@@ -549,7 +552,7 @@ namespace VulnCrawler
{
return string.Empty;
}
foreach (var var in varList.Vars)
foreach (var var in varList.Vars.Where(s => s.All(c => char.IsLower(c) || c == '>' || c == '-' || c == '*' || c == '_')))
{
if (!dict.ContainsKey(var))
{
......@@ -638,5 +641,202 @@ namespace VulnCrawler
return temp;
}
public override IDictionary<int, List<string>> CrawlUserCode(StreamReader reader)
{
var dict = new Dictionary<int, List<string>>();
StringBuilder oldBuilder = new StringBuilder();
bool found = false;
bool found2 = false;
bool commentLine = false;
int bracketCount = -1;
string stringPattern = @"[""].*[""]";
string commentPattern = @"\/\*.+\*\/";
string commentPattern2 = @"\/\*";
string commentPattern3 = @"\*\/";
var regex1 = new Regex(commentPattern3, RegexOptions.Compiled);
var regex2 = new Regex(stringPattern, RegexOptions.Compiled);
var regex3 = new Regex(commentPattern2, RegexOptions.Compiled);
var regex4 = new Regex(commentPattern, RegexOptions.Compiled);
bool found3 = false;
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
Console.WriteLine(line);
// 메서드를 찾은 경우
if (found3)
{
string obStr = oldBuilder.ToString();
obStr = Abstract(obStr, new Dictionary<string, string>(), new Dictionary<string, string>());
if (!dict.ContainsKey(obStr.Length))
{
dict[obStr.Length] = new List<string>();
}
dict[obStr.Length].Add(MD5HashFunc(obStr));
oldBuilder.Clear();
found = false;
found2 = false;
found3 = false;
bracketCount = -1;
commentLine = false;
}
if (found)
{
string trim = line.Trim();
// 범위 주석 진행되고 있으면 넘어감
if (trim.StartsWith("#"))
{
continue;
}
if (commentLine)
{
// 혹시 범위 주석이 끝났는지 체크
if (regex1.IsMatch(trim))
{
commentLine = false;
trim = regex1.Split(trim)[1];
}
else
{
continue;
}
}
// "" 문자열 제거
string removeString = regex2.Replace(trim, "");
// /* ~ 패턴
if (regex3.IsMatch(trim))
{
// /* ~ */ 패턴이 아닌 경우
if (!regex4.IsMatch(trim))
{
commentLine = true;
}
trim = Regex.Split(trim, "/*")[0];
}
// 비어있는 경우 넘어감
if (string.IsNullOrWhiteSpace(trim))
{
continue;
}
int openBracketCount = removeString.Count(c => c == '{');
int closeBracketCount = removeString.Count(c => c == '}');
int subtract = openBracketCount - closeBracketCount;
bracketCount += subtract;
// 메서드 시작 괄호 찾은 경우
if (found2)
{
oldBuilder.AppendLine(line);
// 괄호가 모두 닫혔으니 종료
if (bracketCount < 0)
{
if (reader.EndOfStream)
{
Console.WriteLine("파일끝");
}
found3 = true;
continue;
}
}
else // 메서드는 찾았으나 아직 시작 괄호를 못찾은 경우
{
oldBuilder.AppendLine(line);
if (openBracketCount > 0)
{
found2 = true;
}
else
{
//아직 { 괄호를 못찾았는데 );를 만났다면 메서드 선언 부분이니 넘어감
if (trim.EndsWith(");"))
{
Console.WriteLine("-------");
Console.WriteLine(trim);
Console.WriteLine("-----");
found = false;
oldBuilder.Clear();
continue;
}
}
}
}
// 아직 메서드를 못찾은 경우
else
{
//아직 { 괄호를 못찾았는데 );를 만났다면 메서드 선언 부분이니 넘어감
if (line.Trim().EndsWith(");"))
{
found = false;
oldBuilder.Clear();
continue;
}
// 메서드 찾았는지 확인
if (Regex.IsMatch(line, RegexFuncPattern))
{
string trim = line.Trim();
// 주석으로 시작했다면 넘어감
if (trim.StartsWith("//"))
{
continue;
}
if (trim.StartsWith("/*"))
{
continue;
}
// 만약 찾은 메서드 라인에서 중괄호 {가 시작된 경우
if (trim.Contains("{"))
{
// 동시에 } 닫히기까지 한 경우 드물겠지만..
if (trim.EndsWith("}"))
{
oldBuilder.AppendLine(line);
found3 = true;
continue;
}
found2 = true;
}
// 메서드 찾음
found = true;
oldBuilder.AppendLine(line);
}
}
}
if (found3)
{
string obStr = oldBuilder.ToString();
obStr = Abstract(obStr, new Dictionary<string, string>(), new Dictionary<string, string>());
if (!dict.ContainsKey(obStr.Length))
{
dict[obStr.Length] = new List<string>();
}
dict[obStr.Length].Add(MD5HashFunc(obStr));
oldBuilder.Clear();
found = false;
found2 = false;
found3 = false;
bracketCount = -1;
commentLine = false;
}
return dict;
}
}
}
......
......@@ -80,5 +80,10 @@ namespace VulnCrawler
{
throw new NotImplementedException();
}
public override IDictionary<int, List<string>> CrawlUserCode(StreamReader reader)
{
throw new NotImplementedException();
}
}
}
......
......@@ -100,51 +100,67 @@ namespace VulnCrawler
Console.BackgroundColor = ConsoleColor.DarkRed;
Console.WriteLine($"메서드 이름 : {methodName}");
Console.ResetColor();
foreach (var block in blocks)
{
/* 크리티컬 블록이 아니면 볼 필요 없으니 넘어감 */
if (!block.HasCritical)
{
// Console.WriteLine("크리티컬 아님");
continue;
}
//foreach (var block in blocks)
//{
// /* 크리티컬 블록이 아니면 볼 필요 없으니 넘어감 */
// if (!block.HasCritical)
// {
// // Console.WriteLine("크리티컬 아님");
// continue;
// }
if (block.HasCritical)
{
Console.BackgroundColor = ConsoleColor.DarkMagenta;
}
else
{
Console.BackgroundColor = ConsoleColor.DarkGreen;
}
/* 블록 정보 출력(블록 번호, 블록 소스코드, 블록 추상화 코드, 블록 해쉬값) */
Console.WriteLine($"=====block({block.Num}, {block.HasCritical.ToString()})");
Console.WriteLine(block.Code);
Console.ResetColor();
Console.WriteLine($"AbsCode = \n{block.AbsCode}");
Console.WriteLine($"MD5 = {block.Hash}");
// if (block.HasCritical)
// {
// Console.BackgroundColor = ConsoleColor.DarkMagenta;
// }
// else
// {
// Console.BackgroundColor = ConsoleColor.DarkGreen;
// }
// /* 블록 정보 출력(블록 번호, 블록 소스코드, 블록 추상화 코드, 블록 해쉬값) */
// Console.WriteLine($"=====block({block.Num}, {block.HasCritical.ToString()})");
// Console.WriteLine(block.Code);
// Console.ResetColor();
// Console.WriteLine($"AbsCode = \n{block.AbsCode}");
// Console.WriteLine($"MD5 = {block.Hash}");
/* base64 인코딩(MySQL에 들어갈 수 없는 문자열이 있을 수 있으므로 인코딩) */
byte[] funcNameBytes = Encoding.Unicode.GetBytes(methodName);
byte[] codeOriBeforeBytes = Encoding.Unicode.GetBytes(oriFunc);
byte[] codeAbsBeforeBytes = Encoding.Unicode.GetBytes(block.AbsCode);
// /* base64 인코딩(MySQL에 들어갈 수 없는 문자열이 있을 수 있으므로 인코딩) */
// byte[] funcNameBytes = Encoding.Unicode.GetBytes(methodName);
// byte[] codeOriBeforeBytes = Encoding.Unicode.GetBytes(oriFunc);
// byte[] codeAbsBeforeBytes = Encoding.Unicode.GetBytes(block.AbsCode);
// /* VulnDB에 하나의 레코드로 들어가는 하나의 취약점 객체 */
// VulnRDS.Vuln vuln = new VulnRDS.Vuln()
// {
// Cve = cve,
// BlockHash = block.Hash,
// LenBlock = block.Code.Length,
// FuncName = Convert.ToBase64String(funcNameBytes),
// //CodeOriBefore = Convert.ToBase64String(codeOriBeforeBytes),
// //CodeAbsBefore = Convert.ToBase64String(codeAbsBeforeBytes),
// //NumBlock = block.Num,
// };
// Console.WriteLine($"Vuln FuncName:{vuln.FuncName}");
/* VulnDB에 추가 */
//VulnRDS.InsertVulnData(vuln);
//}
string abstractCode = self.Abstract(oriFunc, new Dictionary<string, string>(), new Dictionary<string, string>());
/* VulnDB에 하나의 레코드로 들어가는 하나의 취약점 객체 */
byte[] funcNameBytes = Encoding.Unicode.GetBytes(methodName);
byte[] absCodeBytes = Encoding.Unicode.GetBytes(abstractCode);
VulnRDS.Vuln vuln = new VulnRDS.Vuln()
{
BlockHash = Convert.ToBase64String(absCodeBytes),
Cve = cve,
BlockHash = block.Hash,
LenBlock = block.Code.Length,
LenBlock = oriFunc.Length,
FuncName = Convert.ToBase64String(funcNameBytes),
CodeOriBefore = Convert.ToBase64String(codeOriBeforeBytes),
CodeAbsBefore = Convert.ToBase64String(codeAbsBeforeBytes),
NumBlock = block.Num,
};
Console.WriteLine($"Vuln FuncName:{vuln.FuncName}");
Console.WriteLine(vuln.BlockHash);
Console.ReadLine();
/* VulnDB에 추가 */
VulnRDS.InsertVulnData(vuln);
}
//VulnRDS.InsertVulnData(vuln);
}
}
else
......
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>
\ No newline at end of file
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using VulnCrawler;
namespace VulnUserCodeAnalyzer
{
class Program
{
static void Main(string[] args)
{
DirectoryInfo dirInfo = new DirectoryInfo(@"c:\code");
var codeFiles = dirInfo.EnumerateFiles("*.c", SearchOption.AllDirectories);
var crawler = new VulnC();
foreach (var codeFile in codeFiles)
{
Console.WriteLine(codeFile.FullName);
using (var reader = codeFile.OpenText())
{
var dict = crawler.CrawlUserCode(reader);
foreach (var item in dict)
{
Console.WriteLine($"----{item.Key}->");
foreach (var hash in item.Value)
{
Console.WriteLine(hash);
}
}
}
}
}
}
}
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("VulnUserCodeAnalyzer")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("VulnUserCodeAnalyzer")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("84c36798-2a15-481e-96d5-e6c547114161")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호가 자동으로
// 지정되도록 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{84C36798-2A15-481E-96D5-E6C547114161}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>VulnUserCodeAnalyzer</RootNamespace>
<AssemblyName>VulnUserCodeAnalyzer</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VulnCrawler\VulnCrawler.csproj">
<Project>{42c06434-1aca-409c-8783-c6341abff8ba}</Project>
<Name>VulnCrawler</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
\ No newline at end of file
......@@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VulnCrawler", "VulnCrawler\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DownloaderGithubClone", "DownloaderGithubClone\DownloaderGithubClone.csproj", "{17D012E2-AD26-437B-83DC-EC8E09AF0F8D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VulnUserCodeAnalyzer", "VulnUserCodeAnalyzer\VulnUserCodeAnalyzer.csproj", "{84C36798-2A15-481E-96D5-E6C547114161}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
......@@ -21,6 +23,10 @@ Global
{17D012E2-AD26-437B-83DC-EC8E09AF0F8D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{17D012E2-AD26-437B-83DC-EC8E09AF0F8D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{17D012E2-AD26-437B-83DC-EC8E09AF0F8D}.Release|Any CPU.Build.0 = Release|Any CPU
{84C36798-2A15-481E-96D5-E6C547114161}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{84C36798-2A15-481E-96D5-E6C547114161}.Debug|Any CPU.Build.0 = Debug|Any CPU
{84C36798-2A15-481E-96D5-E6C547114161}.Release|Any CPU.ActiveCfg = Release|Any CPU
{84C36798-2A15-481E-96D5-E6C547114161}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......