some fixes

This commit is contained in:
Namhyeon Go 2024-04-16 15:33:57 +09:00
parent 31712d00ee
commit 9fdbb01bcd
18 changed files with 239 additions and 306 deletions

View File

@ -93,6 +93,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Config.cs" />
<Compile Include="Worker.cs" />
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
@ -106,10 +107,11 @@
<DependentUpon>Form2.cs</DependentUpon>
</Compile>
<Compile Include="Helper\ApkManifestExtractor.cs" />
<Compile Include="Helper\CbpfExtractor.cs" />
<Compile Include="Helper\FileHasher.cs" />
<Compile Include="Helper\FileExtensionDB.cs" />
<Compile Include="Helper\FileExtensionDatabase.cs" />
<Compile Include="Helper\PeOrganizationExtractor.cs" />
<Compile Include="Helper\FileMagic.cs" />
<Compile Include="Helper\FileMagicExtractor.cs" />
<Compile Include="Helper\LinkExtractor.cs" />
<Compile Include="Helper\ImpHash.cs" />
<Compile Include="Helper\ExifTagExtractor.cs" />
@ -118,8 +120,9 @@
<Compile Include="Model\AndroidPermission.cs" />
<Compile Include="Model\ExifTag.cs" />
<Compile Include="Model\FileHash.cs" />
<Compile Include="Model\Indicator.cs" />
<Compile Include="Model\TimelineMessage.cs" />
<Compile Include="Model\OpenXMLMetadata.cs" />
<Compile Include="Model\Timestamp.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UserControl1.cs">

View File

@ -8,19 +8,18 @@ namespace Catswords.DataType.Client
{
public partial class Form2 : Form
{
private UserControl1 parent;
private UserControl1 Parent;
private FileHash hashed;
public Form2(UserControl1 parent)
{
InitializeComponent();
this.parent = parent;
Parent = parent;
}
private void Form2_Load(object sender, EventArgs e)
{
hashed = Helper.FileHasher.Compute(parent.filePath);
hashed = Helper.FileHasher.Compute(Parent.FilePath);
txtExtension.Text = hashed.Extension;
txtHashMd5.Text = hashed.MD5;
txtHashSha1.Text = hashed.SHA1;
@ -34,7 +33,7 @@ namespace Catswords.DataType.Client
private void button1_Click(object sender, EventArgs e)
{
ByteViewer bv = new ByteViewer();
bv.SetFile(parent.filePath); // or SetBytes
bv.SetFile(Parent.FilePath); // or SetBytes
Form newForm = new Form();
newForm.Size = new System.Drawing.Size(650, 600);

View File

@ -32,7 +32,7 @@ namespace Catswords.DataType.Client.Helper
{
if (entry.FullName == "AndroidManifest.xml")
{
TargetPath = Path.Combine(TempDirectory, entry.FullName);
TargetPath = Path.Combine(TempDirectory, Guid.NewGuid().ToString());
entry.ExtractToFile(TargetPath);
break;
}

View File

@ -0,0 +1,7 @@
namespace Catswords.DataType.Client.Helper
{
internal class CbpfExtractor
{
}
}

View File

@ -1,101 +0,0 @@
using System;
using System.Diagnostics;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
namespace Catswords.DataType.Client.Helper
{
public static class FileCompany
{
static public string Read(string filePath)
{
// 회사 정보 추출
string[] companies = new string[] {
GetCompanyInfo(filePath),
GetProductName(filePath),
GetCopyrightInfo(filePath),
GetOrganization(filePath)
};
foreach (string company in companies)
{
if (company != null && !company.Equals(string.Empty))
{
return company;
}
}
return "Unknown";
}
public static string GetOrganization(string filePath)
{
string organization = string.Empty;
// 서명된 파일인 경우 인증서 정보 추출
X509Certificate2 certificate = GetCertificateInfo(filePath);
if (certificate != null)
{
// Subject 필드에서 O (Organization) 값을 찾아 회사 정보 추출
string[] fields = certificate.Subject.Split(',');
foreach (string field in fields)
{
string[] keyValue = field.Trim().Split('=');
if (keyValue.Length == 2 && keyValue[0].Trim().Equals("O", StringComparison.OrdinalIgnoreCase))
{
organization = keyValue[1].Trim();
}
}
}
return organization;
}
public static string GetCompanyInfo(string filePath)
{
FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(filePath);
return versionInfo.CompanyName;
}
public static string GetProductName(string filePath)
{
FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(filePath);
return versionInfo.ProductName;
}
public static string GetCopyrightInfo(string filePath)
{
FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(filePath);
return versionInfo.LegalCopyright;
}
static X509Certificate2 GetCertificateInfo(string filePath)
{
// GetCertificateInfo 구현
try
{
// 파일에 디지털 서명이 있는지 확인
Assembly assembly = Assembly.LoadFile(filePath);
X509Certificate2 certificate = new X509Certificate2(assembly.Location);
// 서명이 유효한지 확인 (옵션)
X509Chain chain = new X509Chain();
chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; // 여러 인증서를 사용하는 경우 인증서 연쇄를 무시할 수 있습니다.
if (chain.Build(certificate))
{
return certificate;
}
else
{
return null;
}
}
catch
{
return null;
}
}
}
}

View File

@ -8,13 +8,13 @@ using System.Xml;
namespace Catswords.DataType.Client.Helper
{
class FileExtensionDB
class FileExtensionDatabase
{
public List<Indicator> Indicators;
public List<TimelineMessage> Indicators;
public FileExtensionDB()
public FileExtensionDatabase()
{
Indicators = new List<Indicator>();
Indicators = new List<TimelineMessage>();
}
public void Fetch(string q)
@ -39,7 +39,7 @@ namespace Catswords.DataType.Client.Helper
foreach (XmlNode itemNode in itemList)
{
// organization
Indicators.Add(new Indicator()
Indicators.Add(new TimelineMessage()
{
Id = itemNode.SelectSingleNode("id").InnerText,
CreatedAt = GetDateTimeFromString(itemNode.SelectSingleNode("datetime").InnerText),
@ -48,7 +48,7 @@ namespace Catswords.DataType.Client.Helper
});
// description
Indicators.Add(new Indicator()
Indicators.Add(new TimelineMessage()
{
Id = itemNode.SelectSingleNode("id").InnerText,
CreatedAt = GetDateTimeFromString(itemNode.SelectSingleNode("datetime").InnerText),
@ -57,7 +57,7 @@ namespace Catswords.DataType.Client.Helper
});
// content
Indicators.Add(new Indicator()
Indicators.Add(new TimelineMessage()
{
Id = itemNode.SelectSingleNode("id").InnerText,
CreatedAt = GetDateTimeFromString(itemNode.SelectSingleNode("datetime").InnerText),
@ -66,7 +66,7 @@ namespace Catswords.DataType.Client.Helper
});
// openwith
Indicators.Add(new Indicator()
Indicators.Add(new TimelineMessage()
{
Id = itemNode.SelectSingleNode("id").InnerText,
CreatedAt = GetDateTimeFromString(itemNode.SelectSingleNode("datetime").InnerText),
@ -75,7 +75,7 @@ namespace Catswords.DataType.Client.Helper
});
// first reported
Indicators.Add(new Indicator()
Indicators.Add(new TimelineMessage()
{
Id = itemNode.SelectSingleNode("id").InnerText,
CreatedAt = GetDateTimeFromString(itemNode.SelectSingleNode("datetime").InnerText),

View File

@ -139,7 +139,7 @@ namespace Catswords.DataType.Client.Helper
private static string GetMAGIC(string filename)
{
return FileMagic.Read(filename);
return new FileMagicExtractor(filename).GetString();
}
private static string GetInfoHash(string filename, string extension)

View File

@ -3,18 +3,24 @@ using System.IO;
namespace Catswords.DataType.Client.Helper
{
public static class FileMagic
public class FileMagicExtractor
{
public static string Error = string.Empty;
private string FilePath;
private string Error = null;
public static string Read(string filePath)
public FileMagicExtractor(string filePath)
{
FilePath = filePath;
}
public string GetString()
{
string hexString = "";
try
{
// 파일 열기
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read))
{
// 첫 3 바이트 읽기
byte[] buffer = new byte[3] { 0x00, 0x00, 0x00 };
@ -32,5 +38,10 @@ namespace Catswords.DataType.Client.Helper
return hexString;
}
public string GetError()
{
return Error;
}
}
}

View File

@ -29,7 +29,7 @@ namespace Catswords.DataType.Client.Helper
{
if (entry.FullName == "docProps/core.xml")
{
TargetPath = Path.Combine(TempDirectory, "docProps_core.xml");
TargetPath = Path.Combine(TempDirectory, Guid.NewGuid().ToString());
entry.ExtractToFile(TargetPath);
break;
}

View File

@ -12,14 +12,14 @@ namespace Catswords.DataType.Client.Helper
{
public string ApiBaseUrl;
public string AccessToken;
public List<Indicator> Indicators;
public List<TimelineMessage> Messages;
public string ResponseText;
public Timeline(string host, string access_token)
{
ApiBaseUrl = $"https://{host}/api/v1/timelines/tag";
AccessToken = access_token;
Indicators = new List<Indicator>();
Messages = new List<TimelineMessage>();
}
public static string RemoveHtmlTags(string input)
@ -77,7 +77,7 @@ namespace Catswords.DataType.Client.Helper
string createdAt = status["created_at"].Value<string>();
string content = status["content"].Value<string>();
Indicators.Add(new Indicator
Messages.Add(new TimelineMessage
{
CreatedAt = GetDateTimeFromString(createdAt),
Content = RemoveHtmlTags(content)

View File

@ -1,13 +1,9 @@
using System;
namespace Catswords.DataType.Client.Model
namespace Catswords.DataType.Client.Model
{
class AndroidPermission
public class AndroidPermission: Timestamp
{
public string Name { get; set; }
public string Description { get; set; }
public int Severity { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
}

View File

@ -1,6 +1,6 @@
namespace Catswords.DataType.Client.Model
{
class ExifTag
public class ExifTag: Timestamp
{
public string Section { get; set; }
public string Name { get; set; }

View File

@ -1,8 +1,6 @@
using System;
namespace Catswords.DataType.Client.Model
namespace Catswords.DataType.Client.Model
{
public class FileHash
public class FileHash: Timestamp
{
public string Path { get; set; }
public string Extension { get; set; }
@ -13,7 +11,5 @@ namespace Catswords.DataType.Client.Model
public string SHA256 { get; set; }
public string InfoHash { get; set; }
public string SSDEEP { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
}

View File

@ -2,7 +2,7 @@
namespace Catswords.DataType.Client.Model
{
public class OpenXMLMetadata
public class OpenXMLMetadata: Timestamp
{
public string Author { get; set; }
public string Title { get; set; }
@ -12,7 +12,5 @@ namespace Catswords.DataType.Client.Model
public string Description { get; set; }
public string LastUpdatedBy { get; set; }
public DateTime LastPrintedAt { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace Catswords.DataType.Client.Model
{
public class TimelineMessage: Timestamp
{
public string Id { get; set; }
public string Content { get; set; }
public string Url { get; set; }
}
}

View File

@ -2,11 +2,8 @@
namespace Catswords.DataType.Client.Model
{
public class Indicator
public class Timestamp
{
public string Id { get; set; }
public string Content { get; set; }
public string Url { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}

View File

@ -1,5 +1,4 @@
using Catswords.DataType.Client.Helper;
using Catswords.DataType.Client.Model;
using System;
using System.Diagnostics;
using System.IO;
@ -11,10 +10,10 @@ namespace Catswords.DataType.Client
{
private ImageList imageList = new ImageList();
public string filePath;
public string fileMagic;
public string fileName;
public string fileExtension;
public string FilePath;
public string FileMagic;
public string FileName;
public string FileExtension;
public UserControl1(Form parent)
{
@ -32,8 +31,8 @@ namespace Catswords.DataType.Client
listView1.SmallImageList = imageList;
// Store the file path.
filePath = OpenFileDialog();
if (string.IsNullOrEmpty(filePath))
FilePath = OpenFileDialog();
if (string.IsNullOrEmpty(FilePath))
{
MessageBox.Show("Failed to get a file name", "Catswords.DataType.Client");
parent.Close();
@ -41,172 +40,39 @@ namespace Catswords.DataType.Client
}
// Get first 4 bytes from the file.
fileMagic = FileMagic.Read(filePath);
var extractor = new FileMagicExtractor(FilePath);
FileMagic = extractor.GetString();
// Show file magic to the label
label1.Text = "#0x" + fileMagic;
if (FileMagic.Error != string.Empty)
label1.Text = "#0x" + FileMagic;
if (extractor.GetError() != null)
{
textBox1.Text = FileMagic.Error;
ShowStatus(extractor.GetError());
}
// Get file name and file extension
try
{
fileExtension = Path.GetExtension(filePath);
fileName = Path.GetFileName(filePath);
if (fileExtension.Length > 0 && fileExtension.Substring(0, 1) == ".")
FileExtension = Path.GetExtension(FilePath);
FileName = Path.GetFileName(FilePath);
if (FileExtension.Length > 0 && FileExtension.Substring(0, 1) == ".")
{
fileExtension = fileExtension.Substring(1);
FileExtension = FileExtension.Substring(1);
}
}
catch
{
fileExtension = "";
fileName = "";
FileExtension = "";
FileName = "";
}
// Get data from file extension database
FetchFromFileExtensionDB();
// Get data from Android manifest
ExtractAndroidManifest();
// Get data from timeline
FetchFromTimeline();
// Get links from file
ExtractLink();
// Get EXIF tags from file
ExtractExif();
}
private void FetchFromFileExtensionDB()
{
var search = new FileExtensionDB();
search.Fetch(fileExtension);
foreach (Indicator ind in search.Indicators)
{
listView1.Items.Add(new ListViewItem(new string[] { ind.CreatedAt.ToString(), ind.Content }, 0));
}
}
private void FetchFromTimeline()
{
// Request a timeline
var search = new Timeline(Config.MASTODON_HOST, Config.MASTODON_ACCESS_TOKEN);
// fetch data by file magic
search.Fetch("0x" + fileMagic);
// if PE format (ImpHash)
if (fileMagic.StartsWith("4d5a"))
{
try
{
string imphash = ImpHash.Calculate(filePath);
search.Fetch(imphash);
string organization = (new PeOrganizationExtractor(filePath)).GetString();
search.Fetch(organization);
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), "This file are distributed by " + organization }, 4));
textBox1.Text = "ImpHash=" + imphash + "; Organization=" + organization;
}
catch (Exception ex)
{
textBox1.Text = ex.Message;
}
}
// fetch data by file extension
if (fileExtension.Length > 0)
{
search.Fetch(fileExtension);
// if Office365 format
if (fileExtension.StartsWith("xls") || fileExtension.StartsWith("ppt") || fileExtension.StartsWith("doc"))
{
if (fileExtension == "xlsx" || fileExtension == "pptx" || fileExtension == "docx")
{
ExtractOpenXML();
}
search.Fetch("msoffice");
search.Fetch("office365");
}
}
// if it contains ransomware keywords
if (fileName.ToLower().Contains("readme") || fileName.ToLower().Contains("decrypt"))
{
search.Fetch("ransomware");
}
// if IoC (Indicators of Compomise) mode
if (fileMagic == "58354f") // EICAR test file header
{
search.Fetch("malware");
}
// Show the timeline
foreach (Indicator ind in search.Indicators)
{
listView1.Items.Add(new ListViewItem(new string[] { ind.CreatedAt.ToString(), ind.Content }, 1));
}
}
private void ExtractAndroidManifest()
{
if (fileExtension == "apk")
{
var extractor = new ApkManifestExtractor(filePath);
extractor.Open();
foreach (AndroidPermission perm in extractor.GetPermissions())
{
listView1.Items.Add(new ListViewItem(new string[] { perm.CreatedAt.ToString(), perm.Name + ' ' + perm.Description }, 2));
}
extractor.Close();
}
}
private void ExtractOpenXML()
{
var extractor = new OpenXMLExtractor(filePath);
extractor.Open();
var metadata = extractor.GetMetadata();
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), "Author: " + metadata.Author }, 3));
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), "Title: " + metadata.Title }, 3));
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), "Subject: " + metadata.Subject }, 3));
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), "Category: " + metadata.Category }, 3));
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), "Description: " + metadata.Description }, 3));
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), "Created: " + metadata.CreatedAt.ToString() }, 3));
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), "Last updated: " + metadata.UpdatedAt.ToString() }, 3));
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), "Last updated by: " + metadata.LastUpdatedBy }, 3));
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), "Last printed: " + metadata.LastPrintedAt }, 3));
extractor.Close();
}
private void ExtractLink()
{
var extractor = new LinkExtractor(filePath);
var strings = extractor.GetStrings();
foreach (string str in strings)
{
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), str }, 4));
}
}
private void ExtractExif()
{
var extractor = new ExifTagExtractor(filePath);
var tags = extractor.GetTags();
foreach (ExifTag tag in tags)
{
listView1.Items.Add(new ListViewItem(new string[] { DateTime.Now.ToString(), $"{tag.Name} ({tag.Section}): {tag.Description}" }, 5));
}
// Extract
var worker = new Worker(this);
worker.FromFileExtension(); // Get data from file extension database
worker.FromAndroidManifest(); // Get data from Android manifest
worker.FromTimeline(); // Get data from timeline
worker.FromLinks(); // Get links from file
worker.FromExif(); // Get EXIF tags from file
}
public string OpenFileDialog()
@ -225,6 +91,16 @@ namespace Catswords.DataType.Client
return filePath;
}
public void AddIndicator(DateTime dt, string Description, int ImageIndex)
{
listView1.Items.Add(new ListViewItem(new string[] { dt.ToString(), Description }, ImageIndex));
}
public void ShowStatus(string status)
{
textBox1.Text = status;
}
private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
Process.Start("https://catswords.social/auth/sign_up");

View File

@ -0,0 +1,142 @@
using Catswords.DataType.Client.Helper;
using Catswords.DataType.Client.Model;
using System;
namespace Catswords.DataType.Client
{
public class Worker
{
private UserControl1 Parent;
public Worker(UserControl1 parent)
{
Parent = parent;
}
public void FromFileExtension()
{
var search = new FileExtensionDatabase();
search.Fetch(Parent.FileExtension);
foreach (TimelineMessage ind in search.Indicators)
{
Parent.AddIndicator(ind.CreatedAt, ind.Content, 0);
}
}
public void FromTimeline()
{
// Request a timeline
var search = new Timeline(Config.MASTODON_HOST, Config.MASTODON_ACCESS_TOKEN);
// fetch data by file magic
search.Fetch("0x" + Parent.FileMagic);
// if PE format (ImpHash)
if (Parent.FileMagic.StartsWith("4d5a"))
{
try
{
string imphash = ImpHash.Calculate(Parent.FilePath);
search.Fetch(imphash);
string organization = (new PeOrganizationExtractor(Parent.FilePath)).GetString();
search.Fetch(organization);
Parent.AddIndicator(DateTime.Now, "This file are distributed by " + organization, 4);
Parent.ShowStatus("ImpHash=" + imphash + "; Organization=" + organization);
}
catch (Exception ex)
{
Parent.ShowStatus(ex.Message);
}
}
// fetch data by file extension
if (Parent.FileExtension.Length > 0)
{
search.Fetch(Parent.FileExtension);
// if Office365 format
if (Parent.FileExtension.StartsWith("xls") || Parent.FileExtension.StartsWith("ppt") || Parent.FileExtension.StartsWith("doc"))
{
if (Parent.FileExtension == "xlsx" || Parent.FileExtension == "pptx" || Parent.FileExtension == "docx")
{
FromOpenXML();
}
search.Fetch("msoffice");
search.Fetch("office365");
}
}
// if it contains ransomware keywords
if (Parent.FileName.ToLower().Contains("readme") || Parent.FileName.ToLower().Contains("decrypt"))
{
search.Fetch("ransomware");
}
// if IoC (Indicators of Compomise) mode
if (Parent.FileMagic == "58354f") // EICAR test file header
{
search.Fetch("malware");
}
// Show the timeline
foreach (TimelineMessage ind in search.Messages)
{
Parent.AddIndicator(ind.CreatedAt, ind.Content, 1);
}
}
public void FromAndroidManifest()
{
if (Parent.FileExtension == "apk")
{
var extractor = new ApkManifestExtractor(Parent.FilePath);
extractor.Open();
foreach (AndroidPermission perm in extractor.GetPermissions())
{
Parent.AddIndicator(perm.CreatedAt, perm.Name + ' ' + perm.Description, 2);
}
extractor.Close();
}
}
public void FromOpenXML()
{
var extractor = new OpenXMLExtractor(Parent.FilePath);
extractor.Open();
var metadata = extractor.GetMetadata();
Parent.AddIndicator(DateTime.Now, "Author: " + metadata.Author, 3);
Parent.AddIndicator(DateTime.Now, "Title: " + metadata.Title, 3);
Parent.AddIndicator(DateTime.Now, "Subject: " + metadata.Subject, 3);
Parent.AddIndicator(DateTime.Now, "Category: " + metadata.Category, 3);
Parent.AddIndicator(DateTime.Now, "Description: " + metadata.Description, 3);
Parent.AddIndicator(DateTime.Now, "Created: " + metadata.CreatedAt.ToString(), 3);
Parent.AddIndicator(DateTime.Now, "Last updated: " + metadata.UpdatedAt.ToString(), 3);
Parent.AddIndicator(DateTime.Now, "Last updated by: " + metadata.LastUpdatedBy, 3);
Parent.AddIndicator(DateTime.Now, "Last printed: " + metadata.LastPrintedAt, 3);
extractor.Close();
}
public void FromLinks()
{
var extractor = new LinkExtractor(Parent.FilePath);
var strings = extractor.GetStrings();
foreach (string str in strings)
{
Parent.AddIndicator(DateTime.Now, str, 4);
}
}
public void FromExif()
{
var extractor = new ExifTagExtractor(Parent.FilePath);
var tags = extractor.GetTags();
foreach (ExifTag tag in tags)
{
Parent.AddIndicator(DateTime.Now, $"{tag.Name} ({tag.Section}): {tag.Description}", 5);
}
}
}
}