OutDoorFrog의 리버싱 이야기

ShadowPad Shellcode 분석 일기 [수정중, 연구중] 본문

공부/악성코드

ShadowPad Shellcode 분석 일기 [수정중, 연구중]

OutDoorFrog 2018. 11. 5. 12:34

멘탈에 금가는 중인 개구리(OutDoorFrog)입니다.


멘탈붕괴에 대한 이미지 검색결과




프로젝트를 힘차게 진행해야할 시기가 다가옵니다.


개발 부분에서는 크로스 플랫폼 핵심 모듈 설계의 기술이란 도서를 보며 깨지는 중이고


보안 부분에서는 디컴파일을 하고도 기능을 못 유추할 것 같은 쉘코드를 보며 깨지는 중입니다.


오늘은 연구에 조금 진전이 있어서 이야기를 해드릴려고합니다.


썰을 풀어보겠습니다!!



0. DLLMain을 찾았습니다만..



대부분의 프로그램 Main 함수로부터 시작합니다.


악성코드 분석Main 함수를 찾는 것을 첫 번째 목표로 합니다.


베이스 캠프 아이콘에 대한 이미지 검색결과


나뭇잎 책의 말을 빌리자면 베이스 캠프를 설치한다고 보면 되겠네요.


윈도우 시스템 프로그래밍에 1년 반이라는 시간을 투자했던만큼

WinAPI 관련 소스 코드 해석할 때 좀 더 정확하고 빠르게 해석이 가능합니다.




DLL 파일이 프로세스에 로드된 후에는 DllMain 함수가 실행됩니다.


제가 분석 환경을 조금 바꿨는데 분석 속도가 확연히 달라지더군요.




분석 환경 변경 전 : Windows 7, 32bit, IDA Pro  (구버전..)

분석 환경 변경 후 : Windows 10, 64bit, IDA Pro (신버전..)




IDA에서 디컴파일 기능을 이용할 수 있게 되었습니다.



Hex-Ray사 제품만큼 좋은 성능을 발휘하는 디컴파일러,디스어셈블러는 거의 없죠!



짱짱 분석 도구로 편-안하게 분석을 진행해봅시다.




자동으로 DllMain을 찾아주는 기능을 통해 Main 함수를 찾았습니다.


   


DllMain, DllMainCRTStartup 함수가 보입니다.

DLL 파일을 분석할때 반드시 보이는 함수들이니 용인할 수 있습니다.


InternalDllMain,RawDllMain, RawDllMainProxy는 처음보는 함수입니다.



구글링으로 찾아봅시다..




참조할 수 있는 자료가 CFILE23님의 블로그, Msdn에 나와있더군요!


MSDN에서의 MFC DLL에 대한 질문과 대답



CFILE23님께서 작성하신 DLL 관련 설명 PDF파일입니다.


Visual C DLL - Visual Studio 2008.pdf


RawDllMainProxy 함수에 대한 그나마 쓸만한 정보는..


Chenxiao님의 블로그의 포스트에서 찾을 수 있었습니다.




설명에 따르면 DllMain 함수나 RawDllMain 함수가 기본 MFC DLL의 제공 함수이고


VS2008부터 RawDllMain 함수를 올바르게 호출하기 위해서 

RawDllMainProxy 함수를사용하는 것 같습니다.


InternalDllMain 함수는 IDA를 이용해서 따로 해석중입니다.


어쨌든.. 사용자가 직접만든 함수는 아니고 기본적으로 생성해야하는 함수들이였네요..


(트레이싱 없이 유추할 수 있는 정보가 현저히 적네요.)




IDA의 디컴파일 기능을 이용해서 슈도 코드를 봅시다.



처음 분석했을 때 멘탈이 몇 번 깨진 흔적이 보입니다.



형식 : BOOL DllMain( HINSTANCE hinstDLL, DWORD fdReason, LPVOID lpvReserved)




DLL 파일이 프로세스에 로드됬을 때


현재 실행의 흐름을 기준으로 AFX_MODULE_STATE 객체를 변수(module_state)에 담고


인스턴스 핸들을 변수에 담고, 모듈의 상태를 설정한 뒤에 1을 반환하네요.


DLL 파일이 프로세스에 로드된 경우가 아닐 때


InternalDllMain 함수에 인자값을 전달해서 다시 호출하네요.




Teddy's Room 님께서 AFX_MODULE_STATE 구조체에 대한 멤버변수 목록을 정리해주셨습니다!






디버깅할려면 DLL 로더를 만들어야 될 것 같습니다.



1. 바이너리 특정 부분을 XOR 연산하는 코드(암호화..? 복호화..?)



Import 함수를 이용해서 MessageBox 함수를 이용하는 부분을 조사했습니다.


바이너리 파일에서 특정 부분을 어떤 값과 XOR 연산해주는 부분이였는데...


암호화 루틴인지 복호화 루틴인지 구분하려면 디버깅해봐야 알듯 싶습니다.



VirtualAlloc(NULL, 64328, MEM_COMMIT, PAGE_EXECUTE_READWRITE);



2. 디버깅



일단 디버깅을 해야하니 DLL Loader를 만듭시다!




LoadLibrary 함수를 이용해서 로더를 만들어주고..






Runtime 환경을 구성을 안했으니, 런타임 라이브러리 부분을 MT로 바꿔줍니다.



바이너리 데이터가 변경됨으로 파일을 백업하고 해시값도 저장해줍시다.



MD5 : 97363d50a279492fda14cbab53429e75

SHA1 : f1a181d29b38dfe60d8ea487e8ed0ef30f064763





EP에 BP가 안 잡혀서 삽질을 했습니다!


LoadLibrary 함수의 동작 원리를 파악하고,


Ollydbg는 따로 DLL Loader 기능을 내장한 디버거였다는 것을 깨닫고,


어느 특정 소프트웨어에 의존성이 있는 악성코드도 있다는 것을 깨달았습니다.


결국 어느 한 분의 결정적인 도움 덕에 동적 분석을 시작할 수 있게 되었습니다.




 PEViwer를 이용해 IAT 테이블에서 참조해서 사용하는 DLL 목록을 파악합니다.



nsutil2.dll이면 netsarang 관련 DLL 파일로 알고 있습니다.


버전을 맞춰서 XSHELL5.7을 설치합니다.



그리고 VS C++ 2012 RUNTIME 환경도 구성해줍시다.


동적 분석 환경이 끝이나면...





EP에 BP를 설정할 수 있습니다.



3. 진짜 디버깅




GUI 분석 환경 멘탈 보존에 유리하니 IDA를 장전합시다.




DLLEntryPoint에서는 DLL이 프로세스에 로드되면 DLLCRTStartUP을 호출합니다.



CRTStartup 함수에서 DLLMain, 유사 함수들을 반복적으로 호출하는 양상을 보입니다.




DLLMain 함수 안으로 들어가봅시다.



이해 증진을 위해 슈도 코드를 봅시다.



dword_100284F8이 0이면 


InternalDllMain 함수를 호출하는군요.



프로세스에 Dll이 로드되었을 경우


AfxGetModuleState의 결과값을 저장,


인스턴스 핸들을 저장,


모듈의 상태를 설정하고 1을 반환



프로세스에 Dll이 언로드되었을 경우


아무 행동도 하지 않고 1을 반환합니다.



어떤 경우에도 속하지 않으면


InternalDllMain함수에 인자값을 전달합니다.



DLLMain 함수 안에서는 제가 따로 디버깅하면서 확인해보고 싶은 

What_Encryption_OR_Decryption 함수를 호출하지 않습니다.


아마 CRTStartUP 함수 DllMain 함수와 유사 DllMain 함수가 서로를 호출하며


반환값에 따라서 자신이 하는 일을 결정하는 구조인 듯 싶습니다.


일단 제가 원하는 부분부터 바로 확인해보겠습니다.



4. 이 함수는 암호화 함수일까, 복호화 함수일까??




이 함수의 역할이 무엇이지 확인해봅시다.





이해력 증진을 위해 슈도 코드 투입!



VirtuallAlloc 함수는 메모리 포인터를 반환해줍니다.



함수를 실행한 후 반환값 얻어서 Hex View으로 봅시다.




EAX에 001B0000라는 값이 저장이 되었군요.






*(Memory_ptr + i) = Xor한 값 (코드를 제 맘대로 줄였습니다.)


까지 실행시켰더니 어떤 데이터가 저장이 되었군요..


크기(0xFB48)가 맞을 때 까지 이 행위를 반복하는군요!!


행위 반복을 끝내고 Analyze 해봅시다!




특수한 값과 XOR 연산을 하기 전


(Hex View)




(Analyze Code, Code View)




암호화된 느낌이 강하게 드는 것 같습니다.


명령어의 조합부터 구성, 진행 형식까지 굉장히 특이합니다.




특수한 값과 XOR 연산을 한 후


(Hex View)




(Analyze Code, Code View)




프롤로그도 보이고, 명령어의 구성, 진행 방식이 익숙한 느낌이 듭니다.


복호화된 느낌이 강하게 드는 것 같습니다.



일단 복호화 함수라고 추측할 수 있겠군요.


고백 하나 해드리자면 저는 쉘코드를 만들어본 적이 없습니다!

(저 부분이 쉘코드인지는 확실히 모른다는 말입니다!)




음.. 악성코드 분석을 할 때 네이밍은 잘 해둬야합니다.


나중에 다시 되짚을 때 엄청 헷갈립니다.



쉘코드인지 불확실해서 Memory_ptr이라고 이름을 지어놨었는데


시간이 지나고 다시 보니 정말 헷갈리네요..


0을 인자로 0xFB44 크기의 어떤 함수를 호출합니다.


복호화 과정을 진행하는 것을 보아 저 함수가 쉘코드일 것 같습니다.


근데 안타깝게도 Host 컴퓨터에서 동적 분석을 하는 것이 아니라..


쉘코드는 올리디버거로 봐야됩니다. (핸드-레이)


음.. 잠시만요?? Windows 에서도 리모트 디버깅이 되나 확인해보겠습니다.













Comments