-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #31 from AikidoSec/dependency-cleanups-and-improve…
…ments Dependency cleanups and improvements
- Loading branch information
Showing
16 changed files
with
301 additions
and
264 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
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,68 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Reflection; | ||
using System.Text; | ||
|
||
namespace Aikido.Zen.Core.Helpers | ||
{ | ||
/// <summary> | ||
/// Helper class for reflection-related operations. | ||
/// </summary> | ||
public static class ReflectionHelper | ||
{ | ||
private static IDictionary<string, Type> _types; | ||
private static IDictionary<string, Assembly> _assemblies; | ||
|
||
static ReflectionHelper() | ||
{ | ||
_types = new Dictionary<string, Type>(); | ||
_assemblies = new Dictionary<string, Assembly>(); | ||
} | ||
|
||
/// <summary> | ||
/// Attempts to load an assembly, get a type from the loaded assembly, and then get a method from the type. | ||
/// </summary> | ||
/// <param name="assemblyName">The name of the assembly to load.</param> | ||
/// <param name="typeName">The name of the type to get from the assembly.</param> | ||
/// <param name="methodName">The name of the method to get from the type.</param> | ||
/// <param name="parameterTypeNames">The names of the parameter types for the method.</param> | ||
/// <returns>The MethodInfo of the specified method, or null if not found.</returns> | ||
public static MethodInfo GetMethodFromAssembly(string assemblyName, string typeName, string methodName, params string[] parameterTypeNames) | ||
{ | ||
// Attempt to load the assembly | ||
// Attempt to get the assembly from the cache, if not found, load it | ||
if (!_assemblies.TryGetValue(assemblyName, out var assembly)) | ||
{ | ||
assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.GetName().Name == assemblyName); | ||
// If the assembly is not loaded, and the assembly path exists, load it | ||
if (File.Exists($"{assemblyName}.dll") && assembly == null) | ||
{ | ||
assembly = Assembly.LoadFrom($"{assemblyName}.dll"); | ||
} | ||
if (assembly == null) return null; | ||
_assemblies[assemblyName] = assembly; | ||
} | ||
|
||
// Attempt to get the type from the cache, if not found, get it from the loaded assembly | ||
var typeKey = $"{assemblyName}.{typeName}"; | ||
if (!_types.TryGetValue(typeKey, out var type)) | ||
{ | ||
type = assembly.ExportedTypes.FirstOrDefault(t => t.Name == typeName || t.FullName == typeName); | ||
if (type == null) return null; | ||
_types[typeKey] = type; | ||
} | ||
|
||
// Use reflection to get the method | ||
var method = type.GetMethods().FirstOrDefault(m => m.Name == methodName && m.GetParameters().All(p => parameterTypeNames.Any(ptn => ptn == p.ParameterType.FullName))); | ||
return method; | ||
} | ||
|
||
public static void ClearCache() | ||
{ | ||
_types.Clear(); | ||
_assemblies.Clear(); | ||
} | ||
} | ||
} |
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
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
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 |
---|---|---|
@@ -1,72 +1,68 @@ | ||
using Aikido.Zen.Core.Helpers; | ||
using System; | ||
using System.Reflection; | ||
using HarmonyLib; | ||
using Microsoft.Data.Sqlite; | ||
using MySql.Data.MySqlClient; | ||
using System.Data.Common; | ||
using Npgsql; | ||
using Aikido.Zen.Core.Models; | ||
using MySqlX.XDevAPI.Relational; | ||
using System.Reflection; | ||
using Aikido.Zen.Core.Helpers; | ||
|
||
namespace Aikido.Zen.DotNetCore.Patches | ||
{ | ||
internal static class SqlClientPatches | ||
{ | ||
// we need to patch from inside the framework, because we have to pass the context, which is constructed in a framework specific manner | ||
public static void ApplyPatches(Harmony harmony) | ||
{ | ||
|
||
// Generic | ||
PatchMethod(harmony, typeof(DbCommand), "ExecuteNonQueryAsync"); | ||
PatchMethod(harmony, typeof(DbCommand), "ExecuteReaderAsync", typeof(System.Data.CommandBehavior)); | ||
PatchMethod(harmony, typeof(DbCommand), "ExecuteScalarAsync"); | ||
// Use reflection to get the types dynamically | ||
PatchMethod(harmony, "System.Data.Common", "DbCommand", "ExecuteNonQueryAsync"); | ||
PatchMethod(harmony, "System.Data.Common", "DbCommand", "ExecuteReaderAsync", "System.Data.CommandBehavior"); | ||
PatchMethod(harmony, "System.Data.Common", "DbCommand", "ExecuteScalarAsync"); | ||
|
||
// SQL Server | ||
PatchMethod(harmony, typeof(Microsoft.Data.SqlClient.SqlCommand), "ExecuteNonQuery"); | ||
PatchMethod(harmony, typeof(Microsoft.Data.SqlClient.SqlCommand), "ExecuteScalar"); | ||
PatchMethod(harmony, typeof(Microsoft.Data.SqlClient.SqlCommand), "ExecuteReader", typeof(System.Data.CommandBehavior)); | ||
PatchMethod(harmony, typeof(System.Data.SqlClient.SqlCommand), "ExecuteNonQuery"); | ||
PatchMethod(harmony, typeof(System.Data.SqlClient.SqlCommand), "ExecuteScalar"); | ||
PatchMethod(harmony, typeof(System.Data.SqlClient.SqlCommand), "ExecuteReader", typeof(System.Data.CommandBehavior)); | ||
PatchMethod(harmony, "Microsoft.Data.SqlClient", "SqlCommand", "ExecuteNonQuery"); | ||
PatchMethod(harmony, "Microsoft.Data.SqlClient", "SqlCommand", "ExecuteScalar"); | ||
PatchMethod(harmony, "Microsoft.Data.SqlClient", "SqlCommand", "ExecuteReader", "System.Data.CommandBehavior"); | ||
PatchMethod(harmony, "System.Data.SqlClient", "SqlCommand", "ExecuteNonQuery"); | ||
PatchMethod(harmony, "System.Data.SqlClient", "SqlCommand", "ExecuteScalar"); | ||
PatchMethod(harmony, "System.Data.SqlClient", "SqlCommand", "ExecuteReader", "System.Data.CommandBehavior"); | ||
|
||
// SQLite | ||
PatchMethod(harmony, typeof(SqliteCommand), "ExecuteNonQuery"); | ||
PatchMethod(harmony, typeof(SqliteCommand), "ExecuteScalar"); | ||
PatchMethod(harmony, typeof(SqliteCommand), "ExecuteReader", typeof(System.Data.CommandBehavior)); | ||
PatchMethod(harmony, "Microsoft.Data.Sqlite", "SqliteCommand", "ExecuteNonQuery"); | ||
PatchMethod(harmony, "Microsoft.Data.Sqlite", "SqliteCommand", "ExecuteScalar"); | ||
PatchMethod(harmony, "Microsoft.Data.Sqlite", "SqliteCommand", "ExecuteReader", "System.Data.CommandBehavior"); | ||
|
||
// MySql, MariaDB | ||
PatchMethod(harmony, typeof(MySqlCommand), "ExecuteNonQuery"); | ||
PatchMethod(harmony, typeof(MySqlCommand), "ExecuteScalar"); | ||
PatchMethod(harmony, typeof(MySqlCommand), "ExecuteReader", typeof(System.Data.CommandBehavior)); | ||
PatchMethod(harmony, typeof(MySqlConnector.MySqlCommand), "ExecuteNonQuery"); | ||
PatchMethod(harmony, typeof(MySqlConnector.MySqlCommand), "ExecuteScalar"); | ||
PatchMethod(harmony, typeof(MySqlConnector.MySqlCommand), "ExecuteReader", typeof(System.Data.CommandBehavior)); | ||
PatchMethod(harmony, "MySql.Data", "MySqlClient.MySqlCommand", "ExecuteNonQuery"); | ||
PatchMethod(harmony, "MySql.Data", "MySqlClient.MySqlCommand", "ExecuteScalar"); | ||
PatchMethod(harmony, "MySql.Data", "MySqlClient.MySqlCommand", "ExecuteReader", "System.Data.CommandBehavior"); | ||
PatchMethod(harmony, "MySqlConnector", "MySqlCommand", "ExecuteNonQuery"); | ||
PatchMethod(harmony, "MySqlConnector", "MySqlCommand", "ExecuteScalar"); | ||
PatchMethod(harmony, "MySqlConnector", "MySqlCommand", "ExecuteReader", "System.Data.CommandBehavior"); | ||
|
||
// PostgreSQL | ||
PatchMethod(harmony, typeof(NpgsqlCommand), "ExecuteNonQuery"); | ||
PatchMethod(harmony, typeof(NpgsqlCommand), "ExecuteScalar"); | ||
PatchMethod(harmony, typeof(NpgsqlCommand), "ExecuteReader", typeof(System.Data.CommandBehavior)); | ||
PatchMethod(harmony, "Npgsql", "NpgsqlCommand", "ExecuteNonQuery"); | ||
PatchMethod(harmony, "Npgsql", "NpgsqlCommand", "ExecuteScalar"); | ||
PatchMethod(harmony, "Npgsql", "NpgsqlCommand", "ExecuteReader", "System.Data.CommandBehavior"); | ||
|
||
// MySqlX | ||
PatchMethod(harmony, typeof(Table), "Select"); | ||
PatchMethod(harmony, typeof(Table), "Insert"); | ||
PatchMethod(harmony, typeof(Table), "Update"); | ||
PatchMethod(harmony, typeof(Table), "Delete"); | ||
PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Select"); | ||
PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Insert"); | ||
PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Update"); | ||
PatchMethod(harmony, "MySqlX", "XDevAPI.Relational.Table", "Delete"); | ||
} | ||
|
||
private static void PatchMethod(Harmony harmony, Type type, string methodName, params Type[] parameters) | ||
private static void PatchMethod(Harmony harmony, string assemblyName, string typeName, string methodName, params string[] parameterTypeNames) | ||
{ | ||
var method = AccessTools.Method(type, methodName, parameters); | ||
var method = ReflectionHelper.GetMethodFromAssembly(assemblyName, typeName, methodName, parameterTypeNames); | ||
if (method != null) | ||
{ | ||
harmony.Patch(method, new HarmonyMethod(typeof(SqlClientPatches).GetMethod(nameof(OnCommandExecuting), BindingFlags.Static | BindingFlags.NonPublic))); | ||
} | ||
} | ||
|
||
private static bool OnCommandExecuting(object[] __args, MethodBase __originalMethod, DbCommand __instance) | ||
private static bool OnCommandExecuting(object[] __args, MethodBase __originalMethod, object __instance) | ||
{ | ||
var dbCommand = __instance as System.Data.Common.DbCommand; | ||
if (dbCommand == null) return true; | ||
var assembly = __instance.GetType().Assembly.FullName?.Split(", Culture=")[0]; | ||
return Aikido.Zen.Core.Patches.SqlClientPatcher.OnCommandExecuting(__args, __originalMethod, __instance, assembly, Zen.GetContext()); | ||
return Aikido.Zen.Core.Patches.SqlClientPatcher.OnCommandExecuting(__args, __originalMethod, dbCommand, assembly, Zen.GetContext()); | ||
} | ||
} | ||
} |
Oops, something went wrong.