由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。(本文仅用于交流学习)
我们先了解一下什么是管道,也可以叫做进程间的通信。其是用于通信共享内存的一部分,管道有两端,一端允许进程进行写入,另一端允许进程进行读取。
管道又可以分为匿名管道、命名管道
我们着重看一下命名管道,对于命名管道,每个命名管道都有一个唯一的名称。
我们来看看如何编写一个管道服务器:
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
HANDLE lCreatePipe = CreateNamedPipe("\\\\.\\pipe\\pipe\\testname", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE, 1, 2048, 2048, 0, NULL);
if (lCreatePipe == INVALID_HANDLE_VALUE) {
cout << "CreateNamedPipeA Error" << endl;
return 1;
}
cout << "CreateNamedPipeA Success" << endl;
BOOL ConnectSuccess = ConnectNamedPipe(lCreatePipe, NULL);
if (ConnectSuccess == 0) {
cout << "ConnectNamedPipe Error" << endl;
return 1;
}
cout << "客户端成功连接到服务器" << endl;
char buf[2048];
BOOL Read = ReadFile(lCreatePipe, buf, 2048, NULL, NULL);
if (Read) {
cout << "Success receive:" << buf << endl;
}
return 0;
}
接着我们来看看如何编写客户端的代码
#include <windows.h>
#include <iostream>
using namespace std;
int main() {
HANDLE ConectionTo = CreateFile("\\\\.\\pipe\\pipe\\testname", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (ConectionTo == INVALID_HANDLE_VALUE) {
cout << "CreateFileA Error:" << GetLastError() << endl;
return 1;
}
cout << "成功连接到服务端" << endl;
char message[] = "This is a test";
DWORD messageLenght = lstrlen(message) * 2;
BOOL Write = WriteFile(ConectionTo, message, messageLenght, NULL, NULL);
if (Write == 0) {
cout << "WriteFile Error" << endl;
return 1;
}
cout << "WriteFile to server success" << endl;
}
简单来说就是命名管道服务器线程调用ImpersonateNamedPipeClient函数,当客户端连接到服务端时,系统就会根据客户端的权限授予服务端相同的权限。
具体可参考:
https://learn.microsoft.com/zh-cn/windows/win32/ipc/impersonating-a-named-pipe-client
但是ImpersonateNamedPipeClient函数成功调用是有条件的,只要满足如下之一即可 我们看看第二个条件
当我们以管理员权限运行cmd的时候,我们可以发现其开启了SeImpersonatePrivilege
我们可以让具有system权限程序访问我们,那么这样我们也就具有了system权限,msf中的getsystem也是这个原理
我们可以利用其打开一个cmd窗口来验证是否成功,我们先来看看几个Windows的api
OpenThreadToken
https://learn.microsoft.com/zh-cn/windows/win32/api/processthreadsapi/nf-processthreadsapi-openthreadtoken
DuplicateTokenEx
https://learn.microsoft.com/zh-cn/windows/win32/api/securitybaseapi/nf-securitybaseapi-duplicatetokenex
CreateProcessWithTokenW
调用该函数的进程需要开启SE_IMPERSONATE_NAME特权,管理员进程默认开启 https://learn.microsoft.com/zh-cn/windows/win32/api/winbase/nf-winbase-createprocesswithtokenw
因此思路就很简单了
其大致原理就是通过从另外一个正在运行的进程中,窃取其令牌,然后对其令牌进行复制,创建一个新的进程。
当用户登录时,系统会将密码与存储在安全数据库中的信息进行比较来验证用户的密码。 如果密码经过验证,系统会生成访问令牌。之后此用户执行的每个进程都有此访问令牌的副本。 访问令牌包含以下信息:
参考:
https://learn.microsoft.com/zh-cn/windows/win32/secauthz/access-tokens
因此我们现在的思路如下:
这里测试从administrator窃取system进程的令牌,打开一个system权限的cmd
我们这里窃取winlogon进程的令牌,来打开一个新的cmd窗口
9 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!