This repository has been archived by the owner on Feb 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
make a new extractor instead of garbage one
- Loading branch information
Showing
20 changed files
with
659 additions
and
81,138 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<configuration> | ||
<startup> | ||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" /> | ||
</startup> | ||
</configuration> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Runtime.InteropServices.WindowsRuntime; | ||
using System.Runtime.Remoting.Lifetime; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace extractor | ||
{ | ||
public static class AssemblyLoader | ||
{ | ||
static Dictionary<AssemblyName, Assembly> cache = new Dictionary<AssemblyName, Assembly>(); | ||
|
||
static string SanitizePath(string path) | ||
{ | ||
return path.Trim((char)7234); | ||
} | ||
|
||
static AssemblyLoader() | ||
{ | ||
// AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += ResolveHandler; | ||
AppDomain.CurrentDomain.AssemblyResolve += ResolveHandler; | ||
} | ||
|
||
static Assembly ResolveHandler(object sender, ResolveEventArgs e) | ||
{ | ||
// 1) find on cache | ||
var assemName = new AssemblyName(e.Name); | ||
if (cache.TryGetValue(assemName, out var result)) | ||
return result; | ||
|
||
// 2) try to find on current appdomain | ||
// var assem = Assembly.ReflectionOnlyLoad(e.Name); | ||
var name = e.Name.Split(',')[0].Trim(); | ||
var assem = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(assembly => assembly.GetName().Name == name); | ||
if (assem != null) | ||
return assem; | ||
|
||
// 3) try to load | ||
var assem2 = Assembly.Load(e.Name); // it is now registered to appdomain, so we don't have to store it. | ||
return assem2; | ||
|
||
// unused | ||
if (assem != null) | ||
{ | ||
cache.Add(assem.GetName(), assem); | ||
return assem; | ||
} | ||
else | ||
return null; | ||
} | ||
|
||
public static IEnumerable<Assembly> Load(IEnumerable<string> _paths) | ||
{ | ||
var paths = _paths.Select(path => SanitizePath(path)); | ||
var list = new List<Assembly>(); | ||
foreach (var path in paths) | ||
{ | ||
if (Directory.Exists(path)) | ||
{ | ||
var files = Directory.GetFiles(path, "*.dll"); | ||
foreach (var file in files) | ||
{ | ||
try | ||
{ | ||
list.Add(_Load(file)); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Log.Warn(ex.ToString()); | ||
} | ||
} | ||
} | ||
else if (File.Exists(path)) | ||
{ | ||
try | ||
{ | ||
list.Add(_Load(path)); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Log.Warn(ex.ToString()); | ||
} | ||
} | ||
} | ||
|
||
return list; | ||
} | ||
|
||
static Assembly _Load(string path) | ||
{ | ||
// var raw = File.ReadAllBytes(path); | ||
var assem = Assembly.UnsafeLoadFrom(path); | ||
// var assem = Assembly.ReflectionOnlyLoadFrom(path); | ||
cache.Add(assem.GetName(), assem); | ||
|
||
return assem; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
using log4net; | ||
using log4net.Appender; | ||
using log4net.Core; | ||
using log4net.Layout; | ||
using log4net.Repository.Hierarchy; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace extractor | ||
{ | ||
public static class Log | ||
{ | ||
static ILog log = LogManager.GetLogger("Extractor"); | ||
// https://stackoverflow.com/questions/16336917/can-you-configure-log4net-in-code-instead-of-using-a-config-file | ||
public static void SetOutput(string path) | ||
{ | ||
var hierarchy = (Hierarchy)LogManager.GetRepository(); | ||
|
||
var appender = new RollingFileAppender(); | ||
appender.Name = "FileAppender"; | ||
appender.File = path; | ||
appender.AppendToFile = false; | ||
appender.StaticLogFileName = true; | ||
|
||
var layout = new PatternLayout(); | ||
layout.ConversionPattern = "%d %c [%p]: %m%n"; | ||
layout.ActivateOptions(); | ||
|
||
appender.Layout = layout; | ||
appender.ActivateOptions(); | ||
hierarchy.Root.AddAppender(appender); | ||
|
||
hierarchy.Root.Level = Level.Info; | ||
hierarchy.Configured = true; | ||
} | ||
|
||
public static void Info(string message) | ||
{ | ||
log.Info(message); | ||
} | ||
|
||
public static void Debug(string message) | ||
{ | ||
log.Debug(message); | ||
} | ||
|
||
public static void Warn(string message) | ||
{ | ||
log.Warn(message); | ||
} | ||
|
||
public static void Error(string message) | ||
{ | ||
log.Error(message); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
using CommandLine; | ||
using log4net.Appender; | ||
using Newtonsoft.Json; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace extractor | ||
{ | ||
public enum OutputMode | ||
{ | ||
stdout = 0, | ||
stdoutBytes = 1, | ||
file = 2 | ||
} | ||
|
||
public class ProgramOptions | ||
{ | ||
[Option('v', "verbose", Required = false, HelpText = "Set output to verbose messages.")] | ||
public bool Verbose { get; set; } | ||
|
||
[Option("OutputMode", Required = true, HelpText = "select extraction ouptut mode, stdout or file")] | ||
public OutputMode outputMode { get; set; } | ||
|
||
[Option('o', "out", Required = false, HelpText = "Set output file path")] | ||
public string outputPath { get; set; } | ||
|
||
[Option("log", Required = false, HelpText = "Set log output path")] | ||
public string logOutputPath { get; set; } | ||
|
||
// [Option("--file", Required = true, Separator = ' ')] | ||
[Value(0, Required = true, HelpText = "dll file/directory to extract data")] | ||
public IEnumerable<string> targetFiles { get; set; } | ||
} | ||
|
||
class Program | ||
{ | ||
static void Main(string[] args) | ||
{ | ||
var commandline = Parser.Default.ParseArguments<ProgramOptions>(args); | ||
|
||
commandline.WithParsed(option => | ||
{ | ||
if (option.logOutputPath != null) | ||
{ | ||
Log.SetOutput(option.logOutputPath); | ||
} | ||
try | ||
{ | ||
Log.Info("Extracting data from"); | ||
foreach (var file in option.targetFiles) | ||
Log.Info(file); | ||
var assemblies = AssemblyLoader.Load(option.targetFiles); | ||
Log.Info("extracting data..."); | ||
var parseResult = Extractor.parse(assemblies); | ||
Log.Info($"Completed extracting data, data count: {parseResult.Count}"); | ||
|
||
var result = new Dictionary<string, TypeInfo>(); | ||
foreach(var pair in parseResult) | ||
{ | ||
var typeInfo = pair.Value; | ||
if (result.ContainsKey(typeInfo.typeIdentifier)) | ||
continue; | ||
result.Add(typeInfo.typeIdentifier, typeInfo); | ||
} | ||
|
||
var serializerSetting = new JsonSerializerSettings(); | ||
serializerSetting.Formatting = Formatting.None; | ||
serializerSetting.NullValueHandling = NullValueHandling.Ignore; | ||
serializerSetting.DefaultValueHandling = DefaultValueHandling.Ignore; | ||
|
||
var serializedObject = JsonConvert.SerializeObject(result.Select(d => d.Value), serializerSetting); | ||
Log.Info($"serialized Object string length: {serializedObject}"); | ||
|
||
switch(option.outputMode) | ||
{ | ||
case OutputMode.stdout: | ||
Console.WriteLine(serializedObject); | ||
break; | ||
|
||
case OutputMode.stdoutBytes: | ||
var utf8bytes = UTF8Encoding.UTF8.GetBytes(serializedObject); | ||
Log.Info($"serialized text bytes length: {utf8bytes.Length}"); | ||
Console.OpenStandardOutput().Write(utf8bytes, 0, utf8bytes.Length); | ||
break; | ||
|
||
case OutputMode.file: | ||
var path = option.outputPath; | ||
File.WriteAllText(path, serializedObject); | ||
break; | ||
} | ||
Log.Info("Extraction completed!"); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Log.Error(ex.ToString()); | ||
} | ||
|
||
}); | ||
} | ||
} | ||
} |
Oops, something went wrong.