<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Deniz Ariyan's Blog]]></title><description><![CDATA[Deniz Ariyan's Blog]]></description><link>https://denizariyan.com</link><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 15:35:52 GMT</lastBuildDate><atom:link href="https://denizariyan.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Why are my builds so slow?]]></title><description><![CDATA[Intro
I write C++ code almost every day, be it for work or for fun (yes, we exist). While I have great tools for benchmarking runtime performance in my toolbox, I never really tried "benchmarking compile times".
With build times continuously creeping...]]></description><link>https://denizariyan.com/why-are-my-builds-so-slow</link><guid isPermaLink="true">https://denizariyan.com/why-are-my-builds-so-slow</guid><category><![CDATA[slow build]]></category><category><![CDATA[C++]]></category><category><![CDATA[cpp]]></category><category><![CDATA[build time]]></category><category><![CDATA[build]]></category><category><![CDATA[Clang]]></category><category><![CDATA[compiler]]></category><dc:creator><![CDATA[Deniz Ariyan]]></dc:creator><pubDate>Fri, 26 Dec 2025 01:14:29 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/FTKfX3xZIcc/upload/3fdb5cdc3109c53b3ce6cbc8befcf692.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-intro">Intro</h2>
<p>I write C++ code almost every day, be it for work or for fun (yes, we exist). While I have great tools for benchmarking runtime performance in my toolbox, I never really tried <em>"benchmarking compile times"</em>.</p>
<p>With build times continuously creeping up regardless of the build caches I throw at the problem, I wanted to understand what really takes so long to compile.</p>
<p>I don't intend to showcase specific problems, but rather show how one can analyze their own codebase to find the pain points.</p>
<h2 id="heading-how-do-we-do-this">How do we do this?</h2>
<p>The idea is to use the <code>-ftime-trace</code> compiler flag available in Clang to generate a JSON trace of the compilation process and then visualize it. Thanks to Aras Pranckevičius and Anton Afanasyev, this is part of <a target="_blank" href="https://github.com/llvm/llvm-project/commit/d880de2d19d46f7cfea7aa593602458440bc1e8d">Clang since version 9</a>.</p>
<p>You can use this with any build system that supports passing custom flags to the compiler. If you are using Bazel and building within the sandbox, have a look at this <a target="_blank" href="https://github.com/bazelbuild/bazel/issues/9047">Bazel issue</a> as you might need to jump through some hoops to get the trace file out of the sandbox. Enabling the <a target="_blank" href="https://github.com/bazelbuild/bazel/issues/9047#issuecomment-3691815154"><code>--sandbox_debug</code> option</a> is what I did.</p>
<h3 id="heading-example-program">Example program</h3>
<p>I will use a simple example program that uses <code>std::variant</code> and <code>std::visit</code> with multiple types to demonstrate what the generated trace looks like.</p>
<p>Don’t look too much into what the code is doing, it’s just an example of a variant with a couple types, not doing anything fancy or important.</p>
<pre><code class="lang-cpp"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;cstddef&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;string&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;variant&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;vector&gt;</span></span>

<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">Sizer</span>
{</span>
    <span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-keyword">size_t</span> <span class="hljs-title">operator</span><span class="hljs-params">()</span><span class="hljs-params">(<span class="hljs-keyword">int</span>)</span> <span class="hljs-keyword">const</span> </span>{ <span class="hljs-keyword">return</span> <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">int</span>); }
    <span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-keyword">size_t</span> <span class="hljs-title">operator</span><span class="hljs-params">()</span><span class="hljs-params">(<span class="hljs-keyword">double</span>)</span> <span class="hljs-keyword">const</span> </span>{ <span class="hljs-keyword">return</span> <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">double</span>); }
    <span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-keyword">size_t</span> <span class="hljs-title">operator</span><span class="hljs-params">()</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span> &amp;v)</span> <span class="hljs-keyword">const</span> </span>{ <span class="hljs-keyword">return</span> v.size(); }
    <span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-keyword">size_t</span> <span class="hljs-title">operator</span><span class="hljs-params">()</span><span class="hljs-params">(<span class="hljs-keyword">bool</span>)</span> <span class="hljs-keyword">const</span> </span>{ <span class="hljs-keyword">return</span> <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">bool</span>); }
    <span class="hljs-function"><span class="hljs-built_in">std</span>::<span class="hljs-keyword">size_t</span> <span class="hljs-title">operator</span><span class="hljs-params">()</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">int</span>&gt; &amp;v)</span> <span class="hljs-keyword">const</span> </span>{ <span class="hljs-keyword">return</span> v.size() * <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">int</span>); }
};

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>
</span>{
    <span class="hljs-keyword">using</span> Value = <span class="hljs-built_in">std</span>::variant&lt;<span class="hljs-keyword">int</span>, <span class="hljs-keyword">double</span>, <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span>, <span class="hljs-keyword">bool</span>, <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;<span class="hljs-keyword">int</span>&gt;&gt;;
    <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>&lt;Value&gt; values{<span class="hljs-number">42</span>, <span class="hljs-number">3.14</span>, <span class="hljs-built_in">std</span>::<span class="hljs-built_in">string</span>(<span class="hljs-string">"hello"</span>), <span class="hljs-literal">true</span>, <span class="hljs-built_in">std</span>::<span class="hljs-built_in">vector</span>{<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>}};

    <span class="hljs-built_in">std</span>::<span class="hljs-keyword">size_t</span> total{<span class="hljs-number">0</span>};
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> <span class="hljs-keyword">auto</span> &amp;v : values)
    {
        total += <span class="hljs-built_in">std</span>::visit(Sizer{}, v);
    }
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">static_cast</span>&lt;<span class="hljs-keyword">int</span>&gt;(total);
}
</code></pre>
<blockquote>
<p><a target="_blank" href="https://godbolt.org/z/Kq3bvjEYs">Compiler Explorer</a></p>
</blockquote>
<h3 id="heading-generating-the-trace">Generating the trace</h3>
<p>First, make sure you are using Clang as your compiler. Then, add the <code>-ftime-trace</code> flag to your compiler flags. By default, this will generate a json file named <code>&lt;name&gt;.json</code> just next to the object file.</p>
<h3 id="heading-visualizing-the-trace">Visualizing the trace</h3>
<p>Once you have the trace file, you can use either the <code>chrome://tracing</code> tool in a Chromium-based browser or the <a target="_blank" href="https://ui.perfetto.dev/">Perfetto UI</a> to visualize it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766708589140/2f4394fc-667f-4741-a67c-188b56324738.png" alt="A flame graph that illustrates various compiler stages. Color-coded segments display functions and tasks such as ParseFunctionDefinition and CodeGenPasses, indicating different execution phases in a vertical layout." class="image--center mx-auto" /></p>
<p>Flame graphs are great. Clicking one of the sections gives us information about what operation it is related to.</p>
<p>Unsurprisingly, given how simple our program is, a big portion of the time is spent parsing the included files.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766709406719/8034cc08-50ed-4339-a734-6aa004a58645.png" alt="Flame graph showing one of the largest sections which shows that it is related to included header file" class="image--center mx-auto" /></p>
<p>In a larger program, if you are seeing such expensive headers, it might be a good idea to check and see if the header in question can be split up or thinned down a bit into smaller headers that can be included as needed.</p>
<p>Tools like <a target="_blank" href="https://include-what-you-use.org/">Include What You Use</a> are also great to identify unnecessary includes across your codebase. Of course, in our example case, there is not much to improve on this side.</p>
<p>Going further in the timeline, we can also clearly see the time spent instantiating our variant and the vector of variants.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766710625829/56d167b4-d958-4866-a14c-dca7e77aac64.png" alt="Flame graph showing one of the variant instantiation section" class="image--center mx-auto" /></p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766710672482/78e46c03-ab27-46f3-a112-523f46d48700.png" alt="Flame graph showing one of the vector of variants instantiation section" class="image--center mx-auto" /></p>
<h2 id="heading-what-now">What now?</h2>
<p>Go ahead and try this out on your own codebase! If you are looking for more details, check out the Clang developer documentation on <a target="_blank" href="https://clang.llvm.org/docs/analyzer/developer-docs/PerformanceInvestigation.html">Performance Investigation</a> and the <a target="_blank" href="https://perfetto.dev/docs">Perfetto documentation</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Interrupt Based Timer for ATmega328P]]></title><description><![CDATA[Why use interrupt based timers?
There is two main approaches when it comes to delaying something in embedded systems. In most basic terms, busy waiting 
is the act of giving a long and unnecessary work to the CPU, so you can block it from processing ...]]></description><link>https://denizariyan.com/interrupt-based-timer-for-atmega328p</link><guid isPermaLink="true">https://denizariyan.com/interrupt-based-timer-for-atmega328p</guid><category><![CDATA[arduino]]></category><category><![CDATA[Micro Controllers]]></category><category><![CDATA[ATmega328P]]></category><category><![CDATA[timer]]></category><category><![CDATA[interrupt]]></category><dc:creator><![CDATA[Deniz Ariyan]]></dc:creator><pubDate>Sun, 05 Jun 2022 16:56:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/92vbv8ARIkk/upload/v1654448243286/_FA225ere.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-why-use-interrupt-based-timers">Why use interrupt based timers?</h2>
<p>There is two main approaches when it comes to delaying something in embedded systems. In most basic terms, busy waiting 
is the act of giving a long and unnecessary work to the CPU, so you can block it from processing the next operation. 
This is wasteful both in terms of CPU resources and power. In contrast, interrupt based waiting is the act of starting 
a timer which will wait on its own without blocking the CPU until the time comes. When the timer runs out; it will 
go ahead and interrupt the CPU and ask it to do whatever task that is assigned to that timer.</p>
<p>This project is an example of interrupt based waiting, but I will explain both options with examples.
Below you can see a chart which shows the difference of busy waiting and interrupt based waiting.</p>
<p>https://users.ece.utexas.edu/%7Evalvano/Volume1/E-Book/C12_Interrupts.htm</p>
<h3 id="heading-1-busy-waiting-the-blocking-selfish-way">1. Busy Waiting - <em>the blocking selfish way</em></h3>
<p>The selfish and the easy way of delaying something is just blocking the CPU with some unnecessary work,
usually by creating loops that accomplish nothing but look like they do to the compiler. If compiler
realises that your new shiny loop is not doing anything useful it will just throw it out in the 
optimization phase. You can always disable or change the optimization level, but I will just assume that 
you are using the default level of optimization.</p>
<p>An example to this can be; assigning or reading a value from a <strong><em>volatile</em></strong> variable over and over.
The below code will block the CPU for however long it takes for the CPU to process that operation for 100
times. </p>
<pre><code class="lang-c"><span class="hljs-comment">// Define a volatile variable</span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">define</span> SOMEVAR (*(volatile uint8_t *) (0x80))</span>

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">100</span>; ++i) { 
    <span class="hljs-comment">// Set a value to the volatile variable. </span>
    <span class="hljs-comment">// If this is not volatile, the compiler will run this only once and </span>
    <span class="hljs-comment">// optimize out the rest of it to save time and resources since it </span>
    <span class="hljs-comment">// basically does nothing. But because it  is volatile it has no way</span>
    <span class="hljs-comment">// to know if this value will be the same since declaring as volatile </span>
    <span class="hljs-comment">// means that this value can change any time by</span>
    <span class="hljs-comment">// a factor that is not known to the compiler.</span>
    SOMEVAR = <span class="hljs-number">0x00</span>;
}
</code></pre>
<p>If manually implemented this option requires the developer to perform some calculations in order to
understand how long this delay will take, or you can always do trial and error to guesstimate the time 
it takes and try to get it to a value close to what you are looking for but that's going to take some time
going back and forth and will require an oscilloscope to get it at least close to the value you looking for
(no, you can't use your phone's timer).</p>
<p>The <code>delay(ms)</code> function that all of us know from the Arduino lib is an example of busy waiting.</p>
<h3 id="heading-2-interrupt-based-waiting-non-blocking-way">2. Interrupt Based Waiting - <em>non blocking way</em></h3>
<p>Another and arguably the better way of waiting for something is using timers with interrupts to free the CPU 
from the waiting task. This works as in that when the timer is triggered it will go ahead and interrupt the
CPU from whatever it is doing and will ask it to do what it wants immediately. For more details about how 
interrupts work, visit the 
<a target="_blank" href="https://users.ece.utexas.edu/~valvano/Volume1/E-Book/C12_Interrupts.htm">website of University of Texas at Austin.</a></p>
<p>An example code snippet for an interrupt based timer using the 16-bit Timer 1 of ATmega328P can be found below.</p>
<pre><code class="lang-c">ISR (TIMER1_OVF_vect) {
    PORTB ^= (<span class="hljs-number">1</span> &lt;&lt; PORTB5); <span class="hljs-comment">// Toggle the 5th data register of PORTB</span>
    TCNT1 = <span class="hljs-number">64755</span>; <span class="hljs-comment">// 50 ms for 16MHz clock</span>
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-comment">// Set 5th data direction register of PORTB. A set value means output</span>
    DDRB = (<span class="hljs-number">1</span> &lt;&lt; DDB5);
    <span class="hljs-comment">// 50 ms for 16MHz clock</span>
    TCNT1 = <span class="hljs-number">64755</span>;
    <span class="hljs-comment">// Set normal counter mode</span>
    TCCR1A = <span class="hljs-number">0x00</span>;
    <span class="hljs-comment">// Set 1024 pre-scaler</span>
    TCCR1B = (<span class="hljs-number">1</span>&lt;&lt;CS10) | (<span class="hljs-number">1</span>&lt;&lt;CS12);
    <span class="hljs-comment">// Set overflow interrupt enable bit</span>
    TIMSK1 = (<span class="hljs-number">1</span> &lt;&lt; TOIE1); 
    sei(); <span class="hljs-comment">// Enable interrupts globally</span>
    <span class="hljs-keyword">while</span>(<span class="hljs-number">1</span>)
    {
        <span class="hljs-comment">// Do anything, this timer is non-blocking.</span>
        <span class="hljs-comment">// It will interrupt the CPU only when needed</span>
    }
    <span class="hljs-comment">// Add return so compilers don't cry about it being missing.</span>
    <span class="hljs-comment">// Under normal circumstances this will never be hit</span>
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>This creates a non-blocking interrupt based timer that will toggle the 5th data register of PORTB every 50ms.
But how do we calculate how long we need to wait? Unless we need to change the wait time in the runtime we should 
pre-compute the value for <code>TCNT1</code> which is in basic terms what determines the wait time.</p>
<h2 id="heading-calculate-the-wait-time">Calculate the wait time</h2>
<p>So how do we calculate the value we put on <code>TCNT1</code> according to the wait time we want.</p>
<h3 id="heading-1-divide-frequency-to-pre-scaler">1. Divide Frequency to pre-scaler</h3>
<p>Since we are using the Timer 1 of the ATmega328P and this timer is running on 16MHz we divide this value by our selected
pre-scaler of 1024.</p>
<p><code>Freq/Pre-scaler</code> =&gt; <code>16MHz/1024 = 15.625KHz</code></p>
<h3 id="heading-2-calculate-the-tick-time">2. Calculate the tick time</h3>
<p>Then we get the 1 over of this value to find our tick time. Which is 64 micro seconds.</p>
<p><code>1/15.625KHz = 64μs</code></p>
<h3 id="heading-3-get-delay-time">3. Get delay time</h3>
<p>Our clock is 16-bit therefore we need to subtract <code>t/64μs</code> from <code>2^16 = 65536</code> which will in turn give us the value 
we need to put in <code>TCNT1</code>. Where <code>t</code> is the time we want to wait in milliseconds.</p>
<p><code>TCNT1 = 2^16 - (t/64μs)</code></p>
<p>For example, if we want to have wait time of 100ms we would calculate it as;</p>
<p><code>TCNT1 = 2^16 - (100/0.064)</code> =&gt; <code>TCNT1 = 65536 - 1562</code> =&gt; <code>TCNT1 = 63974</code></p>
<h2 id="heading-example-output">Example output</h2>
<p>Below you can see an example output displayed on a simulated oscilloscope when the timer is set to have 
a delay of 1 second.</p>
<p><img src="https://raw.githubusercontent.com/denizariyan/ATmega328P-Interrupt-Based-Timer/master/images/output.png" alt="chart" /></p>
<h2 id="heading-source-code">Source code</h2>
<p>The full source code to compliment this post is available in <a target="_blank" href="https://github.com/denizariyan/ATmega328P-Interrupt-Based-Timer">my Github profile.</a> There you can find an example interrupt based timer that toggles a pin every 50ms by changing the data registers. Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.</p>
]]></content:encoded></item><item><title><![CDATA[Getting shell on TP-Link TD864W modem/router combo]]></title><description><![CDATA[Abstract
TP-Link TD864W is a modem/router combo that is widely used in Turkey mostly because it was given for free to every DSL subscriber by a major ISP in Turkey for years. Its software was modified for use by that particular ISP by TP-Link and is ...]]></description><link>https://denizariyan.com/getting-shell-on-tp-link-td864w-modemrouter-combo</link><guid isPermaLink="true">https://denizariyan.com/getting-shell-on-tp-link-td864w-modemrouter-combo</guid><category><![CDATA[router]]></category><category><![CDATA[hardware]]></category><category><![CDATA[uart]]></category><dc:creator><![CDATA[Deniz Ariyan]]></dc:creator><pubDate>Thu, 21 Jan 2021 17:54:32 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/hXVVNB6Qctg/upload/v1654458143005/iySZT3T-U.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-abstract">Abstract</h2>
<p>TP-Link TD864W is a modem/router combo that is widely used in Turkey mostly because it was given for free to every DSL subscriber by a major ISP in Turkey for years. Its software was modified for use by that particular ISP by TP-Link and is very limited on functionality especially when it comes to setting manual DNS and VPN settings. Today I am going to try to find a way into the shell of this modem/router combo firstly by correctly identifying the serial ports on the PCB, reverse engineering the pinouts with a basic multimeter, then connecting a USB UART so I can read the output and issue commands to the device from my computer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654451793017/PP32NQByp.jpg" alt="external.jpg" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 1. An external photo</em></p>
</blockquote>
<h2 id="heading-examining-the-board">Examining the board</h2>
<p>Unfortunately, this device has no FCC filing so we have to take a look ourselves. When we take the very annoying plastic cover off and take a look at internal photos of the device we can see a very convenient 4-pin port which looks very much like a UART port (Outlined in red below in Figure 2). We can also see some chips which might come in handy later such as RTL8676 outlined in yellow and FL128SAIF00 outlined in blue in Figure 2.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654451939817/13exndRMn.jpg" alt="pcb_big_marked.jpg" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 2. An internal photo of the device</em></p>
</blockquote>
<h2 id="heading-figuring-out-the-pinout">Figuring out the pinout</h2>
<p>Unfortunately, there is no standard for the UART pinouts therefore we will need to figure it out ourselves. There are different ways to identify the pinout of the port such as using a logic analyzer or a multimeter. Since I don't have a logic analyzer we will take the slower route and check every pin against R(ground), R(Vcc), and also watch their voltage range while the device is booting in order to identify their uses. But before we can do this we need a Ground and Vcc reference.</p>
<p>That's where the aforementioned RTL8676 and FL128SAIF00 chips come in handy. Since there is no way I'm gonna manage to freehand probe the pins on the RTL8676 (Outlined in yellow in Figure 2.) we are going to look for the <a target="_blank" href="https://www.cypress.com/file/196851">datasheet of FL128SAIF00</a> (Outlined in blue in Figure 2.). If we take a look at the datasheet of FL128SAIF00, we can see that the pin-2 is Vcc and pin-10 is GND. We are going to use these pins as our Vcc and GND reference respectively while probing for our UART pins.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654452233276/Fyvhw7cR0.jpg" alt="pcb_big_marked_pinout.jpg" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 3. Close-up of the pins</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654453610366/bwIMWWmRP.png" alt="pinout.png" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 4. Measurement results for the pins</em></p>
</blockquote>
<p>Now that the measurements are done we can see that pin-4 is Vcc since it has zero resistance against Vcc and has a stable 3V3 output, we can also see that pin-3 is Ground since it has no resistance against GND and is always on zero Volts. This leaves us the pin-1 and pin-2 in which we have to decide which is TX and RX. The easiest way to do this is just to connect our multimeter in voltage measurement mode and check each pin while the device is booting. As long as the UART is not disabled, there will be a lot of output on the TX pin which means it will fluctuate in value. In this case, the pin-2 is TX since its voltage fluctuates between 1V7 to 3V3 during boot.</p>
<p>The best way to confirm our findings is to connect a USB UART interface and create a serial connection between our computer and the device.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654453663606/nR2IJiMDA.jpg" alt="PCB_UART.jpg" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 5. USB UART interface connected to the pins</em></p>
</blockquote>
<h2 id="heading-connecting-to-the-device">Connecting to the device</h2>
<p>After a mediocre solder work, we can connect our USB UART interface to the pins that we have identified earlier. Using a serial monitor such as PuTTY we can connect to our device. One thing that we still don't know about the connection is the baud rate. The best way to find the baud rate of a device is to just analyze it with an oscilloscope. Well, I don't have an oscilloscope lying around in my home so we will once again take the slower route and just try some common baud rates starting from 115200 because from experience this is what most of the routers I have seen run on.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654453712841/2awkFDhVL.png" alt="Screenshot_15.png" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 6. Settings for PuTTY serial connection</em></p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654453736166/lnhBpjZk2.png" alt="Screenshot_1.png" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 7. Boot sequence output</em></p>
</blockquote>
<p>Thankfully we found the right baud rate on our first try, if you happen to be not as lucky as me you can check <a target="_blank" href="https://electronics.stackexchange.com/questions/9264">this question</a> on the electronics Stack Exchange to get a better idea around the topic. And look what the 4th line says. Let's reboot and spam ESC until we get to the boot console.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654453802974/M3KRP6WZo.png" alt="Screenshot_11.png" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 8. Entering the boot console</em></p>
</blockquote>
<p>Well, that was easy. Let's see what we can do here in Figure 9.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654453891208/iYm0WMGHg.png" alt="Screenshot_13.png" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 9. Boot console commands</em></p>
</blockquote>
<p>Let's try the bootline first it is probably going to ask us to input a string, lets see if it has a limit on how many chars can be put on maybe we can do some easy buffer overflow here.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654453944932/XVCO9LEvf.png" alt="Screenshot_14.png" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 10. Bootline and info commands</em></p>
</blockquote>
<p>Well, it has a set limit on the input so we are not going to get any easy buffer overflows here, we can later come back to this with edge cases if we need to. We also run the info command which displays some basic but very useful information about the device including our newly set bootline.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1654454293276/EljIpAAC3.png" alt="Screenshot_12.png" class="image--center mx-auto" /></p>
<blockquote>
<p><em>Figure 11. Displaying memory with d command</em></p>
</blockquote>
<p>The d command takes a memory address and length parameter then displays the memory region for that address in cleartext. We can easily use this to dump the memory of the device for further research. You can find a basic Python script I wrote which takes the PuTTY log output and clears anything but the memory data and gives you a clean memory dump so you can use it for further research or reverse-engineering on my Github within one week from the publication date.</p>
<p>The rest of the commands in the boot console seems self-explanatory. They even gave us a TFTP command which we can use to flash a new firmware to the device from another host.</p>
]]></content:encoded></item></channel></rss>