diff --git a/client/src/Havoc/Demon/CommandOutput.cc b/client/src/Havoc/Demon/CommandOutput.cc index 0ae99d4a..5053ca51 100644 --- a/client/src/Havoc/Demon/CommandOutput.cc +++ b/client/src/Havoc/Demon/CommandOutput.cc @@ -60,13 +60,14 @@ void DispatchOutput::MessageOutput( QString JsonString, const QString& Date = "" HavocX::Teamserver.TabSession->LootWidget->AddScreenshot( DemonCommandInstance->DemonID, Name, Date, DecodedData ); } - else if ( Type.compare( "download" ) == 0 ) + else if ( Type.compare( "downloadComplete" ) == 0 ) { + auto DecodedData = QByteArray::fromBase64( Data.toLocal8Bit() ); auto MiscDataInfo = JsonDocument[ "MiscData2" ].toString().split( ";" ); auto Name = QByteArray::fromBase64( MiscDataInfo[ 0 ].toLocal8Bit() ); auto Size = ( MiscDataInfo[ 1 ] ); - HavocX::Teamserver.TabSession->LootWidget->AddDownload( DemonCommandInstance->DemonID, Name, Size, Date, nullptr ); + HavocX::Teamserver.TabSession->LootWidget->AddDownload( DemonCommandInstance->DemonID, Name, Size, Date, DecodedData ); } else if ( Type.compare( "ProcessUI" ) == 0 ) { diff --git a/client/src/UserInterface/Widgets/LootWidget.cc b/client/src/UserInterface/Widgets/LootWidget.cc index 37bf5358..6e90e06c 100644 --- a/client/src/UserInterface/Widgets/LootWidget.cc +++ b/client/src/UserInterface/Widgets/LootWidget.cc @@ -12,6 +12,8 @@ #include #include #include +#include +#include // imagelabel.cpp ImageLabel::ImageLabel( QWidget* parent ) : QWidget( parent ) @@ -328,6 +330,28 @@ void LootWidget::onScreenshotTableClick( const QModelIndex &index ) void LootWidget::onDownloadTableClick( const QModelIndex &index ) { + auto DemonID = ComboAgentID->currentText(); + auto FileName = DownloadTable->item( index.row(), 0 )->text(); + + for ( auto& item : LootItems ) + { + if ( DemonID.compare( "[ All ]" ) == 0 || DemonID.compare( item.AgentID ) == 0 ) + { + if ( item.Type == LOOT_FILE ) + { + if ( item.Data.Name.compare( FileName ) == 0 ) + { + QFileInfo fi(FileName); + QString saveFileName = QFileDialog::getSaveFileName(this, tr("Save File"), + fi.fileName(), tr("All (*)")); + QSaveFile file(saveFileName); + file.open(QIODevice::WriteOnly); + file.write(item.Data.Data); + file.commit(); + } + } + } + } } diff --git a/teamserver/pkg/agent/demons.go b/teamserver/pkg/agent/demons.go index 607cdbad..23e0d6f0 100644 --- a/teamserver/pkg/agent/demons.go +++ b/teamserver/pkg/agent/demons.go @@ -3058,6 +3058,19 @@ func (a *Agent) TaskDispatch(RequestID uint32, CommandID uint32, Parser *parser. Output["Type"] = "Good" Output["Message"] = fmt.Sprintf("Finished download of file: %v", FileName) + var err error + var n int + var FileData = make([]byte, download.TotalSize) + n, err = download.File.ReadAt(FileData,0) + logger.Debug(fmt.Sprintf("downloadComplete, %v, %v", n, err)) + if err == nil { + Output["MiscType"] = "downloadComplete" + Output["MiscData"] = base64.StdEncoding.EncodeToString([]byte(FileData)) + Output["MiscData2"] = base64.StdEncoding.EncodeToString([]byte(download.FilePath)) + ";" + strconv.Itoa(int(download.TotalSize)) + } else { + logger.Error(fmt.Sprintf("Could not read file %v after download", download.FilePath)) + } + a.DownloadClose(FileID) } else if Reason == 0x1 { Output["Type"] = "Info"