diff --git a/.gitignore b/.gitignore index 4b3cf55..b409119 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ CMakeCache.txt CMakeLists.txt.user +CMakeLists.txt.user.2.3pre1 CMakeFiles Makefile *.exe @@ -7,4 +8,5 @@ build.sh Scrape.cbp cmake_install.cmake *.pro.user +*.pro.user.2.3pre1 *-build-desktop diff --git a/Agent/Agent.cc b/Agent/Agent.cc index 3def763..ba49943 100644 --- a/Agent/Agent.cc +++ b/Agent/Agent.cc @@ -35,7 +35,7 @@ Agent::Agent(const QString &socketServer, QObject *parent) : QObject(parent) m_timer = new QTimer(this); m_timer->setSingleShot(false); connect(m_timer, SIGNAL(timeout()), SLOT(pollTimeout())); - m_timer->start(100); + m_timer->start(500); Trace("agent starting..."); } @@ -44,7 +44,6 @@ void Agent::socketReadyRead() { // TODO: This is an incomplete hack... while (m_socket->bytesAvailable() >= sizeof(INPUT_RECORD)) { - Trace("reading a word..."); INPUT_RECORD ir; m_socket->read((char*)&ir, sizeof(ir)); DWORD dummy; @@ -60,5 +59,6 @@ void Agent::socketClosed() void Agent::pollTimeout() { + //Trace("poll"); // TODO: ... scan the console and write it to the socket. } diff --git a/Console/Console.pro b/Console/Console.pro index c0a929b..ef9d48f 100644 --- a/Console/Console.pro +++ b/Console/Console.pro @@ -11,12 +11,12 @@ TEMPLATE = app SOURCES += main.cc \ - ConsoleWindow.cc \ - AgentClient.cc \ + ConsoleWindow.cc \ + ../Shared/AgentClient.cc \ TextWidget.cc HEADERS += ConsoleWindow.h \ - AgentClient.h \ + ../Shared/AgentClient.h \ TextWidget.h FORMS += ConsoleWindow.ui diff --git a/Console/ConsoleWindow.cc b/Console/ConsoleWindow.cc index d2de4d1..85f7acb 100644 --- a/Console/ConsoleWindow.cc +++ b/Console/ConsoleWindow.cc @@ -1,13 +1,10 @@ #include "ConsoleWindow.h" #include "ui_ConsoleWindow.h" -#include "AgentClient.h" +#include "../Shared/AgentClient.h" #include #include #include -#define WINVER 0x501 -#include - ConsoleWindow::ConsoleWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::ConsoleWindow) @@ -15,96 +12,10 @@ ConsoleWindow::ConsoleWindow(QWidget *parent) : ui->setupUi(this); m_agentClient = new AgentClient(this); ui->widget->initWithAgent(m_agentClient); - startShell(); + m_agentClient->startShell(); } ConsoleWindow::~ConsoleWindow() { delete ui; } - - -void ConsoleWindow::startShell() -{ - AttachConsole(m_agentClient->agentPid()); - - HANDLE conout1, conout2, conin; - - { - // TODO: Should the permissions be more restrictive? - // TODO: Is this code necessary or even desirable? If I - // don't change these handles, then are the old values - // invalid? If so, what happens if I create a console - // subprocess? - // The handle must be inheritable. See comment below. - SECURITY_ATTRIBUTES sa; - memset(&sa, 0, sizeof(sa)); - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - conout1 = CreateFile(L"CONOUT$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, - OPEN_EXISTING, - 0, NULL); - conout2 = CreateFile(L"CONOUT$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, - OPEN_EXISTING, - 0, NULL); - conin = CreateFile(L"CONIN$", - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sa, - OPEN_EXISTING, - 0, NULL); - Q_ASSERT(conin != NULL); - Q_ASSERT(conout1 != NULL); - Q_ASSERT(conout2 != NULL); - /* - BOOL success; - success = SetStdHandle(STD_OUTPUT_HANDLE, conout1); - Q_ASSERT(success); - success = SetStdHandle(STD_ERROR_HANDLE, conout2); - Q_ASSERT(success); - success = SetStdHandle(STD_INPUT_HANDLE, conin); - Q_ASSERT(success); - */ - } - - { - wchar_t program[80] = L"c:\\windows\\system32\\cmd.exe"; - wchar_t cmdline[80]; - wcscpy(cmdline, program); - STARTUPINFO sui; - memset(&sui, 0, sizeof(sui)); - sui.cb = sizeof(sui); - sui.dwFlags = STARTF_USESTDHANDLES; - sui.hStdInput = conin; - sui.hStdOutput = conout1; - sui.hStdError = conout2; - PROCESS_INFORMATION pi; - memset(&pi, 0, sizeof(pi)); - BOOL success = CreateProcess( - program, - cmdline, - NULL, - NULL, - FALSE, - 0, - NULL, - NULL, - &sui, - &pi); - if (!success) { - qDebug("Could not start shell"); - } - } - - CloseHandle(conout1); - CloseHandle(conout2); - CloseHandle(conin); - - FreeConsole(); -} diff --git a/Console/ConsoleWindow.h b/Console/ConsoleWindow.h index 6b819cf..765a681 100644 --- a/Console/ConsoleWindow.h +++ b/Console/ConsoleWindow.h @@ -17,9 +17,6 @@ public: explicit ConsoleWindow(QWidget *parent = 0); ~ConsoleWindow(); -private: - void startShell(); - private: Ui::ConsoleWindow *ui; AgentClient *m_agentClient; diff --git a/Console/TextWidget.cc b/Console/TextWidget.cc index 05f97b6..c6dd102 100644 --- a/Console/TextWidget.cc +++ b/Console/TextWidget.cc @@ -1,7 +1,8 @@ #include "TextWidget.h" -#include "AgentClient.h" +#include "../Shared/AgentClient.h" #include #include +#include TextWidget::TextWidget(QWidget *parent) : QWidget(parent), @@ -16,10 +17,25 @@ void TextWidget::initWithAgent(AgentClient *agentClient) void TextWidget::keyPressEvent(QKeyEvent *event) { - m_agentClient->sendKeyPress(event); + // TODO: Flesh this out.... Also: this code is intended + // to be portable across operating systems, so using + // nativeVirtualKey is wrong. + if (event->nativeVirtualKey() != 0) { + INPUT_RECORD ir; + memset(&ir, 0, sizeof(ir)); + ir.EventType = KEY_EVENT; + ir.Event.KeyEvent.bKeyDown = TRUE; + ir.Event.KeyEvent.wVirtualKeyCode = event->nativeVirtualKey(); + qDebug() << ir.Event.KeyEvent.wVirtualKeyCode; + ir.Event.KeyEvent.wVirtualScanCode = 0; // event->nativeScanCode(); + ir.Event.KeyEvent.uChar.UnicodeChar = + event->text().isEmpty() ? L'\0' : event->text().at(0).unicode(); + ir.Event.KeyEvent.wRepeatCount = event->count(); + m_agentClient->writeInputRecord(&ir); + } } void TextWidget::keyReleaseEvent(QKeyEvent *event) { - m_agentClient->sendKeyRelease(event); + //m_agentClient->sendKeyRelease(event); } diff --git a/Console/AgentClient.cc b/Shared/AgentClient.cc similarity index 51% rename from Console/AgentClient.cc rename to Shared/AgentClient.cc index 274cc35..b382a99 100644 --- a/Console/AgentClient.cc +++ b/Shared/AgentClient.cc @@ -1,3 +1,4 @@ +#define WINVER 0x501 #include "AgentClient.h" #include #include @@ -54,6 +55,7 @@ AgentClient::AgentClient(QObject *parent) : Q_ASSERT(m_socket != NULL); } +/* void AgentClient::sendKeyPress(QKeyEvent *event) { // TODO: Flesh this out.... Also: this code is intended @@ -77,8 +79,100 @@ void AgentClient::sendKeyRelease(QKeyEvent *event) { } +*/ + +void AgentClient::writeInputRecord(INPUT_RECORD *ir) +{ + m_socket->write((char*)ir, sizeof(*ir)); +} int AgentClient::agentPid() { return m_agentProcess->dwProcessId; } + +void AgentClient::startShell() +{ + FreeConsole(); + AttachConsole(agentPid()); + + HANDLE conout1, conout2, conin; + + { + // TODO: Should the permissions be more restrictive? + // TODO: Is this code necessary or even desirable? If I + // don't change these handles, then are the old values + // invalid? If so, what happens if I create a console + // subprocess? + // The handle must be inheritable. See comment below. + SECURITY_ATTRIBUTES sa; + memset(&sa, 0, sizeof(sa)); + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + conout1 = CreateFile(L"CONOUT$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &sa, + OPEN_EXISTING, + 0, NULL); + conout2 = CreateFile(L"CONOUT$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &sa, + OPEN_EXISTING, + 0, NULL); + conin = CreateFile(L"CONIN$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &sa, + OPEN_EXISTING, + 0, NULL); + Q_ASSERT(conin != NULL); + Q_ASSERT(conout1 != NULL); + Q_ASSERT(conout2 != NULL); + /* + BOOL success; + success = SetStdHandle(STD_OUTPUT_HANDLE, conout1); + Q_ASSERT(success); + success = SetStdHandle(STD_ERROR_HANDLE, conout2); + Q_ASSERT(success); + success = SetStdHandle(STD_INPUT_HANDLE, conin); + Q_ASSERT(success); + */ + } + + { + wchar_t program[80] = L"c:\\windows\\system32\\cmd.exe"; + wchar_t cmdline[80]; + wcscpy(cmdline, program); + STARTUPINFO sui; + memset(&sui, 0, sizeof(sui)); + sui.cb = sizeof(sui); + sui.dwFlags = STARTF_USESTDHANDLES; + sui.hStdInput = conin; + sui.hStdOutput = conout1; + sui.hStdError = conout2; + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(pi)); + BOOL success = CreateProcess( + program, + cmdline, + NULL, + NULL, + FALSE, + 0, + NULL, + NULL, + &sui, + &pi); + if (!success) { + qDebug("Could not start shell"); + } + } + + CloseHandle(conout1); + CloseHandle(conout2); + CloseHandle(conin); + + FreeConsole(); +} diff --git a/Console/AgentClient.h b/Shared/AgentClient.h similarity index 68% rename from Console/AgentClient.h rename to Shared/AgentClient.h index 2242095..584d300 100644 --- a/Console/AgentClient.h +++ b/Shared/AgentClient.h @@ -2,20 +2,23 @@ #define AGENTCLIENT_H #include -#include +//#include class QLocalServer; class QLocalSocket; typedef struct _PROCESS_INFORMATION PROCESS_INFORMATION; +typedef struct _INPUT_RECORD INPUT_RECORD; class AgentClient : public QObject { Q_OBJECT public: explicit AgentClient(QObject *parent = 0); - void sendKeyPress(QKeyEvent *event); - void sendKeyRelease(QKeyEvent *event); + //void sendKeyPress(QKeyEvent *event); + //void sendKeyRelease(QKeyEvent *event); int agentPid(); + void writeInputRecord(INPUT_RECORD *ir); + void startShell(); signals: diff --git a/ShowConsoleInput/ShowConsoleInput.pro b/ShowConsoleInput/ShowConsoleInput.pro new file mode 100644 index 0000000..7901961 --- /dev/null +++ b/ShowConsoleInput/ShowConsoleInput.pro @@ -0,0 +1,18 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2011-11-04T23:26:52 +# +#------------------------------------------------- + +QT += core + +QT -= gui + +TARGET = ShowConsoleInput +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + + +SOURCES += main.cc diff --git a/ShowConsoleInput/main.cc b/ShowConsoleInput/main.cc new file mode 100644 index 0000000..87dc0f7 --- /dev/null +++ b/ShowConsoleInput/main.cc @@ -0,0 +1,31 @@ +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); + while (true) { + DWORD count; + INPUT_RECORD ir; + if (!ReadConsoleInput(hStdin, &ir, 1, &count)) { + printf("ReadConsoleInput failed\n"); + return 1; + } + if (ir.EventType == KEY_EVENT) { + const KEY_EVENT_RECORD &ker = ir.Event.KeyEvent; + printf("%s", ker.bKeyDown ? "dn" : "up"); + printf(" ch="); + if (isprint(ker.uChar.AsciiChar)) + printf("'%c'", ker.uChar.AsciiChar); + printf("%d", ker.uChar.AsciiChar); + printf(" ctrl=%d", (int)ker.dwControlKeyState); + printf(" vk=%d", ker.wVirtualKeyCode); + printf(" scan=%d", ker.wVirtualScanCode); + printf(" repeat=%d", ker.wRepeatCount); + printf("\n"); + } + } +} diff --git a/TelnetServer/Server.cc b/TelnetServer/Server.cc new file mode 100644 index 0000000..965e011 --- /dev/null +++ b/TelnetServer/Server.cc @@ -0,0 +1,19 @@ +#include "Server.h" +#include "Session.h" +#include +#include + +Server::Server(QObject *parent) : + QObject(parent) +{ + m_tcpServer = new QTcpServer(this); + connect(m_tcpServer, SIGNAL(newConnection()), SLOT(newConnection())); + bool ret = m_tcpServer->listen(QHostAddress::Any, 23); + Q_ASSERT(ret); +} + +void Server::newConnection() +{ + QTcpSocket *socket = m_tcpServer->nextPendingConnection(); + new Session(socket, this); +} diff --git a/TelnetServer/Server.h b/TelnetServer/Server.h new file mode 100644 index 0000000..fe2cda2 --- /dev/null +++ b/TelnetServer/Server.h @@ -0,0 +1,25 @@ +#ifndef TELNETSERVER_H +#define TELNETSERVER_H + +#include + +class QTcpServer; + +class Server : public QObject +{ + Q_OBJECT +public: + explicit Server(QObject *parent = 0); + +signals: + +private slots: + void newConnection(); + +public slots: + +private: + QTcpServer *m_tcpServer; +}; + +#endif // TELNETSERVER_H diff --git a/TelnetServer/Session.cc b/TelnetServer/Session.cc new file mode 100644 index 0000000..78c29fd --- /dev/null +++ b/TelnetServer/Session.cc @@ -0,0 +1,40 @@ +#include "Session.h" +#include +#include +#include "../Shared/AgentClient.h" +#include "../Shared/DebugClient.h" +#include + +Session::Session(QTcpSocket *socket, QObject *parent) : + QObject(parent), m_socket(socket) +{ + m_agentClient = new AgentClient(this); + connect(m_socket, SIGNAL(readyRead()), SLOT(onSocketReadyRead())); + m_agentClient->startShell(); +} + +void Session::onSocketReadyRead() +{ + QByteArray data = m_socket->readAll(); + + Trace("session: read %d bytes", data.length()); + + for (int i = 0; i < data.size(); ++i) { + Trace("input: %02x", (unsigned char)data[i]); + + short vk = VkKeyScan((unsigned char)data[i]); + if (vk != -1) { + INPUT_RECORD ir; + memset(&ir, 0, sizeof(ir)); + ir.EventType = KEY_EVENT; + ir.Event.KeyEvent.bKeyDown = TRUE; + ir.Event.KeyEvent.wVirtualKeyCode = vk & 0xff; + ir.Event.KeyEvent.wVirtualScanCode = 0; + ir.Event.KeyEvent.uChar.AsciiChar = data[i]; + ir.Event.KeyEvent.wRepeatCount = 1; + m_agentClient->writeInputRecord(&ir); + } + } + + Trace("session: completed read", data.length()); +} diff --git a/TelnetServer/Session.h b/TelnetServer/Session.h new file mode 100644 index 0000000..2892568 --- /dev/null +++ b/TelnetServer/Session.h @@ -0,0 +1,27 @@ +#ifndef SESSION_H +#define SESSION_H + +#include + +class QTcpSocket; +class AgentClient; + +class Session : public QObject +{ + Q_OBJECT +public: + explicit Session(QTcpSocket *socket, QObject *parent = 0); + +signals: + +public slots: + +private slots: + void onSocketReadyRead(); + +private: + QTcpSocket *m_socket; + AgentClient *m_agentClient; +}; + +#endif // SESSION_H diff --git a/TelnetServer/TelnetServer.pro b/TelnetServer/TelnetServer.pro new file mode 100644 index 0000000..8427a4f --- /dev/null +++ b/TelnetServer/TelnetServer.pro @@ -0,0 +1,28 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2011-11-03T01:45:58 +# +#------------------------------------------------- + +QT += core +QT -= gui +QT += network + +TARGET = TelnetServer +CONFIG += console +CONFIG -= app_bundle + +TEMPLATE = app + + +SOURCES += main.cc \ + ../Shared/AgentClient.cc \ + ../Shared/DebugClient.cc \ + Session.cc \ + Server.cc + +HEADERS += \ + ../Shared/AgentClient.h \ + ../Shared/DebugClient.h \ + Session.h \ + Server.h diff --git a/TelnetServer/main.cc b/TelnetServer/main.cc new file mode 100644 index 0000000..79033f1 --- /dev/null +++ b/TelnetServer/main.cc @@ -0,0 +1,9 @@ +#include +#include "Server.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + Server server; + return a.exec(); +}