Hoppa yfir í efnið

Strikamerki, QR-kóðar og textagreining

Ferningur úr svörtum og hvítum reitum getur geymt vefslóð, texta eða næstu vísbendingu. Röð af strikum getur falið tölur. Óskýr ljósmynd af miða getur orðið að leitanlegum texta með stafakennsl.

Í CTF-verkefnum eru þessi form oft aðeins eitt lag:

mynd → QR-kóði → vefslóðarkóðun → Base64 → fáni

Markmiðið er því ekki bara að „skanna kóðann“. Við þurfum að skoða afkóðuðu gögnin áður en við notum þau.

QR-kóði er ótraust inntak

Kóði getur innihaldið skaðlega vefslóð, greiðslubeiðni, Wi-Fi-stillingu eða texta sem forrit reynir að framkvæma. Afkóðaðu fyrst í texta. Ekki opna slóð eða samþykkja aðgerð sjálfkrafa.

Strikamerki og QR-kóðar

Strikamerki (e. barcode) geymir upplýsingar í mynstri sem vél getur lesið. Einvíð strikamerki nota yfirleitt breidd strika og bila eftir einni stefnu. Tvívíðir kóðar nota flöt og geta geymt meiri gögn.

QR-kóði (e. Quick Response code) er tvívíður kóði úr litlum einingum, oft svörtum og hvítum ferningum.

Auðþekkjanlegu stóru ferningarnir í þremur hornum hjálpa lesara að finna stefnu kóðans. Minni mynstur hjálpa með röðun, útgáfu og villuleiðréttingu.

Vissir þú?

QR-kóðinn var þróaður árið 1994 af Denso Wave til að rekja íhluti í japanskri bílaframleiðslu. Quick Response vísar til þess að kóðinn átti að vera fljótlesinn úr ólíkum áttum.

Byrjum á óbreyttri mynd

Við skoðum fyrst snið og stærð:

file kodi.png
magick identify kodi.png
exiftool kodi.png

Síðan reynum við staðbundinn lesara. zbarimg styður meðal annars QR og mörg einvíð strikamerki:

zbarimg kodi.png

Til að fá aðeins hráa nytjahlassið:

zbarimg --raw kodi.png

Mögulegt úttak:

https://ctf.example/next?data=%67%67%7Bqr_er_texti%7D

Við opnum ekki slóðina strax. Við vistum hana eða sendum í textagreiningu.

zbarimg --raw kodi.png > afkodad.txt
file afkodad.txt

Prófaðu einföldustu útgáfuna fyrst

Góður lesari sér oft um 90° snúning og villuleiðréttingu sjálfur. Ekki skerpa, þröskulda og spegla mynd sem lesst þegar óbreytt.

Æfing: hvað kemur næst?

Æfing 1

QR-lesari skilar:

https://example.invalid/login?user=nemandi&token=abc123

Hvert er öruggasta næsta skrefið?

  1. Opna slóðina í venjulegum vafra og skrá sig inn.
  2. Skoða textann og þáttun slóðarinnar án nettengingar.
  3. Keyra textann sem skeljaskipun.
Lausn við æfingu 1

Svar 2 er öruggast. Við getum greint slóðina sem gögn:

from urllib.parse import parse_qs, urlparse

slod = "https://example.invalid/login?user=nemandi&token=abc123"
hlutar = urlparse(slod)

print(hlutar.scheme)       # https
print(hlutar.hostname)     # example.invalid
print(hlutar.path)         # /login
print(parse_qs(hlutar.query))

Lénið .invalid er frátekið fyrir dæmi og á ekki að virka. Hvorki innskráning né keyrsla í skel er nauðsynleg til að lesa nytjahlassið.

Afkóðum vefslóðarkóðun án þess að heimsækja slóð

Prósentur í slóð geta táknað bæti. Python getur afkóðað þær:

from urllib.parse import unquote

texti = "%67%67%7Bqr_er_texti%7D"
print(unquote(texti))

Úttak:

gg{qr_er_texti}

Við greindum aðeins textann. Engin vefbeiðni var send.

Kóðinn gæti líka skilað:

  • WIFI:T:WPA;S:... fyrir Wi-Fi-stillingu,
  • BEGIN:VCARD fyrir tengilið,
  • otpauth://... fyrir auðkennislykil,
  • mailto: eða tel: fyrir aðgerð,
  • Base64, hex eða JSON,
  • annarri mynd eða skrá.

Þessi forskeyti segja forriti hvað það gæti gert. Við meðhöndlum allt fyrst sem texta.

Þegar QR-kóðinn lesst ekki

Algengar ástæður:

  • kóðinn er of lítill eða óskýr,
  • hann er skorinn við brún,
  • hvíta jaðarsvæðið vantar,
  • birtuskil eru lítil,
  • myndin er spegluð,
  • sjónarhornið skekkir ferninginn,
  • hluti kóðans er skemmdur,
  • myndin var vistuð sem tapsþjappað JPEG.

Við búum til afleidd afrit og breytum einu atriði í einu.

Stækkum án mýkingar

QR-kóði samanstendur af skörpum einingum. Næsti nágranni heldur köntunum:

magick kodi.png -filter point -resize 400% nidurstodur/kodi-stor.png

Bætum við hvítum jaðri

Hvíta svæðið utan um kóða kallast kyrrt svæði (e. quiet zone). Lesari þarf það til að aðgreina kóðann frá bakgrunni.

magick kodi.png -bordercolor white -border 40 nidurstodur/kodi-jadar.png

Snúum og speglum

magick kodi.png -rotate 90 nidurstodur/kodi-90.png
magick kodi.png -flop nidurstodur/kodi-spegill.png
magick kodi.png -flip nidurstodur/kodi-lodrett.png

-flop speglar lárétt en -flip lóðrétt.

Grátónar og þröskuldur

magick kodi.png \
  -colorspace Gray \
  -threshold 55% \
  nidurstodur/kodi-svart-hvitt.png

Þröskuldurinn getur hjálpað þegar bakgrunnur er ójafn, en rangt gildi getur eytt einingum. Við prófum fá gildi kerfisbundið og berum saman.

Skerum kóðann úr stærri mynd

magick mynd.png -crop 600x600+120+80 +repage nidurstodur/kodi-skordur.png

Merkingin er:

breidd x hæð + x-hliðrun + y-hliðrun
600     600     120           80

Við skiljum eftir smá hvítan jaðar ef mögulegt er.

Ekki vista vinnuafritið sem JPEG

JPEG getur búið til óskýra kanta og litlar sveiflur við hverja einingu. PNG er betra vinnusnið fyrir svarta og hvíta kóða.

Æfing: röð umbreytinga

Æfing 2

QR-kóði er aðeins 80×80 dílar, snýr á hlið og snertir brún myndarinnar. Hvaða þrjár einfaldar aðgerðir eru skynsamlegar áður en við reynum flókna viðgerð?

Lausn við æfingu 2

Skynsamleg röð er:

  1. snúa myndinni um 90°,
  2. stækka með -filter point,
  3. bæta við hvítum jaðri.

Til dæmis:

magick kodi.png \
  -rotate 90 \
  -filter point -resize 400% \
  -bordercolor white -border 40 \
  nidurstodur/kodi-lagadur.png

zbarimg --raw nidurstodur/kodi-lagadur.png

Við gætum prófað lesara eftir hvert skref. Þá vitum við hvaða breyting var nauðsynleg.

Villuleiðrétting er ekki töfrar

QR-kóðar geyma umframupplýsingar svo lesari geti endurheimt gögn þótt hluti kóðans sé skemmdur. Stigin eru L, M, Q og H. Þeim er oft lýst þannig að hægt sé að endurheimta um 7%, 15%, 25% og 30% skemmdra kóðaorða (e. codewords), en raunhæf geta fer eftir staðsetningu og eðli skemmdarinnar.

Skemmdir á staðsetningarferningum, sniði eða stórum samfelldum hluta geta verið verri en dreifðir blettir. Við megum því ekki álykta að „30% af myndfletinum megi vanta“.

Í CTF getum við stundum:

  • endurgert augljóst staðsetningarmynstur,
  • sameinað tvo kóða sem skemmast á ólíkum stöðum,
  • rétt sjónarhorn,
  • nýtt villuleiðréttingu eftir að jaðar og einingastærð eru rétt.

Við gerum breytingar á afriti og skráum nákvæmlega hvað var teiknað eða afritað.

Einvíð strikamerki

Algeng snið eru meðal annars:

  • EAN-13 á vörum,
  • Code 128 fyrir fjölbreyttan texta,
  • Code 39 fyrir einfalt stafasett,
  • UPC-A.

zbarimg getur greint mörg þeirra:

zbarimg strikamerki.png

Einvítt strikamerki þarf oft:

  • nægilega lárétta upplausn,
  • skýra kanta,
  • autt svæði við báða enda,
  • rétta stefnu,
  • öll strikin óskorin.

Vartala í EAN-13

Síðasti tölustafur EAN-13 er vartala (e. check digit). Hún greinir margar algengar innsláttar- og lesvillur en er ekki dulritunarvörn.

Fyrir fyrstu tólf tölurnar:

5 9 0 1 2 3 4 1 2 3 4 5

leggjum við saman tölur í oddasætum og þrefalt summu talna í jafnsætum, talið frá vinstri:

oddasæti: 5 + 0 + 2 + 4 + 2 + 4 = 17
jafnsæti: 9 + 1 + 3 + 1 + 3 + 5 = 22
summa: 17 + 3×22 = 83

Vartalan fyllir upp í næsta tug:

(10 - (83 mod 10)) mod 10 = 7

Heili kóðinn er því:

5901234123457

Æfing: staðfestu vartölu

Æfing 3

OCR les EAN-kóða sem:

5901234123451

Samræmist síðasti tölustafurinn vartölunni sem við reiknuðum?

Lausn við æfingu 3

Nei. Fyrstu tólf tölurnar 590123412345 gefa vartöluna 7, ekki 1.

Þetta bendir til OCR- eða lesvillu. Við skoðum myndina aftur og prófum strikamerkjalesara. Réttur kóði samkvæmt útreikningnum er:

5901234123457

Vartalan segir ekki hvaða af fyrri tölunum væri röng ef fleiri villur eru til staðar; hún segir aðeins að runan stenst ekki þessa athugun.

Ljóskennsl stafa

Ljóskennsl stafa (e. optical character recognition, OCR) breytir mynd af texta í stafi sem við getum leitað í og unnið með.

Tesseract er opið OCR-tól:

tesseract texti.png stdout

Fyrir eina textalínu getur síðuskipanarhamur 7 hentað:

tesseract texti.png stdout --psm 7

Fyrir þéttan textablokk er hamur 6 algeng byrjun:

tesseract texti.png stdout --psm 6

Tungumál eru valin með -l ef viðeigandi tungumálagögn eru uppsett:

tesseract texti.png stdout -l isl+eng --psm 6

Undirbúum mynd fyrir OCR

magick texti.jpg \
  -colorspace Gray \
  -resize 300% \
  -contrast-stretch 1%x1% \
  nidurstodur/texti-skyr.png

Við gætum einnig prófað þröskuld eða skorið textasvæðið úr. Aftur breytum við einu í einu og berum úttakið saman við myndina.

Algengar ruglingar

OCR ruglar meðal annars:

Mynd Mögulegir stafir
0 núll eða O
1 einn, I eða l
5 fimm eða S
8 átta eða B
{ slaufusvigi eða (
_ undirstrik eða eyða

Fánasnið og annað samhengi hjálpar okkur að staðfesta, en við eigum ekki að „leiðrétta“ allt sem passar ekki fyrirfram ákveðinni hugmynd.

Æfing: OCR-frambjóðendur

Æfing 4

OCR skilar:

gg(0CR_l3s_ekkl_a11t}

Myndin virðist hins vegar hafa slaufusviga eftir gg, og tveir óskýrir stafir gætu verið I, l eða 1.

Hvernig staðfestum við fánann án þess að giska blint?

Lausn við æfingu 4
  1. Skerum hvert óskýrt svæði út og stækkum með skörpum köntum.
  2. Berum saman lögun sömu stafa annars staðar í myndinni.
  3. Prófum annan OCR-ham og mögulega isl+eng tungumálagögn.
  4. Athugum fánasniðið: upphafið ætti líklega að vera gg{, svo ( er líkleg lesvilla.
  5. Skráum möguleikana fyrir óskýru stafina í stað þess að skipta þeim strax út.

Mjög líklegur texti gæti verið:

gg{OCR_les_ekki_allt}

En við skila aðeins þeirri útgáfu þegar sjónræn skoðun styður O á móti 0, l á móti 1 og lokasvigann. Fánasniðið er staðfesting, ekki heimild til að finna upp stafi.

Mörg lög af kóðum

Afkóðað nytjahlass getur sjálft verið kóðað:

QR → `R0d7a29kaSBvZyB0ZXh0aX0=` → Base64 → texti

Eða QR-kóði getur innihaldið slóð á mynd með öðru strikamerki. Við spyrjum eftir hvert lag:

file nidurstada
wc -c nidurstada
head -c 100 nidurstada

Fyrir texta skoðum við:

  • stafasett,
  • þekkt forskeyti,
  • vefslóðarkóðun,
  • Base64 eða hex,
  • JSON eða XML,
  • hvort textinn sé í raun skráarauðkenni í kóðuðu formi.

Eitt lag, ein staðfesting

Skráðu QR → slóðarafkóðun → Base64 → PNG í stað þess að skrifa bara „notaði CyberChef“. Þá má endurtaka lausnina og sjá hvar röng forsenda gæti hafa komið inn.

Búum til skaðlaust æfingadæmi

qrencode getur búið til QR-mynd úr texta:

qrencode -o aetfing.png 'gg{eg_bjo_til_qr}'
zbarimg --raw aetfing.png

Við getum síðan búið til skemmt afrit, til dæmis snúið og minnkað, en höldum upprunalega kóðanum svo hægt sé að bera saman:

magick aetfing.png -rotate 90 -resize 25% aetfing-skemmd.png

Þetta er örugg leið til að æfa verkfæri án þess að skanna ókunnan kóða af götu eða senda mynd í vefþjónustu.

Persónuvernd og OCR-þjónustur

Skýjaþjónusta fyrir OCR eða QR sendir myndina til annars aðila. Myndin gæti innihaldið:

  • nöfn,
  • heimilisföng,
  • skjöl í bakgrunni,
  • staðsetningarlýsigögn,
  • aðgangslykla í kóðum.

Við notum staðbundin tól fyrir viðkvæm gögn og aðeins tilbúnar CTF-myndir í utanaðkomandi þjónustum.

Lokaverkefni: miðinn á veggnum

Æfing 5

Verkefnið gefur ljósmyndina veggur.jpg. Hún sýnir lítinn, speglaðan QR-kóða og óskýra handskrifaða línu fyrir neðan.

Eftir QR-afkóðun fæst:

data=%52%30%64%37%61%32%39%6b%61%53%42%76%5a%79%42%30%5a%58%68%30%61%58%30%3D

Skrifaðu skipulega leið frá mynd að lokaúttaki og nefndu öryggisathuganir.

Möguleg lausn við æfingu 5
  1. Halda óbreyttu afriti af veggur.jpg og búa til nidurstodur/.
  2. Skera QR-svæðið út með smá jaðri.
  3. Spegla afritið með -flop, stækka með -filter point og bæta við hvítum jaðri ef þarf.
  4. Afkóða í texta, ekki sjálfvirka aðgerð:
zbarimg --raw nidurstodur/qr-lagadur.png > nidurstodur/qr.txt
  1. Þáttum data= og afkóðum prósenturnar án netbeiðni:
from urllib.parse import parse_qs, unquote

texti = open("nidurstodur/qr.txt").read().strip()
gildi = parse_qs(texti)["data"][0]
print(unquote(gildi))

parse_qs afkóðar prósenturnar sjálft, svo niðurstaðan verður Base64-lík runa.

  1. Afkóða Base64 og skoða textann:
printf '%s' 'R0d7a29kaSBvZyB0ZXh0aX0=' | base64 -d

Niðurstaðan er:

GG{kodi og texti}
  1. OCR-greina handskrifuðu línuna sérstaklega, en staðfesta hana sjónrænt. Hún gæti sagt hvort breyta eigi hástöfum, eyðum eða svigum í fánasniðið.
  2. Ekki opna slóðir, keyra afkóðaðan texta eða hlaða ljósmyndinni í skýjaþjónustu án heimildar.

Athugum að úttakið er ekki enn á venjulega gg{...} sniðinu. Ef handskrifaða línan segir „allt með lágstöfum, bil verða undirstrik“ verður lokafáninn:

gg{kodi_og_texti}

Við gerum þessa breytingu aðeins ef vísbendingin segir það.

Samantekt

Í þessum kafla lærðum við að:

  • strikamerki og QR-kóðar eru gagnasnið, ekki sjálfkrafa öruggar aðgerðir,
  • zbarimg --raw afkóðar í texta án þess að opna slóð,
  • við getum stækkað, snúið, speglað, þröskuldað og skorið kóða á afritum,
  • hvítur jaðar og skarpir einingakantar skipta lesara máli,
  • QR-villuleiðrétting þolir sumar skemmdir en ekki hvaða 30% myndarinnar sem er,
  • vartala strikamerkis greinir villur en sannar ekki uppruna eða heilleika,
  • OCR breytir mynd í textaframbjóðanda sem þarf sjónræna staðfestingu,
  • afkóðað nytjahlass getur verið vefslóð, Base64, JSON eða annað lag,
  • við skoðum afkóðaðar slóðir án þess að heimsækja þær,
  • við sendum ekki viðkvæmar myndir í utanaðkomandi OCR- eða QR-þjónustur.

Í næsta kafla skoðum við Unicode, stafi sem líta eins út, núllbreiddarstafi, stefnustýringu og skilaboð sem fela sig í bilum.