Skip to content

Commit

Permalink
SharpSword V2.0
Browse files Browse the repository at this point in the history
Complete redesign of SharpSword
Includes OPSEC safety checks
Utilizes MS Interop Word to support word docs ending with .doc*
Added ability to check if a document is password protected
Added ability to read password protected documents
  • Loading branch information
SadPanda committed Aug 22, 2023
1 parent 09c2e8e commit 07ac098
Show file tree
Hide file tree
Showing 20 changed files with 252 additions and 42 deletions.
Binary file not shown.
Empty file.
Binary file modified .vs/SharpSword/v16/.suo
Binary file not shown.
Binary file added .vs/SharpSword/v17/.suo
Binary file not shown.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# SharpSword
Read the contents of DOCX files using Cobalt Strike's Execute-Assembly

Help: execute-assembly SharpSword.exe
Developed By: @sadpanda_sec & @C0mmand3rOps3c
Description: Read Contents of Word Documents using MS Office Interop (Standalone or with CobaltStrike Execute Assembly)
Usage: SharpSword.exe C:\\Some\\Path\\To\\Document.(doc/docm/docx/etc...) [-checkPassword] -[password <password>]
Examples:
-SharpSword.exe test.docx : read the contents of a word doc
-SharpSword.exe test.docx -checkPassword : checks if the document is password protected
-SharpSword.exe test.docx -password <somepassword> : decrypts the password protected document and reads contents in memory
259 changes: 223 additions & 36 deletions SharpSword/Program.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
using System;
using System.IO.Compression;
using Microsoft.Office.Interop.Word;
using System;
using System.Diagnostics;
using System.IO;
using System.Xml;
using System.Runtime.InteropServices;

namespace SharpSword
{
class Program
{
static bool IsProcessRunning(string processName)
{

Process[] processes = Process.GetProcessesByName(processName.ToLower());

foreach (Process process in processes)
{
try
{
if (process.SessionId == Process.GetCurrentProcess().SessionId)
{
return true;
}
}
catch (Exception ex)
{
Console.WriteLine("Error : " + ex);
}
}

return false;


}


static void Main(string[] args)
{
if (args.Length == 0)
Expand All @@ -23,63 +50,223 @@ _____ _ _____ _
|_|
" +
"" +
"Developed By: @sadpanda_sec \n\n" +
"Description: Read Contents of Word Documents (Docx).\n\n" +
"Usage: SharpSword.exe C:\\Some\\Path\\To\\Document.docx");
"Developed By: @sadpanda_sec & @C0mmand3rOps3c \n\n" +
"Description: Read Contents of Word Documents using MS Office Interop.\n\n" +
"Usage: SharpSword.exe C:\\Some\\Path\\To\\Document.(doc/docm/docx/etc...) [-checkPassword] -[password <password>]\n" +
"Examples:\n" +
" -SharpSword.exe test.doc : read the contents of a word doc\n" +
" -SharpSword.exe test.doc -checkPassword : checks if the document is password protected\n" +
" -SharpSword.exe test.doc -password <somepassword> : decrypts the password protected document and reads contents");
System.Environment.Exit(0);

}
else if (args.Length == 1)

string docFullPath = Path.GetFullPath(args[0]);
string docName = Path.GetFileName(docFullPath);
bool checkPassword = false;
string documentPassword = null;

for (int i = 1; i < args.Length; i++)
{
if (File.Exists(args[0]) && Path.GetExtension(args[0]).ToLower() == ".docx")
if (args[i] == "-checkPassword")
{
var docPath = Path.GetFullPath(args[0]);
checkPassword = true;
}
else if (args[i] == "-password" && i + 1 < args.Length)
{
documentPassword = args[i + 1];
}
}


if (File.Exists(docFullPath) && Path.GetExtension(docFullPath).Contains("doc"))
{
bool isWordRunning = IsProcessRunning("winword");
Application wordApp = null;
Document doc = null;
bool isWordOpen = false;
bool isDocOpen = false;
bool isPWprotected = false;

using (var archive = ZipFile.OpenRead(docPath))
if (isWordRunning)
{
Console.WriteLine("OPSEC WARNING: Microsoft Word is currently running...Using existing Winword Application\n");
wordApp = (Application)Marshal.GetActiveObject("Word.Application");
wordApp.DisplayAlerts = WdAlertLevel.wdAlertsNone;
isWordOpen = true;
}
else
{
Console.WriteLine("Microsoft Word is not running...Using New COM Winword Application. \n");
wordApp = new Application();
wordApp.Visible = false;
wordApp.DisplayAlerts = WdAlertLevel.wdAlertsNone;
isWordOpen = false;
}


try
{

if (checkPassword)
{

var xmlFile = archive.GetEntry(@"word/document.xml");
if (xmlFile == null)
return;

using (var stream = xmlFile.Open())
if (isWordOpen)
{
using (var reader = new StreamReader(stream))
foreach (Document docs in wordApp.Documents)
{
if (string.Equals(docs.FullName, docFullPath, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"OPSEC WARNING: Document '{docName}' is already open by user...\n" +
$"By default, this check will always pass as document is unprotected.\n" +
$"Run this command again when the document is no longer opened by the user.");
isDocOpen = true;
doc = docs;
}
}

if (!isDocOpen)
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(stream);
XmlNodeList plaintext = xmldoc.GetElementsByTagName("w:t");
DateTime date = DateTime.Now;
Console.WriteLine("\n" + date + ": " + "Reading Document: " + docPath + "\n\n");
for (int i=0; i < plaintext.Count; i++)

try
{

doc = wordApp.Documents.Open(docFullPath, ReadOnly: true, PasswordDocument: " ", Visible: false);
Console.WriteLine("The document is NOT password protected.");
}
catch
{
Console.WriteLine(plaintext[i].InnerText);
Console.WriteLine("WARNING: The document is password protected.");
isPWprotected = true;
}
System.Environment.Exit(0);

}

}
else
{
try
{
doc = wordApp.Documents.Open(docFullPath, ReadOnly: true, PasswordDocument: " ", Visible: false);
Console.WriteLine("The document is NOT password protected.");
}
catch
{
Console.WriteLine("WARNING: The document is password protected.");
isPWprotected = true;
}

}

}
else
{
if (!string.IsNullOrEmpty(documentPassword))
{

foreach (Document docs in wordApp.Documents)
{
if (string.Equals(docs.FullName, docFullPath, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"Document '{docName}' is already open.");
isDocOpen = true;
doc = docs;
}
}
if (!isDocOpen)
{
doc = wordApp.Documents.Open(docFullPath, ReadOnly: true, PasswordDocument: documentPassword, Visible: false);

}

string content = doc.Content.Text;
DateTime date = DateTime.Now;
Console.WriteLine("\n" + date + ": " + "Reading Document: " + docName + "\n\n");
Console.WriteLine("File Content:");
Console.WriteLine(content);
}

}

if (!checkPassword && string.IsNullOrEmpty(documentPassword))
{
try
{

foreach (Document docs in wordApp.Documents)
{

if (string.Equals(docs.FullName, docFullPath, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"Document '{docName}' is already open.");
isDocOpen = true;
doc = docs;
}
}

if (!isDocOpen)
{
doc = wordApp.Documents.Open(docFullPath, ReadOnly: true, Visible: false);
}

string content = doc.Content.Text;
DateTime date = DateTime.Now;
Console.WriteLine("\n" + date + ": " + "Reading Document: " + docName + "\n\n");
Console.WriteLine("File Content:");
Console.WriteLine(content);


}
catch (COMException ex)
{
Console.WriteLine("Error: " + ex);
}


}
}
else
catch (Exception ex)
{
Console.WriteLine("Error: " + ex);
}
finally
{
Console.WriteLine("File Does Not Exist Or File Extention is Not DOCX");
System.Environment.Exit(0);

if (isDocOpen == false && isPWprotected == false)
{

doc.Close(false, null, null);

}

if (isWordOpen == false)
{
wordApp.Quit(false, null, null);
Marshal.ReleaseComObject(wordApp);
wordApp = null;


}
else
{
wordApp.Visible = true;

}
if (doc != null)
{
Marshal.ReleaseComObject(doc);
doc = null;
}


}
}
else
{
if (args.Length > 1)
{
Console.WriteLine("Error...Provided more than one command line argument\n\n" +
"Usage: SharpSword.exe C:\\Some\\Path\\To\\Document.docx");
System.Environment.Exit(0);
}
Console.WriteLine("File Does Not Exist Or File Extention is Not an MSWord Doc");

}
}

}

}


1 change: 0 additions & 1 deletion SharpSword/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// General Information about an assembly is controlled through the following
Expand Down
7 changes: 6 additions & 1 deletion SharpSword/SharpSword.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<OutputType>Exe</OutputType>
<RootNamespace>SharpSword</RootNamespace>
<AssemblyName>SharpSword</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
Expand Down Expand Up @@ -37,10 +37,15 @@
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Office.Interop.Word, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Office.Interop.Word.15.0.4797.1004\lib\net20\Microsoft.Office.Interop.Word.dll</HintPath>
<EmbedInteropTypes>True</EmbedInteropTypes>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
<Reference Include="System.Management" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
Expand Down
6 changes: 6 additions & 0 deletions SharpSword/SharpSword.csproj.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<StartArguments>test.doc -checkPassword</StartArguments>
</PropertyGroup>
</Project>
2 changes: 1 addition & 1 deletion SharpSword/app.config
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
Binary file modified SharpSword/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
Binary file not shown.
1 change: 1 addition & 0 deletions SharpSword/packages.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Office.Interop.Word" version="15.0.4797.1004" targetFramework="net48" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net45" />
</packages>
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 07ac098

Please sign in to comment.