How To Play an Audio file in JavaScript

Here is a quick and simple way to play an audio clip in JavaScript

const audio = new Audio('path/to/audio.mp3')
audio.play()

That is literally it.

You can set “audio.play()” to where ever you need in your code so it gets triggered when needed.

https://stackoverflow.com/questions/9419263/how-to-play-audio

JavaScript – The media resource indicated by the src attribute or assigned media provider object was not suitable.

If you receive the following error,

The media resource indicated by the src attribute or assigned media provider object was not suitable.

It could be because your media file is not supported. Try converting your audio file to a different format.

https://stackoverflow.com/questions/57246199/domexception-the-media-resource-indicated-by-the-src-attribute-or-assigned-med

Operation Triangulation – iOS Zero-click APT Exploit Info

Quick Summary: Operation Triangulation is an iOS zero-click exploit that will self destruct, looks to have been used since at least 2019, works on iOS 15.7, unsure if it works on iOS 16. Can collect location, mic recordings, photos, and manipulate iMessages. First point of entry is from an iMessage message, that compromises the device, after compromise, the message gets deleted.

https://securelist.com/operation-triangulation/109842/

https://www.kaspersky.com/about/press-releases/2023_kaspersky-reports-on-new-mobile-apt-campaign-targeting-ios-devices

https://arstechnica.com/information-technology/2023/06/clickless-ios-exploits-infect-kaspersky-iphones-with-never-before-seen-malware/

Links for checking for infection.

https://securelist.com/find-the-triangulation-utility/109867/

https://github.com/KasperskyLab/triangle_check

The following is a list of C&C domains from the securelist.com article. Did a quick DNS lookup for each domain and they currently have the following records & IP addresses. Note that these can change at any time and some of the IP addresses are/can be shared with other legitimate websites if it is on a shared hosting provider.

addatamarket.net - sandy.ns.cloudflare.com, doug.ns.cloudflare.com - No A records, or TXT
backuprabbit.com - nelci.ns.cloudflare.com, morgan.ns.cloudflare.com - No A records, or TXT
businessvideonews.com - ns2.dnsowl.com, ns3.dnsowl.com, ns1.dnsowl.com - 198.251.81.30, 209.141.38.71, 107.161.23.204
cloudsponcer.com - Cloudflare, kipp.ns.cloudflare.com, joyce.ns.cloudflare.com
datamarketplace.net - ns78.domaincontrol.com, ns77.domaincontrol.com, 34.98.99.30
mobilegamerstats.com - ns1.bitdomain.biz, No A records, TXT=v=spf1 redirect=_spf.mailhostbox.com
snoweeanalytics.com - cody.ns.cloudflare.com, arlee.ns.cloudflare.com - 104.21.76.6, 172.67.184.201
tagclick-cdn.com - ns4.bitdomain.biz, ns3.bitdomain.biz, ns2.bitdomain.biz, ns1.bitdomain.biz - No A records, TXT=v=spf1 redirect=_spf.mailhostbox.com"
topographyupdates.com - nero.ns.cloudflare.com, dalary.ns.cloudflare.com - 104.21.27.67, 172.67.141.199
unlimitedteacup.com - nelci.ns.cloudflare.com, javon.ns.cloudflare.com - 104.21.55.58, 172.67.145.72
virtuallaughing.com - elaine.ns.cloudflare.com, braden.ns.cloudflare.com - 104.21.60.240, 172.67.202.140
web-trackers.com - dns1.registrar-servers.com, dns2.registrar-servers.com - 15.164.228.250
growthtransport.com - ns3.dnsowl.com, ns2.dnsowl.com, ns1.dnsowl.com - 198.251.81.30, 107.161.23.204, 209.141.38.71
anstv.net - ns64.domaincontrol.com, ns63.domaincontrol.com. - 93.90.223.185
ans7tv.net - ns37.domaincontrol.com,ns37.domaincontrol.com - 93.90.223.185

List of domains

addatamarket.net
backuprabbit.com
businessvideonews.com
cloudsponcer.com
datamarketplace.net
mobilegamerstats.com
snoweeanalytics.com
tagclick-cdn.com
topographyupdates.com
unlimitedteacup.com
virtuallaughing.com
web-trackers.com
growthtransport.com
anstv.net
ans7tv.net

List of IPv4 addresses used

107.161.23.204
198.251.81.30
209.141.38.71
34.98.99.30
172.67.184.201
104.21.76.6
172.67.141.199
104.21.27.67
172.67.145.72
104.21.55.58
104.21.60.240
172.67.202.140
15.164.228.250
209.141.38.71
198.251.81.30
93.90.223.185

Bash command to get an updated IP address list. bad.txt contains all the above domain names.

for i in `cat bad.txt` ; do dig $i a +short >> badips.lst; done

Check DNS logs

If you have a DNS server, you can check to see if there has been any name resolution by using the following. Change named.log to your dns log

# list=""addatamarket.net"
"backuprabbit.com"
"businessvideonews.com"
"cloudsponcer.com"
"datamarketplace.net"
"mobilegamerstats.com"
"snoweeanalytics.com"
"tagclick-cdn.com"
"topographyupdates.com"
"unlimitedteacup.com"
"virtuallaughing.com"
"web-trackers.com"
"growthtransport.com"
"anstv.net"
"ans7tv.net""

# for domain in $list; do echo $domain && sudo grep -i $domain /var/log/named.log; done

Setup Mikrotik capture traffic

Mikrotik packet sniffer settings to capture traffic coming or going to the above IP addresses.

/tool sniffer
set file-limit=32000KiB file-name=Triangulation filter-ip-address="107.161.23.20\
    4/32,198.251.81.30/32,209.141.38.71/32,34.98.99.30/32,172.67.184.201/32,104.\
    21.76.6/32,172.67.141.199/32,104.21.27.67/32,172.67.145.72/32,104.21.55.58/3\
    2,104.21.60.240/32,172.67.202.140/32,15.164.228.250/32,209.141.38.71/32,198.\
    251.81.30/32,93.90.223.185/32" 

You can then start the sniffer by running Tools -> Packet Sniffer Settings -> Start

or run

/tool/sniffer/start

Resolution

Apple issued an update that fixes the kernel part of the vulnerability.

https://securelist.com/triangledb-triangulation-implant/110050/

Wireshark – Please turn off promiscuous mode for this device

Recently received the following error while trying to do a packet capture on windows.

There are two solutions to this problem

  1. Disable promiscuous mode for the adapter
  2. Update Npcap

Disable Promiscuous mode

“Please turn off promiscuous mode for this device”

You can turn on promiscuous mode by going to Capture -> Options

Uncheck promiscuous

And click Start

Update Npcap

If you need promiscuous mode on, then look at installing a newer version of Npcap

https://npcap.com/dist/

Restart Wireshark, and Start a capture.

https://ask.wireshark.org/question/30138/please-turn-off-promiscuous-mode-for-this-device/

JavaScript Basic Spread and Rest (…) usage

The Spread and Rest operators i.e. the three dots (…) can be used to make code cleaner and more concise.

Difference between Spread and Rest

Spread: Works on elements on the right side of the = operator, and breaks them out into individual elements.

Rest: Works on the left hand side of the = operator, and compresses them into an array.

Using Spread to Iterate over Arrays

Spread works on iterables like strings, arrays, maps and sets.

The spread operator operates similar to taking all the elements out of an array and operating on them or writing them to a new array. Say for instance we have an array of computers and we want to log each element to the console.

const computersA = ['Acer', 'Apple', 'ASUS']

We can log each element by running

console.log(computersA[0], computersA[1], computersA[2])

Or we can use the spread operator

console.log(...computersA)

The output is the same.

Joining Arrays

We can also use the spread operator to join two arrays together. Say we have two arrays

const computersA = ['Acer', 'Apple', 'ASUS']
const computersB = ['HP', 'Dell', 'Lenovo']

And we want to concatenate them together. We can do that simply by

const computerAll = [...computersA, ...computersB]

Rest Example

Rest is simply the opposite of spread. Spread take an item like an array and expands it out into elements we can use. Rest takes elements and packs them into an array. This can be extremely helpful if we want to pass in an unknown amount of elements into a function for processing.

const computersA = ['Acer', 'Apple', 'ASUS']
function writeToLog (...arr) {
  for (const element of arr) {
    console.log(element)
  }
}

Now we can call the function with as many elements in the array and they will all get logged to the console.

writeToLog('Razer', 'Alienware', 'Legion')

We could also use both the Spread and Rest functions

const gamingLaptops = ['Razer', 'Alienware', 'Legion']
writeToLog(...gamingLaptops)

Now as we add more laptops to the gamingLaptops array, the function will automatically process the line and write to console.

https://www.freecodecamp.org/news/three-dots-operator-in-javascript/

Notes on Setting up a Cambium 850C PTP

These are set up a bit weird compared to normal WISP radio equipment. The default IP address is 192.0.2.1 for the radio. So you need to set a 192.0.2.3 with a subnet of 255.255.255.240. Looks like it is usually only accessible via the management port and you need to make or buy a special patch cable.

https://community.cambiumnetworks.com/t/physical-reset-on-ptp850c/88884/2

The User Guide is available here

https://www.cambiumnetworks.com/wp-content/uploads/2021/07/PTP-850-C-E-S-User-Guide-11.5.pdf

You can download the Installation Guide from here

https://support.cambiumnetworks.com/file/5034c6e4b584c5d40429a163cef0d7a6257f8dc3

Both those documents show how to install and get into the device.

JavaScript Delete Object if it Collides or Overlaps with another object that has CSS Class X

Imagine we have a page that has anywhere from 1 to 100 floating blocks. Now what if I want the block(s) to disappear if it runs into another type of block or a boarder? How would we do that?

First lets get a list of all elements with X and Y class. We could swap one of these classes out for an ID if we wanted to.

const elements1 = document.querySelectorAll('.boxes')
const elements2 = document.querySelectorAll('.borders')

The variable elements1 and 2 are both arrays of all the elements that have class .boxes and boarders.

Now lets create a function to detect a collision.

function detectCollision(class1, class2) {
  for (let i = 0; i < class1.length; i++) {
    const e1Rectangle = class1[i].getBoundingClientRect()
    for (let i2 = 0; i2 < e2.length; i2++) {
      const e2Rectangle = class2[i2].getBoundingClientRect()
      if (
        e1Rectangle.left < e2Rectangle.right &&
        e1Rectangle.right > e2Rectangle.left &&
        e1Rectangle.top < e2Rectangle.bottom &&
        e1Rectangle.bottom > e2Rectangle.top
      ) {
        destroyElement(class1[i])
        destroyElement(class1[i2])
      }
    }
  }
}

This function takes two arrays as inputs, loops over each array object and compares to see if any are overlapping. If they are overlapping, run the destroyElement() function for those two specific elements.

Create the destroyElement function with

 function destroyElement(element) {
  elementId.parentNode.removeChild(elementId)
}

Here is our full code

const elements1 = document.querySelectorAll('.boxes')
const elements2 = document.querySelectorAll('.borders')

function detectCollision (class1, class2) {
  for (let i = 0; i < class1.length; i++) {
    const e1Rectangle = class1[i].getBoundingClientRect()
    for (let i2 = 0; i2 < e2.length; i2++) {
      const e2Rectangle = class2[i2].getBoundingClientRect()
      if (
        e1Rectangle.left < e2Rectangle.right &&
        e1Rectangle.right > e2Rectangle.left &&
        e1Rectangle.top < e2Rectangle.bottom &&
        e1Rectangle.bottom > e2Rectangle.top
      ) {
        destroyElement(class1[i])
        destroyElement(class1[i2])
      }
    }
  }
}

// Element is element[arraynumber].etc
function destroyElement(element) {
  elementId.parentNode.removeChild(elementId)
}

// Every second, let's run our collision function to check for collisions
setInterval(function () {
   detectCollision(elements1, elements2)
  }, 1000)

Ansible Error – An unhandled exception occurred while templating

}}'. Error was a <class 'ansible.errors.AnsibleError'>, original message: An unhandled exception occurred while templating '{{ ntfy_visitor_request_limit_exempt_hosts_container_networks_inspect_commands_string | split('###') }}'. Error was a <class 'ansible.errors.AnsibleError'>, original message: template error while templating string: no filter named 'split'. String: {{ ntfy_visitor_request_limit_exempt_hosts_container_networks_inspect_commands_string | split('###') }

To solve the issue, update Ansible. If you are already on the “latest” version of ansible available to for your distro, uninstall, and then install it again following the directions on Ansible’s website

For Ubuntu we can simply do that with

sudo apt remove ansible
sudo apt-add-repository ppa:ansible/ansible
sudo apt install ansible

Notes on Buttons with JavaScript

Here are some very basic notes on using buttons to change elements on a web page

We have a very simple page with three buttons that change the background color when the button is clicked.

Clicking a button changes the text and the background color.

Create a button in our html file.

    <button type="button" class="button green">Green</button>

We have two classes assigned to this button, button which is used for styling, and the green, which JavaScript will use to know which button is clicked.

In our JavaScript, we will set up an event listener for when the button is clicked.

document.querySelector('.green').addEventListener('click', function () {
  document.querySelector('body').style.backgroundColor = 'Green'
  console.log('Green')
})

We use the document.querySelector to interact with HTML objects. So we setup the event listener to listen to the button that is in Class green, and we wait for the click event. Once that happens, we run the code in the function(){ }.

Line 2 is what changes our background color. We query the body tag, and set the backgroundColor to Green. Notice that the background color name is slightly different between JavaScript and HTML.
HTML and CSS it has a – in it: background-color
JavaScript is it Camel Case: backgroundColor

Here is the full code for the above screenshots. There are three files. index.html, style.css, and index.js. Should be able to copy them to the same folder and run the index.html file.

Index.html code

<!DOCTYPE html>
<html lang="en">
  <head>
    <link rel="stylesheet" href="style.css" />
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JavaScript DOM Practice</title>
  </head>
  <br />
  <section class="mainwindow">
    <div class="output">Click a button to change the background color</div>
    <br />
    <br />
    <br />
    <button type="button" class="button green">Green</button>
    <button type="button" class="button blue">Blue</button>
    <button type="button" class="button yellow">Yellow</button>
  </section>

  <body>
    <script src="index.js"></script>
  </body>
</html>

JavaScript index.js

'use strict'

document.querySelector('.green').addEventListener('click', function () {
  ChangeBackgrounColor('Green')
  LogBackgroundColor('Green')
})

document.querySelector('.blue').addEventListener('click', function () {
  ChangeBackgrounColor('Blue')
  LogBackgroundColor('Blue')
})

document.querySelector('.yellow').addEventListener('click', function () {
  ChangeBackgrounColor('Yellow')
  LogBackgroundColor('Yellow')
})

function ChangeBackgrounColor (color) {
  document.querySelector('body').style.backgroundColor = color
}

function LogBackgroundColor (color) {
  document.querySelector('.output').innerHTML = `Background is ${color}`
  console.log(`Background color is ${color}`)
}

CSS File style.css

.mainwindow {
  padding: 1rem;
}
body {
  background-color: white;
}
button {
  border: none;
  font-size: 24px;
  cursor: pointer;
  padding: 1rem 1.5rem;
  margin: 1rem;
}
.output {
  font-size: 2rem;
}

Javascript Ternary Operator

The ternary operator is a conditional operator that takes three (ternary) options. We can almost think of it as a concise if then statement.

The basic syntax is as follows.

Condition ? Value-If-True : Value-If-False

For an example

const isOver21 = age >= 21 ? "Is over 21" : "Is Under 21"

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#conditional_ternary_operator