Skip to main content

Notes From Addressing Penetration Test Findings

· 3 min read
Mark Burton
Software Engineer & Technical Writer

In the Pentest reports I have read it has been common for the first section to be about identifying the technology the application is written in, this is used to make some initial suggestions on shortcomings in the application. For me, as a .NET developer writing WPF applications, it was surprising to see it be reported repeatedly that our application was discovered to be written in Microsoft Visual C++ 8 and that we failed to implement protection like SafeSEH and ControlFlowGuard. As much as I wanted to say wanted to say we don't write our software in C++ so these findings were not valid I dug deeper into the reports to understand why multiple pentests by multiple suppliers returned the same result.

Binary Identification

I have seen a few methods of identifying the language used to develop an application, first of which is CFF Explorer.

CFF Explorer

This has been used each time the binary has been misidentified as C++ when it was actually written in csharp, however it is not a fault with CFF Explorer, it is simply that the wrong executable had been analysed. Select file File Details Select file File Details ### Grep on WSL While I am working Windows to build a WPF application I can still use useful Linux commands like file and grep through WSL to find out more about a file.

mburton@zitherldwx01:mntc/UsersanonAppDataLocalWpfSampleAppFullFramework$ ls
Update.exe WpfApp2FullFramework.exe app-1.0.0 packages mburton@zitherldwx01:mntc/UsersanonAppDataLocalWpfSampleAppFullFramework$ file WpfApp2FullFramework.exe
WpfApp2FullFramework.exe: PE32 executable (GUI) Intel 80386, for MS Windows mburton@zitherldwx01:mntc/UsersanonAppDataLocalWpfSampleAppFullFramework$ cd app-1.0.0/ mburton@zitherldwx01:mntc/UsersanonAppDataLocalWpfSampleAppFullFrameworkapp-1.0.0$ file WpfApp2FullFramework.exe
WpfApp2FullFramework.exe: PE32 executable (GUI) Intel 80386 Mono.Net assembly, for MS Windows mburton@zitherldwx01:mntc/UsersanonAppDataLocalWpfSampleAppFullFrameworkapp-1.0.0$ file *.dll | grep "Mono.Net" | wc -l
10 mburton@zitherldwx01:mntc/UsersanonAppDataLocalWpfSampleAppFullFrameworkapp-1.0.0$ ls *.dll
DeltaCompressionDotNet.MsDelta.dll Mono.Cecil.Mdb.dll Mono.Cecil.dll Squirrel.dll
DeltaCompressionDotNet.PatchApi.dll Mono.Cecil.Pdb.dll NuGet.Squirrel.dll
DeltaCompressionDotNet.dll Mono.Cecil.Rocks.dll SharpCompress.dll mburton@zitherldwx01:mntc/UsersanonAppDataLocalWpfSampleAppFullFrameworkapp-1.0.0$ file *.dll | grep "Mono.Net" | wc -l
10

Binary Security

Having identified the binary the reports then flag security options which have not been used. This can be done using a PowerShell Module PESecurity

warning

WARNING!!! Use PESecurity at your own risk, read the code yourself before you use it!

PS C:\Source\GitRepos\PESecurity> Get-PESecurity -file $env:LOCALAPPDATA\WpfSampleAppFullFramework\app-1.0.0\WpfApp2FullFramework.exe  FileName  : $env:LOCALAPPDATA\WpfSampleAppFullFramework\app-1.0.0\WpfApp2FullFramework.exe
ARCH : I386
DotNET : True
ASLR : True
DEP : True
Authenticode : False
StrongNaming : False
SafeSEH : NA
ControlFlowGuard : NA
HighentropyVA : NA
PS C:\Source\GitRepos\PESecurity> Get-PESecurity -file $env:LOCALAPPDATA\WpfSampleAppFullFramework\WpfApp2FullFramework.exe  FileName  : $env:LOCALAPPDATA\WpfSampleAppFullFramework\WpfApp2FullFramework.exe
ARCH : I386
DotNET : False
ASLR : True
DEP : True
Authenticode : False
StrongNaming : NA
SafeSEH : True
ControlFlowGuard : False
HighentropyVA : NA

The Cause of the misidentification

The application installer is built using Squirrel, the file being opened in CFF Explorer is part of the Squirrel installer as described in the Installing Documentation. The actual application executable is in the application version subdirectory app-n.n.n. ## How to fix it? I had a very constructive discussion with caesay who is one of the maintainers of Clowd.Squirrel, a fork of Squirrel.Windows moments after our discussion this commit Enable ControlFlowGuard for Setup.exe was made.

How To Create a Custom UserStore in ASP.NET Core 6

· One min read
Mark Burton
Software Engineer & Technical Writer
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));

builder.Services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

builder.Services.AddTransient<IUserStore<ApplicationUser>, DirectUserStore<ApplicationUser>>();

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/identity-custom-storage-providers?view=aspnetcore-6.0

https://github.com/dotnet/AspNetCore.Docs/tree/main/aspnetcore/security/authentication/identity-custom-storage-providers/sample/CustomIdentityProviderSample

Making pizza in my Ooni Koda 12

· 2 min read
Mark Burton
Software Engineer & Technical Writer

I love pizza but nothing you can buy from the shop comes close to freshly made pizza and delivery is usually getting cold by the time it arrives. Luckily for Christmas I received an Ooni Koda 12 (Thanks Caitriona), just connect the bottle of gas turn it on and after 15 minutes you have a 400°C oven ready to cook a pizza in only 90 seconds. Ooni have great recipes on their website for Classic Pizza Dough and Classic Pizza Sauce but the dough recipe doesn't seem to be quite right for the Ooni Koda 12, the bases just seem too big for the peels, but this could be my lack of knowledge with making bases, but I find a little less is better and I only usually want 2 pizzas each time I use the oven. ## My Tweaked Recipe The proportions remain the same, but the accuracy of the proportions are all important. :::primary 242g “00” flour 2.8g instant dried yeast (3.7g active dried yeast, 8g fresh yeast) 48.5ml boiled water 97ml cold water 7.2g salt ::: For everything else follow the Classic Pizza Dough instructions for 2 perfectly sized pizzas for your Ooni Koda 12.

Centralizing VSTO add in exception management with postsharp 6

· 3 min read
Mark Burton
Software Engineer & Technical Writer

After much reading around trying to find the best way to implement a global exception handler for a VSTO add-in on social msdn, stackoverflow and the Add-in Express forum I came across this solution using postsharp, this was the best solution I found but was 11 years old and relevant to postsharp 2, the library has changed a lot since then and the PostSharp.Laos namespace no longer exists as explained the postsharp support forum. ## The Solution in PostSharp 6 Happily this is still possible with PostSharp Community and is well documented in the postsharp handling exceptions documentation. First create a class which inherits from OnExceptionAspect for example VstoUnhandledExceptionAttribute. csharp using Microsoft.Extensions.Logging; using PostSharp.Aspects; using PostSharp.Serialization; namespace MarkZither.KimaiDotNet.ExcelAddin \\\{ [PSerializable] public class VstoUnhandledExceptionAttribute : OnExceptionAspect \{ public override void OnException(MethodExecutionArgs args) { ExcelAddin.Globals.ThisAddIn.Logger.LogCritical(args.Exception, "Handled by postsharp OnExceptionAspect"); args.FlowBehavior = FlowBehavior.Return; \\} } } This step will vary depending on how you are doing logging in your VSTO Add-In, I chose to use Microsoft.Extensions.Logging, while it arrived with .NET Core it is a .NETStandard 2.0 library and compatible all the way back to .NETFramework 4.6.1. csharp private void ThisAddIn_Startup(object sender, System.EventArgs e) \\{ instantiate and configure logging. Using serilog here, to log to console and a text-file. var loggerFactory = new Microsoft.Extensions.Logging.LoggerFactory(); var loggerConfig = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.File("c:\\temp\\logs\\myapp.txt", rollingInterval: RollingInterval.Day) .CreateLogger(); loggerFactory.AddSerilog(loggerConfig); // create logger and put it to work. var logProvider = loggerFactory.CreateLogger<ThisAddIn />(); logProvider.LogDebug("debiggung"); Logger = logProvider; Configure PostSharp Logging to use Serilog LoggingServices.DefaultBackend = new MicrosoftLoggingBackend(loggerFactory); Globals.ThisAddIn.ApiUrl = Settings.Default?.ApiUrl; Globals.ThisAddIn.ApiUsername = Settings.Default?.ApiUsername; this.Application.WorkbookActivate += Application_WorkbookActivate; this.Application.WorkbookOpen += Application_WorkbookOpen; \} There is one important line in the logging setup which differs to the PostSharp Logging documentation at the time of writing, LoggingServices.DefaultBackend = new MicrosoftLoggingBackend(loggerFactory); which needs using PostSharp.Patterns.Diagnostics.Backends.Microsoft;. This is also useful for trace logging which I will explain further in the next section. Now decorate methods or entire classes with the [VstoUnhandledException] attribute and every exception will be handled by the OnException method. ## Bonus functionality in PostSharp community As I had logging working I also made use of the features of PostSharp Logging

First add a postsharp.config file, to comply with the license it is required to set the LoggingDeveloperMode to true. Be sure it has the Build Action set to Content so that it is copied to the output directory.

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.postsharp.org/1.0/configuration">
<Property Name="LoggingDeveloperMode" Value="True" />
</Project>

This still gives you 24 hours of trace logging after every publish of your VSTO Add-In and full tracing while debugging.

To control what is logged create a class called GlobalAspects, this is explained in the Adding logging to your projects section.

using PostSharp.Patterns.Diagnostics;
using PostSharp.Extensibility; [assembly: Log(AttributePriority = 1, AttributeTargetMemberAttributes = MulticastAttributes.Protected | MulticastAttributes.Internal | MulticastAttributes.Public)]
[assembly: Log(AttributePriority = 2, AttributeExclude = true, AttributeTargetMembers = "get_*")]
``` Now the logging will contain all the entry and exits from methods along with the parameters which were passed, providing valuable debug information for free for a whole day after pushing out and update to the Add-In.

My First Skydive @ LuxFly

· 3 min read
Mark Burton
Software Engineer & Technical Writer

For a birthday present I received a voucher to do an indoor skydive at LuxFly at the Luxembourg and Belgium border. Thanks to Covid 19 lockdowns I had another birthday before I could actually make use of the Falcon9 experience. ## Arrival As Covid restrictions were still in place there were not many people there when I arrived, but the staff were very welcoming and efficient finding my booking, checking me in and explaining how things would work. I was early so had time to watch some experienced people flying around, hovering in a seated position, doing headstands and slow motion backflips, sometimes it reminded me of wire work in a Wuxia movie. I remember it something like this...

or more far fetched a bit of Money Magic

## The group I was surprised when I noticed that an RTL camera crew had turned up for my skydive. Unfortunately, despite the fact that there only being 2 of us in the group at that point, the camera was for the other person, who, based on the car outside was there for "de Journal". ## The Briefing After being greeted by our instructor, Lane, we were shown a short video explaining the basics of the skydive, the "simple instructions" were: * relax, Lane will help guide you into the correct position.

  • 2 straight fingers means straighten your legs
  • bent fingers means bend your legs
  • finger pointing up means look upwards That's it! Simple, right? ## The Reality I was assured I was good for a first timer, after 3 flights of 1 minute 20 seconds each I was able to hover without assistance, spin left and right by moving my hands a little, move forward and back by straightening and bending my legs and control myself up and down to some extent by pushing my hips through or straightening my body. In truth that also included belly flopping into the floor and crashing into the window and crumpling a little which caused me to drop quickly and get caught by Lane before I hit the floor again, not to mention the far from elegant wrestling to get me to the door at the end of my first go. Somehow when you are in free fall those simple instructions I mentioned earlier become much more difficult, my eyes saw 2 straight fingers, but it took an age to convince my legs to move. ## The Grand Finale The HighFly, this was truly a heart in mouth stomach turning experience which I can't wait to do again.

https://www.tvlux.be/video/info/arlon-le-luxfly-skydive-a-ouvert-ses-portes_34978.html

KimaiDotNet based Office Add-ins

· 2 min read
Mark Burton
Software Engineer & Technical Writer

As of v1.0.0.0 released on 09032023 the VSTO is signed with an open source code signing cert from Certum this should mean the installation is automatically trusted. If you installed a version before v1.0.0.0 you must uninstall it before installing v1.0.0.0 as the change in signing cert will prevent the upgrade working. Until I get a real certificate you will need to install this self-signed certificate as a trusted root certification authority to be able to install the add-in. Download Excel Add-in ## Create an API password in Kimai

warning

WARNING!!! If you try and login with your normal password it will fail!

Create an API Password in Kimai ## Set the API credentials in the Excel Add-in Set the API credentials in the Excel Add-in ## Save the API credentials to activate the sync Set the API credentials in the Excel Add-in ## Usage of the Add-in For now the Add-in only supports reading existing timesheets and adding new ones, and editing of timesheets will need to be done in Kimai. ## Questions and suggestions The GitHub repo can be found at the KimaiDotNet on GitHub. ### Milestones Follow the Milestones. ### Issues Create any bugs or suggestions on GitHub Issues. ### Discussions Start a discussion on the GitHub Discussions.

Reset Forgotten Domain Admin Password

· 3 min read
Mark Burton
Software Engineer & Technical Writer

Following a series of errors I found myself in a very similar situation to that described by Rob Beekmans, just without the excuse of a bout of flu. But it was just a lab environment so The basic mistakes I made were: * Only having a single domain admin in the domain.

  • Setting up a DSRM password but not testing it
  • Creating a single snapshot of the VM over 2 years ago
  • Allowing Windows update to reboot the machine with the new password unsaved in the vault.
  • Using Hyper-V with an external Virtual Switch, but that is a that is for a different post
  • Using a keyboards with different layouts to type passwords So there was no reason to find myself in this position really, but having ended up there and having found Robs post it looked like the solution was still quite easy, however I am running Windows Server 2019 Core, so there is not GUI and therefore no UTILMAN.exe. ## The Recovery Boot using the installation media, choose Repair your computer, Troubleshoot and Command Prompt. You will now be in the command prompt at X:\Sources. To find your Windows install change directory cd /d c:\Windows\System32 Where Rob suggests to overwrite UTILMAN.exe with cmd.exe that is not possible in Windows Server Core, instead we can replace LogonUI.exe ``` copy LogonUI.exe LogonUI.exe.BAK copy CMD.EXE LogonUI.exe
Answer yes when asked if you want to overwrite LogonUI.exe and then reboot normally.  ```
shutdown /r /t 1
``` When it reboots you will be taken straight to `cmd.exe`, you can now set the Administrator password with the command ```
net user Administrator "new password"
``` Boot again using the installation media to change the file names back ```
copy LogonUI.exe.BAK LogonUI.exe
del LogonUI.exe.BAK
``` Reboot a final time and login with your new Administrator password ## Other options
Various blogs suggest it is possible to get to safe mode using F8 or Ctrl+Shift+Alt+F8 from a cold boot.
https:/www.surfacetablethelp.com201801how-to-use-f8-key-to-boot-hyper-v-vm-into-safe-mode-on-windows-10.html I was not able to make that work reliably, in fact it worked once and caused much frustration trying to make it happen again. I found 2 more reliable ways to get to the safe boot menu:
boot from the installation media to access to troubleshoot menu and boot to a command prompt. At the command prompt type the following command to enable to boot menu. ```
bcdedit /set displaybootmenu yes
``` The next command sets the timeout after which the boot will continue to the OS, 5 second should be plenty to press F8 without adding excessive time to the boot. ```
bcdedit /set timeout 5
``` It is then possible to login with the Test it, shut it down, cold boot it, test it again
https:/docs.microsoft.comen-ustroubleshootwindows-serveridentityreset-directory-services-restore-mode-admin-pwd https:/docs.microsoft.comen-ustroubleshootazurevirtual-machinescannot-connect-rdp-azure-vm#:~:text=The%20remote%20computer%20that%20you,the%20System%20Properties%20dialog%20box.