
			-----------------------------------
			 Immortal Descendants CrackMe 6.0
			           (by TORN@DO)
			Tutorial by Lucifer48, 19 june 1999
			-----------------------------------


======================
1. THEORETICAL APPROCH
======================

By observing the structure of the executable, we discover few things:
Firstly: there are six segments 'suspicious': .CRYP, .ID60, http://L, EARN2CR, RK.CBJ., NET.
The four segments .CRYP, http://L, EARN2CR, RK.CBJ. have the same size (remark: it makes me think
to the packed target 'id crackme v4.0', with several segments named .Stone)
We sure that the crackme is packed few times with the same packer (let's call it PACKER #2).
This packer add a new segment at the end of the exe which contains informations for unpacking
(as a example, see Stone's PE Encrypter 1.13 in idcrkme40.exe).
Secondly: .ID60 et NET have the same size (Phys size & Virt size), looks like another packer
(let's call it PACKER #1), used twice times.
Thirdly: the entrypoint is: RVA: 00019319h
The "319" don't evocate you something ??? The size of a segment packed with PACKER #2...
It appears that, PACKER #1 insert his code at the end of the last segment (change the length),
and pack the exe (we will see how and where after).

Finaly: we have this:
  initial exe (unpacked)
+ pack 2 times with PACKER #2
+ pack 1 time  with PACKER #1
+ pack 4 times with PACKER #2
+ pack 1 time  with PACKER #1
------------------------------
= idcrkme60.exe


=====================
2. STUDY OF PACKER #1
=====================

We load the crackme with the symbol loader, EAX=00419319 (entrypoint):

XXXX:00419319  PUSHFD                           ;save flags in the stack (on 32 bits)
XXXX:0041931A  PUSH EBP
XXXX:0041931B  CALL 0041940C                    ;not interesting (very short call)
XXXX:00419320  XCHG EDX,EBP
XXXX:00419322  POP  EBP
XXXX:00419323  PUSHAD                           ;save registers
XXXX:00419324  XCHG EDX,EBP                     ;ebp=00016CFE
XXXX:00419326  CMP  BYTE PTR [EBP+00412715],01
XXXX:0041932D  JZ   00419368                    ;(no jump)
XXXX:0041932F  MOV  BYTE PTR [EBP+00402715],01
XXXX:00419336  JMP  0041941F

we continue:

XXXX:0041941F  CALL 0041943F
XXXX:00419424  MOV  ESP,[ESP+08]
XXXX:00419428  CALL 0041940C                    ;not interesting (very short call)
XXXX:0041942D  MOV  BYTE PTR [EBP+004026CC],C3
XXXX:00419434  CALL 00419384                    ;HERE, call to explore!! (*)
XXXX:00419439  JMP  00419354

(*) This call is very important, because it's the unpacking routine.

XXXX:00419384  LEA  EDI,[EBP+004026CD]         ;offset RVA (it's an "array" of few RVA)
XXXX:0041938A  MOV  ESI,[EDI]                  ;RVA        (see remark below)
XXXX:0041938C  OR   ESI,ESI                    ;if ESI=0, we have unpacked every segments
XXXX:0041938E  JZ   004193C1
XXXX:00419390  ADD  ESI,[EBP+0040270D]         ;add the image base (00400000)
XXXX:00419396  MOV  ECX,[EDI+04]               ;length of the area to unpack (Phys size)
XXXX:00419399  PUSH EDI
XXXX:0041939A  MOV  EDI,ESI
...
unpack 32 bits per 32 bits (ADD / XOR / ROR / SUB)
...
XXXX:004193B5  STOSD                           ;<=> MOV [EDI],EAX / ADD EDI,4
XXXX:004193B6  SUB  ECX,04
XXXX:004193B9  JAE  004193A6                   ;while ecx<>0, we continue
XXXX:004193BB  POP  EDI
XXXX:004193BC  ADD  EDI,08                     ;next area (segment) to unpack
XXXX:004193BF  JMP  0041938A                   ;jump, see above
XXXX:004193C1  RET                             ;end of call 00419384

Remark:
-----IDCRKME60!NET+03C2---------------------------byte--------------PROT---(0)--
XXXX:004193C2 00 10 00 00 08 0A 00 00-00 40 00 00 10 03 00 00  .........@......
XXXX:004193D2 00 30 01 00 19 03 00 00-00 40 01 00 00 06 00 00  .0.......@......
XXXX:004193E2 00 60 01 00 19 03 00 00-00 70 01 00 19 03 00 00  ..`......p......
XXXX:004193F2 00 00 00 00                                      ....
---------------------------------------------------------------------------------

We recognize sizes (Phys size) and adress of the different segments, which are unpacked.
Maybe this array is more clear:

RVA       Phys size    Name
00401000    A08        .text           ;first loop
00404000    310        .data           ;second loop
00413000    319        .CRYP           ;third loop
00414000    600        .ID60           ;4th loop
00416000    319        http://L        ;5th loop
00417000    319        EARN2CR         ;6th loop

this is the end of the packer's code (very *classical* end):

XXXX:00419374  POPAD                           ;reload registers
XXXX:00419375  POPFD                           ;reload flags
XXXX:00419376  MOV  EBX,[EDX+00402709]         ;EBX=00419000 (segment NET)
XXXX:0041937C  MOV  [EDX+00402709],ECX
XXXX:00419382  JMP  EBX                        ;end of PACKER #1


Everything all right, PACKER #1 has done its job and jump to EBX (this is the PACKER #2's turn).


=====================
3. STUDY OF PACKER #2
=====================

It begins like this:

XXXX:00419000  PUSH EBP
XXXX:00419001  PUSH EDI
XXXX:00419002  PUSH ESI
XXXX:00419003  PUSH EDX
XXXX:00419004  PUSH ECX
XXXX:00419005  PUSH EBX
XXXX:00419006  CALL 0041900B
XXXX:0041900B  POP EBP                            ;good trick to obtain the current adress

we continue:

XXXX:00419025  CALL 004190C3
XXXX:0041902A  CMP  DWORD PTR [EBP+0040378F],00   ;we have [EBP+0040378F]=0 
XXXX:00419031  JZ   0041907F                      ;jmp = exit the program, no unpacking
XXXX:00419033  SUB  EDX,[EBP+00403655]
XXXX:00419039  SUB  EDX,0B
XXXX:0041903C  MOV  [EBP+0040365D],EDX            ;save image base (here: 00400000)
XXXX:00419042  MOV  ESI,004037B7                  ;small buffer of 8*32 bits
XXXX:00419047  ADD  ESI,EBP                       ;buffer located in the current segment (NET)
XXXX:00419049  PUSH ESI
XXXX:0041904A  CALL [EBP+00403793]                ;CALL [KERNEL32!GetLocalTime]
XXXX:00419050  CMP  WORD PTR [EBP+004037B9],01    ;month
XXXX:00419058  JB   0041908B                      ;jump to the unpack routine
XXXX:0041905A  CMP  WORD PTR [EBP+004037B7],07D0  ;year
XXXX:00419063  JB   0041908B                      ;jump to the unpack routine
XXXX:00419065  MOV  EAX,00403769
XXXX:0041906A  ADD  EAX,EBP                       ;d EAX: "Ding Boy's PE-lockv0.07    1999-2000"
XXXX:0041906C  MOV  EBX,004037F9
XXXX:00419071  ADD  EBX,EBP                       ;d EBX: "  " (two space chars)
XXXX:00419073  PUSH 00                            ;MB_OK
XXXX:00419075  PUSH EAX                           ;offset text
XXXX:00419076  PUSH EBX                           ;offset title
XXXX:00419077  PUSH 00                            ;no handle
XXXX:00419079  CALL [EBP+0040378F]                ;CALL [USER32!MessageBoxA]
XXXX:0041907F  MOV  EAX,FFFFFFFF                  ;exit the program (nothing has been unpacked)

Few explainations: the call 004190C3; it is used to fix system adress (api call), indeed
PACKER #2 may have to use CALL [KERNEL32!GetLocalTime] or/and CALL [USER32!MessageBoxA],
and that's the job of the call 004190C3 to find these adress. Three cases are possible:
* everything ok, system (api) adress have been found => we jump to the unpacking proc.
* we are in year 2000, we receive a messagebox, the unpacking isn't done.
* for a unknown reason, PACKER #2 didn't find these adress, still here, the unpacking isn't done.

In our case, it is the last proposal (for a unknown reason, no unpacking, exit/close the program).
But I want to unpack this crackme! So i won't jump in 0041907F (with JZ 0041907F), i will nop this
and continue until XXXX:00419042, here i will do in soft-ice: r eip=0041908B, to jump in the
unpack routine.
Remark: of course, we mustn't try to run api call, because we immediatly get a GFP
(General Protection Fault). Remenber that adress of [KERNEL32!GetLocalTime] and
[USER32!MessageBoxA] haven't been found.

This is the unpacking proc:

XXXX:00419092  CMP  DWORD PTR [ESI],00            ;still a segment to unpack ?
XXXX:00419095  JZ   004190AD                      ;if yes => (no jump)
XXXX:00419097  MOV  EBX,[EBP+0040365D]            ;00400000
XXXX:0041909D  ADD  EBX,[ESI]
XXXX:0041909F  MOV  ECX,[ESI+04]                  ;size of area (the segment)
XXXX:004190A2  SUB  BYTE PTR [EBX],01             ;"unpack": very very simple!
XXXX:004190A5  INC  EBX                           ;byte per byte...
XXXX:004190A6  LOOP 004190A2                      ;loop
XXXX:004190A8  ADD  ESI,08                        ;[ESI+0]: RVA, [ESI+4]: size
XXXX:004190AB  JMP  00419092                      ;loop
XXXX:004190AD  MOV  EAX,[EBP+00403659]            ;00018000
XXXX:004190B3  MOV  EBX,[EBP+0040365D]            ;00400000
XXXX:004190B9  ADD  EAX,EBX                       ;00418000 (RK.CJB.)
XXXX:004190BB  POP  EBX
XXXX:004190BC  POP  ECX
XXXX:004190BD  POP  EDX
XXXX:004190BE  POP  ESI
XXXX:004190BF  POP  EDI
XXXX:004190C0  POP  EBP
XXXX:004190C1  JMP  EAX                           ;end of PACKER #2

This unpacking routine is very easy...


===================
4. PRACTICAL METHOD
===================

It's time to unpack this crackme.

 Begin         End         Segment      Owner               Unpacked segments
00419319  *  00419382  *  NET       *  PACKER #1  *  .text .data .CRYP .ID60 http://L EARN2CR
00419000  *  004190C1  *  NET       *  PACKER #2  *  .text .data
00418000  *  004180C1  *  RK.CJB.   *  PACKER #2  *  .text .data
00417000  *  004170C1  *  EARN2CR   *  PACKER #2  *  .text .data
00416000  *  004160C1  *  http://L  *  PACKER #2  *  .text .data
00414319  *  00414382  *  .ID60     *  PACKER #1  *  .text .data .CRYP .ID60
00414000  *  004140C1  *  .ID60     *  PACKER #2  *  .text .data
00413000  *  004130C1  *  .CRYP     *  PACKER #2  *  .text .data
004011CB  <--- guess what it is!!!

We you arrive at the end of the last unpacking proc (XXXX:004130C1 JMP EAX); don't forget to
dump the process... (under soft-ice, press A then JMP EIP to put the program in a infinite loop,
press F5 and launch Procdump).

Don't forget too, to change the entrypoint (11CB) in the new exe. The crackme is unpacked!!!!!


=================================
5. RE-ENABLING THE REQUEST BUTTON
=================================

Windows are created with the api call "DialogBoxParamA", so we must have a look in the
"dialog box procedure", juste before the check (if we have pressed a button, message 
WM_COMMAND = 0111h), we see another message: WM_INITDIALOG (= 0110h), which, as his name
indicate... we see the api call EnableWindow, and just before:

:004012E9 837DFC00                cmp dword ptr [ebp-04], 00000000
:004012ED 7515                    jne 00401304

if [ebp-04]=0 the button (request) is disabled (in the main window).
So change: JNE => JMP
After:

:00401379 837DFC00                cmp dword ptr [ebp-04], 00000000
:0040137D 751C                    jne 0040139B

same thing here!

Remark: if you only patch the first JNE, the (request) button will be enabled but it will
activate nothing! The dialog box "Request" won't be created.


=============
6. CONCLUSION
=============

That's all for this crackme! No more to say...
Greetings: TORN@DO (of course, for his crackme), Volatility (will we work together ?),
           Eternal Bliss (for his site), MiZ (what a good essay for idcrkme5.0), ACiD BuRN,
           and others people i forgot.


Lucifer48
