Netsamskipti og Pwntools
Til hamingju! Þú ert komin á lokaáfangann í Python vegvísnum okkar. Nú þegar við kunnum að vinna með tölur, bæti og skrár skulum við læra hvernig við látum forritin okkar eiga samskipti við umheiminn yfir netið, eða ræsa og stýra öðrum forritum á tölvunni okkar.
Í þessum kafla ætlum við að kynnast því hvað netsamskiptasökkull er og hvernig við notum iðnaðarstaðalinn pwntools til að leysa áskoranir á sjálfvirkan hátt.
Hvað er netsamskiptasökkull?
Þegar tvö forrit á ólíkum tölvum vilja tala saman yfir netið (t.d. vafrinn þinn við vefþjón), þá þurfa þau að stofna samskiptatengingu. Sú tenging er kölluð sökkull (e. socket).
- Samanburður: Hugsaðu um sökkul eins og símtal.
- Annar aðilinn (þjónninn eða server) bíður eftir að síminn hringi á ákveðnu númeri (sem við köllum tengi eða port).
- Hinn aðilinn (biðlarinn eða client, þ.e. þú) „hringir inn“ með því að gefa upp vistfang tölvunnar (IP-tölu) og tenginúmerið.
- Þegar þjónninn svarar er komin á tenging. Nú geta báðir aðilar sent og tekið á móti raddskilaboðum (bætum) jafnharðan þar til símtalinu er slitnað.
Í netöryggisáskorunum (CTF) og hagnýtu netöryggi mætum við mjög oft þrautum sem keyra á ákveðinni tengi á netþjóni. Við þurfum þá að tengjast henni, lesa leiðbeiningar, leysa verkefni og senda svarið til baka til að fá fánann.
Hvað er Pwntools?
Í stað þess að nota innbyggt netsafn Python (sem getur verið flókið og krafist mikils kóða), þá nota flestir bókasafnið pwntools. Þetta er sérhæft safn hannað af netöryggissérfræðingum til að gera sjálfvirkni og samskipti eins fljótleg og einföld og hægt er.
Þú setur pwntools upp á tölvunni þinni með því að keyra eftirfarandi skipun í skeljaglugganum þínum (ekki inni í Python REPL, heldur í venjulegu skelinni):
pip install pwntools
Tenging yfir netið: remote
Þegar við viljum stofna samskipti við netþjón notum við klasann remote(address, port) í pwntools.
Hér eru mikilvægustu föllin sem við notum til að stýra samskiptunum:
conn.recvline(): Les gögn frá netþjóninum þar til hún mætir nýrri línu (\n).conn.recvuntil(b"trigger"): Les gögn þar til tiltekin bætaruna kemur upp. Þetta er okkar helsta tól til að bíða eftir spurningum eða boðstöfum (t.d. bíða þar til þjónninn segir"Sláðu inn svar: ").conn.send(b"gogn"): Sendir hrá bæti til netþjónsins.conn.sendline(b"gogn"): Sendir bæti og bætir sjálfkrafa við nýrri línu (\n) aftan á gagnaflutninginn (eins og þú hafir ýtt á Enter).
Prófum að skrifa lítið dæmi:
from pwn import *
# Við tengjumst við fjarstýrðan netþjón á thraut.ggc.tf á tengi 9000
conn = remote("thraut.ggc.tf", 9000)
# Við bíðum þar til þjónninn spyr um nafn
conn.recvuntil(b"Hvad heitir thu? ")
# Sendum svarið okkar (ATH: verður að vera bytes, þess vegna b' fyrir framan!)
conn.sendline(b"Eyvor")
# Lesum svarið sem kemur til baka
svar = conn.recvline()
print("Svar frá þjóni:", svar.decode("utf-8"))
# Lokum símtalinu
conn.close()
Keyrsla á staðbundnu forriti: process
Hvað ef þrautin keyrir ekki á netinu, heldur er hún forrit (.bin eða .exe) á okkar eigin tölvu?
Einn stærsti kosturinn við pwntools er að þú notar nákvæmlega sömu föllin til að eiga samskipti við staðbundin forrit! Það eina sem breytist er hvernig við ræsum tenginguna. Í stað remote() notum við process():
from pwn import *
# Ræsum forritið "./vulnerable" á tölvunni okkar
p = process("./vulnerable")
# Við notum nákvæmlega sömu föll og áður!
p.recvuntil(b"Slegðu inn lykilorð: ")
p.sendline(b"leyndarmal123")
svar = p.recvline()
print(svar)
p.close()
Þetta gerir það að verkum að við getum þróað sjálfvirkniskriftuna okkar á staðbundnu forriti fyrst, og þegar hún virkar breytum við bara einni línu úr process í remote til að keyra hana gegn raunverulega netþjóninum!
Sýnidæmi: Að leysa stærðfræðiþraut sjálfvirkt
Skoðum hvernig við tengjum alla fimm kaflana okkar saman í eina glæsilega heild.
Ímyndum okkur að við séum með þraut á netþjóni sem krefst þess að við leysum 100 stærðfræðidæmi á undir 5 sekúndum. Það er ómögulegt fyrir mannveru að reikna og slá þetta inn svo hratt handvirkt. Við verðum að skrifa Python forrit sem leysir þetta sjálfvirkt!
Þjónninn sendir skilaboð sem líta svona út:
Reiknaðu: 45 + 12 = ?
Hér er Python forritið okkar sem leysir þetta:
from pwn import *
# 1. Tengjumst við þjóninn
conn = remote("reikna.ggc.tf", 8000)
# Keyrum lykkju 100 sinnum til að leysa öll dæmin
for i in range(100):
# 2. Lesum texta þar til dæmið byrjar
conn.recvuntil(b"Reiknadu: ")
# 3. Lesum jöfnuna sjálfa sem kemur í sömu línu (t.d. b"45 + 12 = ?\n")
jafna_baeti = conn.recvline()
# 4. Breytum bætum í lesanlegan streng
jafna_strengur = jafna_baeti.decode("utf-8")
# Við hreinsum " = ?" af endanum á strengnum
jafna_hrein = jafna_strengur.replace(" = ?", "").strip()
# Notum sneiðar eða skiptingu til að finna tölurnar tvær
hlutar = jafna_hrein.split(" + ")
tala_1 = int(hlutar[0])
tala_2 = int(hlutar[1])
# 5. Reiknum út svarið
svar = tala_1 + tala_2
print(f"Dæmi {i+1}: {tala_1} + {tala_2} = {svar}")
# 6. Sendum svarið aftur sem bætaskrifaðan streng til baka
conn.sendline(str(svar).encode("utf-8"))
# 7. Eftir að hafa leyst öll dæmin prentum við fánann sem þjónninn gefur okkur!
fani = conn.recvline()
print("FÁNINN OKKAR:", fani.decode("utf-8"))
# 8. Lokum tengingunni
conn.close()
Þetta forrit mun tengjast netþjóninum, lesa dæmin, leysa þau á innan við 0,2 sekúndum samtals, og skila okkur fánanum áreynslulaust! Þetta er styrkurinn og fegurðin við sjálfvirkni með Python.