Skip to content

Instantly share code, notes, and snippets.

@dqsully
Last active August 13, 2016 15:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dqsully/47ee7fbecdbfe37209e1baee5b532c7b to your computer and use it in GitHub Desktop.
Save dqsully/47ee7fbecdbfe37209e1baee5b532c7b to your computer and use it in GitHub Desktop.
Atom Command Piping
// 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;
}
// 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