티스토리 뷰
며칠전에 요상하게 생긴 악성코드가 하나 잡혔다.
https://www.virustotal.com/gui/file/e2487b33a6510d6f51b8aa158a36c6c290e885a66a9e30d54e3bb1fe0ea79777/detection
이전에 분석했던 베트남 상충제 관련건과 비슷하게 생긴거 같아 살펴보기 시작했다.
이번파일은 악성코드내에 HWP 대신 PDF파일이 있고 악성 DLL파일을 드랍한 후 실행한다
어째뜬, VMWare와 x64dbg를 켜기 귀찮아 IDA로 둘러보았는데...
예전이랑 똑같이 생겼겠지 했는데.. 드롭퍼는 유사한데 추가 악성코드가 달라졌다.
(분석은 귀찮으니 생략하고 C2만 공개하자 - (http://happy-new-year.esy](http://happy-new-year.esy/)[.]es)
사용하는 F문U자C열K들이 모두 암호화 되어있다. 함수를 살펴보았다.
짧다면 짧고 길다면 길다. 구간을 나누어 분석해보자
Part1. Get Key From String
do while 문을 통해 문자열 길이를 재고 32보다 작을경우 종료한다. .
32보다 클경우 앞의 32바이트를 가져와 16바이트 hex array로 변환한다. 이후 문자열 인덱스를 재설정해준다.
Part2. Decrypt
디크립트 루틴은 두번의 XOR로 이뤄진다.
xor 1 : 이전 연산에서 사용했던 암호화된 값과 keytable의 값을 xor
xor 2 : 1에서 생성한 1byte 키와 암호화된 문자와 xor
저 길다란 문자열의 형태는 다음과 같은 구조로 되어있는것이다.
손으로 한땀한땀 짜기 힘드니 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
만족스럽다.
결과가 잘뽑히니 누군가에게 도움이 되길 바래보면서 스크립트를 공유한다.
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