Last active
August 13, 2016 15:39
-
-
Save dqsully/47ee7fbecdbfe37209e1baee5b532c7b to your computer and use it in GitHub Desktop.
Atom Command Piping
This file contains 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
// Atom Command Piping (Client).cpp : Defines the entry point for the console application. | |
// | |
/* | |
Created solely for the purpose of getting around silly Atom security problems | |
*/ | |
#include "stdafx.h" | |
/* | |
#include <stdio.h> | |
#include <tchar.h> | |
#include <iostream> | |
#include <cstdio> | |
#include <cwchar> | |
#include <memory> | |
#include <string> | |
#include <Windows.h> | |
*/ | |
using namespace std; | |
int wmain(int argc, wchar_t **argv) { | |
wstring bashCommand = L""; | |
HANDLE pAtomPipe; | |
BOOL result; | |
DWORD cBytesRead, cBytesWritten, cBytesAvailable; | |
wchar_t buffer[128]; | |
int c; | |
// Take all parameters and string them together into one to be passed into bash | |
if(argc > 0) bashCommand += argv[1]; | |
for(int i=2; i<argc; i++) { | |
bashCommand += L" "; | |
bashCommand += argv[i]; | |
} | |
// wcout << "Command is: " << bashCommand << endl; | |
bashCommand += L'\uF8FF'; | |
// wcout << "Connecting to pipe..."; | |
pAtomPipe = CreateFile( | |
L"\\\\.\\pipe\\atomcommands", | |
GENERIC_READ | GENERIC_WRITE, | |
FILE_SHARE_WRITE | FILE_SHARE_READ, | |
NULL, | |
OPEN_EXISTING, | |
FILE_ATTRIBUTE_NORMAL, | |
NULL | |
); | |
if(pAtomPipe == INVALID_HANDLE_VALUE) { | |
// wcout << "Failed: " << GetLastError() << endl; | |
system("pause"); | |
return 1; | |
} | |
// wcout << "Done" << endl; | |
// wcout << "Writing command through pipe..."; | |
result = WriteFile( | |
pAtomPipe, | |
bashCommand.c_str(), | |
bashCommand.length() * sizeof(wchar_t), | |
&cBytesWritten, | |
NULL | |
); | |
if(!result) { | |
// wcout << "Failed: " << GetLastError() << endl; | |
system("pause"); | |
CloseHandle(pAtomPipe); | |
return 2; | |
} | |
// wcout << "Done" << endl; | |
// wcout << "Reading Data..." << endl; | |
for(;;) { | |
for(;;) { | |
result = PeekNamedPipe( | |
pAtomPipe, | |
NULL, | |
0, | |
NULL, | |
&cBytesAvailable, | |
NULL | |
); | |
if(!result) { | |
// cout << "PeekNamedPipe Error: " << GetLastError() << endl; | |
break; | |
} | |
if(!cBytesAvailable) { | |
// cout << "No more bytes available" << endl; | |
break; | |
} | |
result = ReadFile( | |
pAtomPipe, | |
buffer, | |
min(sizeof(buffer) - sizeof(wchar_t), cBytesAvailable), | |
&cBytesRead, | |
NULL | |
); | |
if(!result) { | |
// cout << "ReadFile Error: " << GetLastError() << endl; | |
break; | |
} | |
buffer[cBytesRead / sizeof(wchar_t)] = 0; | |
for(c = 0; c < wcslen(buffer); c++) { | |
if(buffer[c] == L'\uF8FF') { | |
wcout.write(buffer, c); | |
goto exitread; | |
} | |
} | |
wcout << buffer; | |
} | |
Sleep(100); | |
} | |
exitread: | |
// wcout << "Done" << endl; | |
CloseHandle(pAtomPipe); | |
return 0; | |
} |
This file contains 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
// Atom Command Piping.cpp : Defines the entry point for the console application. | |
// | |
/* | |
Created solely for the purpose of getting around silly Atom security problems | |
*/ | |
#include "stdafx.h" | |
/* | |
#include <stdio.h> | |
#include <tchar.h> | |
#include <iostream> | |
#include <cstdio> | |
#include <cwchar> | |
#include <memory> | |
#include <string> | |
#include <Windows.h> | |
*/ | |
using namespace std; | |
HANDLE gpAtomPipe, gpCmdPipeW, gpCmdPipeR; | |
PROCESS_INFORMATION gfProcessInformation = { 0 }; | |
bool eCmdPipe, eAtomPipe, eProcess, eAtomPipeConnection; | |
int wmain(int argc, wchar_t **argv) { | |
bool result, processEnded = false; | |
wchar_t buffer[128]; | |
wstring str; | |
DWORD cBytesRead, cBytesAvailable, cBytesWritten; | |
SECURITY_ATTRIBUTES fSecurityAttributes = { sizeof(SECURITY_ATTRIBUTES) }; | |
STARTUPINFO fStartupInfo = { sizeof(STARTUPINFO) }; | |
int c; | |
// Bash process settings setup | |
fSecurityAttributes.bInheritHandle = TRUE; // Pipe handles are inherited by child process | |
fSecurityAttributes.lpSecurityDescriptor = NULL; | |
// Create pipe to get results from child's stdout | |
wcout << "Creating command line pipe..."; | |
result = CreatePipe( | |
&gpCmdPipeR, // read stream | |
&gpCmdPipeW, // write stream | |
&fSecurityAttributes, // security attributes | |
0 | |
); | |
if (!result) { | |
wcout << "Failed: " << GetLastError() << endl; | |
system("pause"); | |
return 1; | |
} | |
wcout << "Done" << endl; | |
eCmdPipe = true; | |
fStartupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; | |
fStartupInfo.hStdOutput = gpCmdPipeW; | |
fStartupInfo.hStdError = gpCmdPipeW; | |
fStartupInfo.wShowWindow = SW_HIDE; | |
wcout << "Creating an instance of a named pipe..."; | |
// Create a pipe to receive and send data | |
gpAtomPipe = CreateNamedPipe( | |
L"\\\\.\\pipe\\atomcommands", // pipe name | |
PIPE_ACCESS_DUPLEX, // 2-way pipe -- receive commands, send outputs | |
PIPE_TYPE_BYTE, // send data as a byte stream | |
1, // only allow 1 instance of this pipe | |
0, // no outbound buffer | |
0, // no inbound buffer | |
0, // use default wait time | |
NULL // use default security attributes | |
); | |
// Handle pipe creation error | |
if (gpAtomPipe == NULL || gpAtomPipe == INVALID_HANDLE_VALUE) { | |
wcout << "Failed: " << GetLastError() << endl; | |
system("pause"); // For testing, make sure user knows what happened | |
return 2; | |
} | |
wcout << "Done" << endl; | |
eAtomPipe = true; | |
// Allow a client multiple times (stay alive as a service) | |
for (;;) { | |
// Reset variables | |
str = L"bash -c "; | |
wcout << "Waiting for a client to connect to the pipe..."; | |
// Wait for client to connect | |
result = ConnectNamedPipe(gpAtomPipe, NULL); | |
// Handle connection error | |
if (!result) { | |
wcout << "Failed: " << GetLastError() << endl; | |
system("pause"); // For testing, make sure user knows what happened, and don't continuously loop errors | |
} | |
else { | |
wcout << "Connected" << endl; | |
wcout << "Reading command from pipe..."; | |
// Read entire command from pipe | |
for(;;) { | |
for (;;) { | |
result = PeekNamedPipe( | |
gpAtomPipe, // pipe | |
NULL, // no output buffer | |
0, // buffer size 0 | |
NULL, // don't care about bytes read | |
&cBytesAvailable, // get # of bytes available | |
NULL // don't care about current message | |
); | |
if (!result) break; | |
// Make sure there is still data to read | |
if (!cBytesAvailable) break; | |
// Get data, or stop if error | |
result = ReadFile( | |
gpAtomPipe, // pipe/stream | |
buffer, // output buffer | |
min(sizeof(buffer) - sizeof(wchar_t), cBytesAvailable), // # of bytes max to read | |
&cBytesRead, // get # of bytes read | |
NULL // no overlapped io | |
); | |
if (!result) break; | |
// Add null terminator and append to result string | |
buffer[cBytesRead / sizeof(wchar_t)] = 0; | |
for(c = 0; c < wcslen(buffer); c++) { | |
if(buffer[c] == L'\uF8FF') { | |
str.append(buffer, c); | |
goto exitread; | |
} | |
} | |
str += buffer; | |
} | |
Sleep(100); | |
} | |
exitread: | |
wcout << "Done" << endl; | |
wcout << "Command is: " << str << endl; | |
wcout << "Starting received command..."; | |
// Run command and pipe output directly to client | |
result = CreateProcessW( | |
NULL, | |
(LPWSTR)str.c_str(), | |
NULL, | |
NULL, | |
TRUE, | |
CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT, | |
NULL, | |
NULL, | |
&fStartupInfo, | |
&gfProcessInformation | |
); | |
if (!result) { | |
wcout << "Failed: " << GetLastError() << endl; | |
system("pause"); // you know what this means | |
} else { | |
wcout << "Done" << endl << "Sending data..." << endl; | |
eProcess = true; | |
while (!processEnded) { | |
// Make sure not to hog CPU | |
processEnded = WaitForSingleObject(gfProcessInformation.hProcess, 50) == WAIT_OBJECT_0; | |
// Read data and send | |
for (;;) { | |
result = PeekNamedPipe( | |
gpCmdPipeR, | |
NULL, | |
0, | |
NULL, | |
&cBytesAvailable, | |
NULL | |
); | |
if (!result) break; | |
if (!cBytesAvailable) break; | |
result = ReadFile( | |
gpCmdPipeR, | |
buffer, | |
min(sizeof(buffer) - sizeof(wchar_t), cBytesAvailable), | |
&cBytesRead, | |
NULL | |
); | |
if (!result) break; | |
buffer[cBytesRead / sizeof(wchar_t)] = 0; // just in case | |
wcout << buffer; | |
result = WriteFile( | |
gpAtomPipe, // back to Atom | |
buffer, // data to send | |
cBytesRead, // length of data | |
&cBytesWritten, // get data actually sent | |
NULL | |
); | |
if (!result) { | |
wcout << "Failed: " << GetLastError() << endl; | |
system("pause"); | |
break; | |
} | |
} | |
} | |
result = WriteFile( | |
gpAtomPipe, // back to Atom | |
L"\uF8FF", // data to send | |
sizeof(wchar_t) * 2, // length of data | |
NULL, // get data actually sent | |
NULL | |
); | |
if (!result) { | |
wcout << "Failed: " << GetLastError() << endl; | |
system("pause"); | |
break; | |
} | |
if (result) wcout << "Done" << endl; | |
CloseHandle(gfProcessInformation.hProcess); | |
CloseHandle(gfProcessInformation.hThread); | |
eProcess = false; | |
} | |
} | |
} | |
} | |
BOOL WINAPI consoleHandler(DWORD signal) { | |
if(signal == CTRL_C_EVENT) { | |
// Cleanup | |
if(eCmdPipe) { | |
CloseHandle(gpCmdPipeW); | |
CloseHandle(gpCmdPipeR); | |
} | |
if(eAtomPipe) | |
CloseHandle(gpAtomPipe); | |
if(eProcess) { | |
CloseHandle(gfProcessInformation.hProcess); | |
CloseHandle(gfProcessInformation.hThread); | |
} | |
return true; | |
} | |
return false; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment