0. 개요

.... 0.1 개념

1. 분석

.... 1.1 간단한 크랙미 분석

.... 1.2 악성코드 분석

2. 추가적인 문제와 해결 방안

.... 2.1 함수 호출 규약

.... 2.2 객체 지향적이다.

.... 2.3 다른 Unit을 임포트할 경우





0. 개요

  델파이로 만들어진 바이너리를 분석하기 위해서는 알아야 할 것들과 필요한 것들이 많다. 간단한 크랙미의 경우라면 인터넷의 자료들을 보면서 손쉽게 처리할 수 있겠지만 진지하게 만들어진 악성코드의 경우라면 사람이 할 짓이 못 된다는 것을 느낄 수도 있기 때문이다.


  개인적으로 델파이 개발 경험은 예제를 그대로 따라 써가면서 만들어 본 몇 개가 전부이기 때문에 언어적인 개념 및 더 깊은 내용을 다룰 수는 없다. 하지만 이미 관심이 생겼으므로 꾸준히 공부해 나가면서 이곳에도 배우고 정리한 내용을 계속 추가할 예정이다. 그러므로 아직까지는 분석에 필요한 부분들 위주로 정리하겠다.


  기본적으로 델파이는 Visual Basic과 비슷한 언어로 보인다. GUI 형태의 프로그램을 간단하게 제작할 수 있는 방식에서 그렇게 보인다는 말이다. 물론 오래된 언어이며 매니아들도 많아서인지 편리성 외에도 시스템적인 내용까지 다룰 수 있으며 성능 같은 면에서도 괜찮다고 한다.


  문제는 이러한 형태의 언어들이 그렇듯이 객체 지향적인 언어이며 이러한 개념을 매우 많이 사용할 것이라는 점이다. 또한 그래픽 처리와 관련된 수 많은 루틴들 덕분에 크기도 커지게 된다. 객체 지향적이라는 것은 콜백 함수도 많고 객체 (단순히 구조체 수준의 난이도가 아니다) 생성 및 해제도 많으며 함수 호출 시에 인자로 객체가 들어가게 될 것이며 가상 함수라는 개념이 많이 사용될 것이다.


  물론 꼭 GUI 형태가 아니라 콘솔 애플리케이션 형태로도 제작할 수 있는데 이 경우에는 조금 더 간단해지기는 한다. 하지만 델파이는 Visual Basic과는 달리 MS에서 제공해주는 DLL이 없다. 즉 VB는 MS에서 만들었기 때문에 vbvm60.dll 같은 VB 만의 DLL이 운영체제에서 제공되어 (최신 버전은 모르겠지만) 언어만의 기능을 가져다 쓸 수 있다. 하지만 델파이의 경우 저러한 런타임 라이브러리와 같이 배포하지 않는 이상 즉 독립적인 실행 파일로 제공하기 위해서는 델파이의 언어적인 기능을 직접 바이너리에 정적으로 링크해야 하므로 용량이 매우 크다. 예를들어 WriteLN()이라는 printf()와 비슷한 역할을 하는 함수도 간단하게 DLL에서 임포트하는 것이 아닌, 직접 구현해야 한다는 것이다. 물론 kernel32.dll 같은 기본 DLL들은 임포트할 것이기 때문에 아주 마지막에는 윈도우의 API 함수를 사용할 것이다.


  결론적으로 델파이 바이너리를 디버거로 켜는 순간 뭐부터 시작해야 할지를 모르는 상황이 온다. 그러므로 여기에서는 차례차례 쉬운 것부터 방식에 대해서 정리하기로 한다.



0.1 개념

  이것은 나중에 공부해가면서 추가해야 하지만 그래도 간단하게 배운 내용을 적어보기로 한다. 스텁의 처음 부분을 보면 @Sysinit@@InitExe을 호출하는데 인자 즉 EAX에는 배열이 들어간다. 델파이는 객체 지향 언어이기 때문에 사용할 라이브러리들을 초기화할 필요가 있다. 배열에는 각 라이브러리 init이 있으며 클래스의 Init 함수를 호출하여 Sub 함수들에 대한 포인터를 저장한다. 즉 사용할 것들에 대한 초기화가 진행되는 것이다.





1. 분석

1.1 간단한 크랙미 분석

  먼저 간단한 크랙미 문제라고 가정해 보겠다. 사실 이렇게 간단한 것은 필요한 루틴이 어딘지만 파악한 후에 그 부분만 분석하면 되므로 분석보다는 그 루틴을 찾는 것이 중요하다. 예를들어 시리얼을 입력받아 일치 여부를 확인하는 크랙미가 있다고 하자.


  여기서 중요한 것은 GUI를 초기화하고 메시지 루프를 돌면서 이벤트를 받는 등의 과정이 아니다. 우리는 버튼을 누르는 이벤트가 발생했을 때 수행되는 루틴을 찾아서 거기에서 시리얼 번호를 비교하는 부분이 있다면 그 부분만 분석하면 된다.


  이 경우에 유용한 것이 DeDe라는 도구이다. 크랙미를 열고 "Process" 버튼을 눌러서 분석한다. 이후 분석이 완료되면 "Procedures" 탭을 보자. 왼쪽에는 Unit1이 보인다. 간단해서인지 unit은 하나밖에 없는 것 같다. Unit이란 그냥 모듈이라고 생각하면 될 듯 싶다. 큰 프로그램이라면 언어에서 제공하는 것들도 많이 가져다가 쓰고 직접 제작한 여러 모듈들도 모두 임포트해서 프로젝트가 구성될 것이기 때문에 많은 Unit들을 볼 수 있을 것이다.


  어쨌든 여기에는 Unit1에 Class 이름은 TFom1이다. 오른쪽을 보면 Event와 RVA가 보인다. Event는 "SpeedButtion1Click", "SpeedButtion2Click"이다. 크랙미를 보면 버튼이 2개 있었다. 이것을 가지고 추측해 보면 각각 특정 버튼이 눌렸을 때의 이벤트를 의미하는 것으로 보이며 옆의 RVA에 나온 주소는 그 이벤트가 발생했을 때 실행될 루틴의 주소라고 할 수 있을 것이다. 이에 따라 우리는 이 루틴으로 가서 BP를 건 후에 해당 루틴만 분석하면 될 것이다.



1.2 악성코드 분석

  악성코드를 상세하게 분석해 보려고 하자. 일반적으로 Console 형태로 만들어졌거나 GUI 형태라고 하더라도 GUI 객체들을 초기화하는 루틴에서 악성 루틴이 실행되는 등 GUI와 관련된 내용은 별로 없을 수 있다. 어쨌든 중요한 것은 진행해 가면서 루틴을 파악해 가는 것이다.


  하지만 디버거로 열어보면 수 많은 함수들이 있고 직접 진행하면서 분석해 보려고 하더라도 이해도 못하면서 진행만 할 수 밖에 없을 것이다. 개인적으로는 윈도우의 API를 호출하는 부분들 위주로라도 분석하려고 했지만 이것도 쉬운 일이 아니었다. 또한 MOVE라는 memcpy()와 비슷해 보이는 명령어라고 하더라도 내부적으로는 본 적도 없는 명령어들이 사용되어 구현되어 있는 경우도 있었다.


  이것을 제대로 분석하는 것은 말이 안되기 때문에 도구의 힘을 빌릴 수 밖에 없다. 앞에서 말한 DeDe는 없는 것 보다는 낫지만 어느 정도 이상의 분석을 제공하지 않는다. 이것은 IDA Pro의 시그니처도 마찬가지이다. [ http://sanseolab.tistory.com/55 ] 사실 IDA Pro도 여러 개의 델파이 관련 시그니처를 제공해 주지만 개인적으로 반 이상 제대로 분석해 주는 것을 보지 못했다.


  이 경우에 쓸 수 있는 것이 IDR이라는 델파이 디컴파일러이다. 이것은 kbsyskb라는 이름이 붙은 DB 파일을 가지고 해당 버전에 맞는 델파이 바이너리를 분석해 준다. 인터넷에 IDR을 다운로드 받을 수 있는 곳이 많이 있지만 이것은 옛날 버전의 컴파일러로 제작된 바이너리만 통한다. 최신 버전의 경우에는 추가적인 DB 파일들이 필요하다.


  결론부터 말하자면 다음 링크에서 idr.exe 및 dll 파일들을 다운로드 받는다. https://github.com/crypto2011/IDR ] 이것을 받는 것이 중요한 이유는 최신 버전이라서 더 빠르며 최신 버전의 DB를 제대로 인식할 수 있기 때문이다. 그래서 옛날 버전의 idr에 뒤에서 말할 DB만 추가하면 안된다.


  이제 DB를 추가해야 한다. DB 파일은 kb2.bin, kb2010.bin 등의 kb 파일들과 syskb5.bin, syskb2007.bin 같은 syskb 파일들이다. 인터넷에서 자주 볼 수 있는 IDR은 최신 버전의 DB가 포함되어 있지 않을 확률이 높다. 다음 링크에서 2014 버전까지 다운로드 받자. [ https://www.dropbox.com/sh/9ran313nidqtagb/AADl_m_9GVYSiXUviZtDQWQHa?dl=0 ] 델파이의 버전 구분을 정확히는 모르지만 적어도 XE4까지는 커버되는 것으로 보인다.


  이제 IDR을 켜고 바이너리를 오픈하면 "Use native Knowledge Base?"라는 팝업이 뜨는데 최신 버전이므로 OK를 누르자. 그러면 분석을 시작하게 되고 Unit3, Unit4 등으로 보였던 부분들이 System, SysInit, System.SysUtils 등으로 이름이 붙는 것을 볼 수 있다. 그대로 Unit3 같이 있다면 이것은 제작자가 직접 제작한 부분이므로 직접 리버싱을 해서 기능을 파악해야 한다. 하지만 걱정할 것이 없는 것이 C로 제작한 프로그램이 API 함수를 이용해서 진행하듯이 델파이의 정적으로 링크된 함수들이 IDR을 통해 이름이 붙여져서 이 함수들을 파악해가면 분석하다 보면 그다지 큰 어려움을 느끼지 않을 것이다. IDR이 분석해주는 전과 후의 차이는 DLL 내부로 들어가 API 함수까지 분석하는지 여부의 차이와 같은 수준이다.


  여기서 멈추지 않고 "Tools - MAP Generator"를 클릭하여 .map 파일을 생성하자. 이후 OllyDbg 1에서는 MapConv라는 플러그인을, OllyDbg 2에서는 VicPlugin이라는 플러그인을, x64dbg에서는 SwissArmyKnife라는 플러그인을 사용해서 맵 파일을 임포트시킨다. 그러면 Label에 등록되어 함수에 이름이 붙는 것을 확인할 수 있다. 이것과 관련된 내용은 이 블로그에 많으니 블로그 내부 검색을 이용해서 알아보자.


  그럼 이제 이 함수들이 어떤 함수들인지만 파악한다면 내부에 들어가서 기능을 파악할 필요가 없고 인자만 파악한 후에 Step Over로 간단하게 넘길 수 있을 것이다. 사실 델파이에서 사용되는 내부 시스템 함수들은 MSDN과는 다르게 검색하기도 쉽지 않다. 시스템 API 관련 설명이 나누어져 있고 통합해서 검색하는 부분이 없기 때문이다. 그렇기 때문에 구글에서 다음과 같이 검색한다.


함수이름 site:embarcadero.com


  이것은 embarcadero.com 사이트 내에서 우리가 원하는 함수와 관련된 레퍼런스를 찾을 수 있게 해준다. 예를들어 "strcat site:embarcadero.com"를 검색하면 구글에서 처음 1, 2번째에 검색 결과가 나온다. SysUtils.StrCat이라고 나오는 것을 클릭하여 인자 및 여러 설명을 볼 수 있다.


  이런 방식으로 시스템 함수들을 마주칠 때마다 인자와 반환값을 확인하고 인터넷으로 그 기능을 익혀가면서 진행하다 보면 그나마 손쉽게 분석이 가능해 진다.


  참고로 Unit1이 System이라면 디버거에서도 (맵 파일이 생성될 때) "System.함수 이름" 같이 볼 수 있지만 어떤 것들은 시스템 함수들이 사용된 유닛인데도 불구하고 그대로 Unit3 같이 나오는 경우를 볼 수 있다. 이것은 해당 Unit이 여러 가지를 임포트해서인 것으로 보이며 함수 자체는 잘 파악되어 있기 때문에 큰 상관은 없다. 





2. 추가적인 문제와 해결 방안

  지금까지 진행함으로써 우리는 델파이 컴파일러가 정적으로 링크시켜 준 함수들을 파악할 수 있었고 찾아가면서 진행할 수 있다는 것을 알게되었다. 하지만 앞에서 다 설명하지 못한 부분도 있고 추가적인 부분도 존재하므로 아래에서 못다한 설명을 추가하도록 하겠다.



2.1 함수 호출 규약

  VC++로 컴파일된 32비트 바이너리에 익숙하다면 스택을 통해 파라미터를 넣는다는 것에 편해져 있을 것이다. 하지만 델파이를 분석하면서 느꼈겠지만 델파이는 함수 호출 규약이 좀 다르다. 델파이는 먼저 레지스터를 이용해서 인자를 전달한다. 순서는 EAX, EDX, ECX 순이며 그 이후로는 스택을 통해 집어넣는다. x64에서의 호출 방식도 레지스터를 이용하므로 이러한 방식에 익숙해질 필요가 있어 보인다. 간단해 보이는 차이지만 분석하다 보면 은근히 귀찮은 점을 느낄 수 있다. 스택을 사용한 경우에는 거의 그대로 그 위치에 원본 인자가 존재하지만 레지스터를 사용하는 경우에는 필연적으로 이 값을 스택 등으로 옮겨야 이후 해당 레지스터를 사용할 수 있기 때문에 추가적인 루틴이 더 들어가며 그것까지 파악해야 하기 때문이다. 하지만 그렇게까지 귀찮은 특징은 아니다.



2.2 객체 지향적이다

  이 말은 예를들어 함수를 호출할 때 인자를 집어넣는데 이게 객체가 될 수 있으며 우리는 이것의 주시해야 한다는 점이다. 이 객체라는 것이 여러 멤버로 이루어져 있고 한 번의 참조가 아니라 두 번 이상의 참조를 통해 접근되거나 하는 경우에는 난이도가 매우 높아질 수 밖에 없다.


  사실 여기에 대한 답은 없다. 하지만 개인적으로 OllyDbg와 x64dbg의 Label (블로그 내부 검색으로 찾아보자) 기능을 이용한다면 꽤 편리하게 분석할 수 있을거라는 생각이 든다. 메커니즘은 파악한 구조체를 디버거에 등록하고 거기에 각 멤버별로 Label을 달아줄 경우 추후 분석에는 매우 유용해질 것이기 때문이다. 이것을 자동화 해주는 플러그인을 구현한 후에 따로 다른 문서에서 예시와 함께 정리하기로 하겠다.



2.3 다른 Unit을 임포트할 경우

  개발자가 제작한 부분은 그렇다고 치지만 어떤 라이브러리를 임포트해서 정적으로 링크한 경우에는 분석의 난이도가 다시 높아질 수 밖에 없다. 특히 이것이 암호화 라이브러리라면 답이 없다. 물론 이것이 오픈소스일 경우 아주 고전적인 방식으로 상수 값이나 문자열을 찾아서 소스 코드를 보며 루틴을 파악한 후 어셈블리와 비교해가며 파악할 수도 있고 단지 공개 버전이라면 더 추상적으로 접근해야 할 것이다. 또는 직접 컴파일해 가면서 비교해야할 필요가 있을 수도 있다.


  아까 IDA Pro의 시그니처가 그다지 쓸만하지 않다고 했는데 (꽤 괜찮은 편이지만 IDR이 워낙 좋다보니) 여기서부터는 유용하게 사용될 수 있다. 여기서 원하는 것은 VC++에서 처럼 라이브러리를 생성한 후에 시그니처를 따던가 idb2pat이라는 플러그인을 이용해 파악한 함수들에 대해 각각 시그니처를 딸 수 있을 것이다. idb2pat을 이용하는 방식은 같으므로 그냥 넘어가기로 하고 여기서는 라이브러리를 이용한 방식을 설명하겠다.


  사실 델파이에 대해서 잘 모르지만 델파이가 exe 파일은 생성해도 .dll이나 .lib 파일을 생성할 것이라는 기대조차 하지 않았기 때문에 직접 라이브러리를 사용하는 스텁 프로그램을 만든 후에 idb2pat으로 시그니처를 따야 하나 생각했다. 하지만 인터넷을 보니 dcu2pat이라는 프로그램이 존재한다. 이것을 통해 우리는 델파이가 .lib 생성을 지원하지 않아도 특정 라이브러리를 .dcu (Delphi Compiled Unit)로 생성한 후에 .pat 패턴 파일을 생성할 수 있게 되었다. 이후 sigmake를 이용하는 방식은 동일하다. 이제 악성코드를 분석하다가 오픈 소스 암호 라이브러리를 사용하는 델파이 바이너리를 만나면 직접 .dcu로 컴파일한 후에 패턴 파일을 추출할 수 있을 것이다. dcu2pat은 다음 링크에서 다운로드 받을 수 있다. [ http://uploaded.net/file/kgw21z97 ]


  추가 사항으로서 이것을 읽는 사람들은 델파이 개발자가 아니기 때문에 .dcu를 만드는 방식도 찾아봐야 할 것이다. 본인도 개발하는 법을 모르지만 그나마 가장 쉬운 방법을 찾게되었다. 델파이의 버전마다 다르겠지만 여기서는 델파이 6 기준으로 설명하겠다. 먼저 다음을 선택한다.


File - New - Others


  이후 Package를 선택하면 패키지 관리자 창을 볼 수 있다. 여기서 add를 선택하고 Browse를 누른 후 원하는 .pas 소스 코드들을 모두 선택한다. 일반적으로 원하는 유닛만을 선택하고 싶더라도 Dependency에 의해 이 유닛이 Import하는 다른 유닛들도 그리고 이 유닛들이 사용하는 다른 유닛들까지 모두 선택해야 하므로 어느 정도 이상 큰 경우에는 이 방식을 이용하는 것이 가장 쉬운 방식이다.


  이렇게 관련된 모든 소스 코드들 즉 .pas 파일들을 add하였으면, 단순하게 Compile을 누르면 된다. 원래는 .bpl을 만드는 과정이지만 어찌되었든 .pas 즉 소스 코드들이 있던 디렉터리에 

각각의 소스 코드에 해당하는 .dcu 파일들이 모두 생성되어 있는 것을 확인할 수 있다. 이제 Batch 스크립트를 이용해서 각각의 .dcu 파일들을 .pat 파일로 변환시키면 된다.



Posted by SanseoLab

블로그 이미지
Malware Analyst
SanseoLab

태그목록

공지사항

Yesterday
Today
Total

달력

 « |  » 2024.4
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30

최근에 올라온 글

최근에 달린 댓글

글 보관함