├── .gitignore ├── Frida.Exports ├── Frida.Exports.cpp ├── Frida.Exports.vcxproj └── Frida.Exports.vcxproj.filters ├── Frida.NetStandard.sln ├── Frida.NetStandard ├── Device.cs ├── DeviceManager.cs ├── Frida.NetStandard.csproj ├── FridaProcess.cs ├── FridaSession.cs ├── GError.cs ├── Handle.cs ├── Ref.cs ├── Runtime.cs ├── Script.cs ├── ScriptWithRpc.cs └── Utilities │ └── InterfaceImplementer.cs ├── README.md ├── TestProgram ├── Program.cs ├── TestProgram.csproj └── script.js └── setup.ps1 /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | #ignore thumbnails created by windows 3 | Thumbs.db 4 | #Ignore files build by Visual Studio 5 | *.obj 6 | *.exe 7 | *.pdb 8 | *.user 9 | *.aps 10 | *.pch 11 | *.vspscc 12 | *_i.c 13 | *_p.c 14 | *.ncb 15 | *.suo 16 | *.tlb 17 | *.tlh 18 | *.bak 19 | *.cache 20 | *.ilk 21 | *.log 22 | [Bb]in 23 | [Dd]ebug*/ 24 | *.lib 25 | *.sbr 26 | obj/ 27 | [Rr]elease*/ 28 | _ReSharper*/ 29 | [Tt]est[Rr]esult* 30 | .vs 31 | Frida.Exports/lib/ 32 | -------------------------------------------------------------------------------- /Frida.Exports/Frida.Exports.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lenacloud/frida-netstandard/89dd2167e947a028c07f5610381bc2af3136caa9/Frida.Exports/Frida.Exports.cpp -------------------------------------------------------------------------------- /Frida.Exports/Frida.Exports.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {44A9C4E0-9EE0-487E-A209-FBF78497027F} 24 | Win32Proj 25 | FridaExports 26 | 10.0.16299.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | $(SolutionDir)$(PROCESSOR_ARCHITECTURE)\$(Configuration)\ 76 | 77 | 78 | true 79 | $(SolutionDir)$(PROCESSOR_ARCHITECTURE)\$(Configuration)\ 80 | 81 | 82 | false 83 | 84 | 85 | false 86 | 87 | 88 | 89 | NotUsing 90 | Level3 91 | Disabled 92 | true 93 | WIN32;_DEBUG;FRIDAEXPORTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 94 | true 95 | lib/x86;%(AdditionalIncludeDirectories) 96 | 97 | 98 | Windows 99 | true 100 | frida-core.lib;%(AdditionalDependencies) 101 | lib/x86;%(AdditionalLibraryDirectories) 102 | $(OutDir)$(TargetName)$(TargetExt) 103 | 104 | 105 | 106 | 107 | NotUsing 108 | Level3 109 | Disabled 110 | true 111 | _DEBUG;FRIDAEXPORTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 112 | true 113 | lib/x64;%(AdditionalIncludeDirectories) 114 | 115 | 116 | Windows 117 | true 118 | frida-core.lib;%(AdditionalDependencies) 119 | lib/x64 120 | $(OutDir)$(TargetName)$(TargetExt) 121 | 122 | 123 | 124 | 125 | Use 126 | Level3 127 | MaxSpeed 128 | true 129 | true 130 | true 131 | WIN32;NDEBUG;FRIDAEXPORTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 132 | true 133 | 134 | 135 | Windows 136 | true 137 | true 138 | true 139 | 140 | 141 | 142 | 143 | Use 144 | Level3 145 | MaxSpeed 146 | true 147 | true 148 | true 149 | NDEBUG;FRIDAEXPORTS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) 150 | true 151 | 152 | 153 | Windows 154 | true 155 | true 156 | true 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | -------------------------------------------------------------------------------- /Frida.Exports/Frida.Exports.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | -------------------------------------------------------------------------------- /Frida.NetStandard.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2015 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Frida.Exports", "Frida.Exports\Frida.Exports.vcxproj", "{44A9C4E0-9EE0-487E-A209-FBF78497027F}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Frida.NetStandard", "Frida.NetStandard\Frida.NetStandard.csproj", "{CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestProgram", "TestProgram\TestProgram.csproj", "{17503C7C-38BC-482D-8756-858CCFFC6DBF}" 11 | EndProject 12 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{1E514DD4-E232-4675-8B59-6BB89053D72C}" 13 | ProjectSection(SolutionItems) = preProject 14 | README.md = README.md 15 | setup.ps1 = setup.ps1 16 | EndProjectSection 17 | EndProject 18 | Global 19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 20 | Debug|Any CPU = Debug|Any CPU 21 | Debug|x64 = Debug|x64 22 | Debug|x86 = Debug|x86 23 | Release|Any CPU = Release|Any CPU 24 | Release|x64 = Release|x64 25 | Release|x86 = Release|x86 26 | EndGlobalSection 27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 28 | {44A9C4E0-9EE0-487E-A209-FBF78497027F}.Debug|Any CPU.ActiveCfg = Debug|Win32 29 | {44A9C4E0-9EE0-487E-A209-FBF78497027F}.Debug|x64.ActiveCfg = Debug|x64 30 | {44A9C4E0-9EE0-487E-A209-FBF78497027F}.Debug|x64.Build.0 = Debug|x64 31 | {44A9C4E0-9EE0-487E-A209-FBF78497027F}.Debug|x86.ActiveCfg = Debug|Win32 32 | {44A9C4E0-9EE0-487E-A209-FBF78497027F}.Debug|x86.Build.0 = Debug|Win32 33 | {44A9C4E0-9EE0-487E-A209-FBF78497027F}.Release|Any CPU.ActiveCfg = Release|Win32 34 | {44A9C4E0-9EE0-487E-A209-FBF78497027F}.Release|x64.ActiveCfg = Release|x64 35 | {44A9C4E0-9EE0-487E-A209-FBF78497027F}.Release|x64.Build.0 = Release|x64 36 | {44A9C4E0-9EE0-487E-A209-FBF78497027F}.Release|x86.ActiveCfg = Release|Win32 37 | {44A9C4E0-9EE0-487E-A209-FBF78497027F}.Release|x86.Build.0 = Release|Win32 38 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Debug|x64.ActiveCfg = Debug|Any CPU 41 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Debug|x64.Build.0 = Debug|Any CPU 42 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Debug|x86.ActiveCfg = Debug|Any CPU 43 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Debug|x86.Build.0 = Debug|Any CPU 44 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Release|x64.ActiveCfg = Release|Any CPU 47 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Release|x64.Build.0 = Release|Any CPU 48 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Release|x86.ActiveCfg = Release|Any CPU 49 | {CB9B5A82-92C6-4B35-A6ED-D063C6878FC9}.Release|x86.Build.0 = Release|Any CPU 50 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 51 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Debug|Any CPU.Build.0 = Debug|Any CPU 52 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Debug|x64.ActiveCfg = Debug|Any CPU 53 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Debug|x64.Build.0 = Debug|Any CPU 54 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Debug|x86.ActiveCfg = Debug|Any CPU 55 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Debug|x86.Build.0 = Debug|Any CPU 56 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Release|Any CPU.ActiveCfg = Release|Any CPU 57 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Release|Any CPU.Build.0 = Release|Any CPU 58 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Release|x64.ActiveCfg = Release|Any CPU 59 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Release|x64.Build.0 = Release|Any CPU 60 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Release|x86.ActiveCfg = Release|Any CPU 61 | {17503C7C-38BC-482D-8756-858CCFFC6DBF}.Release|x86.Build.0 = Release|Any CPU 62 | EndGlobalSection 63 | GlobalSection(SolutionProperties) = preSolution 64 | HideSolutionNode = FALSE 65 | EndGlobalSection 66 | GlobalSection(ExtensibilityGlobals) = postSolution 67 | SolutionGuid = {90172FFC-B641-445A-B00F-2DDE6AADC762} 68 | EndGlobalSection 69 | EndGlobal 70 | -------------------------------------------------------------------------------- /Frida.NetStandard/Device.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace Frida.NetStandard 6 | { 7 | public enum FridaDeviceType 8 | { 9 | Local = 0, 10 | Remote = 1, 11 | USB = 2, 12 | } 13 | public class Device 14 | { 15 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 16 | static extern IntPtr _frida_device_get_name(IntPtr device); 17 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 18 | static extern IntPtr _frida_device_get_id(IntPtr device); 19 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 20 | static extern bool _frida_device_is_lost(IntPtr device); 21 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 22 | static extern FridaDeviceType _frida_device_get_dtype(IntPtr device); 23 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 24 | static extern IntPtr _frida_device_enumerate_processes_sync(IntPtr self, out IntPtr error); 25 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 26 | static extern int _frida_process_list_size(IntPtr list); 27 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 28 | static extern IntPtr _frida_process_list_get(IntPtr list, Int32 index); 29 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 30 | static extern void _frida_device_resume_sync(IntPtr self, UInt32 pid, out IntPtr error); 31 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 32 | static extern IntPtr _frida_device_attach_sync(IntPtr self, UInt32 pid, out IntPtr error); 33 | 34 | Handle handle; 35 | 36 | public Device(Func builder) 37 | { 38 | handle = new Handle(builder); 39 | } 40 | 41 | public string Name => _frida_device_get_name(handle.Pointer).ReadStringAndFree(); 42 | public string Id => _frida_device_get_id(handle.Pointer).ReadStringAndFree(); 43 | public bool IsLost => _frida_device_is_lost(handle.Pointer); 44 | public FridaDeviceType Type => _frida_device_get_dtype(handle.Pointer); 45 | public byte[] Icon => throw new NotImplementedException(); 46 | public List EnumerateProcesses() 47 | { 48 | IntPtr error; 49 | using (var devices = new Ref(_frida_device_enumerate_processes_sync(handle.Pointer, out error))) 50 | { 51 | GError.Throw(error); 52 | var len = _frida_process_list_size(devices.Pointer); 53 | var ret = new List(); 54 | for (int i = 0; i < len; i++) 55 | { 56 | ret.Add(new FridaProcess(() => _frida_process_list_get(devices.Pointer, i))); 57 | } 58 | return ret; 59 | } 60 | } 61 | 62 | public uint Spawn() 63 | => throw new NotImplementedException(); 64 | 65 | 66 | public void Resume(uint pid) 67 | { 68 | IntPtr error; 69 | _frida_device_resume_sync(handle.Pointer, pid, out error); 70 | GError.Throw(error); 71 | } 72 | 73 | public FridaSession Attach(uint pid) 74 | { 75 | return new FridaSession(() => 76 | { 77 | IntPtr error; 78 | var session = _frida_device_attach_sync(handle.Pointer, pid, out error); 79 | GError.Throw(error); 80 | return session; 81 | }); 82 | } 83 | 84 | public override string ToString() 85 | { 86 | return "Device " + handle.Pointer; 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /Frida.NetStandard/DeviceManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | 5 | namespace Frida.NetStandard 6 | { 7 | public class DeviceManager 8 | { 9 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 10 | static extern IntPtr _frida_device_manager_new(); 11 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 12 | static extern void _frida_device_manager_close_sync(IntPtr deviceManager); 13 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 14 | static extern IntPtr _frida_device_manager_enumerate_devices_sync(IntPtr deviceManager, out IntPtr error); 15 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 16 | static extern int _frida_device_list_size(IntPtr list); 17 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 18 | static extern IntPtr _frida_device_list_get(IntPtr list, Int32 index); 19 | 20 | Handle handle; 21 | 22 | public DeviceManager() 23 | { 24 | handle = new Handle(_frida_device_manager_new); 25 | } 26 | 27 | public List EnumerateDevices() 28 | { 29 | 30 | IntPtr error; 31 | using (var devices = new Ref(_frida_device_manager_enumerate_devices_sync(handle.Pointer, out error))) 32 | { 33 | GError.Throw(error); 34 | var len = _frida_device_list_size(devices.Pointer); 35 | var ret = new List(); 36 | for (int i = 0; i < len; i++) 37 | { 38 | ret.Add(new Device(() => _frida_device_list_get(devices.Pointer, i))); 39 | } 40 | return ret; 41 | } 42 | } 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /Frida.NetStandard/Frida.NetStandard.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Frida.NetStandard/FridaProcess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace Frida.NetStandard 7 | { 8 | public class FridaProcess 9 | { 10 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 11 | static extern IntPtr _frida_device_get_name(IntPtr device); 12 | 13 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 14 | static extern uint _frida_process_get_pid(IntPtr device); 15 | 16 | Handle handle; 17 | public FridaProcess(Func builder) 18 | { 19 | handle = new Handle(builder); 20 | } 21 | 22 | public string Name => _frida_device_get_name(handle.Pointer).ReadStringAndFree(); 23 | public uint Pid => _frida_process_get_pid(handle.Pointer); 24 | 25 | public byte[] SmallIcon => throw new NotImplementedException(); 26 | public byte[] LargeIcon => throw new NotImplementedException(); 27 | 28 | public override string ToString() 29 | => $"{Name} ({Pid})"; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /Frida.NetStandard/FridaSession.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Runtime.InteropServices; 4 | using System.Text; 5 | 6 | namespace Frida.NetStandard 7 | { 8 | public class FridaSession 9 | { 10 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 11 | static extern Int32 _frida_session_get_pid(IntPtr self); 12 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 13 | static extern void _frida_session_detach_sync(IntPtr self); 14 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 15 | static extern IntPtr _frida_session_create_script_sync(IntPtr self, string name, string source, out IntPtr error); 16 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 17 | static extern IntPtr _frida_session_enable_debugger_sync(IntPtr self, UInt16 port, out IntPtr error); 18 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 19 | static extern IntPtr _frida_session_disable_debugger_sync(IntPtr self, out IntPtr error); 20 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 21 | static extern IntPtr _frida_session_enable_jit_sync(IntPtr self, out IntPtr error); 22 | 23 | Handle handle; 24 | public FridaSession(Func builder) 25 | { 26 | handle = new Handle(builder); 27 | } 28 | 29 | public int Pid => _frida_session_get_pid(handle.Pointer); 30 | public void Dettach() 31 | => _frida_session_detach_sync(handle.Pointer); 32 | 33 | public ScriptWithRpc CreateScriptWithRpc(string source) 34 | => CreateScriptWithRpc(null, source); 35 | 36 | public ScriptWithRpc CreateScriptWithRpc(string name, string source) 37 | { 38 | return new ScriptWithRpc(() => 39 | { 40 | IntPtr error; 41 | var script = _frida_session_create_script_sync(handle.Pointer, name, source, out error); 42 | GError.Throw(error); 43 | return script; 44 | }); 45 | } 46 | 47 | 48 | public Script CreateScript(string source) 49 | => CreateScript(null, source); 50 | public Script CreateScript(string name, string source) 51 | { 52 | return new Script(() => 53 | { 54 | IntPtr error; 55 | var script = _frida_session_create_script_sync(handle.Pointer, name, source, out error); 56 | GError.Throw(error); 57 | return script; 58 | }); 59 | } 60 | 61 | public void EnableDebugger(UInt16 port = 0) 62 | { 63 | IntPtr error; 64 | _frida_session_enable_debugger_sync(handle.Pointer, port, out error); 65 | GError.Throw(error); 66 | } 67 | 68 | public void DisableDebugger() 69 | { 70 | IntPtr error; 71 | _frida_session_disable_debugger_sync(handle.Pointer, out error); 72 | GError.Throw(error); 73 | } 74 | 75 | public void EnableJit() 76 | { 77 | IntPtr error; 78 | _frida_session_enable_jit_sync(handle.Pointer, out error); 79 | GError.Throw(error); 80 | } 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /Frida.NetStandard/GError.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Frida.NetStandard 5 | { 6 | [StructLayout(LayoutKind.Sequential)] 7 | struct GError 8 | { 9 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 10 | static extern void _frida_g_clear_error(ref IntPtr ptr); 11 | 12 | public Int32 GQuark; 13 | public Int32 Code; 14 | public string Message; 15 | public static void Throw(IntPtr ptr) 16 | { 17 | if (ptr == IntPtr.Zero) 18 | return; 19 | var err = (GError)Marshal.PtrToStructure(ptr, typeof(GError)); 20 | _frida_g_clear_error(ref ptr); 21 | throw new InvalidOperationException(err.Message ?? "Unknown frida error"); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Frida.NetStandard/Handle.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Frida.NetStandard 5 | { 6 | class Handle 7 | { 8 | 9 | public IntPtr Pointer { get; private set; } 10 | 11 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 12 | static extern void _frida_g_object_unref(IntPtr ptr); 13 | 14 | public Handle(Func handle) 15 | { 16 | try 17 | { 18 | Runtime.Ref(); 19 | Pointer = handle(); 20 | if (Pointer == IntPtr.Zero) 21 | Runtime.Unref(); 22 | } 23 | catch 24 | { 25 | Runtime.Unref(); 26 | throw; 27 | } 28 | } 29 | 30 | ~Handle() 31 | { 32 | if (Pointer == IntPtr.Zero) 33 | return; 34 | _frida_g_object_unref(Pointer); 35 | Runtime.Unref(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Frida.NetStandard/Ref.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | 4 | namespace Frida.NetStandard 5 | { 6 | class Ref : IDisposable 7 | { 8 | public IntPtr Pointer { get; private set; } 9 | bool disposed = false; 10 | 11 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 12 | static extern void _frida_g_object_unref(IntPtr ptr); 13 | 14 | public void Dispose() 15 | { 16 | if (disposed) 17 | return; 18 | disposed = true; 19 | if (Pointer != IntPtr.Zero) 20 | _frida_g_object_unref(Pointer); 21 | Runtime.Unref(); 22 | } 23 | 24 | public Ref(IntPtr handle) 25 | { 26 | Pointer = handle; 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Frida.NetStandard/Runtime.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Threading; 4 | 5 | namespace Frida.NetStandard 6 | { 7 | static class Runtime 8 | { 9 | public const string LibName = "Frida.Exports.dll"; 10 | static volatile int refs = 0; 11 | 12 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 13 | static extern void _frida_init(); 14 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 15 | static extern void _frida_deinit(); 16 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 17 | static extern void _frida_g_free(IntPtr ptr); 18 | 19 | public static void Ref() 20 | { 21 | if (Interlocked.Increment(ref refs) == 1) 22 | { 23 | Console.WriteLine("Initializing frida"); 24 | _frida_init(); 25 | } 26 | } 27 | 28 | public static void Unref() 29 | { 30 | 31 | if (Interlocked.Decrement(ref refs) <= 0) 32 | { 33 | Console.WriteLine("Deinitializing frida"); 34 | _frida_deinit(); 35 | } 36 | } 37 | public static string ReadStringAndFree(this IntPtr ptr) 38 | { 39 | var ret = Marshal.PtrToStringAuto(ptr); 40 | _frida_g_free(ptr); 41 | return ret; 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Frida.NetStandard/Script.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using Newtonsoft.Json.Linq; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Runtime.InteropServices; 6 | using System.Text; 7 | 8 | namespace Frida.NetStandard 9 | { 10 | public class Script 11 | { 12 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 13 | static extern void _frida_script_load_sync(IntPtr device, out IntPtr error); 14 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 15 | static extern void _frida_script_unload_sync(IntPtr device, out IntPtr error); 16 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 17 | static extern void _frida_script_eternalize_sync(IntPtr device, out IntPtr error); 18 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 19 | static extern void _frida_script_post_sync(IntPtr device, string message, IntPtr data, UInt32 dataLength, out IntPtr error); 20 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 21 | static extern void _frida_script_connect_message_handler(IntPtr handle, IntPtr fnPointer); 22 | [DllImport(Runtime.LibName, CharSet = CharSet.Unicode)] 23 | static extern void _frida_script_disconnect_message_handler(IntPtr handle, IntPtr fnPointer); 24 | 25 | delegate void OnScriptMessageDelegate(IntPtr message, IntPtr data, UInt32 dataSize); 26 | Handle handle; 27 | IntPtr onMessageDelegate; 28 | GCHandle onMessageDelegateHandle; 29 | 30 | public Script(Func builder) 31 | { 32 | handle = new Handle(builder); 33 | OnScriptMessageDelegate del = OnScriptMessage; 34 | onMessageDelegateHandle = GCHandle.Alloc(del); 35 | onMessageDelegate = Marshal.GetFunctionPointerForDelegate(del); 36 | _frida_script_connect_message_handler(handle.Pointer, onMessageDelegate); 37 | } 38 | 39 | ~Script() 40 | { 41 | if (handle != null && onMessageDelegate != IntPtr.Zero) 42 | { 43 | _frida_script_disconnect_message_handler(handle.Pointer, onMessageDelegate); 44 | onMessageDelegateHandle.Free(); 45 | } 46 | } 47 | 48 | // {"type":"log","level":"info","payload":"Script initialized"} 49 | public delegate void MessageDelegate(string type, JToken payload, byte[] data); 50 | public event MessageDelegate OnMessage; 51 | public delegate void ConsoleDelegate(string level, string data); 52 | public event ConsoleDelegate OnConsole; 53 | 54 | 55 | 56 | void OnScriptMessage(IntPtr messagePtr, IntPtr data, UInt32 dataSize) 57 | { 58 | try 59 | { 60 | var message = messagePtr.ReadStringAndFree(); 61 | byte[] dataBytes = null; 62 | if (data != IntPtr.Zero) 63 | { 64 | dataBytes = new byte[dataSize]; 65 | Marshal.Copy(data, dataBytes, 0, (int)dataSize); 66 | } 67 | 68 | var payload = JsonConvert.DeserializeObject(message); 69 | JToken type; 70 | if (!payload.TryGetValue("type", out type) || type.Type != JTokenType.String) 71 | return; 72 | ProcessMessage(type.Value(), payload, dataBytes); 73 | 74 | } catch (Exception ex) 75 | { 76 | OnConsole?.Invoke("error", "ERROR PROCESSING MESSAGE: " + ex.Message); 77 | } 78 | } 79 | 80 | class FridaLog 81 | { 82 | public string level { get; set; } 83 | public string payload { get; set; } 84 | } 85 | protected virtual void ProcessMessage(string type, JObject data, byte[] dataBytes) 86 | { 87 | switch (type) 88 | { 89 | case "log": 90 | var msg = data.ToObject(); 91 | OnConsole?.Invoke(msg.level, msg.payload); 92 | break; 93 | default: 94 | JToken payload; 95 | data.TryGetValue("payload", out payload); 96 | OnMessage?.Invoke(type, payload, dataBytes); 97 | break; 98 | } 99 | } 100 | 101 | public void Load() 102 | { 103 | IntPtr error; 104 | _frida_script_load_sync(handle.Pointer, out error); 105 | GError.Throw(error); 106 | } 107 | 108 | public void Unload() 109 | { 110 | IntPtr error; 111 | _frida_script_unload_sync(handle.Pointer, out error); 112 | GError.Throw(error); 113 | } 114 | 115 | public void Eternalize() 116 | { 117 | IntPtr error; 118 | _frida_script_eternalize_sync(handle.Pointer, out error); 119 | GError.Throw(error); 120 | } 121 | 122 | public void Post(object payload, byte[] data = null) 123 | { 124 | IntPtr dataPtr = IntPtr.Zero; 125 | try 126 | { 127 | var message = JsonConvert.SerializeObject(payload); 128 | if (data != null) 129 | { 130 | dataPtr = Marshal.AllocHGlobal(data.Length); 131 | Marshal.Copy(data, 0, dataPtr, data.Length); 132 | } 133 | IntPtr error; 134 | _frida_script_post_sync(handle.Pointer, message, dataPtr, (uint)(data?.Length ?? 0), out error); 135 | GError.Throw(error); 136 | } 137 | finally 138 | { 139 | if (dataPtr != IntPtr.Zero) 140 | Marshal.FreeHGlobal(dataPtr); 141 | } 142 | } 143 | } 144 | 145 | } 146 | -------------------------------------------------------------------------------- /Frida.NetStandard/ScriptWithRpc.cs: -------------------------------------------------------------------------------- 1 | using Frida.NetStandard.Utilities; 2 | using Newtonsoft.Json; 3 | using Newtonsoft.Json.Linq; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Text; 9 | using System.Threading.Tasks; 10 | 11 | namespace Frida.NetStandard 12 | { 13 | public abstract class FridaRpcException : Exception 14 | { 15 | protected FridaRpcException(string message, Exception ex = null) : base(message, ex) { } 16 | } 17 | public class FridaRpcSerializationException : FridaRpcException 18 | { 19 | public FridaRpcSerializationException(Exception ex) : base(ex.Message, ex){ } 20 | } 21 | 22 | public class FridaRpcScriptException : FridaRpcException 23 | { 24 | public string ErrorName { get; private set; } 25 | public string JsErrorStack { get; private set; } 26 | 27 | public FridaRpcScriptException(string message, string errName, string errStack) : base(errStack ?? message) 28 | { 29 | this.ErrorName = errName; 30 | this.JsErrorStack = errStack; 31 | } 32 | 33 | public override string ToString() 34 | { 35 | return $"{Message} at \n {JsErrorStack}"; 36 | } 37 | } 38 | public class ScriptWithRpc : Script, IInterfaceImplementation 39 | { 40 | public ScriptWithRpc(Func builder) 41 | : base(builder) 42 | { 43 | Rpc = InterfaceImplementer.Create(this); 44 | } 45 | 46 | public TRpc Rpc { get; } 47 | 48 | object IInterfaceImplementation.Call(MethodInfo method, object[] arguments) 49 | { 50 | return ((IInterfaceImplementation)this).CallAsync(method, arguments) 51 | .ConfigureAwait(false) 52 | .GetAwaiter() 53 | .GetResult(); 54 | } 55 | 56 | class Operation 57 | { 58 | public TaskCompletionSource Source; 59 | public Type ExpectedReturnType; 60 | } 61 | Dictionary operations = new Dictionary(); 62 | Task IInterfaceImplementation.CallAsync(MethodInfo method, object[] arguments) 63 | { 64 | Type expectedReturnType = null; 65 | if (typeof(Task).IsAssignableFrom(method.ReturnType)) 66 | { 67 | if (method.ReturnType.IsGenericType) 68 | expectedReturnType = method.ReturnType.GetGenericArguments()[0]; 69 | } 70 | else 71 | expectedReturnType = method.ReturnType; 72 | 73 | var id = Guid.NewGuid(); 74 | var op = operations[id] = new Operation 75 | { 76 | Source = new TaskCompletionSource(), 77 | ExpectedReturnType = expectedReturnType, 78 | }; 79 | 80 | var payload = new object[] 81 | { 82 | "frida:rpc", 83 | id, 84 | "call", 85 | method.Name, 86 | arguments, 87 | }; 88 | Post(payload); 89 | 90 | return op.Source.Task; 91 | } 92 | 93 | class FridaRpcMessage 94 | { 95 | public string type { get; set; } 96 | public string[] payload { get; set; } 97 | } 98 | 99 | protected override void ProcessMessage(string type, JObject data, byte[] dataBytes) 100 | { 101 | switch(type) 102 | { 103 | case "send": 104 | case "error": 105 | JToken payload; 106 | if(data.TryGetValue("payload", out payload) && payload is JArray args) 107 | { 108 | Guid callId; 109 | if (args.Count >= 3 110 | && args[0].Type == JTokenType.String 111 | && args[1].Type == JTokenType.String 112 | && args[2].Type == JTokenType.String 113 | && args[0].Value() == "frida:rpc" 114 | && Guid.TryParse(args[1].Value(), out callId)) 115 | { 116 | 117 | Operation operation; 118 | if (!operations.TryGetValue(callId, out operation)) 119 | return; 120 | 121 | var opResult = args[2].Value(); 122 | switch (opResult) 123 | { 124 | case "ok": 125 | try 126 | { 127 | object retValue = null; 128 | if (operation.ExpectedReturnType != null) 129 | retValue = dataBytes != null && operation.ExpectedReturnType == typeof(byte[]) 130 | ? dataBytes 131 | : args[3].ToObject(operation.ExpectedReturnType); 132 | operation.Source.SetResult(retValue); 133 | } 134 | catch (Exception ex) 135 | { 136 | operation.Source.SetException(new FridaRpcSerializationException(ex)); 137 | } 138 | break; 139 | case "error": 140 | var errMessage = args[3].Value(); 141 | var errName = args.Count > 4 ? args[4].Value() : null; 142 | var errStack = args.Count > 5 ? args[5].Value() : null; 143 | operation.Source.SetException(new FridaRpcScriptException(errMessage, errName, errStack)); 144 | break; 145 | default: 146 | break; 147 | } 148 | operations.Remove(callId); 149 | 150 | return; 151 | } 152 | } 153 | break; 154 | default: 155 | break; 156 | } 157 | base.ProcessMessage(type, data, dataBytes); 158 | } 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /Frida.NetStandard/Utilities/InterfaceImplementer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using System.Reflection.Emit; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace Frida.NetStandard.Utilities 10 | { 11 | class InterfaceImplementer 12 | { 13 | static InterfaceImplementer implem = new InterfaceImplementer(typeof(T)); 14 | public static T Create(IInterfaceImplementation callback) 15 | => (T)implem.Create(callback); 16 | } 17 | 18 | public interface IInterfaceImplementation 19 | { 20 | object Call(MethodInfo method, object[] arguments); 21 | Task CallAsync(MethodInfo method, object[] arguments); 22 | } 23 | 24 | public class InterfaceImplementer 25 | { 26 | private readonly Type interfaceType; 27 | Dictionary methods = new Dictionary(); 28 | private TypeInfo created; 29 | 30 | 31 | public InterfaceImplementer(Type interfaceType) 32 | { 33 | this.interfaceType = interfaceType; 34 | AssemblyName assemblyName = new AssemblyName(string.Concat(interfaceType.Namespace, "_", Guid.NewGuid().ToString())); 35 | var ab = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndCollect); 36 | var mb = ab.DefineDynamicModule(string.Concat(assemblyName.Name, ".dll")); 37 | 38 | 39 | 40 | var tb = mb.DefineType(interfaceType.Name + Guid.NewGuid(), TypeAttributes.Public); 41 | tb.AddInterfaceImplementation(interfaceType); 42 | var owner = tb.DefineField("implem", typeof(Store), FieldAttributes.Private); 43 | 44 | GenerateConstructor(tb, owner); 45 | foreach (MethodInfo mi in GetMethods()) 46 | GenerateMethod(tb, mi, owner); 47 | 48 | created = tb.CreateTypeInfo(); 49 | } 50 | 51 | HashSet GetMethods() 52 | { 53 | var methods = new HashSet(); 54 | var types = new Queue(new[] { interfaceType }); 55 | while (types.Count > 0) 56 | { 57 | var type = types.Dequeue(); 58 | foreach (var m in type.GetMethods()) 59 | methods.Add(m); 60 | foreach (var t in type.GetInterfaces()) 61 | types.Enqueue(t); 62 | } 63 | return methods; 64 | } 65 | public object Create(IInterfaceImplementation implem) 66 | { 67 | return Activator.CreateInstance(created, new[] { new Store(this, implem) }); 68 | } 69 | 70 | public class Store 71 | { 72 | public IInterfaceImplementation implem; 73 | private InterfaceImplementer owner; 74 | 75 | public Store(InterfaceImplementer interfaceImplementer, IInterfaceImplementation implem) 76 | { 77 | this.owner = interfaceImplementer; 78 | this.implem = implem; 79 | } 80 | 81 | public T Invoke(string method, object[] arguments) 82 | { 83 | var m = owner.methods[method]; 84 | var ret = implem.Call(m, arguments); 85 | return (T)ret; 86 | } 87 | 88 | public async Task InvokeAsync(string method, object[] arguments) 89 | { 90 | var m = owner.methods[method]; 91 | var ret = await implem.CallAsync(m, arguments); 92 | return (T)ret; 93 | } 94 | } 95 | 96 | 97 | private void GenerateConstructor(TypeBuilder tb, FieldBuilder owner) 98 | { 99 | var ctor = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard 100 | , new[] { typeof(Store) }); 101 | var il = ctor.GetILGenerator(); 102 | 103 | il.Emit(OpCodes.Ldarg_0); 104 | il.Emit(OpCodes.Ldarg_1); 105 | il.Emit(OpCodes.Stfld, owner); 106 | il.Emit(OpCodes.Ret); 107 | } 108 | 109 | private void GenerateMethod(TypeBuilder tb, MethodInfo mi, FieldInfo owner) 110 | { 111 | var parameters = mi.GetParameters(); 112 | var genericArgumentArray = mi.GetGenericArguments(); 113 | 114 | MethodBuilder mb = tb.DefineMethod(mi.Name, MethodAttributes.Public | MethodAttributes.Virtual, mi.ReturnType, parameters.Select(pi => pi.ParameterType).ToArray()); 115 | if (genericArgumentArray.Any()) 116 | { 117 | mb.DefineGenericParameters(genericArgumentArray.Select(s => s.Name).ToArray()); 118 | } 119 | 120 | 121 | var il = mb.GetILGenerator(); 122 | il.Emit(OpCodes.Ldarg_0); 123 | il.Emit(OpCodes.Ldfld, owner); 124 | il.Emit(OpCodes.Ldstr, mi.Name); 125 | 126 | // method has parameters ? 127 | if (parameters.Length > 0) 128 | { 129 | il.Emit(OpCodes.Ldc_I4_S, parameters.Length); 130 | il.Emit(OpCodes.Newarr, typeof(object)); 131 | for (int i = 0; i < parameters.Length; i++) 132 | { 133 | il.Emit(OpCodes.Dup); 134 | il.Emit(OpCodes.Ldc_I4_S, i); 135 | il.Emit(OpCodes.Ldarg, i + 1); 136 | if (parameters[i].ParameterType.IsValueType) 137 | il.Emit(OpCodes.Box, parameters[i].ParameterType); 138 | il.Emit(OpCodes.Stelem_Ref); 139 | } 140 | } 141 | else 142 | il.Emit(OpCodes.Ldnull); 143 | 144 | MethodInfo method; 145 | if (typeof(Task).IsAssignableFrom(mi.ReturnType)) 146 | { 147 | method = typeof(Store).GetMethod(nameof(Store.InvokeAsync)); 148 | if (mi.ReturnType.IsGenericType) 149 | method = method.MakeGenericMethod(mi.ReturnType.GetGenericArguments()); 150 | else 151 | method = method.MakeGenericMethod(typeof(string)); // yea, whatever 152 | } 153 | else 154 | { 155 | method = typeof(Store).GetMethod(nameof(Store.Invoke)); 156 | if (mi.ReturnType == typeof(void)) 157 | method = method.MakeGenericMethod(typeof(string)); // yea, whatever 158 | else 159 | method = method.MakeGenericMethod(mi.ReturnType); 160 | } 161 | 162 | il.Emit(OpCodes.Call, method); 163 | 164 | if (mi.ReturnType == typeof(void)) // method has no return type => just pop the result and return. 165 | il.Emit(OpCodes.Pop); 166 | 167 | il.Emit(OpCodes.Ret); 168 | 169 | tb.DefineMethodOverride(mb, mi); 170 | methods[mi.Name] = mi; 171 | } 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | .Net standard binding for Frida (https://www.frida.re) , with RPC calls support 2 | 3 | Tested on: 4 | * Windows 10 (X64) 5 | * OSX 6 | 7 | # Use it 8 | 9 | See [TestProgram/Program.cs](TestProgram/Program.cs) for an example 10 | 11 | 12 | # Build it 13 | 14 | Clone the Frida.NetStandard directory 15 | ``` 16 | $ git clone https://github.com/lenacloud/frida-netstandard 17 | ``` 18 | 19 | ## ... on Windows 20 | Then, enter the `frida-netstandard` folder, and download dependencies running the script below (downloads Frida release binaries & extracts them) 21 | 22 | ``` 23 | $ git clone 24 | $ powershell 25 | PS> Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted 26 | PS> .\setup.ps1 27 | ``` 28 | 29 | Then: 30 | 1) open "Frida.NetStandard.sln" 31 | 2) build Fria.Exports.vcxproj 32 | 3) Run TestProgram.ccsproj : It should pop a notepad, and inject it. 33 | 34 | 35 | # Distribute it 36 | 37 | You __must__ distribute and load the correct Frida.Exports library yourself, depending on the platform you are running on (see [TestProgram/Program.cs](TestProgram/Program.cs)). 38 | 39 | Frida being a quite big library, this behaviour is indended to force you to chose which platform/architecture you are willing to distribute. -------------------------------------------------------------------------------- /TestProgram/Program.cs: -------------------------------------------------------------------------------- 1 | using Frida.NetStandard; 2 | using Newtonsoft.Json; 3 | using System; 4 | using System.Diagnostics; 5 | using System.IO; 6 | using System.Linq; 7 | using System.Reflection; 8 | using System.Runtime.InteropServices; 9 | using System.Threading; 10 | using System.Threading.Tasks; 11 | 12 | namespace TestProgram 13 | { 14 | 15 | 16 | public class Msg 17 | { 18 | public string message { get; set; } 19 | public int number { get; set; } 20 | } 21 | public class Input 22 | { 23 | public string author { get; set; } 24 | } 25 | 26 | public interface IRpc 27 | { 28 | Msg pingScript(Input input); 29 | 30 | // supports Task results for long operations 31 | Task longOperation(); 32 | } 33 | 34 | class Program 35 | { 36 | 37 | // for windows 38 | [DllImport("kernel32.dll", SetLastError = true)] 39 | static extern bool SetDllDirectory(string lpPathName); 40 | 41 | static void Main(string[] args) 42 | { 43 | // register dll directory (so the frida DLL can be found) 44 | var dir = new DirectoryInfo(Path.Combine(Path.GetDirectoryName(typeof(Program).Assembly.Location), "..", "..", "..", "..", "x86", "Debug")); 45 | if (!dir.Exists) 46 | throw new InvalidOperationException("Build Frida.Exports first"); 47 | SetDllDirectory(dir.FullName); 48 | 49 | var man = new DeviceManager(); 50 | var notepad = Process.Start("notepad"); 51 | try 52 | { 53 | // attach to local 'notepad' 54 | var device = man.EnumerateDevices().First(x => x.Type == FridaDeviceType.Local); 55 | var session = device.Attach((uint)notepad.Id); 56 | Console.WriteLine("Attached to " + notepad.Id); 57 | 58 | // inject script 59 | var script = session.CreateScriptWithRpc(File.ReadAllText("script.js")); 60 | script.OnMessage += (type, msg, data) => Console.WriteLine("Received message: " + msg); 61 | script.OnConsole += (level, msg) => Console.WriteLine($"[frida {level}] {msg}"); 62 | 63 | script.Load(); 64 | 65 | // perform a synchronous RPC call 66 | var pong = script.Rpc?.pingScript(new Input { author = "c#" }); 67 | Console.WriteLine("RPC answer: " + pong?.message); 68 | 69 | // perform an async RPC call, non blocking. 70 | script.Rpc.longOperation() 71 | .ContinueWith(t => Console.WriteLine("End of long operation")); 72 | 73 | Console.WriteLine("===== Press ESC to quit ======"); 74 | while (Console.ReadKey().Key != ConsoleKey.Escape); 75 | 76 | } 77 | finally 78 | { 79 | notepad.Kill(); 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /TestProgram/TestProgram.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | PreserveNewest 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /TestProgram/script.js: -------------------------------------------------------------------------------- 1 |  2 | rpc.exports.pingScript = function (x) { 3 | return { message: 'Pong back to ' + x.author }; 4 | } 5 | rpc.exports.longOperation = function () { 6 | Thread.sleep(2); 7 | } 8 | 9 | console.log('Script initialized'); 10 | -------------------------------------------------------------------------------- /setup.ps1: -------------------------------------------------------------------------------- 1 | $url = "https://github.com/frida/frida/releases/download/12.2.23/frida-core-devkit-12.2.23-windows-x86_64.exe" 2 | $fridaLibDir = "Frida.Exports\lib\x64\" 3 | $output = "$PSScriptRoot\$fridaLibDir\extractor.exe" 4 | 5 | echo "Downloading frida release" 6 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 7 | # Invoke-WebRequest -Uri $url -OutFile $output 8 | 9 | echo "Extracting frida release" 10 | pushd 11 | cd $fridaLibDir 12 | Invoke-Expression $output 13 | popd --------------------------------------------------------------------------------