Windows Defender detects Trojan:Script/Wacatac.B!ml in a zipped .NET 9 AOT binary
Posted by Dylan Beattie on 09 December 2024
•
permalink
Earlier today, somebody alerted me that Rockstar binary releases for Windows were being blocked by Windows Defender… and sure enough, since I switched the build system from .NET 8 to .NET 9, the Windows ZIP file releases on the releases page are being incorrectly identified as being infected with Trojan:Script/Wacatac.B!ml malware.
It’s not just Rockstar, though. It’s any .NET 9 binary compiled with AOT enabled and then compressed in a ZIP file. Try it. First, create a new .NET 9 console app:
dotnet new console -o HelloWorld
Then edit the .csproj file and add StripSymbols and PublishAot directives:
<ProjectSdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>Exe</OutputType><TargetFramework>net9.0</TargetFramework><ImplicitUsings>enable</ImplicitUsings><Nullable>enable</Nullable></PropertyGroup><!-- ADD THIS PropertyGroup to create native binary EXE builds --><PropertyGroupCondition="'$(Configuration)'=='Release'"><DebugSymbols>False</DebugSymbols><DebugType>None</DebugType><PublishAot>true</PublishAot><StripSymbols>true</StripSymbols></PropertyGroup></Project>
Now publish a binary release:
dotnet publish -c Release -o published
Look in /published and you’ll see a single binary HelloWorld.exe
Create a ZIP file containing that EXE - in Windows Explorer, right-click, Send to > Compressed (zipped) folder:
Right-click the ZIP file, Scan with Microsoft Defender…
For a second opinion, upload the ZIP file to VirusTotal.com, and you’ll probably see that Microsoft Defender thinks it’s infected with a trojan. I’ve had multiple hits reporting Trojan:Script/Wacatac.B!ml and one reporting Trojan:Win32/AgentTesla!ml
"Windows Defender detects Trojan:Script/Wacatac.B!ml in a zipped .NET 9 AOT binary" was posted by Dylan Beattie on 09 December 2024
•
permalink
Running Corel Linux on QEMU
Posted by Dylan Beattie on 27 May 2024
•
permalink
In my latest YouTube video, I talk about Corel Linux, which I think is one of the most interesting “what if?” scenarios in the history of mainstream computing, and show some clips of Corel Linux actually running. It’s not easy getting a 25-year-old Linux distro to boot on a modern PC - but here’s how I did it.
Install QEMU
VirtualBox, HyperV et al won’t work here - Corel Linux is just too old to support most of the virtual hardware they expose to their guest operating systems. Instead, we’re going to use QEMU.
Download it from https://www.qemu.org/, install it, get it running. Check it works by running qemu-system-i386 at a terminal window:
> qemu-system-i386 --version
QEMU emulator version 9.0.0 (v9.0.0-12054-g923cf646f4)
Copyright (c) 2003-2024 Fabrice Bellard and the QEMU Project developers
>
Create a virtual disk
This will create a 2Gb virtual disk file called corel_linux_hd.img:
Yeah. This is where it gets interesting: the Cirrus VGA driver provided by QEMU displays garbled text until we get into the OS and hack it, but we can’t do that until we’ve got it installed, so we’ll need to walk through the installation without being able to read anything.
You probably also don’t have any mouse support, so use Tab to move forwards, Ctrl-Tab to move backwards, and the Spacebar to click:
Don’t change anything here - “Install Standard Desktop” is already selected so just press Enter:
The next few screens, accept all the defaults - tab to Next> if it’s not already focused, press Enter:
and finally, Install:
If you get to here, you’re on the right track:
Once it’s installed, let it reboot, then at the loading screen select Linux - Text Mode
It’ll happily chunter away for a few screens worth of messages, and then you’ll get a login prompt.
Log in a root with a blank password. (Don’t ask. It was the early 2000s. Things were different then.)
Now we need to configure X11 so that it won’t try to use various accelerated hardware features that don’t work in QEMU.
Save the file, reboot (shutdown -r now), and select Corel Linux from the boot menu:
Networking support
Networking support in QEMU is powerful, flexible, and incredibly complicated.
Here’s how I made it work. Disclaimer: I don’t 100% understand exactly what all this does… I tried just about every combination I could think of until I found something that worked.
First, you’ll need to install a TAP network driver. This adds another network interface to Windows, which emulates a physical network card. Apparently.
Right-click your main network connection (ethernet, wifi - whatever connects your Windows machine to the internet)
Properties > Sharing > Allow other network users to connect…
Choose your TapWindows connection as the “Home networking connection”
You’ll get a popup about your LAN adapter. The wording here is misleading - it’s not your LAN adapter, it’s whichever adapter you selected as you” Home networking connection”:
If you remember using Internet Connection Sharing with a dial-up modem… this is the same tech, only we’re pretending that QEMU is our house network, TapWindows is the network card connecting our PC to the rest of the house, and “Ethernet” is the dial-up modem that connects to the internet.
Now, run QEMU using this command line:
I’m using Powershell so a backtick ` is a line continuation character.
That’s telling QEMU “create a network connection using TAP, call it mynet0, and connect it to the TapWindows interface on the host PC”, and then on the next line “then create a virtual device using the pcnet and connect it to the mynet0 network”.
For me, this worked 80% of the time. When it didn’t work, it’s because something meant the Linux guest couldn’t get an IP address from Internet Connection Sharing’s DHCP server. Manually setting the guest IP to 192.168.137.2, subnet 255.255.255.0, gateway 192.168.137.1 usually fixed this.
That got me to the point where I could boot Linux, open Netscape, point it at http://info.cern.ch/, and browse the world’s first website.
Stuff I Couldn’t Figure Out
I couldn’t get audio working. QEMU audio works fine - I created a Windows 2000 guest just to test this - and I tried both the ac97 and sb16 virtual audio devices in QEMU, but no luck yet.
I also couldn’t figure out how to change the CD-ROM. When you’re running QEMU, Ctrl-Alt-F2 drops you into an emulation console where you can use info block to see which devices/images are connected, and change ide1-cd0 <filename.iso> to change the virtual disk:
But… then I couldn’t work out how to get Corel Linux to mount the disk image, so to install WordPerfect, CorelDRAW!, etc. I had to shut down the VM and then boot it specifying the -cdrom command line switch:
"Running Corel Linux on QEMU" was posted by Dylan Beattie on 27 May 2024
•
permalink
Using the Contour ShuttleXpress with Camtasia
Posted by Dylan Beattie on 17 March 2024
•
permalink
The Contour ShuttleXpress is a controller designed for editing audio and video. I use it all the time in applications like Logic Pro X; the jog dial and shuttle wheel are brilliant for, well, jogging and shuttling around your project’s timeline.
Camtasia is a screen recording and video editing app from the folks at TechSmith, which I use for doing the screen recordings I use in my presentations and workshops.
Out of the box, the ShuttleXpress doesn’t support Camtasia, so I created an application profile for it.
Action
Keystroke
What it does
Jog Left
,
Step backwards in timeline
Jog Right
.
Step forwards in timeline
Shuttle left/right
,.
Move forwards backwards in timeline. Each position on the shuttle is independently programmable, so “shuttle in left 7” sends , as fast as possible, “shuttle in left 6” sends 60 strokes per second, and so on. It’s not a perfect timeline shuttle but it’s close enough.
Button 1
Ctrl + Home
Jump to beginning of timeline
Button 2
Ctrl+Alt+,
Move playhead to previous clip
Button 3
Shift+Ctrl+Alt+Left Arrow
Extend selection to previous clip
Button 4
Ctrl+Alt+.
Move playhead to next clip
Button 5
Shift+Ctrl+S
Split all tracks at playhead
The workflow here is:
Shuttle until you find the start of the mistake
Button 5 to split all tracks
Shuttle forward to the end of the mistake
Button 5 again to split all tracks
Button 3 to select the new region with the mistake in it
Delete to remove the region.
and if you switch on “magnet mode” for the track you’re editing, when you delete the mistake it’ll automatically snap the remaining pieces together so it doesn’t leave a gap.
and import it using Settings Management > Options > Import Settings in the Contour Shuttle Device Configuration app:
Happy shuttling :)
"Using the Contour ShuttleXpress with Camtasia" was posted by Dylan Beattie on 17 March 2024
•
permalink
Recording Meetups
Posted by Dylan Beattie on 20 February 2024
•
permalink
For the last few months, I’ve been recording the talks at the London .NET User Group on video so we can post them on YouTube after the event. The videos are online at https://www.youtube.com/@LondonDotNet, and I’ve had some questions about the setup I use to record them. Some from interested people looking to do something similar at their own events, some from people who show up early while I’m still setting up and go “wow, what’s with all the shiny things?” So here’s how it works.
For the long answer: the key here is minimal post-production. When it comes to editing two hours of video footage, “tomorrow” turns into “later” turns into “never” with astonishing regularity. Other than editing out any major technical problems, I want to leave the meetup with a video file that’s ready to upload to YouTube.
I also don’t want presenters to have to do any more than plug in HDMI, clip on a microphone, and go. I’ve done a few events where I’ve had to install drivers or sharing software for their “wireless smart display” system: I really don’t like doing that, and I’m not going to ask our presenters to do it either.
In terms of portability, I assume the venue will provide HDMI for the presenter’s slides, and there’s a power socket available to plug everything in. Everything else needs to fit in a backpack and set up in less than fifteen minutes.
Camera: Canon EOS M200 + Elgato Camlink
The camera I use is a Canon EOS M200. It’s a mirrorless SLR with clean HDMI out: what this means in practice is you can plug it into an Elgato Camlink, plug that into your laptop, and it shows up as a webcam - albeit a really, really good one. The camera runs off a USB power supply so I don’t have to worry about running out of battery halfway through a recording.
Bad news: Canon has apparently discontinued the M200, along with the rest of the M series, in favour of the Canon EOS R series. This makes me sad, because the M200 is a wonderful camera.
Good news: Elgato maintain a list of supported cameras, so any of the cameras on this list will do the trick:
If I can, I’ll bring a proper camera tripod along. If not, I’ll bring a SmallRig “magic arm” clamp and find a convenient chair, lamp, window frame or something to clamp it to.
Slides: Elgato Game Capture HD60S+
To capture the speaker’s laptop, I use an Elgato Game Capture HD60S+ (now superseded by the Game Capture HD60 X) This works like a Camlink - turns HDMI into a USB video signal - but it has an HDMI output that uses passthrough, so I can plug it in between the speaker’s laptop and the venue’s projector/screen and then tap a USB feed off the side into my laptop.
Audio: Ankerwork M650 Wireless Microphones
The first time I tried this, I used a RØDE shotgun microphone attached to the camera, but the audio quality wasn’t great, so I invested in a set of AnkerWork M650 wireless microphones. These are wonderful and amazing and excellent and I can’t say enough good things about them, but I’m a big fan of Anker gear, and folks I know who use the RØDE Wireless ME or the DJI MIC system say the same things about their setup.
Recording: Macbook Pro + OBS Studio
I run all these devices into an M1 Macbook Pro, and then record everything using OBS Studio.
Set OBS to record MKV format, and enable “automatically remux to MP4” in Settings > Advanced.
If you record direct to MP4, a system crash will leave you with an unusable video file, but MKV files aren’t as widely supported, so recording to MKV and then automatically remuxing to MP4 gives you the best of both worlds.
This is where the “minimal post-production” bit kicks in. I’ve got four scenes set up in OBS:
Camera Only:
Slides + Camera:
Camera + Slides:
Slides Only:
Plus, before the meetup I’ll make a title slide for each speaker and create a scene with that title slide plus the microphone, which means you can record audio over the title - great for introductions and preamble:
Note that “Slides + Camera” has the slides on the left, and “Camera + Slides” is the same thing, but with the slides on the right. Composition works better if the speaker is facing towards the middle of the frame, so which one of these gets used depends on where the camera is in relation to the speaker on the night.
OK, showtime. Plug everything in, get it working, probably reboot a couple of things because HDMI can be tricksy.
Mic up your presenter, and check the audio in every scene - nothing worse than recording the whole event and finding out later that one of your presents wasn’t recording any sound. Ask your speaker to stand where they’re going to stand, check the camera angle. I clip the other mic on to myself so I can introduce the speaker, repeat questions, etc. and have it come through on the recording.
Then bring up the title slide, hit Record, introduce the talk, and then switch scenes as you go, and all being well, you’ll end up with a MP4 file you can upload straight to YouTube when you get home.
5 metres seems to be the sweet spot for cable length. Too short, and you’re going to be in the way. Too long and you get weird signal problems, or no signal at all.
MicroHDMI > HDMI cable (camera HDMI OUT > Camlink HDMI)
Total investment if you’re starting from scratch will come to just over £1200.
How much?!
OK, you don’t need to spend that all in one go. Get a copy of Reincubate Camo and use your phone instead of buying an SLR camera + Camlink. For slides, you can pick up cheap HDMI splitter and an HDMI > USB capture gizmo on Amazon for about £20 each, and see how you go.
I wouldn’t skimp on microphones, though: as they say in Hollywood, “your ears never blink”, and you can probably get away with significantly worse video quality if the audio is up to scratch.
Here’s two clips I recorded using the old camera-mounted RØDE shotgun mic:
So, that’s your lot. Good luck with it, and let me know if you found this useful.
"Recording Meetups" was posted by Dylan Beattie on 20 February 2024
•
permalink
Custom Validation Attributes in ASP.NET Core 8
Posted by Dylan Beattie on 24 January 2024
•
permalink
ASP.NET Core 8 rocks. It’s fast, powerful, cross-platform… and, yes, includes jQuery.
Chill. jQuery’s fine. It’s solid, it’s proven, it works, and we’re not here to impress hipsters hiring frontend devs for their Web3 startup, we’re here to build stuff that works (and will probably still work next year.)
Out of the box, ASP.NET Core includes jQuery, jquery.validate and jquery.validation.unobtrusive, which together provide client-side validation that integrates really closely with the server-side validation provided by ASP.NET and System.ComponentModel.
Most of the stuff you’ll find online about how to extend ASP.NET Core validation still works, but there’s a few new things in .NET 8 which make it a little cleaner. Specifically, IDictionary<TKey,TValue> in .NET 8 includes a .TryAdd(key, value) method, which means the MergeAttributes helper method you’ll find in lots of examples of custom validation attributes isn’t required any more.
Here’s how to extend ASP.NET with a custom validation attribute that’ll make a checkbox a required field – the classic “You must accept the terms and conditions” scenario.
Don’t put this code inside the jQuery onload handler (the one that’s normally wrapped in $(function() { }) – it doesn’t rely on any DOM elements and the call to jquery.validator.unobtrusive.adapters.addBool() has to run before the validation code parses your form.
To use this attribute in your view model:
publicclassSignupPostData{[MustBeTrue(ErrorMessage="You must accept the terms and conditions")]publicboolAcceptTerms{get;set;}}
and then in your Razor view:
@model SignupPostData
<formmethod="post"><labelasp-for="@Model.AcceptTerms"><inputtype="checkbox"asp-for="@Model.AcceptTerms"/>
I accept the terms and conditions
</label><spanclass="form-text text-danger"asp-validation-for="@Model.AcceptTerms"></span></form>
@section Scripts {
@{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
"Custom Validation Attributes in ASP.NET Core 8" was posted by Dylan Beattie on 24 January 2024
•
permalink
Hi there. I'm Dylan.
I do interesting things with computers, code, comedy, music and video, then I travel all over the
world and tell people about it. I provide software training and consultancy through my company Ursatile. I'm a keynote speaker, I'm a Microsoft MVP,
I created Rockstar, an esoteric programming language that
started as a joke and ended up in Classic Rock magazine, and I
own the best web address in the
history of the internet.
Conferences & Events
Here's where I'm hoping to be over the next few months: