.

[Python] 나름대로 만들어본 PyV8를 이용한 악성스크립트 분석

by 담배맛구마

우연하게 PvV8로 자바스크립트 악성코드를 분석하는 글을 봤는데 재밋을것 같아서 샘플가지고 이것저것 해보며 만듬

PvV8로 자바스크립트 악성코드를 분석하는 글 : http://www.hanul93.com/kicomav-pyv8/

 

PyV8을 이용한 자바스크립트 악성코드 분석하기 - Kei Choi

1. 들어가며 악성코드를 분석하다보면 자바스크립트와 같은 텍스트 기반의 악성코드들은 백신을 만들기에 너무 까다로운 존재이다. 특히 난독화된 자바스크립트의 경우 분석도 쉽지 않고 이를 진단하는 백신을 만들기도 어렵기만하다. 유사한 형태로 다형성 바이러스가 존재한다. 매 감염때마다 형태가 바뀌고 분석하기도 까다롭고 백신의 시그너처를 선정하기도 힘들기만 했다. 결국 다형성 바이러스를 진단하기 위해 에뮬레이터를 백신에 탑재하는 방법을 선택하게 되었다. 자바스크립

www.hanul93.com

 

 

시작하기

PyV8 도큐먼트는 정말 찾기가 힘들었다. 답답해서 소스코드를 보려고 다운로드받았는데 거깄네; 근데 막상 그 도큐먼트 처음부터 끝까지 다봐도 써먹어야겠다는 영감이 안떠오른다.

Javascript 외에도 JScript, hta 까지 샘플 유형이 다양하다보니 그냥 도큐먼트보면서 모든 함수, 프로퍼티까지 정의하는게 정신건강에 이롭지 않을까 싶다.

구현하다보니 분석기능과 난독화를 푸는 기능이 분리되어야 한 것 같다.

  1. 분석 기능 : 악성코드가 필요로 하는 함수 및 프로퍼티들을 모두 정의한 클래스
  2. 난독화푸는기능 : 단순히 코드를 눈으로 보는게 아니라 분석을 하려면 난독화를 일부분 해제해야되는 경우가 많음 예를 들어, 난독화 푸는 기능에 다음과 같은 코드를 넣었다.
code = sub(r'<(/)*job( .+?)*>', '', code)
code = sub(r'<(/)*script( language=".+?")*>', '', code)
code = sub(r'(/\*@cc_on|/\*@|@\*/|@end)', '', code)

<job>, <script ...>, /*@cc_on  .... @*/ 구문은 V8이 해석을 못한다. 제거해줘야 분석이 가능하다.

 

 

결과물

# -*- coding: utf-8 -*-
import PyV8
from AnalyzeMalScript import Global as baseGlobal
from re import sub, search, compile, findall

class Global(baseGlobal):
    def eval(self, code):
        f = open('detox_result', 'w')
        f.write(code)
        f.close()
    @property
    def _win32(self):
        return True
    @property
    def _win64(self):
        return True

def Main(script_name, scope):
    with open(script_name, 'rb') as f:
        code = f.read()
    #Eliminate dummy code.
    code = sub(r'<(/)*job( .+?)*>', '', code)
    code = sub(r'<(/)*script( language=".+?")*>', '', code)
    code = sub(r'(/\*@cc_on|/\*@|@\*/|@end)', '', code)
    code = sub(r'@(if|elif|else|end)', r'\1', code)
    code = sub(r'@_(win32|win64)', r'_\1', code)
    code = sub(r';\r', r';', code)

    #Convert hex to string.
    reg_hex_string = compile(r'(\\x[0-9a-fA-F]{2})+')
    for hex_string in reg_hex_string.findall(code):
        code = code.replace(hex_string, hex_string.replace('\\x', '').decode('hex'))

    #Eliminate concatenated string code.
    #"aa" + "bb" => "aabb"
    reg_concat_string1 = compile(r'''("|')(.*)(\1)(\s)*\+(\s)*("|')(.*)(\6)''')
    while True:
        if reg_concat_string1.search(code):
            code = reg_concat_string1.sub(r'\1\2\7\1', code)
        else:
            break
    #"" + a => a
    reg_concat_string2 = compile(r'''("|'){2}(\s)*\+(\s)*(.*)''')
    while True:
        if reg_concat_string2.search(code):
            code = reg_concat_string2.sub(r'\4', code)
        else:
            break
    #a + "" => a
    reg_concat_string3 = compile(r'''(.*)(\s)*\+(\s)*("|'){2}''')
    while True:
        if reg_concat_string3.search(code):
            code = reg_concat_string3.sub(r'\1', code)
        else:
            break
    f = open('decompusedScript_', 'w')
    f.write(code)
    f.close()

    with PyV8.JSContext(scope) as ctx:
        ctx.eval(code)
        for obj in ctx.locals.__members__:
            print obj, ctx.locals.__getitem__(obj)
            code = sub(r'[^\w]' + obj + r'[^\w]', ctx.locals.__getitem__(obj), code)

if __name__ == "__main__" :
    js_scope = Global()
    script_name = 'dummy2.js_'
    Main(script_name, js_scope)
반응형

블로그의 정보

정윤상이다.

담배맛구마

활동하기