웹서핑을 하다보니, 오렌지님께서 올리신 언팩미를 봤습니다.

원문포스트 : http://0range.net/entry/첫번째-언팩미Unpack-me

분석해보죠


일단 tls 는 깨끗하고..

사용자 삽입 이미지


olly 출격!

(대부분의 분석문은 그림속에 주석으로 넣었습니다. 클릭해서 봐주세요)

사용자 삽입 이미지
좋은 언팩미 답게 많은 anti debug 레퍼런스를 가르쳐주시네요.
peb정보중 BeingDebugged, NtGlobalFlag, heap정보로 디버거를 디텍트합니다. 회피하고 나면,
peb->LoaderData에서 feeefeee를 찾는데, 저도 이게 뭔지 몰랐습니다.
구글링을 해서 다음 페이지를 찾았습니다.
http://en.wikipedia.org/wiki/Magic_debug_values#Magic_debug_values


힙을 free할때 HeapFree()함수가 free된 영역을 마크하는 값이라고 합니다.
정말 그런지, 또 디버그모드일때만 그런지 봐야겠죠?
그래서 HeapFree()를 분석해 들어갔습니다.
그랬더니 ntdll 내부 함수에 여기가 나오네요.

사용자 삽입 이미지

NtGlobalFlag를 얻어서 디버그여부를 체크합니다.
디버그 중일 경우에는 디버그 메시지도 남기고, 아래 작업도 하네요.


사용자 삽입 이미지

0xfeeefeee로 메모리를 채워버립니다.
새로운걸 배웠군요^^

계속 디버깅해보죠.

사용자 삽입 이미지

xor복호화 한 뒤 3개의 함수호출이 나옵니다. 하나하나 들어가보죠.
첫번째 함수입니다.
사용자 삽입 이미지
음 dll LinkedList에서 InitializationOrderModuleList, 즉 초기화 순서로 정렬된 리스트중 첫번째 dll을 얻어오네요.
즉, Kernel32.dll의 imagebase( hModule )을 얻어오는 함수인 거죠.
두번째 함수에 들어가 볼까요?

사용자 삽입 이미지
kernel32.dll을 파고들어가, export table의 rva와 갯수를 저장후 아래에 있는 loop로 뛰어듭니다.
뭐하는 루프인지 봐야겠네요.


사용자 삽입 이미지

name table에서 함수 이름을 얻어다가 뭘 하려는데, 뭐하는지 보려면 내부함수(0x101f120)를 먼저 보고
계속 분석하죠^^

내부함수는 아래와 같습니다.
사용자 삽입 이미지
함수 이름을 가지고 특정 결과값(dword)을 내는 것으로 보입니다.
다시 돌아와서, 마저 분석하죠


사용자 삽입 이미지
몇몇 함수의 주소를 구해서 저장합니다.
원본의 import를 해주는거 같진 않습니다... rva도 추가된 섹션이고, 원본의 import가 멀쩡히 있기 때문이죠.
그래도 혹시 모릅니다. 원본을 변경했을지도... 체크해놓고
이 함수 분석 끝났으니 이제 아까 세개의 함수중 마지막 세번째 함수를 보죠.


사용자 삽입 이미지
따라오고 계시죠? 자 들어가봅시다.

사용자 삽입 이미지
세번째 함수는 보는 것처럼 seyool님의 시그니쳐를 표시하는 메시지박스를 띄우고, 스레드를 하나 만듭니다.
사용자 삽입 이미지


쓰레드가 뭔지 봐야겠죠?
사용자 삽입 이미지
이게 ThreadProc이며, 하는일은 아까의 안티 디버깅을 sleep하며 1초마다 체크하는 겁니다.
실행 후 디버거를 attach 하는 것을 방지하기 위한 감시 스레드죠.
아까 import를 세팅해주는 것 같던 모습은, 이 thread에서 쓰기 위한 것으로 보입니다.
디버거가 감지되면 어떻게 되나 볼까요?


사용자 삽입 이미지
디버거가 감지되면 메시지박스 함수주소를 구해서, 디버거가 감지됐다는 경고메시지를 띄우고
프로세스를 종료시켜버리는 군요. 이 스레드는 원본 프로그램엔 아무 영향이 없으므로
그냥 죽이면 되겠습니다.
사용자 삽입 이미지
                                                                      "dodge this"



이제 마지막 세 함수와 스레드까지 분석이 끝났습니다.
push 1012475
ret
 은 1012475로 가는 루틴입니다. original entry point, 원본 entry point이죠.

사용자 삽입 이미지


oep입니다.
사용자 삽입 이미지


여기서 dump뜨고, import는 rebuild해줄 필요 없고.. 하면 원본이 나옵니다.

잘 만든 unpackme를 제작해주신 seyool님께 감사의 박수를!

우리도 옆동네 중국처럼 언팩에 관심이 많아졌으면 좋겠습니다.








  1. Commented by seyool at 2008.09.18 13:31 신고

    상세한 풀이 고맙습니다. 모든걸 파헤치셨군요 ㄷㄷ;;
    중간에 내부함수 나오는 부분은 필요한 API를 찾기 위함이에요.
    필요한 함수를 문자열 비교해서 검색하는 것은 눈치채기 쉽기때문에
    해쉬함수로 필요한 함수명에 대한 해쉬값을 구한후 비교해서 찾는 방식을
    이용했습니다 :-)
    2번쨰 언팩미는 조금 기다려주세요 ㅎㅎ

  2. Commented by 한자돌이 at 2008.11.13 10:04 신고

    PEB->LoaderData에서 0xFEEEFEEE 를 찾는 것은 2006년에 OpenRCE에도 이미 올라와있네요...

    http://www.openrce.org/reference_library/anti_reversing_view/33/Ring3%20Debugger%20Detection%20via%20LDR_MODULE/

    • Commented by 한자돌이 at 2008.11.13 10:04 신고

      역시 세상엔 고수가 많습니다 ㅠㅠ...;; 저도 안티 디버그 방법 하나 개발했는데 구글링하니까 이미 있더라는 ㅎㄷㄷ

    • Commented by jz- at 2008.11.13 10:52 신고

      ㅋㅋ 그렇군요

      single step을 감지해내는 안티 디버그 루틴을 하나 찾아낸게 있는데

      이건 공개되지 않은거 같더군요(흐흐)

      언팩미를 만들기는 귀찮고, 포스팅하긴 좀 그렇고(cpu동작까지 설명해야해서)

      나중에 갠적으로 만나면 설명드릴께요 재밌는 원리라는 ㅋㅋ

      근데 sca2008에 혹시 안오시나요?ㅋㅋ

    • Commented by 한자돌이 at 2008.11.13 15:16 신고

      Single Step Exception을 이용한 안티 디버그 방법은 알고 있지만,

      Single Step을 감지한다니 음... 구체적으로 어떤식으로 동작하는지 알려주실 수 있으세요?

      ※ p.s: SCA2008에는 오기 힘들듯 합니다. 제가 사는 곳이 부산인지라 :-)

    • Commented by 한자돌이 at 2008.11.13 15:21 신고

      혹시 MSN 하세요? MSN 하신다면 아이디 좀 :-)

    • Commented by 한자돌이 at 2008.11.13 18:22 신고

      혹시 Single Step Detection이

      http://www.openrce.org/reference_library/anti_reversing_view/32/Single%20Step%20Detection/

      말씀하시는건 아니겠죠?

      이거라면 저도 이미 알고 있었던 거라는... ㄷㄷ

      트렙 플래그를 이용한 예외 유도...

    • Commented by jz at 2008.11.13 18:56 신고

      네 아닙니다..ㅋ rep prefix와 관련된거예요.

      cpu의 fetch 동작이 차이가 나는거죠

      msn은 잘 안들어가서 문제인데-_-;; 일단 아이디 방명록에 비밀로 쓸께요 ^^

    • Commented by 한자돌이 at 2008.11.18 19:31 신고

      음... 서핑하다 발견한 문서인데요.

      http://pferrie.tripod.com/papers/unpackers.pdf

      여기에 REP prefix를 이용한 Single Step Detection이 중간에 나와있네요...

    • Commented by jz at 2008.11.19 09:41 신고

      오 이것과 흡사합니다!
      한가지 다른 점은, 이걸 좀 응용하면 표시만 남겨놓고 flow는 똑같이 가게 할 수 있습니다. 나중에 활용하면 찾기 힘들겠죠.(저 문서에서는 flow가 달라지네요)
      똑같지는 않지만 비슷한게 역시 알려져 있긴 하군요 젠장 ㅋㅋ

    • Commented by 한자돌이 at 2008.11.19 21:01 신고

      ProcessDebugObjectHandle, ProcessDebugFlag 등의 트릭도 이미 공개되어있네요...ㄷㄷ

    • Commented by 한자돌이 at 2008.11.19 21:16 신고

      그리고 jz님 말씀을 들으니 정말

      0xF8 (CLC) opcode로 채운 후,

      SETC BYTE PTR [xxxxxx] 과 같이 하면

      플래그를 바꿀수도 있겠네요...

    • Commented by jz- at 2008.11.20 22:27 신고

      ecx를 크게잡고 현 eip 이후 아쥬 먼곳을 write하고 자연스레 참조하면.. 뭐 그런 정도? 하하
      좋은 문서 감사합니다.

    • Commented by 한자돌이 at 2008.11.21 18:45 신고

      네. 저도 저 문서에서 많은 것을 배웠네요..ㅋㅋ;

      저 문서 제작자 정말 짱인듯...;; 저번에 저 혼자

      잘 때 생각해냈던 아이디어중 하나가,

      'Guard Page를 이용해서 Memory I/O를 통제하면 어떨까…'

      라는 것을 떠올렸는데, 이 문서에 이미 있었네요.

      ASProtect에서도 쓰였다고 하고...

  3. Commented by seyool at 2009.04.18 01:54 신고

    2번째 언팩미가 공개되었습니다.
    시간 나실때 한번 살짝 봐주세요~ ㅎㅎ

    • Commented by jz- at 2009.04.27 09:09 신고

      와우 너무 늦었군요 ^^;;

      이번엔 aplib압축모듈도 들어갔네요 오호

      올리의 floating ptr 버그도 넣으신 것 같고

      trap flag 트릭을 잘 숨겨 넣으셨네요^^


      첫번째로 푼 사람같은 경우를 막기 위해

      api redirection등 원본을 뿌숴버리시면 좋을 듯 하네요^^

      3번째 언팩미는 포스팅까지 해볼께요 요새 왜이리 블로깅하기가 힘이든지 ㅜㅜ ㅎㅎ

  4. Commented by 하미미 at 2010.06.05 23:29 신고

    아 부산 사시네요? 몇 년 전부터 리버싱에 관심은 많지만 여러가지 핑계로 진전이 없는 초보 개발자 입니다.
    언제 한번 소주나 한잔 하시는게;;