Samsett lokaverkefni
Nú tengjum við saman vinnulagið úr allri Ýmislegt-leiðinni. Verkefnið hefur sex lög:
villandi skráarending
↓
safnskrá
↓
mynd og lýsigögn
↓
faldar PNG-upplýsingar
↓
QR-kóði
↓
hávaðasamur texti og Base64
↓
fáni
Við fáum tilbúna skrá sem heitir:
gjof.jpg
Öll úttök sem þarf eru sýnd í kaflanum, svo hægt er að leysa verkefnið sem skriflega æfingu þótt einstök verkfæri séu ekki uppsett. Best er þó að skrifa skipanirnar í lausnadagbók eins og um raunverulega CTF-skrá væri að ræða.
Verkefnisgögnin eru ótraust inntak
Við keyrum engar útdregnar skrár, opnum engar afkóðaðar vefslóðir og drögum safnskrár aðeins út í tóma möppu. Dæmið er tilbúið og inniheldur engar persónuupplýsingar.
Reglur verkefnisins
- Fáninn er á sniðinu
gg{...}. - Við megum nota staðbundin verkfæri og Python.
- Við eigum að geta endurtekið hvert skref.
- Við eigum að útskýra af hverju næsta próf var valið.
- Handahófskennt „keyrði öll tól“ fær ekki fulla lausn.
Búum til vinnumöppu og varðveitum afrit:
mkdir -p lokaverkefni/{inntak,vinnu,nidurstodur}
cp gjof.jpg lokaverkefni/inntak/
cp gjof.jpg lokaverkefni/vinnu/gjof.jpg
cd lokaverkefni
Skráum kássu svo við getum athugað vinnuafritið síðar:
sha256sum inntak/gjof.jpg vinnu/gjof.jpg
Kássurnar eiga að vera eins áður en greining hefst.
Lag 1: skráin er ekki það sem nafnið segir
Fyrsta próf:
file vinnu/gjof.jpg
Úttak:
vinnu/gjof.jpg: Zip archive data, at least v2.0 to extract
Hex-skoðun staðfestir hausinn:
xxd -l 16 vinnu/gjof.jpg
00000000: 504b 0304 1400 0000 0800 2a51 2a5b .........*Q*[
50 4b 03 04 er algengt ZIP-auðkenni.
Æfing: næsta skref
Æfing 1
Hvað vitum við, hvað vitum við ekki og hvaða skipun er skynsamleg næst?
Lausn við æfingu 1
Við vitum:
- innihaldið lítur út eins og ZIP,
.jpg-endingin er villandi,fileog hausinn styðja sömu niðurstöðu.
Við vitum ekki:
- hvort safnið sé heilt,
- hvaða skrár eru inni,
- hvort slóðir eða stærðir séu öruggar,
- hvort safnið sé lykilorðsvarið.
Við skoðum skráalistann án útdráttar:
unzip -l vinnu/gjof.jpg
unzip -t vinnu/gjof.jpg
Við endurnefnum ekki endilega strax. Flest ZIP-tól lesa innihaldið þrátt fyrir endinguna, og núverandi heiti minnir okkur á blekkinguna.
Lag 2: skoðum safnið
unzip -l sýnir:
Archive: vinnu/gjof.jpg
Length Date Time Name
--------- ---------- ----- ----
118 2026-07-10 10:00 leidbeining.txt
18432 2026-07-10 10:00 mynd.png
--------- -------
18550 2 files
Listinn hefur:
- aðeins tvær litlar skrár,
- engar algildar slóðir,
- ekkert
.., - engin augljós stærðarmerki þjöppunarsprengju.
Við drögum út í nýja möppu:
mkdir -p vinnu/lag-02
unzip vinnu/gjof.jpg -d vinnu/lag-02
file vinnu/lag-02/*
leidbeining.txt segir:
Augun sjá myndina, en bláa rásin geymir síðasta orðið.
Lestu lýsinguna áður en þú leitar í bitum.
Æfing: þrjár tilgátur
Æfing 2
Skrifaðu þrjár afmarkaðar tilgátur sem textinn styður og raðaðu ódýrum prófum á þær.
Lausn við æfingu 2
Mögulegar tilgátur:
- „Lýsinguna“ vísar á lýsigagnareit, til dæmis
DescriptioneðaComment. - „Bláa rásin“ vísar á B-rás RGB-myndarinnar.
- „Síðasta orðið“ vísar á gildislægsta bita, LSB, frekar en síðasta sýnilega orð textaskrárinnar.
Ódýr röð prófa:
exiftool vinnu/lag-02/mynd.png
magick vinnu/lag-02/mynd.png -channel B -separate nidurstodur/bla.png
zsteg vinnu/lag-02/mynd.png
Lýsigögn eru ódýrasta prófið og textinn segir beinlínis að lesa lýsinguna áður en bitaleit hefst.
Lag 3: lýsigögnin velja nákvæma leið
exiftool sýnir:
File Type : PNG
Image Width : 512
Image Height : 512
Color Type : RGB
Description : b1,b,lsb,xy — úttakið er önnur PNG-mynd
Software : Synthetic CTF Builder
Við túlkum:
b1 eitt bitaplan
a? engin alfa-rás samkvæmt Color Type
b bláa rásin
lsb gildislægsti biti
xy lestrarröð eftir x og síðan y samkvæmt verkfærinu
Vísbendingin passar við zsteg-heiti. Við prófum markvisst:
zsteg vinnu/lag-02/mynd.png
Stytt úttak:
b1,b,lsb,xy .. file: PNG image data, 290 x 290, 8-bit grayscale
b2,r,msb,yx .. text: "q!A"
Æfing: veldu niðurstöðu
Æfing 3
Hvora zsteg-niðurstöðuna skoðum við fyrst og hvernig staðfestum við hana?
Lausn við æfingu 3
Við veljum:
b1,b,lsb,xy .. file: PNG image data
Hún passar nákvæmlega við:
Description-reitinn,- bláu rásina úr leiðbeiningunni,
- LSB-vísbendinguna,
- loforðið um að úttakið sé PNG.
Við drögum hana út:
zsteg -E 'b1,b,lsb,xy' vinnu/lag-02/mynd.png \
> nidurstodur/falin.png
file nidurstodur/falin.png
pngcheck -v nidurstodur/falin.png
Stutta textabrotið q!A hefur hvorki stuðning úr vísbendingum né sterkt skráarsnið og gæti verið tilviljun.
Lag 4: myndin er QR-kóði
file staðfestir gilda PNG-mynd. Þegar hún er opnuð sést QR-kóði, en við þurfum ekki að nota síma eða láta forrit opna innihaldið sjálfkrafa.
zbarimg --raw nidurstodur/falin.png \
> nidurstodur/qr.txt
qr.txt inniheldur:
# parts are shuffled
part=3/4 data=X2xvZ3
note=sort numerically; join only data
part=1/4 data=Z2d7Z2
part=4/4 data=VtfQ==
part=2/4 data=9nbl9p
Þetta er ekki vefslóð. Það er lítið sérsnið með fjórum hlutum og einni athugasemd.
Æfing: af hverju ekki einföld skeljaröð?
Æfing 4
Af hverju er sort qr.txt | cut -d= -f3 brothætt lausn? Hvaða atriði þarf þáttari að staðfesta?
Lausn við æfingu 4
Skipunin er brothætt vegna þess að:
- athugasemda- og
note-línur fylgja ekki gagnasniðinu, - venjuleg textaröðun bilar þegar hlutanúmer verða
10,11og svo framvegis, - Base64-gildi getur sjálft endað á
=, cut -f3gerir ráð fyrir nákvæmum fjölda=-tákna,- ekkert staðfestir að hlutar 1–4 séu allir til staðar eða aðeins einu sinni.
Þáttari ætti að staðfesta:
- alla gagnalínuna,
- númer hluta og heildarfjölda,
- að númer séu einkvæm,
- að nákvæmlega hlutar 1, 2, 3 og 4 séu til,
- leyfilegt stafasett gagnanna,
- að aðrar línur séu annaðhvort skilgreindar athugasemdir eða skráðar sem ógildar.
Lag 5: hreinsum og röðum með Python
Skrifum lítið forrit, leysa.py:
import base64
import re
from pathlib import Path
mynstur = re.compile(
r"^part=(?P<numer>[0-9]+)/(?P<heild>[0-9]+) "
r"data=(?P<data>[A-Za-z0-9+/=]+)$"
)
hlutar = {}
heild = None
hunsadar = []
for linunumer, lina in enumerate(
Path("nidurstodur/qr.txt").read_text(encoding="utf-8").splitlines(),
start=1,
):
if not lina or lina.startswith("#") or lina.startswith("note="):
hunsadar.append((linunumer, lina))
continue
m = mynstur.fullmatch(lina)
if not m:
raise ValueError(f"Ógild lína {linunumer}: {lina!r}")
numer = int(m.group("numer"))
ny_heild = int(m.group("heild"))
if heild is None:
heild = ny_heild
elif ny_heild != heild:
raise ValueError("Ósamræmdur heildarfjöldi")
if numer in hlutar:
raise ValueError(f"Tvítekinn hluti: {numer}")
hlutar[numer] = m.group("data")
if heild is None or heild < 1:
raise ValueError("Engir gagnahlutar fundust")
vaentanleg = set(range(1, heild + 1))
if set(hlutar) != vaentanleg:
raise ValueError(
f"Vantar eða fékk óvænta hluta: {set(hlutar) ^ vaentanleg}"
)
samsett = "".join(hlutar[numer] for numer in range(1, heild + 1))
try:
afkodad = base64.b64decode(samsett, validate=True)
except ValueError as villa:
raise ValueError("Ógilt Base64 eftir samsetningu") from villa
try:
texti = afkodad.decode("ascii")
except UnicodeDecodeError as villa:
raise ValueError("Afkóðuð gögn eru ekki ASCII") from villa
print("Raðað Base64:", samsett)
print("Hunsaðar línur:", hunsadar)
print("Niðurstaða:", texti)
Keyrum úr lokaverkefni/:
python3 leysa.py
Úttak:
Raðað Base64: Z2d7Z29nbl9pX2xvZ3VtfQ==
Hunsaðar línur: [(1, '# parts are shuffled'), (3, 'note=sort numerically; join only data')]
Niðurstaða: gg{gogn_i_logum}
Æfing: staðfestu fánann
Æfing 5
Hvaða athuganir styðja að gg{gogn_i_logum} sé lokaúttakið en ekki tilviljunarkenndur texti?
Lausn við æfingu 5
- QR-gögnin segja skýrt að raða hlutum tölulega og tengja aðeins
data. - Allir fjórir hlutar eru til nákvæmlega einu sinni.
- Samsetta runan er gilt Base64 með réttri fyllingu.
- Base64-afkóðunin er gildur ASCII-texti.
- Textinn passar nákvæmlega við skilgreint fánasnið
gg{...}. - Ferlið er endurtakanlegt frá QR-úttakinu með stuttu forriti.
Við staðfestum einnig handvirkt:
printf '%s' 'Z2d7Z29nbl9pX2xvZ3VtfQ==' | base64 -d
gg{gogn_i_logum}
Lausnadagbókin í heild
Stutt en endurtakanleg dagbók gæti verið:
| Skref | Athugun | Tilgáta | Prófun | Niðurstaða |
|---|---|---|---|---|
| 1 | .jpg, en file segir ZIP |
Ending er blekking | xxd -l 16 |
ZIP-haus staðfestur |
| 2 | Tvær litlar, eðlilegar slóðir | Öruggt að draga í tóma möppu | unzip -t, unzip -d |
Texti og PNG |
| 3 | Texti nefnir lýsingu, blátt og síðast | Lýsigögn velja LSB-rás | exiftool |
b1,b,lsb,xy |
| 4 | zsteg sér PNG í þeirri rás |
Falda skráin er næsta lag | zsteg -E, file, pngcheck |
Gild QR-mynd |
| 5 | QR inniheldur fjóra ruglaða hluta | Raða og tengja gögn | Staðfest Python-forrit | Gilt Base64 |
| 6 | Afkóðun passar fánasniði | Lokafáni fundinn | Sjálfstæð base64 -d prófun |
gg{gogn_i_logum} |
Þessi tafla sýnir rauða þráðinn. Hvert tól svarar spurningu sem fyrri athugun vakti.
Hvað hefði getað farið úrskeiðis?
Við treystum endingunni
Þá hefðum við reynt myndskoðara og talið skrána skemmda. file var ódýrara og nákvæmara fyrsta próf.
Við drógum safnið út án skoðunar
Þá hefðum við ekki vitað hvort það innihéldi hættulegar slóðir eða gríðarlegar skrár.
Við keyrðum zsteg -a og völdum fyrsta orðið
Þá hefði q!A getað sent okkur í kanínuholu. Lýsigögnin gáfu nákvæma rás.
Við skönnuðum QR með síma
Síminn hefði mögulega boðið að opna slóð eða framkvæma aðgerð. zbarimg --raw gaf okkur textann án sjálfvirkrar aðgerðar.
Við límdum línur með augunum
Þá hefðum við getað ruglað röð, tekið note með eða misst Base64-fyllingu. Forritið staðfesti uppbygginguna.
Við skrifuðum aðeins niður fánann
Þá væri ómögulegt að sjá hvort lausnin kom úr gögnunum eða ágiskun. Lausnadagbókin varðveitir röksemdakeðjuna.
Viðbótaræfingar
Þegar grunnlausnin er skýr getum við breytt afriti af gervigögnunum og athugað hvort lausnin hafni villum:
- Fjarlægja
part=3/4— forritið á að kvarta yfir vöntun. - Tvírita
part=2/4— forritið á að hafna tvítekningu. - Breyta einum Base64-staf í
!— reglulega segðin eða afkóðun á að hafna. - Breyta
3/4í3/5— heildarfjöldi á að verða ósamræmdur. - Setja
../ut.txtinn í tilbúinn ZIP-lista — útdráttur á að stöðvast fyrir skoðun.
Þetta eru ekki aðeins „neikvæð próf“. Þau sýna hvaða forsendur lausnin okkar verndar.
Samantekt
Í lokaverkefninu notuðum við:
sha256sumtil að auðkenna vinnuafrit,fileogxxdtil að finna raunverulegt skráarsnið,unzip -logunzip -tfyrir örugga safnskoðun,exiftooltil að finna markvissa vísbendingu,- rásir og gildislægsta bita til að finna falda PNG-mynd,
zbarimg --rawtil að afkóða QR án sjálfvirkrar aðgerðar,- reglulega segð og Python til að staðfesta, raða og tengja gögn,
- Base64-afkóðun og fánasnið til lokastaðfestingar,
- lausnadagbók til að tengja athuganir, tilgátur og prófanir.
Mikilvægasti lærdómurinn er ekki hvaða skipun fann fánann. Hann er að við gátum útskýrt af hverju við keyrðum hana, hvað úttakið sýndi og hvernig næsta skref fylgdi af því.
Í síðasta kaflanum veljum við vettvanga og verkefni til að æfa áfram án þess að týnast í endalausum verkfæralistum.