ハイレベルなCTFにはまったく歯が立たないが、いざというときに使えるようリストアップしてみた。
シーザー暗号
よく出てくるシーザー暗号。
def _rot13(c):
if 'A' <= c and c <= 'Z':
return chr((ord(c) - ord('A') + 13) % 26 + ord('A'))
if 'a' <= c and c <= 'z':
return chr((ord(c) - ord('a') + 13) % 26 + ord('a'))
return c
def rot13(s):
g = (_rot13(c) for c in s)
return ''.join(g)
pycurl
curlをpythonから使えるようになると、パスワードリスト攻撃などを効率的にしやすくなる。(あ、もちろんCTFでの話ですよ・・・)
import pycurl
from io import BytesIO
buffer = BytesIO()
c = pycurl.Curl()
c.setopt(c.URL, 'http://ctfq.sweetduet.info:10080/~q32/auth.php')
c.setopt(c.WRITEDATA, buffer)
c.setopt(pycurl.POST, 1)
c.setopt(pycurl.HTTPPOST, [('password[1]', 'dummy'),('password[2]', 'dummy')])
c.perform()
c.close()
body = buffer.getvalue()
print(body.decode('iso-8859-1'))
nc
import socket
import time
def mysend(s, message):
time.sleep(0.1)
message = message + '\n'
s.send(message.encode())
time.sleep(0.1)
data = s.recv(1024).decode('utf-8').splitlines()[0]
print(data)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('example.com', 1234))
numpy
numpyは多次元配列などを扱いやすくするモジュールだが、matplotlibと組み合わせて、計算結果をざっと確認するのに便利。
import numpy as np
import matplotlib.pyplot as plt
arr2d = []
arr2d.append([1,0])
arr2d.append([0,1])
arr2dnp = np.asarray(arr2d)
plt.imshow(arr2dnp)
バイナリ、文字列
print(chr(int('0b01110100',0))) # t
crypt
最後にcrypt。ksnctfのJohnという問題はJohn the ripperというプログラムを使ってパスワードリストから総当たりするのが王道かもしれないが、Pythonのcryptで解くのもスマートな感じで気持ち良い。
import crypt
s = '''
user00:$6$Z4xEy/1KTCW.rz$Yxkc8XkscDusGWKan621H4eaPRjHc1bkXDjyFtcTtgxzlxvuPiE1rnqdQVO1lYgNOzg72FU95RQut93JF6Deo/:15491:0:99999:7:::
user01:$6$ffl1bXDBqKUiD$PoXP69PaxTTX.cgzYS6Tlj7UBvstr6JruGctoObFXCr4cYXjIbxBSMiQZiVkKvUxXUC23zP8PUyXjq6qEq63u1:15491:0:99999:7:::
user02:$6$ZsJXadT/rv$T/2gVzYwMBaAsZnHIjnUSmTozIF/ebMvtHIJjikFehvB8pvy28DUIQYbTJLG6QAxhzJAKOROnZq0xV4hUGefM1:15491:0:99999:7:::
'''
salt = []
hash = []
for line in s.splitlines():
m = line.split(":")
n = m[1].split("$")
hash.append(m[1])
salt.append(n[2])
password = []
for line in open('password_list.txt', 'r'):
password.append(line.strip())
for s in salt:
for p in password:
h = crypt.crypt(p, salt='$6$'+s+'$')
if h in hash:
print(p)
break