off_by_one_001 문제풀이
1. 취약점 확인
먼저 checksec 으로 취약점을 확인해보자
[*] '/home/gunp4ng/study/SF/off_by_one_001/off_by_one_001'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
Stripped: No
x86 아키텍처에 Partial RELRO 가 적용된 것을 확인할 수 있다
1. C 코드
#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 read_str(char *ptr, int size)
{
int len;
len = read(0, ptr, size);
printf("%d", len);
ptr[len] = '\0';
}
void get_shell()
{
system("/bin/sh");
}
int main()
{
char name[20];
int age = 1;
initialize();
printf("Name: ");
read_str(name, 20);
printf("Are you baby?");
if (age == 0)
{
get_shell();
}
else
{
printf("Ok, chance: \n");
read(0, name, 20);
}
return 0;
}
셸을 실행할 수 있는 get_shell() 함수가 존재한다
read_str 함수를 살펴보자
void read_str(char *ptr, int size)
{
int len;
len = read(0, ptr, size);
printf("%d", len);
ptr[len] = '\0';
}
입력받은 바이트 수를 출력하고 문자열의 맨 끝에 NULL byte 를 추가한다
main함수에서
char name[20];
이기 때문에 20바이트를 입력하면 20바이트 뒤에 NULL byte 가 추가된다
→ off-by-one 취약점이 존재한다
age 를 0으로 만들면 get_shell() 함수가 실행되는 코드이다
2. 어셈블리
main 함수의 어셈블리이다
Dump of assembler code for function main:
0x08048654 <+0>: push ebp
0x08048655 <+1>: mov ebp,esp
0x08048657 <+3>: sub esp,0x18
0x0804865a <+6>: mov DWORD PTR [ebp-0x4],0x1
0x08048661 <+13>: call 0x80485c2 <initialize>
0x08048666 <+18>: push 0x8048754
0x0804866b <+23>: call 0x8048420 <printf@plt>
0x08048670 <+28>: add esp,0x4
0x08048673 <+31>: push 0x14
0x08048675 <+33>: lea eax,[ebp-0x18]
0x08048678 <+36>: push eax
0x08048679 <+37>: call 0x8048609 <read_str>
0x0804867e <+42>: add esp,0x8
0x08048681 <+45>: push 0x804875b
0x08048686 <+50>: call 0x8048420 <printf@plt>
0x0804868b <+55>: add esp,0x4
0x0804868e <+58>: cmp DWORD PTR [ebp-0x4],0x0
0x08048692 <+62>: jne 0x804869b <main+71>
0x08048694 <+64>: call 0x8048641 <get_shell>
0x08048699 <+69>: jmp 0x80486b8 <main+100>
0x0804869b <+71>: push 0x8048769
0x080486a0 <+76>: call 0x8048450 <puts@plt>
0x080486a5 <+81>: add esp,0x4
0x080486a8 <+84>: push 0x14
0x080486aa <+86>: lea eax,[ebp-0x18]
0x080486ad <+89>: push eax
0x080486ae <+90>: push 0x0
0x080486b0 <+92>: call 0x8048410 <read@plt>
0x080486b5 <+97>: add esp,0xc
0x080486b8 <+100>: mov eax,0x0
0x080486bd <+105>: leave
0x080486be <+106>: ret
End of assembler dump.
name 은 ebp-0x18 에 있는 것을 알 수 있다
age 는 ebp-0x4 에 있다
2. 익스플로잇 구성
1. 익스플로잇
- 스택에서 name 문자열 다음 age 변수가 오게 된다
- name 에 20바이트를 입력하면 name 다음에 있는 age 의 1바이트가 NULL 값으로 조작된다
→ age 가 0이 되어 get_shell() 함수가 실행된다
아무 값이나 20바이트를 입력하면 플래그를 획득할 수 있다
'War Game > Pwnable' 카테고리의 다른 글
[Dreamhack] send_sig (0) | 2025.03.26 |
---|---|
[Dreamhack] off_by_one_000 (0) | 2025.03.18 |
[sschall] tutor_rop (0) | 2024.10.17 |
[sschall] pie (0) | 2024.10.15 |
[sschall] adult_canary (0) | 2024.10.03 |