[H&NCTF] maybe_xor題解

S1nyer發表於2024-05-14

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()

結果: