Decryptor to celebrate Lunar New Year (Present From Kimsuky?!?!)

며칠전에 요상하게 생긴 악성코드가 하나 잡혔다. 
https://www.virustotal.com/gui/file/e2487b33a6510d6f51b8aa158a36c6c290e885a66a9e30d54e3bb1fe0ea79777/detection

이전에 분석했던 베트남 상충제 관련건과 비슷하게 생긴거 같아 살펴보기 시작했다.

https://sfkino.tistory.com/76

 

이번파일은 악성코드내에 HWP 대신 PDF파일이 있고 악성 DLL파일을 드랍한 후 실행한다

리소스 영역에 존재하는 PDF 파일

어째뜬, VMWare와 x64dbg를 켜기 귀찮아 IDA로 둘러보았는데...

암호화된 문자열, 달라진 코드형태.

예전이랑 똑같이 생겼겠지 했는데.. 드롭퍼는 유사한데 추가 악성코드가 달라졌다. 
(분석은 귀찮으니 생략하고 C2만 공개하자 - (http://happy-new-year.esy](http://happy-new-year.esy/)[.]es) 

사용하는 F문U자C열K들이 모두 암호화 되어있다.  함수를 살펴보았다.

Decrypt 함수

짧다면 짧고 길다면 길다. 구간을 나누어 분석해보자


Part1. Get Key From String

do while 문을 통해 문자열 길이를 재고 32보다 작을경우 종료한다. .
32보다 클경우 앞의 32바이트를 가져와 16바이트 hex array로 변환한다. 이후 문자열 인덱스를 재설정해준다.

Part 1.

Part2.  Decrypt

디크립트 루틴은 두번의 XOR로 이뤄진다.
xor 1 : 이전 연산에서 사용했던 암호화된 값과 keytable의 값을 xor
xor 2 : 1에서 생성한 1byte 키와 암호화된 문자와 xor

Part 2.

저 길다란 문자열의 형태는 다음과 같은 구조로 되어있는것이다.

암호화 문자열 형태

손으로 한땀한땀 짜기 힘드니 IDA Script를 만들어주자. (IDA 7.4를 기준으로 제작되었다.)

getXref : 암호화 알고리즘 함수 주소를 입력하면 크로스레퍼런스된 곳의 주소를 리스트로 반환
FindEncodedStr : 참조하는곳의 주소를 가져와 함수 호출 전 lea rcx, offset 로 암호화된 문자열을 가져오는 곳을 찾아 주소와 암호화된 문자열을 딕셔너리 형태로 반환

#Find Decrypt Function Reference
def getXref(addr):
    xref = []
    for ref in CodeRefsTo(addr,1):
        xref.append(ref)
    
    return xref

#Find Encrypted String From Address
# Check lea and rcx
def FindEncodedStr(addrList):
    encodedStr = []

    for addr in addrList:
        while True:
            addr = idc.prev_head(addr)
            disasm = idc.GetDisasm(addr)
            print disasm
            if disasm[:3] == 'lea' and 'rcx' in disasm:
                break
        strAddr = idc.get_operand_value(addr,1)
        encStr = idc.get_strlit_contents(strAddr)
        encodedStr.append({'addr': addr,'encStr' : encStr})
    
    return encodedStr

makeKeyTable : 암호화된 문자열의 상위 32바이트를 16byte hex 리스트로 변환

#Make Key Table From Encrypted Data
#Split by 2bytes
def makeKeyTable(encStr):
    keyTable = []
    for x in range(0,32,2):
        keyTable.append(int(encStr[x:x+2],16))
return keyTable

setComments : 복호화된 문자열을 주석으로 달아주는 함수

def setComments(info,decStr):
    #Set Comment for Decompile (hexray) 
    cfunc = idaapi.decompile(info['addr'])
    tl = idaapi.treeloc_t()
    tl.ea = info['addr'] + 7
    tl.itp = idaapi.ITP_SEMI
    cfunc.set_user_cmt(tl, decStr)
    cfunc.save_user_cmts()

#Set Comment for Disasemble (IDA)
idaapi.set_cmt(info[‘addr’],decStr,None)

run : 복호화를 시작하는 함수

def run(addr):
    #Get Encrypted String Address From Function
    data = getXref(addr)
    
    #Get Encrypted String From Address
    encData = FindEncodedStr(data)

    for x in encData:
        
        if x['encStr'] == None:
            continue
        else:
            decStr = decrypt(x['encStr'])
            print ("{0} : {1} -> {2}".format(hex(x['addr']).rstrip("L"), x['encStr'], decStr))
        
        setComments(x,decStr)

Test

Before
Run
After

만족스럽다.

결과가 잘뽑히니 누군가에게 도움이 되길 바래보면서 스크립트를 공유한다.

https://github.com/saweol/decoderScript

Conclusion

악성코드는 백도어, 암호화된 문자열 사용, 분석하기 귀찮음, 해피뉴이어로 통신함. 앞으로 종종나올지 어떨지 모르겠지만.. 어차피 공격할거면 같은걸로 해줬으면 좋겠다.. 스크립트 잘 써먹게...

그럼.. 모두 설날 잘 보내시고 새해복 많이 받으세요!!!

 

IOC

FileName : PDF오성사 MC2-500 외형도 P1307033 Model_수정.pdf.exe
MD5 : DA799D16AED24CF4F8EC62D5048AFD1A
SHA1 : DE700699E8185497A82BB121FCC4CC6B470F1CE3
SHA256 : E2487B33A6510D6F51B8AA158A36C6C290E885A66A9E30D54E3BB1FE0EA79777

FileName : resource_PDF
MD5 : 5FDC8906A03FFD214E09816FDC58059A
SHA1 : C618645233B311E18E13322FFEBEC2677893DF50
SHA256 : F7E04D06690CC6C2FA699C70B9F95AC47E1393E0F6B5470BA2D85DFEF28AF996

FileName : resource_DLL (Main Malware)
MD5 : C315DE8AC15B51163A3BC075063A58AA
SHA1 : 6F715EB6815E9A44BF9A48D89C1B92F590F1FA1A
SHA256 : 6D870937675B98355747ECFDF4768B274191B4679DEDE4B93828D2EBD7198883

C2 : http://happy-new-year.esy](http://happy-new-year.esy/)[.]es

Article Link: https://sfkino.tistory.com/77