Checkpoint Console work.
- Add a very incomplete "telnet" server. It doesn't recognize any telnet commands, so it's "telnet" only in the sense that I can connect to the server and type commands. The commands are fed to a Win32 Console, but I don't get to see the output over the network. - Move AgentClient to the Shared directory and move QtEvent-specific code out of it. - Move the startShell routine into the AgentClient so I can share it between the different console-consuming prototypes.
This commit is contained in:
parent
22b4de90b8
commit
6021840a1f
2
.gitignore
vendored
2
.gitignore
vendored
@ -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
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -1,13 +1,10 @@
|
||||
#include "ConsoleWindow.h"
|
||||
#include "ui_ConsoleWindow.h"
|
||||
#include "AgentClient.h"
|
||||
#include "../Shared/AgentClient.h"
|
||||
#include <QProcess>
|
||||
#include <QtDebug>
|
||||
#include <stdio.h>
|
||||
|
||||
#define WINVER 0x501
|
||||
#include <windows.h>
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -17,9 +17,6 @@ public:
|
||||
explicit ConsoleWindow(QWidget *parent = 0);
|
||||
~ConsoleWindow();
|
||||
|
||||
private:
|
||||
void startShell();
|
||||
|
||||
private:
|
||||
Ui::ConsoleWindow *ui;
|
||||
AgentClient *m_agentClient;
|
||||
|
@ -1,7 +1,8 @@
|
||||
#include "TextWidget.h"
|
||||
#include "AgentClient.h"
|
||||
#include "../Shared/AgentClient.h"
|
||||
#include <QKeyEvent>
|
||||
#include <QtDebug>
|
||||
#include <windows.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
#define WINVER 0x501
|
||||
#include "AgentClient.h"
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
@ -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();
|
||||
}
|
@ -2,20 +2,23 @@
|
||||
#define AGENTCLIENT_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QKeyEvent>
|
||||
//#include <QKeyEvent>
|
||||
|
||||
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:
|
||||
|
18
ShowConsoleInput/ShowConsoleInput.pro
Normal file
18
ShowConsoleInput/ShowConsoleInput.pro
Normal file
@ -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
|
31
ShowConsoleInput/main.cc
Normal file
31
ShowConsoleInput/main.cc
Normal file
@ -0,0 +1,31 @@
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
19
TelnetServer/Server.cc
Normal file
19
TelnetServer/Server.cc
Normal file
@ -0,0 +1,19 @@
|
||||
#include "Server.h"
|
||||
#include "Session.h"
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
|
||||
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);
|
||||
}
|
25
TelnetServer/Server.h
Normal file
25
TelnetServer/Server.h
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef TELNETSERVER_H
|
||||
#define TELNETSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
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
|
40
TelnetServer/Session.cc
Normal file
40
TelnetServer/Session.cc
Normal file
@ -0,0 +1,40 @@
|
||||
#include "Session.h"
|
||||
#include <QTcpSocket>
|
||||
#include <QtDebug>
|
||||
#include "../Shared/AgentClient.h"
|
||||
#include "../Shared/DebugClient.h"
|
||||
#include <windows.h>
|
||||
|
||||
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());
|
||||
}
|
27
TelnetServer/Session.h
Normal file
27
TelnetServer/Session.h
Normal file
@ -0,0 +1,27 @@
|
||||
#ifndef SESSION_H
|
||||
#define SESSION_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
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
|
28
TelnetServer/TelnetServer.pro
Normal file
28
TelnetServer/TelnetServer.pro
Normal file
@ -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
|
9
TelnetServer/main.cc
Normal file
9
TelnetServer/main.cc
Normal file
@ -0,0 +1,9 @@
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include "Server.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
Server server;
|
||||
return a.exec();
|
||||
}
|
Loading…
Reference in New Issue
Block a user