Skip to content

Commit 865304f

Browse files
authored
Merge pull request #32 from maxDcb/codex/migrate-c2client-to-pyqt6
feat: migrate C2Client to PyQt6
2 parents f1d6f43 + 8fde8ff commit 865304f

File tree

12 files changed

+73
-76
lines changed

12 files changed

+73
-76
lines changed

C2Client/C2Client/AssistantPanel.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@
66

77
from threading import Thread, Lock, Semaphore
88

9-
from PyQt5.QtCore import Qt, QEvent, QTimer, pyqtSignal
10-
from PyQt5.QtGui import QFont, QTextCursor, QStandardItem, QStandardItemModel
11-
from PyQt5.QtWidgets import (
9+
from PyQt6.QtCore import Qt, QEvent, QTimer, pyqtSignal
10+
from PyQt6.QtGui import QFont, QTextCursor, QStandardItem, QStandardItemModel, QShortcut
11+
from PyQt6.QtWidgets import (
1212
QCompleter,
1313
QLineEdit,
1414
QPlainTextEdit,
15-
QShortcut,
1615
QVBoxLayout,
1716
QWidget,
1817
)
@@ -113,7 +112,7 @@ def consoleAssistantMethod(self, action, beaconHash, listenerHash, context, cmd,
113112

114113

115114
def event(self, event):
116-
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
115+
if event.type() == QEvent.Type.KeyPress and event.key() == Qt.Key.Key_Tab:
117116
self.tabPressed.emit()
118117
return True
119118
return super().event(event)
@@ -389,7 +388,7 @@ def executeCmd(self, cmd, args):
389388
# setCursorEditorAtEnd
390389
def setCursorEditorAtEnd(self):
391390
cursor = self.editorOutput.textCursor()
392-
cursor.movePosition(QTextCursor.End,)
391+
cursor.movePosition(QTextCursor.MoveOperation.End)
393392
self.editorOutput.setTextCursor(cursor)
394393

395394

@@ -401,8 +400,8 @@ class CommandEditor(QLineEdit):
401400
def __init__(self, parent=None):
402401
super().__init__(parent)
403402

404-
QShortcut(Qt.Key_Up, self, self.historyUp)
405-
QShortcut(Qt.Key_Down, self, self.historyDown)
403+
QShortcut(Qt.Key.Key_Up, self, self.historyUp)
404+
QShortcut(Qt.Key.Key_Down, self, self.historyDown)
406405

407406
# self.codeCompleter = CodeCompleter(completerData, self)
408407
# # needed to clear the completer after activation
@@ -418,7 +417,7 @@ def nextCompletion(self):
418417
self.codeCompleter.setCurrentRow(0)
419418

420419
def event(self, event):
421-
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
420+
if event.type() == QEvent.Type.KeyPress and event.key() == Qt.Key.Key_Tab:
422421
self.tabPressed.emit()
423422
return True
424423
return super().event(event)
@@ -449,7 +448,7 @@ def onActivated(self):
449448

450449

451450
class CodeCompleter(QCompleter):
452-
ConcatenationRole = Qt.UserRole + 1
451+
ConcatenationRole = Qt.ItemDataRole.UserRole + 1
453452

454453
def __init__(self, data, parent=None):
455454
super().__init__(parent)

C2Client/C2Client/ConsolePanel.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,15 @@
55
from datetime import datetime
66
from threading import Thread, Lock
77

8-
from PyQt5.QtCore import QObject, Qt, QEvent, QThread, QTimer, pyqtSignal, pyqtSlot
9-
from PyQt5.QtGui import QFont, QStandardItem, QStandardItemModel, QTextCursor
10-
from PyQt5.QtWidgets import (
8+
from PyQt6.QtCore import QObject, Qt, QEvent, QThread, QTimer, pyqtSignal, pyqtSlot
9+
from PyQt6.QtGui import QFont, QStandardItem, QStandardItemModel, QTextCursor, QShortcut
10+
from PyQt6.QtWidgets import (
1111
QWidget,
1212
QTabWidget,
1313
QVBoxLayout,
1414
QHBoxLayout,
1515
QTextEdit,
1616
QLineEdit,
17-
QShortcut,
1817
QCompleter,
1918
QTableWidget,
2019
QTableWidgetItem,
@@ -535,7 +534,7 @@ def nextCompletion(self):
535534
self._compl.setCurrentRow(0)
536535

537536
def event(self, event):
538-
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
537+
if event.type() == QEvent.Type.KeyPress and event.key() == Qt.Key.Key_Tab:
539538
self.tabPressed.emit()
540539
return True
541540
return super().event(event)
@@ -626,7 +625,7 @@ def displayResponse(self):
626625

627626
def setCursorEditorAtEnd(self):
628627
cursor = self.editorOutput.textCursor()
629-
cursor.movePosition(QTextCursor.End,)
628+
cursor.movePosition(QTextCursor.MoveOperation.End)
630629
self.editorOutput.setTextCursor(cursor)
631630

632631

@@ -662,8 +661,8 @@ def __init__(self, parent: QWidget | None = None) -> None:
662661
self.cmdHistory = cmdHistoryFile.readlines()
663662
self.idx = len(self.cmdHistory) - 1
664663

665-
QShortcut(Qt.Key_Up, self, self.historyUp)
666-
QShortcut(Qt.Key_Down, self, self.historyDown)
664+
QShortcut(Qt.Key.Key_Up, self, self.historyUp)
665+
QShortcut(Qt.Key.Key_Down, self, self.historyDown)
667666

668667
self.codeCompleter = CodeCompleter(completerData, self)
669668
# needed to clear the completer after activation
@@ -679,7 +678,7 @@ def nextCompletion(self):
679678
self.codeCompleter.setCurrentRow(0)
680679

681680
def event(self, event):
682-
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
681+
if event.type() == QEvent.Type.KeyPress and event.key() == Qt.Key.Key_Tab:
683682
self.tabPressed.emit()
684683
return True
685684
return super().event(event)
@@ -709,7 +708,7 @@ def onActivated(self):
709708

710709

711710
class CodeCompleter(QCompleter):
712-
ConcatenationRole = Qt.UserRole + 1
711+
ConcatenationRole = Qt.ItemDataRole.UserRole + 1
713712

714713
def __init__(self, data, parent=None):
715714
super().__init__(parent)

C2Client/C2Client/GUI.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import sys
55
from typing import Optional
66

7-
from PyQt5.QtWidgets import (
7+
from PyQt6.QtWidgets import (
88
QApplication,
99
QGridLayout,
1010
QHBoxLayout,
@@ -139,10 +139,10 @@ def main() -> None:
139139
try:
140140
window = App(args.ip, args.port, args.dev)
141141
window.show()
142-
sys.exit(app.exec_())
142+
sys.exit(app.exec())
143143
except ValueError:
144144
sys.exit(1)
145-
sys.exit(app.exec_())
145+
sys.exit(app.exec())
146146

147147

148148
if __name__ == "__main__":

C2Client/C2Client/GraphPanel.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import time
44
from threading import Thread, Lock
55

6-
from PyQt5.QtCore import QObject, Qt, QThread, QLineF, pyqtSignal
7-
from PyQt5.QtGui import QColor, QFont, QPainter, QPen, QPixmap
8-
from PyQt5.QtWidgets import (
6+
from PyQt6.QtCore import QObject, Qt, QThread, QLineF, pyqtSignal
7+
from PyQt6.QtGui import QColor, QFont, QPainter, QPen, QPixmap
8+
from PyQt6.QtWidgets import (
99
QGraphicsLineItem,
1010
QGraphicsPixmapItem,
1111
QGraphicsScene,
@@ -89,7 +89,7 @@ def __init__(self, type, hash, os="", privilege="", hostname="", parent=None):
8989
else:
9090
pixmap = self.addImageNode(WindowsSessionImage, hostname)
9191
else:
92-
pixmap = QPixmap(LinuxSessionImage).scaled(64, 64, Qt.KeepAspectRatio, Qt.SmoothTransformation)
92+
pixmap = QPixmap(LinuxSessionImage).scaled(64, 64, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
9393
self.beaconHash=hash
9494
self.hostname = hostname
9595
self.connectedListenerHash = ""
@@ -112,21 +112,21 @@ def mouseMoveEvent(self, event):
112112

113113
def mousePressEvent(self, event):
114114
super().mousePressEvent(event)
115-
self.setCursor(Qt.ClosedHandCursor)
115+
self.setCursor(Qt.CursorShape.ClosedHandCursor)
116116

117117
def mouseReleaseEvent(self, event):
118118
super().mouseReleaseEvent(event)
119-
self.setCursor(Qt.ArrowCursor)
119+
self.setCursor(Qt.CursorShape.ArrowCursor)
120120

121-
def addImageNode(self, image_path, legend_text, font_size=9, padding=5, text_color=Qt.white):
121+
def addImageNode(self, image_path, legend_text, font_size=9, padding=5, text_color=Qt.GlobalColor.white):
122122
# Load and scale the image
123-
pixmap = QPixmap(image_path).scaled(64, 64, Qt.KeepAspectRatio, Qt.SmoothTransformation)
123+
pixmap = QPixmap(image_path).scaled(64, 64, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
124124

125125
# Create a new QPixmap larger than the original for the image and text
126126
legend_height = font_size + padding * 2
127127
legend_width = len(legend_text) * font_size + padding * 2
128128
combined_pixmap = QPixmap(max(legend_width, pixmap.width()), pixmap.height() + legend_height)
129-
combined_pixmap.fill(Qt.transparent) # Transparent background
129+
combined_pixmap.fill(Qt.GlobalColor.transparent) # Transparent background
130130

131131
# Paint the image and the legend onto the combined pixmap
132132
painter = QPainter(combined_pixmap)
@@ -143,9 +143,9 @@ def addImageNode(self, image_path, legend_text, font_size=9, padding=5, text_col
143143

144144
# Draw the legend text centered below the image
145145
text_rect = painter.boundingRect(
146-
0, pixmap.height(), combined_pixmap.width(), legend_height, Qt.AlignCenter, legend_text
146+
0, pixmap.height(), combined_pixmap.width(), legend_height, Qt.AlignmentFlag.AlignCenter, legend_text
147147
)
148-
painter.drawText(text_rect, Qt.AlignCenter, legend_text)
148+
painter.drawText(text_rect, Qt.AlignmentFlag.AlignCenter, legend_text)
149149

150150
painter.end()
151151
return combined_pixmap
@@ -189,7 +189,7 @@ def __init__(self, parent, grpcClient):
189189
self.scene = QGraphicsScene()
190190

191191
self.view = QGraphicsView(self.scene)
192-
self.view.setRenderHint(QPainter.Antialiasing)
192+
self.view.setRenderHint(QPainter.RenderHint.Antialiasing)
193193

194194
self.vbox = QVBoxLayout()
195195
self.vbox.setContentsMargins(0, 0, 0, 0)
@@ -336,8 +336,8 @@ def updateGraph(self):
336336
print("[+] add connector listener:", listenerHash, "beacon", beaconHash)
337337

338338
for item in self.listNodeItem:
339-
item.setFlag(QGraphicsItem.ItemIsMovable)
340-
item.setFlag(QGraphicsItem.ItemIsSelectable)
339+
item.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable)
340+
item.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable)
341341

342342

343343
class GetGraphInfoWorker(QObject):

C2Client/C2Client/ListenerPanel.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import time
22
import logging
33

4-
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QObject
5-
from PyQt5.QtWidgets import (
4+
from PyQt6.QtCore import Qt, QThread, pyqtSignal, QObject
5+
from PyQt6.QtWidgets import (
66
QComboBox,
77
QFormLayout,
88
QGridLayout,
@@ -15,6 +15,7 @@
1515
QTableWidgetItem,
1616
QWidget,
1717
QHeaderView,
18+
QAbstractItemView,
1819
)
1920

2021
from .grpcClient import TeamServerApi_pb2
@@ -79,19 +80,19 @@ def __init__(self, parent, grpcClient):
7980
# List of sessions
8081
self.listListener = QTableWidget()
8182
self.listListener.setShowGrid(False)
82-
self.listListener.setSelectionBehavior(QTableView.SelectRows)
83+
self.listListener.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
8384

8485
self.listListener.setRowCount(0)
8586
self.listListener.setColumnCount(4)
8687

8788
# self.listListener.cellPressed.connect(self.listListenerClicked)
88-
self.listListener.setContextMenuPolicy(Qt.CustomContextMenu)
89+
self.listListener.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
8990
self.listListener.customContextMenuRequested.connect(self.showContextMenu)
9091

9192
self.listListener.verticalHeader().setVisible(False)
9293
header = self.listListener.horizontalHeader()
9394
for i in range(header.count()):
94-
header.setSectionResizeMode(i, QHeaderView.Stretch)
95+
header.setSectionResizeMode(i, QHeaderView.ResizeMode.Stretch)
9596
self.layout.addWidget(self.listListener)
9697

9798
# Thread to get listeners every second
@@ -118,15 +119,15 @@ def showContextMenu(self, position):
118119
menu = QMenu()
119120
menu.addAction('Add')
120121
menu.triggered.connect(self.actionClicked)
121-
menu.exec_(self.listListener.viewport().mapToGlobal(position))
122+
menu.exec(self.listListener.viewport().mapToGlobal(position))
122123
else:
123124
row = index.row()
124125
self.item = str(self.listListener.item(row, 0).data(0))
125126

126127
menu = QMenu()
127128
menu.addAction('Stop')
128129
menu.triggered.connect(self.actionClicked)
129-
menu.exec_(self.listListener.viewport().mapToGlobal(position))
130+
menu.exec(self.listListener.viewport().mapToGlobal(position))
130131

131132

132133
# catch stopListener menu click

C2Client/C2Client/ScriptPanel.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77

88
from threading import Thread, Lock, Semaphore
99

10-
from PyQt5.QtCore import Qt, QEvent, QTimer, pyqtSignal
11-
from PyQt5.QtGui import QFont, QTextCursor, QStandardItem, QStandardItemModel
12-
from PyQt5.QtWidgets import (
10+
from PyQt6.QtCore import Qt, QEvent, QTimer, pyqtSignal
11+
from PyQt6.QtGui import QFont, QTextCursor, QStandardItem, QStandardItemModel, QShortcut
12+
from PyQt6.QtWidgets import (
1313
QCompleter,
1414
QLineEdit,
1515
QPlainTextEdit,
16-
QShortcut,
1716
QVBoxLayout,
1817
QWidget,
1918
)
@@ -177,7 +176,7 @@ def mainScriptMethod(self, action, str2, str3, str4):
177176

178177

179178
def event(self, event):
180-
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
179+
if event.type() == QEvent.Type.KeyPress and event.key() == Qt.Key.Key_Tab:
181180
self.tabPressed.emit()
182181
return True
183182
return super().event(event)
@@ -215,7 +214,7 @@ def runCommand(self):
215214
# setCursorEditorAtEnd
216215
def setCursorEditorAtEnd(self):
217216
cursor = self.editorOutput.textCursor()
218-
cursor.movePosition(QTextCursor.End,)
217+
cursor.movePosition(QTextCursor.MoveOperation.End)
219218
self.editorOutput.setTextCursor(cursor)
220219

221220

@@ -227,8 +226,8 @@ class CommandEditor(QLineEdit):
227226
def __init__(self, parent=None):
228227
super().__init__(parent)
229228

230-
QShortcut(Qt.Key_Up, self, self.historyUp)
231-
QShortcut(Qt.Key_Down, self, self.historyDown)
229+
QShortcut(Qt.Key.Key_Up, self, self.historyUp)
230+
QShortcut(Qt.Key.Key_Down, self, self.historyDown)
232231

233232
# self.codeCompleter = CodeCompleter(completerData, self)
234233
# # needed to clear the completer after activation
@@ -244,7 +243,7 @@ def nextCompletion(self):
244243
self.codeCompleter.setCurrentRow(0)
245244

246245
def event(self, event):
247-
if event.type() == QEvent.KeyPress and event.key() == Qt.Key_Tab:
246+
if event.type() == QEvent.Type.KeyPress and event.key() == Qt.Key.Key_Tab:
248247
self.tabPressed.emit()
249248
return True
250249
return super().event(event)
@@ -275,7 +274,7 @@ def onActivated(self):
275274

276275

277276
class CodeCompleter(QCompleter):
278-
ConcatenationRole = Qt.UserRole + 1
277+
ConcatenationRole = Qt.ItemDataRole.UserRole + 1
279278

280279
def __init__(self, data, parent=None):
281280
super().__init__(parent)

0 commit comments

Comments
 (0)