Search This Blog

Wednesday, January 29, 2025

AI: Prompt Engineering

The other day I got an advertising on social media about a free certificate in responsible AI use and Prompt Engineering. The course was a collaboration between Microsoft and Founderz who hosted AI Skills 4 All which was educational and interesting.

As a regular user of both Copilot and Edge I decided to give it a go, it was free and took less than 8 hours, so I thought why not?

Basically they brought up the basics of how generative AI work, how to write good prompts and how they leverage the Edge browser. 

The way we should see Copilot is not as the primary agent of choice, but rather our second pilot, that can offload us from certain tasks. We are still responsible for what we do with the tool in that sense. At this stage these generative AI:s, especially Copilot, is better at texts and images than math.

Its strengths are brainstorming, handling large amount of information and creating general ideas for the low risk scenarios. The general downsides of Copilot is that it does not think or feel, it is not always accurate and you can't rely on it as a friend. It also comes with biases of its own.

Improve your prompts

Writing good prompts for AI consists of four main parts.

1. A goal, such as creating a bunch of bullet points detailing the last quarter

2. Context, such as defining a setting where the material will be used, for example a breakfast presentation. You could also specify what type of people that will attend. For example whether it is marketers, competitors or managers.

3. Source of the information, make sure to ask Copilot where to get the data from. This is important because not only is it your job to ensure the quality of the result, but you might know that some sources are better in certain fields. You will notice that the sources are linked in the result as well, if you want to continue your research.

4. Expectations, define what you want out of the material, what sort of result should it create?

Customizing your prompts further

There are additional things that you need to think about in order to create better prompts, such as being rich with details. Remember to add the most important things first, it is valued higher, this is especially true when creating images.

Here is an example of the prompt "Create an image of the planet Mars"


This is the result of the prompt "Now create an image of the planet Mars, from the surface of the planet, where you can an early human settlement, do not include any people. The sky should be daytime."



You can also ask the AI to ask you controlling questions back to you before presenting the result. This increased content quality. You could ask Copilot to return five questions about the material as an example.

To shape the content further, ask the chatbot to take on certain personas. You could for instance ask it to act as an PR-expert to create a certain effect with the text.

Keep in mind that if you are logged in, you can save a history of previous chats. You can also attempt to regenerate the reply, by simply asking it to do so, you might then get a variation of the reply.

What to avoid

There are a few things to avoid when you work with the Copilot, these pointers will also help you make better decisions when taking the help from AI. 

1. Avoid math that you cannot check yourself afterwards, this is due to the probabilistic nature of the generative AI. It uses mathematical models to predict what the next "token" in a sentence is, such as a word or another small piece of data. You can in worst case get different results from the same question. Instead try to focus on outputting text and code for example.

2. Don't be too sparse with the details, it will negatively impact your results.

3. Don't upload information, data, images and so on that might be sensitive or personal.

Troubleshooting the output

If an error occurs you can try to figure out what could have been causing the mishap.

For this it is also important to know how Copilot works. First it searches, then a Large Language Model is used to summarize the content and then it is filtered and presented. 

You can ask yourself these questions when troubleshooting the result:

  • Is there an issue with how the question was asked?
  • Are there problems with the sources used? Can other sources be used instead?
  • Was there something wrong at the search stage?
  • Was there an issue with the summarizing stage?
  • Did something happen when it was presented?

Different ways to use Copilot

One thing that I myself learned from the course was an efficient way to use Copilot in the sidebar together with Microsoft Office in the browser. This is handy as Copilot is not necessarily integrated into the Office programs that you install on your PC, at the time of this blogpost.

Use the sidebar AI in Microsoft Edge to analyse, summarize, correct or improve Word documents that you have open in the browser, when you are working in Office online. You can of course use it on other sites too and let it assist you in evaluating and working with different content. Another hack I like to use is to take a snippet and upload it, and ask questions about the content.

There is also a speech function and if you use it, you will notice that it speaks back to you.

For mobile they have a dedicated app for Copilot as well, it pretty much fills the same role there, a plus for using the app is that you can use the camera to identify objects for example or transcribe text that you take a photo of.

Summary

Let's wrap this post up by saying that Copilot has helped me a lot, both professionally and in private. Personally I use it as an advanced search engine sometimes, with whom I can discuss the results and ask clarifying questions. I also use it to generate PowerShell code these days, but I try to understand the concept before I ask it to produce the code, this is so that I can evaluate the result better. It is a philosophy of mine that it is better to have done something the hard way (or at least have tried) first, because it gives a better intuitions of the subject.

The course raised my awareness of the probabilistic side of the AI, which explains the interesting results that one sometimes gets. Remember to use the up and down thumb to continue to train the AI, so that it becomes better.

Enjoy!

Saturday, January 11, 2025

Hardware: Building a gaming computer


Background

Just like the jedi knights of Star Wars needs to build their own lightsaber, we techies should build our own computer to get a greater understanding for the tech we use and because it is an interesting project and a test of our ability.

This is the second proper gaming desktop that I have, the first was a prebuild that lasted me for 10 years (with some repairs included), but this was before my career in IT. Now I wanted to take on the challenge of building my own gaming computer. As a sidenote the primary games I wanted to play with this new computer were Enlisted, Minecraft, World of Warcraft and Skyrim. Later on I also want to try GTA 5 and League of Legends.

Building was the quick part, while budgeting and planning was the slower part of the adventure. This will be a post about my observations and what I learned. 

Preparations

The decision to build a computer started roughly a year ago, or a bit more. I postponed it for two reasons, I needed to save up some money and I wanted to wait for prices to go down. Furthermore I was also not sure about the parts or even the process itself. So I started by putting together many various setups using the online tool at Inet where I would play around, see what the best parts would give me or how expensive some setups could be. Some setups would be around 2500 euros, which is a lot. So a part of the problem was knowing how much to scale down the computer in performance to lower the costs. It took quite a few sample builds before I realized what would be "good enough".

So my lesson for you is that you can save a lot of money on your build by adapting it for the realistic use case. Maxing everything out is probably fun and definitely expensive. It would future proof your build as well. Which is something you want to keep in mind. You could for example focus on getting parts that are modern, but not necessarily the best performers, to allow for reasonable upgrades in the future.  

So when it was finally time to pick out the parts I would use for my real build what I focused on was getting enough performance for my games and getting relatively modern pieces, this allowed me to cut the costs down to 1200 euro. I can still upgrade RAM, processor and add more storage for example.

These are the parts I ordered for my build, two of the small fans were never used.

  • Chassi: Chieftec Pro Mini Svart
  • Processor: AMD Ryzen 7 8700F 4.1 GHz 24MB
  • Graphics card: ASRock Radeon RX 6600 8GB Challenger
  • Motherboard: ASUS Prime B650M-R
  • RAM: Kingston 32GB (2x16GB) DDR5 5200MHz CL36 FURY Beast AMD EXPO/Intel XMP 3.0
  • Storage: Kingston KC3000 M.2 NVMe SSD Gen 4 512GB
  • Big fans: Phanteks M25 140mm PWM Svart
  • Small fans: Arctic P12 PWM Svart PST Svart
  • CPU-cooler: Cooler Master Hyper 212 Black Edition
  • Power supply: Chieftec Proton 750W

I chose 32 GB ram to give me ample of headroom, while allowing me to upgrade to 96 GB in the future. The NVMe on 512 GB allows me to quickly boot up the computer, store all of my games at the same time while still leaving me a bit of room. I have a whole slot that I can install a much larger storage into later as well. The CPU felt quite modern and it didn't come with integrated graphics, which means I am 100% reliant on the graphics card. 

Another part of the preparations was to create a bootable USB-drive with Windows 11 Pro, so that I instantly could install it once the computer was ready.

Building the computer

Seeing as this was the first build I had no complete desktop building experience to draw upon. Instead I had a bit of laptop maintenance experience and knowledge from general tinkering and exploring. 

The first step was to gather all the boxes with components and look it over, bringing a general screwdriver and a knife for opening the boxes. The general principle is to complete your motherboard first, before putting it into the chassis. 

So after unboxing what had to be unboxed right away, I put the CPU, RAM and SSD in place. The RAM was the easiest, just make sure to put it facing the right direction and that it fits the slot. The SSD is also quite easy once you know how to keep it in place, in this case I used a locking mechanism made from some type of plastic. The CPU was a bit interesting, make sure to align the corners properly and drop it in straight from above. Then you use the clasp to hold it in place, at this point a plastic cover flew off which I wasn't prepared for. Scary!

Once the CPU was equipped, I first used a default CPU cooler, it already had thermal paste on. But later when I had research the non-stock cooler I equipped it using thermal paste that comes with the cooler in a tube. The CPU cooler was relatively easy to install, the trick is to lower it down on top of the CPU in an even fashion to not create too much bubbles in the thermal paste. Remember to remove the plastic sticker covering the area that connects to the CPU. Fasten the screws a bit at a time, once again making sure to spread the pressure evenly until it sits properly against the CPU.

Next step was to prepare the chassis, I installed the backplate for the motherboard. The secret to installing this backplate is to push it out evenly from the inside, just make sure to align the holes correctly. The role of the backplate is to protect the computer, it can help with both heat and to some degree interference, it also offers extra stability.

Continuing on the journey I now installed the front fans. This was very tricky because it was a challenge to get the front cover off. If I could have traveled back in time, I would perhaps have installed it earlier. I also installed the chassis to the motherboard, along with the power supply. At times it was a bit tricky to see which component that needed which cable, and in some case it was difficult to connect them to the motherboard. Here I also could have done a better cable management job, by running some of the cables behind the motherboard (there is a space there). My advice is that if you are working in a dark chassis, bring plenty of light, a lamp on the forehead would have helped a lot.

Lastly I put in the graphics card, I noted that it looks like it sits upside down in this build and on the backside you only need to remove the sliders that makes room for the card's interface. The graphics card was relatively easy to install, in part thanks to a combination of a good enough chassis and that the PCIe-slot didn't cause any issues. The graphics card needs electricity too, so I connected the power to it from the power supply.

Finally I installed some additional fans (and it was after this that I installed the non-stock CPU cooler).

Setup, first time use and finishing touches

I must admit that the first time I started the computer, I stretched my arm out to the power button, just in case it would explode. But fortunately, it worked on the first go. However, I did not connect it to my main setup at this stage, I had a small touch screen connected just to get through the Windows 11 setup and then of course the USB drive with the operative system.

After making sure it was correctly setup and working, I brought it to my desk and connected it to the ethernet cable and monitor, along with peripherals. 

First thing to do was running Windows Update, downloading specific drivers and update the firmware.

When everything was set and done it was time to download games and start enjoying the product, and what a relief it was to finally be able to play the favorite games again on full graphics. As the games were installed on the desktop I could also remove the from my Framework 13, who had been struggling even at the lowest graphics. 

Sunday, January 5, 2025

Flipper Zero: Ducky scripts

Yesterday I received my Flipper Zero and after a long wait I was ready to tinker away with it.

After capturing some infrared signals and replicating them, it was time to test the legendary Bad USB functionality.

The content of this post is based on the GitHub page.

The BadUsb app on the Flipper Zero uses extended Ducky script syntax which is compatible with the classic USB Rubber Ducky 1.0 language but with extra components such as custom USB ID (how the keyboard is identified), ALT-codes (pressing ALT and numbers on the numpad) and the old SYSRQ command. Both \n and \r\n line endings are supported, empty lines are allowed and you can use spaces or tabs for line indentation.

The script is written in simple .txt files and can be copied over to the Flipper Zero using the Windows app for example, and it must be located in the correct Bad USB folder.

To use the Bad USB function, make sure to have a USB-C to USB-A cable that you connect between the Flipper and the computer that you want to run your script on.

Navigate to "Bad USB" in the main menu, select the script that you want to execute and then press run.
Almost instantly it will execute the keypresses that you preprogrammed.

Here is a simple example that helps you start a PowerShell window with administrative privileges.

GUI r
DELAY 500
STRING powershell
CTRL-SHIFT ENTER
DELAY 500
ALT Y
DELAY 500
STRING write-host "This script is running as admin"
ENTER

Spoof keyboard ID

You can set the custom ID of the Flipper USB HID device. ID command should be in the **first line** of script, it is executed before script run. VID and PID are hex codes and are mandatory. Manufacturer and Product are text strings and are optional.

ID, VID:PID Manufacturer:Product        

Example: "ID 1234:abcd Flipper Devices:Flipper Zero".

Delay, comments, holding down

DELAY, one delay value in ms

DEFAULT_DELAY, delay value in ms before every next command

DEFAULTDELAY, alternative to DEFAULT_DELAY

REM, commenting is done by writing REM followed by a single line of text

HOLD, press and hold key until RELEASE command. Up to 5 keys can be held at the same time.

RELEASE, release key

Arrow keys

DOWNARROW / DOWN

LEFTARROW / LEFT

RIGHTARROW / RIGHT

UPARROW / UP

Various buttons

APP, same as MENU, context menu key (right-clicking)

BACKSPACE

BREAK

CAPSLOCK

DELETE

END

ENTER

ESCAPE / ESC

Fx, F1-F12 keys

HOME

INSERT

MENU, same as APP, context menu key (right-clicking)

NUMLOCK

PAGEDOWN

PAGEUP

PAUSE

PRINTSCREEN

SCROLLLOCK

SPACE

TAB

You can combine the following with a special key command or a single character.

CONTROL / CTRL

SHIFT

ALT

WINDOWS / GUI, the Windows key

CTRL-ALT, ctrl plus alt

CTRL-SHIFT, ctrl plus shift

ALT-SHIFT, alt plus shift

ALT-GUI, alt plus the Windows key

GUI-SHIFT, the Windows key plus shift

GUI-CTRL, the Windows key plus ctrl

Strings and delay between keypresses

STRING, print text string, such as writing something in a terminal

STRINGLN, print text string and press enter after it

STRING_DELAY, delay value in ms which is applied once to next appearing STRING command

STRINGDELAY, an alternative to STRING_DELAY  

DEFAULT_STRING_DELAY, delay value in ms, applied to every appearing STRING command

DEFAULTSTRINGDELAY, alternative to DEFAULT_STRING_DELAY

REPEAT   Number of additional repeats  Repeat previous command

WAIT_FOR_BUTTON_PRESS, will wait for the user to press a button to continue script execution. Will wait indefinitely for a button to be pressed.

On Windows and some Linux systems, you can print characters by holding ALT key and entering its code on Numpad.

ALTCHAR, print single character

ALTSTRING, print text string using ALT+Numpad method

ALTCODE, same as ALTSTRING, presents in some Duckyscript implementations

Send SysRq command, which is a way to interact with the computer even in a frozen state.

SYSRQ, single character

Media keys

Some Media/Consumer Control keys can be pressed with "MEDIA" command

MEDIA, used with commands in the list below:

POWER

REBOOT

SLEEP

LOGOFF

EXIT

BRIGHT_UP, brightness up

BRIGHT_DOWN, brightness down

HOME

BACK

FORWARD

REFRESH

SNAPSHOT, take photo in a camera app

PLAY

PAUSE

PLAY_PAUSE

NEXT_TRACK

PREV_TRACK

STOP

EJECT

MUTE

VOLUME_UP

VOLUME_DOWN

FN, Fn/Globe key on Mac keyboard

GLOBE, special key or single character (Fn/Globe key commands for Mac/iPad)

Monday, December 2, 2024

PowerShell: Scan wifi range

This app was inspired by the project Wigle, where you can locate wifi routers in the world.
The script uses some functions for signal strength, some simple math for calculating approximate distance and Windows Forms for the GUI.

In this version the buttons have been created using a function, instead of hard coding every attribute for each button. It doesn't require admin rights to run. It does however require you to place the image file in the same directory and point the script toward it so you get a cool background image.

I was also able to package it into a .exe so it could be run as an app, using Iexpress. 

Enjoy!

<# Prerequisites #>
Add-Type -AssemblyName System.Windows.Forms 
Add-Type -AssemblyName System.Drawing

<# Main Form #>
$Form_Main_Window = New-Object System.Windows.Forms.Form
$Form_Main_Window.Size = New-Object system.drawing.size(670,400)
$Form_Main_Window.Text = "Wifi Tool 1.0"
$Form_Main_Window.FormBorderStyle = "FixedDialog"
$Form_Main_Window.StartPosition = "CenterScreen"
$Form_Main_Window.ForeColor = [System.Drawing.Color]::LightGreen;
$Form_Main_Window.BackColor = [System.Drawing.Color]::Black;
$Form_Main_Window.MaximizeBox = $False
$Img_Background = "$PSScriptRoot\background_network.png"
$Form_Main_Window.BackgroundImage = [System.Drawing.Image]::FromFile($Img_Background)
$Form_Main_Window.BackgroundImageLayout = [System.Windows.Forms.ImageLayout]::Stretch

function Set-StatusText {
    param ([string]$StatusText)
    $Txt_Status_Box.Text = $StatusText
}

function Create-Button {
    param (
        [string]$Text,[System.Drawing.Point]$Location,[System.Drawing.Size]$Size,[scriptblock]$ClickAction        
    )

    $button = New-Object System.Windows.Forms.Button
    $button.Text = $Text
    $button.Location = $Location
    $button.Size = New-Object System.Drawing.Size(100,20)

    $button.ForeColor = [System.Drawing.Color]::LightGreen
    $button.BackColor = [System.Drawing.Color]::Black
    $button.TextAlign = "MiddleLeft"

    if ($ClickAction) {
        $button.Add_Click($ClickAction)
    }

    return $button
}

function Scan-Wifi {
    param (
        [string]$wifiName
    )
    
    $wifi_data_in = netsh wlan show networks mode=bssid
    $wifi_signal_percentage = $null

    $wifi_data_in -split "`r?`n" | ForEach-Object {
        if ($_ -match '^SSID\s+\d+\s*:\s*(.+)$') {
            $ssid = $matches[1]
        }
        elseif ($_ -match '^\s*Signal\s*:\s*(\d+)%\s*$') {
            $signal = $matches[1]
            if ($ssid -eq $wifiName) {
                $wifi_signal_percentage = [int]$signal
            }
        }
    }

    return $wifi_signal_percentage
}

function Calculate-Distance {
    $percentage = Scan-Wifi -wifiName $Txt_Target_Box.Text;
    if (-not $percentage) {
        Set-StatusText -StatusText "Couldn't calculate distance"
        }
    $twodotfour = 150 - ($percentage * 1.5);
    $five = 70 - ($percentage * 0.7);
    $six = 50 - ($percentage * 0.5);
    return "`r`nSignal strength: $percentage%`r`n2.4 Ghz: $twodotfour meters`r`n5 Ghz: $five meter`r`n6 Ghz: $six meters";
}

function Scan-AllWifi {
    Set-StatusText -StatusText "Scanning nearby wifis";

    $wifi_data_in = netsh wlan show networks mode=bssid
    $results = @()

    $wifi_data_in -split "`r?`n" | ForEach-Object {
        if ($_ -match '^SSID\s+\d+\s*:\s*(.+)$') {
            $ssid = $matches[1]
        }
        elseif ($_ -match '^\s*Signal\s*:\s*(\d+)%\s*$') {
            $signal = $matches[1]
            if ($ssid) {$results += [PSCustomObject]@{SSID   = $ssid; Signal = "$signal%"}}
        }
    }

    # Filter, Sort, and Format the results in one step
    $outputText = ($results | Where-Object { -not [string]::IsNullOrWhiteSpace($_.SSID) } | 
                   Sort-Object -Property Signal -Descending | 
                   ForEach-Object {"{0,-30} {1,-10}" -f $_.Signal,$_.SSID}) -join "`r`n"

    # Save to file and update textbox
    $Txt_Main_Box.Text = $outputText
    Set-StatusText -StatusText "Log file created. Mainbox updated.";
}

function Loop-Scan {

    if ($Txt_Status_Box.Text -ne "Scanning") {

    # If not already scanning, set scanning status #
    Set-StatusText -StatusText "Scanning";
    # Loop the scan and update the meter #
    for ($i = 1; $i -le [int]$Txt_Loop_Box.Text; $i++) {$target_output = Scan-Wifi -wifiName $Txt_Target_Box.Text; $ProgressBar.Value = $target_output; Start-Sleep -Milliseconds 1500;}
    # Mark scanning as complete #
    Set-StatusText -StatusText "Scan complete";

    } else {
    Set-StatusText -StatusText "Scanning attempt failed"
    }

}

function Scan-Target {
    $Txt_Main_Box.Text = Calculate-Distance; 
    $target_output = Scan-Wifi -wifiName $Txt_Target_Box.Text;
    $ProgressBar.Value = $target_output;
    Set-StatusText -StatusText "Target was scanned";
}

function Quick-Export {
$Txt_Main_Box.Text | Out-File -FilePath "$PSScriptRoot\Wifi-log.txt";
Set-StatusText -StatusText "Quick export clicked";
}

function QuickImport-Log {
# File dialog or just quick import? #
Set-StatusText -StatusText "Quick import button clicked";
$ImportFile = Get-Content -Path $PSScriptRoot\wifi-log.txt -Delimiter "%";
$Txt_Main_Box.Text = $ImportFile;
}

function Export-ResultAs {
    Set-StatusText -StatusText "Export as clicked";
    $SaveFile_Window = New-Object System.Windows.Forms.SaveFileDialog;
    $SaveFile_Window.Filter = "Text files (*.txt)|*.txt";
    $SaveFile_Window.FileName = "wifi-log-custom.txt"
    $Export_File = $Null;
    if ($SaveFile_Window.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {$Export_File = $SaveFile_Window.FileName};
    if($Export_File) {$Txt_Main_Box.text | Out-File $Export_File};
}

function Import-Log {
    Set-StatusText -StatusText "Import log button clicked.";
    $ImportFile_Window = New-Object System.Windows.Forms.OpenFileDialog;
    $ImportFile_Window.Filter = "Text files (*.txt)|*.txt";
    $ImportFile = $null
    if ($ImportFile_Window.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
        $ImportFile = $ImportFile_Window.FileName;
        $Txt_Main_Box.Text = Get-Content -Path $ImportFile -Raw}
    }

function Reset-App {
Set-StatusText -StatusText "Reset button clicked"; 
$Txt_Main_Box.Text = ""; 
$Txt_Target_Box.Text = ""; 
$ProgressBar.Value = 0;
}

function Exit-App {
Set-StatusText -StatusText "Closing"; 
$Form_Main_Window.Close();
}

<# Main textbox #>
$Txt_Main_Box = New-Object System.Windows.Forms.TextBox
    $Txt_Main_Box.Location = New-Object System.Drawing.Size (50,50)
    $Txt_Main_Box.Size = New-Object System.Drawing.Size (395,260)
    $Txt_Main_Box.Text = "Scan to populate"
    $Txt_Main_Box.Multiline = $True
    $Txt_Main_Box.ForeColor = [System.Drawing.Color]::LightGreen;
    $Txt_Main_Box.BackColor = [System.Drawing.Color]::Black;
    $Form_Main_Window.Controls.Add($Txt_Main_Box)

<# Status textbox #>
$Txt_Status_Box = New-Object System.Windows.Forms.TextBox
    $Txt_Status_Box.Location = New-Object System.Drawing.Size (50,320)
    $Txt_Status_Box.Size = New-Object System.Drawing.Size (200,20)
    $Txt_Status_Box.Text = "App is running. Awaiting input."
    $Txt_Status_Box.Multiline = $True
    $Txt_Status_Box.ForeColor = [System.Drawing.Color]::LightGreen;
    $Txt_Status_Box.BackColor = [System.Drawing.Color]::Black;
    $Form_Main_Window.Controls.Add($Txt_Status_Box)

<# Target textbox #>
$Txt_Target_Box = New-Object System.Windows.Forms.TextBox
    $Txt_Target_Box.Location = New-Object System.Drawing.Size (560,80)
    $Txt_Target_Box.Size = New-Object System.Drawing.Size (100,20)
    $Txt_Target_Box.Text = "Enter a wifi name"
    $Txt_Target_Box.ForeColor = [System.Drawing.Color]::LightGreen;
    $Txt_Target_Box.BackColor = [System.Drawing.Color]::Black;
    $Form_Main_Window.Controls.Add($Txt_Target_Box)
    $Form_Main_Window.Add_Shown({
    $Txt_Target_Box.Focus()
    $Txt_Target_Box.SelectAll()
    })

<# Scan N textbox #>
$Txt_Loop_Box = New-Object System.Windows.Forms.TextBox
    $Txt_Loop_Box.Location = New-Object System.Drawing.Size (560,110)
    $Txt_Loop_Box.Size = New-Object System.Drawing.Size (50,20)
    $Txt_Loop_Box.Text = "10"
    $Txt_Loop_Box.Multiline = $True
    $Txt_Loop_Box.ForeColor = [System.Drawing.Color]::LightGreen;
    $Txt_Loop_Box.BackColor = [System.Drawing.Color]::Black;
    $Form_Main_Window.Controls.Add($Txt_Loop_Box)

<# Progress bar #>
$ProgressBar = New-Object System.Windows.Forms.ProgressBar
    $ProgressBar.Minimum = 0
    $ProgressBar.Maximum = 100
    $ProgressBar.Value = 0
    $ProgressBar.Location = New-Object System.Drawing.Point(50,10)
    $ProgressBar.Size = New-Object System.Drawing.Size(200,20)
    $ProgressBar.Style = "Continuous"
    $ProgressBar.Text
    $ProgressBar.ForeColor = [System.Drawing.Color]::Green
    $ProgressBar.BackColor = [System.Drawing.Color]::Red
    $Form_Main_Window.Controls.Add($ProgressBar)

<# Label for progress bar #>
$Lbl_ProgressBar = New-Object System.Windows.Forms.Label;
    $Lbl_ProgressBar.Location = New-Object System.Drawing.Point(255,10);
    $Lbl_ProgressBar.Size = $ProgressBar.Size;
    $Lbl_ProgressBar.Text = "Signal strength";
    $Lbl_ProgressBar.TextAlign = "MiddleLeft";
    $Lbl_ProgressBar.ForeColor = [System.Drawing.Color]::DarkGreen;
    $Lbl_ProgressBar.BackColor = [System.Drawing.Color]::Transparent;
    $Form_Main_Window.Controls.Add($Lbl_ProgressBar);

<# Scan all button #>
$Btn_Scan_All = Create-Button -Text "Scan All" -Location (New-Object System.Drawing.Point 450, 50) -ClickAction { Scan-AllWifi }
$Form_Main_Window.Controls.Add($Btn_Scan_All)

<# Scan target button #>
$Btn_Scan_Specific = Create-Button -Text "Scan target ->" -Location (New-Object System.Drawing.Point 450, 80) -ClickAction { Scan-Target }
$Form_Main_Window.Controls.Add($Btn_Scan_Specific)

<# Loop scan button #>
$Btn_Loop_Scan = Create-Button -Text "Loop scan ->" -Location (New-Object System.Drawing.Size 450,110) -ClickAction { Loop-Scan }
$Form_Main_Window.Controls.Add($Btn_Loop_Scan)

<# Quick Export button #>
$Btn_Quick_Export = Create-Button -Text "Quick Export" -Location (New-Object System.Drawing.Point 450, 200) -ClickAction { Quick-Export }
$Form_Main_Window.Controls.Add($Btn_Quick_Export)

<# Import Quick button #>
$Btn_Quick_Import = Create-Button -Text "Quick Import" -Location (New-Object System.Drawing.Point 555, 200) -ClickAction { QuickImport-Log }
$Form_Main_Window.Controls.Add($Btn_Quick_Import)

<# Export As button #>
$Btn_Export_As = Create-Button -Text "Export As" -Location (New-Object System.Drawing.Point 450, 230) -ClickAction { Export-ResultAs }
$Form_Main_Window.Controls.Add($Btn_Export_As)

<# Import specific button #>
$Btn_Import = Create-Button -Text "Import Log" -Location (New-Object System.Drawing.Point 555, 230) -ClickAction { Import-Log }
$Form_Main_Window.Controls.Add($Btn_Import)

<# Reset button #>
$Btn_Reset = Create-Button -Text "Reset" -Location (New-Object System.Drawing.Point 450, 260) -ClickAction { Reset-App }
$Form_Main_Window.Controls.Add($Btn_Reset)

<# Exit button #>
$Btn_Exit = Create-Button -Text "Exit App" -Location (New-Object System.Drawing.Point 450, 290) -ClickAction { Exit-App }
$Form_Main_Window.Controls.Add($Btn_Exit)

<# Display the window #>
$Form_Main_Window.ShowDialog()

Saturday, November 9, 2024

Raspberry Pi: Pi-hole network wide adblocker

These days our browsing experience can feel very cluttered with ads and it has been like that for many decades. I remember how quiet the internet browsing experience became with the first adblockers. My first addon for this purpose was Adblock Plus, later on I switched over to uBlock Origin. Since I have many devices, including phones it requires me to manage these addons on multiple devices.

It was a few years ago that I heard of Pi-hole and I liked the idea that it would remove ads even from my phone and the games I play there. That it would remove many ads on multiple devices was also a clear selling point.

Over time my understanding of how a network is built has increased and so has my understanding of Raspberry Pi, to the degree that I now felt ready to try create a Pi-hole installation and run it at home.
My current router is locked down from my ISP point of view, so I tested it by redirecting a device to the Pi-hole for testing.

This is a practical guide of how I did it. What I used is: Raspberry Pi 5 (8gb RAM), SD card for the OS, USB-C charger. 

Creating a Pi-hole installation

1. Download Raspberry Pi Imager to flash the OS to your SD card: https://downloads.raspberrypi.org/imager/imager_latest.exe
The operative system image is already included in your Raspberry Pi Imager.

2. Install it by running as admin and run the program after the installation is complete.

3. The GUI of the program let's you choose your Raspberry Pi Model. In my case I took the 5.

4. Choose the OS "Raspberry Pi OS Lite (64-bit)" it has no GUI, so it is all command line.
Pi-hole is compatible with Ubuntu and Debian as well, along with a few other Linux distros.

5. Set options such as SSH-access and the proper wifi-settings so the Raspberry Pi connects to your wifi directly. In the future I plan to use a regular Cat 8, 0.5m ethernet cable or something similar. Put the finished SD card in your Raspberry Pi and start it up, it should then connect to your network.

6. To SSH into it you will need to know the IP address, you get this by looking in your router's list of connected devices. At this stage you also want to lock the IP address, this is because you will lose network connectivity if the router/device won't find the Pi-hole at the given IP in the DNS-settings.

7. It is time to start PowerShell as admin now and install Pi-hole on the headless Raspberry Pi OS Lite. Write SSH and the username@IP. 
Example: SSH admin@192.168.0.14
The password is the same you put in the Raspberry Imager setup for SSH.

8. Once successfully connected you will get a command line available to you.
Run sudo raspi-config to set details for your computer. If you did the settings in the Raspberry Pi Imager correctly, you won't need much config here. 

9. When you have double checked your settings, run sudo curl -sSL https://install.pi-hole.net | bash
This will start the installation process of the actual Pi-hole software.

10. Make sure your Pi has a static IP and then continue through the prompts.
Add Cloudflare as uplink DNS, install the premade list and install the web server.
Enable query logging.
Show everything.
Then let the script work.
Take note of the login password, and access the page using the IP/admin.
Example: 192.168.0.14/admin

Now you have set up your Pi-hole and the next step to actually block ad traffic is to direct it through the device.

Directing traffic through the Pi-hole

Debian 12
Open terminal and write the following commands:
sudo su
nano /etc/resolv.conf

Replace the pre-existing numbers with the IP-address of your Pi-hole
nameserver 8.8.8.8
nameserver 8.8.4.4

Click ctrl+x to save and then confirm with Y.

Windows 11
Press ctrl+r
Write ncpa.cpl and hit enter
Right-click your adapter of choice and take properties
Go into the properties of IPv4
Enter a manual DNS (the IP of your Pi-hole device)




Your router
Since the GUIs of routers differ this is the general guideline.
Logon to your router by browsing to its IP (you can find this gateway IP by doing ipconfig)
Set both primary and secondary DNS addresses to your Pi-hole's IP. Should you set the secondary IP to 1.1.1.1 for example, then it will use the backup DNS if your primary goes down.


Saturday, October 26, 2024

Windows: Enable Windows Hello on a Framework 13

I have had my Framework Laptop 13 for a few months now and I have gotten used to many of its features. The physical design is very nice and it has a premium feel to it in many ways.

However, one feature that I have been missing is additional biometrics, namely face recognition.
The screen that Framework uses for this laptop contains a camera that simply doesn't allow for facial recognition. The reason for this could be both a cost and a technology reason. 

This doesn't stop the user from having an external camera, personally I am running a Logitech Brio 4K through a docking station. With other computers I can use this but for some reason I couldn't use it with the Framework Laptop 13.

Research led me to finding a registry value and a Windows setting that needed to be changed.

You can look at "Settings --> Accounts --> Sign-in options" if you have a setting called "Sign in with an external camera or fingerprint reader." This should be turned on. For me, this was missing which resulted in Facial recognition (Windows hello) claiming that the function was not available on my device.

If you cannot find the option to allow external devices for biometric sign-in you can adjust the following key and value.

The reg file way

Create a reg file containing this information, run it as administrator and restart afterwards.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WinBio]

"SupportPeripheralsWithEnhancedSignInSecurity"=dword:00000001

The registry way

Start registry editor as admin and go to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WinBio and create a new key DWORD (32-bit) value named SupportPeripheralsWithEnhancedSignInSecurity which you then give the value 1.

The PowerShell way

To add the value needed you need to start PowerShell as an administrator.

New-ItemProperty -path "registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WinBio" -name SupportPeripheralsWithEnhancedSignInSecurity -PropertyType dword -Value 1

Saturday, August 3, 2024

Review: Framework Laptop 13

 A few weeks ago I bought a Framework Laptop 13 on Ebay, it was a preowned product and these are the technical details:

Processor: i5-1340p

Ram: 64 GB, DDR4

Storage: 1 TB, NVMe

The PC also comes with expansion slots, which in other words are swappable connection ports.
This came with 1 USB-C, which I use for my docking station and charging. 2 USB-A and an HDMI.

In the future I will sell the HDMI port and trade it for either a USB-C, ethernet port or perhaps a micro SD reader. It depends a bit on what need there will be, the docking station does provide these but you also need to evaluate how often you are without the docking station.

The overall feel is a computer of high quality, I was a bit worried that it would be flimsy but so far it feels like a solid computer, and it is actually a nice looking computer with a slightly textured surface making it nice to carry as well. Compared to other computers the aspect ratio makes it feel a bit more square.

Battery life has been good so far, I am running it on about 80% capacity to prevent overcharging the battery. Being used to other laptops and 2-in-1 devices I consider the battery to perform quite well.

The speakers are relatively clear and are good enough for me. The display does not support touch and it is quite average, which was to be expected after doing research. Another downside is that the camera does not support face recognition. The biggest downside so far has been loud fans of the computer, that activate at low tresholds. It is not annoying in of itself, but it is loud and starts too early in my opinion.

Some other benefits are the obvious repairability and the upgradability. You can simply switch out any piece of the computer with relative ease. In the future I will also invest in a cool Dbrand skin probably. A computer is faster if it looks cooler. As I bought the computer on the secondhand market online, I made sure to ask the seller to include stickers and the Framework official screwdriver, which has two types of heads that you can rotate, kept in place with magnets.

The power button allows you to sign in with your fingerprint which is a great alternative.
The camera and mic can be disabled with switches, for those with privacy concerns.

It came preinstalled with Windows 11 Pro, and overall the operativesystem has been performing well. I have had some connectivity issues with the monitors, but I believe the error is with the docking station.

The price was around 1000 euro while a new one with the same specs would be around 1250 euro. Which makes this a good deal.

Remember to buy from trusted sources and ask for pictures before you buy something.
I used PayPal to protect my purchase as well.



The top cover has a nice matte finish and the emblem seems to be of smooth plastic.
The keyboard is really nice to write on, currently using international english ANSI layout.
Going to buy a Swedish ISO layout in the future.

After many months of usage I decided to update the review with my latest findings.
The fingerprint sensor is still really responsive and using facial recognition is not possible due to the limitations of the physical camera, however, I managed to get it running using a Logitech BRIO 4K connected to the docking station.

The main issue with the computer is that it disconnects itself from the dock, as if it is a software bug. 
The second issue is that it becomes extremely warm when playing games. In order to help it with the cooling, I open it up and put it on its side.


Friday, July 26, 2024

Fiction: The Loop, a short story

The Loop

A short story, by Erik Engström, 2024-07-24

 

“I wonder what this button does” the inventor softly said to herself.

She had been working on this device for a long time, it was the pinnacle of her own achievements. In her own workshop she could lose herself in her interests for hours. It could sometimes start with an idea out of nowhere or after reading something somewhere. These ideas got to her as naturally as the sun itself rises in the morning.

Being deeply focused on her creations she would sometimes lose track of time, not stopping her pursuit until her search reached an end. Even though she didn’t even remember what it was that she was searching for, her feeling told her to keep trying to fix the machine, she was so close now.

She had spent the better part of two years working on the machine, following an instruction manual laying in front of her. It was not only her body that deteriorated, but as the machine became more complete, her connection to other people was falling apart.

Those that knew her saw something else when they entered her workshop. Tools everywhere, blueprints spread out on the bench. She in turn saw a machine in the making, something that would change the world for the better, remove incurable suffering and help a chaotic mind to finally find peace from the worries of the world.

She read the notes in the instructions, right next to where someone had doodled the initials TTC.

“This machine has not been tested yet, results may vary, use at own risk” she read from the handwritten words in the corner of one of the pages.

“Press button to activate”.
That sounds simple enough, a push of a button to fix all the pain and suffering. Who wouldn’t press it? She continued to look through the pages for additional answers, what would the machine actually do? There was a page titled “results” but it was completely blank. It looked like it was up to her to take the step into the unknown and see what would happen.

Excitement and curiosity overshadowed reason at this stage, years of research was documented in the notebook, and she was finally at the end of the process. How come no one had ever proceeded after this point? She looked at the machine that stood on the table, now taunting her to push the small silvery button on the front.

“I wonder what this button does” the inventor said once again as she finally clicked the button.
In front of her was a notebook with a familiar handwriting and a machine that she was just seeing for the very first time.

Fiction: The Wanderer, a short horror story

The Wanderer

A short horror story, by Erik Engström, 2024-07-20


“Find him.”

This command had echoed within my mind the past week as the voice had grown louder.

I did not recognize the voice, but at the same time it felt like a voice I had heard somewhere before.

This fact gnawed at my sanity, I needed to know, but how? I was here for another reason though, my mind was too occupied with the task at hand to pursue the truth behind the voice.

This town was familiar to me. In this moment it was if it was all I had ever known. Nothing before, nothing after it. The moment was at its purest clarity, and the voices demanded that I had to find him. It was as if the unknown presence was guiding me, all to bring him home. Wherever that is.

They had sought him for so long and the task was mine to finish.

A gentle breeze swept through the trees as I walked down the neighborhood. It was a beautiful day to the unknowing, all who were out to enjoy the day. People in the gardens tending to their plants, children playing in the street and the occasional cyclist riding by.

By the side of the road I stopped a woman and asked, “excuse me, I am looking for a Mr. Lotti, does he live here?”. She eyed me suspiciously for a moment, finally pointing further down in the same direction I had been walking. 

“Try there” she said as she took a step away from me, before walking away.

“Thanks.” I replied and continued on.

A few minutes later after having rounded a bend I noticed an older man standing by his mailbox on the same side of the road. When I got close enough for him to see me, his mouth closed and he tensed up in worry. 

“Are you here for me?” He asked with a trembling voice.

I looked at my wrist watch, while shaking my head as an answer to his question. 

“It is not time. I am looking for Ryan, does he live nearby?”

“Yes, I saw one of his kids playing in the street earlier. Maybe he knows if Mr. Lotti is home.” The man replied, trying to hide his relief.

“Thank you. Until next time.” I said and nodded.

Just as the man had finished replying I heard the sound of laughter not much further away, it was the young son of Ryan. I made my way over there to ask about his father.

“Hello, what is your name?” The child asked me before I could say anything.

"Well, hello there, I am Saul Atoke, I am a friend of your father, is he here?”

With big eyes the young kid dropped the stick that he was playing, “he is at home”, he said cheerfully and pointed at house number 13, a lightly teal colored house at the end of the street, framed between two large oak trees with leaves rustling in the wind.

“Thank you” I said and waved.

I was nearing the end and stood just outside the house for a moment. Was it always going to be like this? Would he know why? 

The voices whispered to me in a maniacal rhythm “take it, take it, take it, we demand it”. 

I could see the child with his red sweater running past me, into the house, clearly caught up in an imaginary world as he forgot to close the door behind him. A minute passed and a hand pulled the door shut again. To them this was just an ordinary day. To me, it was also an ordinary day.

I braced myself as I entered the gate, I never got used to this but there was nothing to be done now. 

“Ryan E. Lotti, this must his place”, I thought to myself as I read the sign next to the door. 

I reached to knock. A moments silence was followed by a thud and footsteps getting closer to the door. The door handle turned and the door opened up.

Our eyes met for a moment. If he really was afraid of me his face did not reveal that secret, it was as if he already knew who I was, and more importantly why I was there. It was time to take him home.

The unspoken conversation between me and him was broken by a sound behind him. It was the kid I had seen before. His eyes spoke of confusion, as he remembered me from earlier. Unlike his father, he did not know who I was.

The masters’ words echoed in my mind. These damnable voices that I had heard for such a long time. As long as I remembered. They reminded me that the man in front of me had to pay his debt. His time was long overdue and the job of collecting was mine.

Just as my hand reached through what felt like an infinite distance to claim his soul there and then, I felt time slowing down. My hand slowed down to a complete halt, even the man and his son stood still, light no longer reflecting in their eyes. Darkness flooded the corridor in his house like a wild river washing over rocks. The ambiance from the street outside went silent, cars stopped and darkness covered every corner as if the sun had suddenly gone missing.

Silence, darkness and then it was over.

More silence.

More darkness.

Until a tiny sharp light glared at me.

“I’ve seen enough, this is the perfect candidate, we have what we need.” Said a faceless man, with a voice muffled by a surgical mask.

“Will he survive the process?” Asked another, just as faceless woman, holding a scalpel.

“It does not matter. We have extracted the mind and created a fully functional model. It will be used elsewhere. Our mortality has controlled our lives, but now even Death will serve us.” Replied the man as they walked away from the table.


The End.


 

Monday, July 15, 2024

Fiction: The Creature, a short horror story

The Creature 

A short horror story

I am a private investigator on a mission from The Time Councils Cryptid Department.
It was in the middle of the winter and I had just parked my car at the only parking area available in this remote part. This used to be a national park but since a couple of years ago it had been permanently closed. This was the last known location of what the organization referred to as The Pale Stalker. Few had survived their encounter with the otherworldly being. Even fewer had information about it. They talked about a tall, lean and pale humanoid figure that would stand in the distance at the forest’s edge, just staring at them. Most people would just leave immediately upon seeing it, but the park is not closed without a reason. Ever since the first sightings of the pale creature people has started going missing and strange phenomenon had been reported.

Heavy footsteps left footprints in the snow as I left my vehicle. I thought to myself that if I were lucky
enough to find the creature, it would observe me at most, there was little risk of danger. Carrying
light equipment would make me mobile enough, I reasoned to myself. My arrogance would
prove to be my undoing that night. I got my flashlight and I started heading down the dark path.

Mere minutes had passed before the strange feeling of being watched made me turn to the side and every second suddenly felt like a minute. The forest felt darker and the snow deeper, as I looked.

There, leaning out behind a tree was a head sticking out, a pale face lacking the basic features was staring right at me. Black eyes like those of a shark was studying me without blinking.
I looked away for a second and when I looked back it looked like the creature had moved, it now stood behind a tree that was closer to me. I brought my flashlight up to point it at the creature, to get a better look. This might be the only chance to get a good look, I convinced myself. However, instead of shying away, it walked out at the tree line in full view.

My mistake was now clear to me, I knew that I was playing a game of high risk here and I had to act fast. There was no time to lose so I started running, but every step was heavy and the adrenaline made me lose my sense of direction. “I came from that direction, right?” I desperately said to myself as I let out a big puff of warm air in the cold winter night. The small cloud of fog dissipated in the air, just like my hope of survival. It was clear to me that I had gone in the wrong direction.

I saw movement to my side, the creature was after me. It was out there. I could feel it. The deep snow wore me down and I was losing energy quickly. By now I was using the last of my strength.

After running along the path I was on, I came out in a clearing and the silhouette of a cabin stood out against the tree line further away. Moonlight broke through the cracks in the cloudy sky and reflected in the windows of the small building. This was my chance I thought in desperation, as I rushed to the door.

My throat was hurting from the cold air and the sprint toward the cabin had raised my heartbeat, the beating was almost deafening to my ears. This is what true fear felt like.

The wooden door of the cabin now stood in front of me, all I had to do was push it open.
Would it yield to my desperate push?
As fate would have it, the door opened up with a creak as I pushed it open and a gust of old and stale air reached me. For a single moment in time everything was still, I saw dust dance in a single beam of faint moonlight. My eyes had not yet adjusted to the darkness of the cabin. But now I was safe.

My feeling of safety was not much longer than the moment of that very thought. I realized that there had been tracks leading to this cabin, but not leading away from it. Now it was too late to turn back.

I felt a drop touch my cheek, but it wasn’t a tear or a raindrop. A sigh of resignation left my body, and even though fear filled my body it would not run away from there, it was if I lost control over myself.

It all went so fast after that, the sound of movement was quickly followed by a pale figure appearing out of nowhere. It leapt right down upon me, and it held me down against the floor as it gazed upon me with dead eyes. The eyes were completely black, there was no trace of a soul, only the moonlight was reflected in the infinite darkness of this nightmare. Pale hands with long claws dug into my chest and shoulders. I let out a tormented scream and the creature simply tilted its head a bit and then opened its mouth, revealing thousands of small, gleaming teeth. As I was trapped in its sadistic grip, it reached for me with its mouth. I was met with a stench of old blood and rotten meat that was so strong that it made me forget my pain for a moment.

Ignoring my every effort of resistance it bit me in the neck. Thousands of small teeth piercing my skin. A stinging, acidic pain jolted through me, which was more than I could handle. Laying there in a growing puddle of blood, I felt my body grow colder and my vision faded.

This was it, I was done for. Resistance would had proven futile and hope was gone. I felt my body shutting down and the creature that had been impaling me was now just a blur before me.

What must have been hours passed and I woke up on the cabin floor, as I moved I heard my frozen blood crack as it had frozen my clothes stuck to the floor. I felt dizzy from the attack.
”Was I still alive?” I wondered to myself.

I wish I wasn’t. Because an unsatiable hunger has risen in me, that no regular food can satisfy.
I am now prowling the forest at night, sleeping at day, an empty husk of what I once was. In an eternal state of being somewhere between living and dead.

And that creature, the damn creature responsible for my cursed doom, is still out there. Still hunting.