maybe_xor
感覺這道逆向題與其說是考逆向水平,倒不如說是考編寫指令碼的能力
首先題目給了個遠端地址,nc連線會回顯ELF:
接一串base64編碼的東東,解碼後發現是ELF檔案。
用IDA開啟發現是從資料段讀取24個位元組到棧上並進行異或,每個位元組異或的值都不同,但異或後的結果不會寫回棧
程式的目的是讓你算出異或後的位元組陣列併傳送過去,並且這個過程會重複多次
除錯可知,雖然每次檔案的資料不同,程式入口不同,但彙編程式碼都差不多。只是每次資料段的偏移和異或值有變化罷了,寫一個檔案處理指令碼即可
具體思路看下面指令碼註釋即可
from base64 import *
from pwn import *
import struct
# context.log_level = 'debug'
image_base = 0x8048000
def get_hex():
f = open('elf', 'rb')
f.seek(0x18)
# 獲取程式入口地址並轉為檔案偏移地址
EP = u64(f.read(8)) - image_base
# 獲取資料的偏移地址
f.seek(EP + 7)
rsi = struct.unpack("<i", f.read(4))[0] + EP + 11
# 讀取資料
f.seek(rsi)
data = f.read(24)
# 讀取機器碼
f.seek(EP + 4)
opcode = f.read(0x100)
i = 0
key = bytearray()
result = bytearray()
# 匯出異或陣列key
while i < 0xff:
# 判斷是不是真的xor指令
if opcode[i] == 0x34 and opcode[i+2] == 0x48:
key.append(opcode[i+1])
i = i + 2
continue
# 如果到達exit指令則退出
if(opcode[i] == 0xf) and (opcode[i+1] == 0x5):
break
i = i + 1
# 獲得結果
for i in range(24):
result.append((data[i] ^ key[i]) & 0xff)
f.close()
return bytes(result).hex()
# 獲取ELF檔案
def get_elf():
f = open("./elf","wb")
base = b64decode(io.recvline()[0:-1])
f.write(base)
f.close()
# 第一次結果程式已給出,將它給的結果傳送即可
io = remote("hnctf.imxbt.cn", 37580)
io.recvuntil("Expected bytes: ")
io.send(io.recvline())
# 迴圈處理
try:
while(io.recvuntil("ELF: ",timeout=3)):
get_elf()
io.sendline(get_hex().encode('utf-8'))
except(PwnlibException, EOFError):
io.interactive()
結果: