首页
社区
课程
招聘
XtremeProtector 1.07
发表于: 2004-10-8 19:31 5348

XtremeProtector 1.07

2004-10-8 19:31
5348
机器翻译http://www.cracklab.ru/art/index.php?action=read&id=278的结果。

The author: dragon <c_dragon@mail.ru>

1. Analytics (beginning)
        Protectors as well as can be divided(shared) many other things into three categories on a level of protection of the program - low end, middle end and high end. To low end it is possible to attribute(relate) all simple packers such as UPX, ASPack, and also some protectors. To middle end such things, as ASProtect, Armadillo, Obsidum undoubtedly concern, etc. And among high end, i.e. the most powerful protectors it is known only two - XtremeProtector and StarForce. Them very good antidebugging (especially it concerns XProtector'á, try it(him) to start if in system costs(stands) softice), rather quite good protection of import, concealment of a program code which to not receive so simply as it can be made with copymem II in Armadillo distinguishes, and the most important - use Ring0 of a code which most strongly complicates research.

        It is possible to allocate two ways of removal of protectors. The first - research in a forehead from a point of an input(entrance) up to OEP and a spelling automatic распаковщика. The second - manual unpacking with the help of a presence(finding) and use of "rear entrances" in a code of a protector, with the purpose of removal дампа, presence(findings) OEP, receptions of import and. т. д. At unpacking XProtector'á we shall go естесственно in the second way as it in any case is easier and faster.

2. The small description of protection
        As the purpose it will be used XtremeProtector 1.07 DEMO which is accessible on an official site of the manufacturer. At the moment of a spelling of clause(article) version 1.08 is accessible already, but she(it) is protected worse, therefore in clause(article) and will be described 1.07.

        Before perusal it is recommended to understand a little the protected mode and device Windows NT, in particular in a nucleus. Without it it will be difficult to understand, how protection works. As to tools the basic will be IDA versions not ancient 4.50. Also editor PE of files (PE Tools recommended), ImpRec, the hexadecimal editor (WinHex), and also package MASM32 will be necessary. Also it is necessary to establish the plug-in - emulator x86 for IDA (it is accessible on wasm.ru) and a plug-in for clearing from scrambled a code (is in archive accompanying clause(article)). All right, now it is possible to proceed(pass) directly to the description.

        So, protection will consist of two parts, the most packed program and the driver under a name xprotector.sys which lays in the catalogue \System32\Drivers. During the certain moment of work the code of a protector causes function DeviceIoControl with a code 1800h at which processing the driver carries out(spends) some initialization. We look, that it(he) there does(makes):

Defines(Determines) number of processors in system
Finds IDT address for each processor and resolves access to IDT from the user mode at a level of pages
Opens access to the first page with the data where there is a file with IDT addresses
Opens access to all ports of input-output
In most cases IDT there will be certainly one, only in case of the multiprocessing machine or Pentium IV HT tables of interruptions will be more one though it does not affect unpacking in any way. And that the code of a protector gets direct access in ring0 affects and can do(make) that wants. And it(he) wants that, for example that it(him) did not debug and not дампили much. In fact it is valid, to the started program it will not be risen, attempt сдампить from PE Tools leads to to the message on impossibility of reading of memory of process. If to start softice the appendix is closed and if приаттачится to process Ollydbg will be in general перезагрузка. First of all it is necessary to liquidate антидамповую protection and antidebugging, and then already to think, what to do(make) further

3. Removal антидамповой and antidebugging protection
        It is obvious, that if memory is accessible to reading from one process and inaccessibl from another are intercepted API functions for work with memory. We start to look a code of function ReadProcessMemory from kernel32.dll. Apparently interceptions it is not observed. Also them it is not observed and in native api functions NtReadVirtualMemory. Further already a nucleus. As management gets on corresponding function in nucleus WinNT is well described in second clause(article) about packers on wasm.ru. The first where it is necessary to look so it in system service table or is shorter sst - the table of addresses of functions ntoskrnl.exe. For this purpose in archive utility R0cmd.exe and the driver lays. With its(her) help it is possible дампить and to load IDT, SST, SST shadow for ntoskrnl.exe and win32k.sys and in general any sites of memory in the field of a nucleus. For definition of interception it is possible to compare two дампа sst - before start XProtector'á and the ambassador. Tables differ, means XProtector контроллирует some functions ntoskrnl. To find out, what it is functions, displacement отличающися elements in дампе is necessary to divide on 4 and to find number in a file of Zw-functions from library ntdll.dll. In result we have the list of the intercepted functions:

NtAllocateVirtualMemory
NtCreateThread
NtQueryVirtualMemory
NtReadVirtualMemory
ZwTerminateProcess
NtWriteVirtualMemory
The maintenance(contents) of these functions to result there is no sense, there at attempt of access from other process to the protected program the error code comes back. Also it is blocked дамп with the help removed треда (CreateRemoteThread). But most surprising it that the ambassador in обработчике ZwTerminateProcess is not restored neither sst nor idt. Probably the protector has climbed somewhere else, it is probable in the scheduler of streams. I give to check up it that who well understands nucleus WinNT. We here are interested with removal антидампа more. It is obvious, that it(him) to remove(take off), there is enough подгрузить on a place the normal table sst by means of same utility R0cmd. And now it is possible to use such utilities, as PE Tools and ImpRec. But here it is impossible while to use a debugger.

        R0cmd/viewidt:??? - allows to look IDT in a text kind. Attention the cut down debugging interruptions int1 and int3 (their address began 0FFFFFFFFh) at once draw. All would seem simply, has restored IDT yes debug, but leaves nothing. At attempt to restore IDT the program or is cut down, or IDT comes back to an initial condition. The matter is that the superfluous streams generated by a protector which check IDT. But though the protected program to debug it is impossible, but it is possible to debug other programs. How it is possible? And here is how, by a call int1 or int3 management gets on 0FFFFFFFFh address, memory to this address usually is not present, therefore there is exception Page fault (*PF), обработчик which too is intercepted. Clearly, that in it(him) also there is a processing of any debugging actions of the user. It is necessary to result his(its) code обработчика:

seg000:F8AB8000                 pushf
seg000:F8AB8001                 pusha
seg000:F8AB8002                 call    $ +5
seg000:F8AB8007                 pop     ebp
seg000:F8AB8008                 sub     ebp, 1E09229h
seg000:F8AB800E                 inc     dword ptr [ebp+1E0925Fh]
seg000:F8AB8014                 cmp     dword ptr [ebp+1E0925Fh], 63h

Transition will be executed at overflow of the counter therefore
on a place of int1/int3 addresses in IDT will be written down 0FFFFFFFFh, it is
not especially interesting seg000:F8AB801B                 ja      loc_F8AB80B0

seg000:F8AB8021
seg000:F8AB8021 loc_F8AB8021:;                           CODE XREF: sub_F8AB8000+128

And here that comparison EIP with 0FFFFFFFFh is necessary, means we go on пореходу on F8AB8041
seg000:F8AB8021                 mov     eax, [esp+28h]
seg000:F8AB8025                 cmp     eax, 0FFFFFFFFh
seg000:F8AB8028                 jz      short loc_F8AB8041

--------------------------------------------------------------------------------

seg000:F8AB8041 loc_F8AB8041:;                           CODE XREF: sub_F8AB8000+28
seg000:F8AB8041                 mov     eax, 1
seg000:F8AB8046                 mov     ecx, eax
seg000:F8AB8048                 or      eax, eax

Well is not present, that it is simple jmp to write..
seg000:F8AB804A                 jnz     loc_F8AB8138

--------------------------------------------------------------------------------

seg000:F8AB8138                 push    fs
seg000:F8AB813A                 mov     eax, 30h; the selector for the register fs in a nucleus - 30h
seg000:F8AB813F                 db      66h
seg000:F8AB813F                 mov     fs, ax

;We receive the index on structure KTHREAD (or ETHREAD)
seg000:F8AB8142                 mov     eax, large fs:KPRCB.CurrentThread

;And it is the index on KPROCESS, it(he) the index on object of
process seg000:F8AB8148                 mov     eax, [eax+KTHREAD.ApcState. Process]
seg000:F8AB814B                 pop     fs
seg000:F8AB814D                 mov     ebx, eax
seg000:F8AB814F                 and     ebx, 7FFFFFFFh

;Probably to this address or hardly the index on object
  protected XProtector'ом process, if it(he) current, or a constant 47616420h if is not present further enters
the name.
  All this probably occurs in a code of switching of
streams seg000:F8AB8155                 mov     esi, 0F8AB6000h
seg000:F8AB815A                 cmp     dword ptr [esi], 0
seg000:F8AB815D                 jz      loc_F8AB8075
seg000:F8AB8163
seg000:F8AB8163 loc_F8AB8163:;                           CODE XREF: sub_F8AB8000+17A
seg000:F8AB8163                 add     esi, 4
seg000:F8AB8166                 cmp     dword ptr [esi], 47616420h

Ага, transition to a call old обработчика interruptions if process is not protected.
seg000:F8AB816C                 jz      short loc_F8AB8187
seg000:F8AB816E                 cmp     [esi], eax
And further transitions not there where it is necessary, and they are carried out, if
*PF has taken place in the protected process
seg000:F8AB8170                 jz      short loc_F8AB817C
seg000:F8AB8172                 cmp     [esi], ebx
seg000:F8AB8174                 jz      loc_F8AB8075
seg000:F8AB817A                 jmp     short loc_F8AB8163

        It is obvious, that if пропатчить transition to the address F8AB816C (In general that it(he) can be and another, the main thing, that this address is calculated as *PF+16Ch. In the programs protected XProtector'ом 1.08 displacement will be 17A). Патчить the nucleus without special tools is impossible, but possible to take advantage again R0cmd. For this purpose it is necessary to create a file in the size of 1 byte and to write down in him(it) EB, and then to load, using a command(team)/load. After restoration sst and a patch обработчика *PF debugging with help Ring3 of debuggers, for example Ollydbg becomes possible(probable). On softice to expect it is not necessary, too a lot of attention was given it(him) by developers.

4. Restoration of import and presence(finding) OEP
        Now we start traditional enough things in unpacking - to import and OEP. For presence(finding) OEP it will be described the whole two ways, but for one of them it is required распалогать by some information, namely the address of procedure of decoding of blocks of a code which to learn(find out) it is not obviously possible yet. Therefore for the beginning a way such: we find the table with adapters on imported functions, and instead of the present(true) transitions to write down there transitions to function which shall tell shows in MessageBox'Ñ the address of the call. It is obvious, that this address will be is close to OEP. It are necessary to find only the table of these transitions and пропатчить her(it). To find the table, problems do not arise, simply it is necessary to look through a code for calls of procedures and to look, where it(he) conducts. It is visible, that the table of transitions begins to the address 439850h and comes to an end on 439AF0h address And here so that пропатчить, problems is greater. Way such, we create process with the frozen stream (flag CREATE_SUSPENDED in соотв. Parameter), then using API CreateRemoteThread with the address of the removed stream equal to the address of function LoadLibraryA and the parameter equal to a name introduced DLL it is loaded this the most introduced DLL in address space of the protected program. The name естесственно should be registered beforehand with the help of pair functions VirtualAllocEx and WriteProcessMemory. All this is shown in a source code. Now DLL will receive notices on loading in address space of process, creation of a stream, и.т.д. The most such obvious way - to use a multithreading of a code of a protector, i.e. to wait creations of last stream, and during processing the notice to alter all this table of transitions under the needs, but XProtector not so it is simple, it(he) of it does not allow (If in the table changes the protector will change transitions once again, one change to it(him) will be appreciable appears a little). The output(exit) in that all this to do right after fillings of this table, and is even better during its(her) creation. Now this code is necessary for finding somehow. It very much is useful and at restoration of import since other opportunities well in any way do not approach. Reduction of a code of adapters the order and serial comparison with exported functions - is too difficult, and the variant to palm off instead of functions push XXXXXXXX/ret does not pass adapters of a kind, the protector notices it and is cut down.

        If присмотрется to addresses of adapters it is possible to notice, that they are in the allocated virtual memory with which it is possible to allocate with function VirtualAlloc. Now is farther, depending on version Windows the size of code API of functions different, allocation of memory means occurs directly in procedure of creation of import. The output(exit) means in catching calls of this API. Basically at a protector all is seized, patch API is direct kernel32.dll will not help, since she(it) is read directly from a disk in memory, processed, and functions therefrom are caused. In a nucleus to climb too uneasily, the idealest place for interception - Zw-functions means. Function ZwAllocateVirtualMemory necessary to us (I Hope in Microsoft will not take offence, in fact it is forbidden to spread source codes Windows) here is how looks:

.text:77F75832                 public ZwAllocateVirtualMemory
.text:77F75832 ZwAllocateVirtualMemory proc near
.text:77F75832                 mov     eax, 11h
.text:77F75837                 mov     edx, 7FFE0300h
.text:77F7583C                 call    edx
.text:77F7583E                 retn    18h
.text:77F7583E ZwAllocateVirtualMemory endp

Simply we change the instruction to the address 77F75837 so that in the register edx обработчика address of the intercepted procedure which, say, collects all addresses calls VirtualAlloc in a file was. To receive the address of call VirtualAlloc it is possible, having read it(him) from a stack. Displacement is relative esp can be found out, having debugged the program causing VirtualAlloc. In Windows XP SP1 this displacement is equal 68h. At unloading DLL contents of this file can be thrown off in a file, as well as it is made in a source code on restoration of import.

        The address which should draw attention - 7E0B0Eh since at return on this address memory which addresses very much remind addresses of adapters is allocated. From him(it) also it is necessary to dig all procedure. Here I shall result only the most interesting moments in this procedure. Here for example a small piece of a code which keeps displacement after опкода 0E9 (long jmp):

XPROT ___:007E0C21 lStoreJumpToImportFunction:;             CODE XREF: XPROT ___:007E0C05
XPROT ___:007E0C21;                                         XPROT ___:007E0C10

  ;edi - the address on which there is this displacement
XPROT ___:007E0C21                 mov     eax, [ebp+AddressOfImportFunction]
XPROT ___:007E0C27                 sub     eax, edi
XPROT ___:007E0C29                 sub     eax, 4
XPROT ___:007E0C2C                 stosd

For the beginning it will suffice us, we change the instruction mov eax, [ebp+AddressOfImportFunction] for something like mov eax, offset import_accepted. To change it is necessary after first interception ZwAllocateVirtualMemory with the required address of return from VirtualAlloc. And again we are waited with a surprise, namely one bad MessageBox with the message " An Error has ocurred while loading imports ". Certainly no mistake can be, and here check of integrity of a code of procedure very much even can. Looking through a code of creation of procedure is farther, I was involved with the following code:
XPROT ___:007E0737                 pusha
XPROT ___:007E0738                 lea     esi, [ebp+BeginProtectedArea]; 007E046F - the beginning of
procedure XPROT ___:007E073E                 lea     edi, [ebp+EndProtectedArea]; 007E12F9 - and the end of
procedure XPROT ___:007E0744                 sub     edi, esi
XPROT ___:007E0746                 mov     edx, edi; edx - length of checked code
XPROT ___:007E0748                 mov     edi, [ebp+1D70619h]
XPROT ___:007E074E                 or      ecx, 0FFFFFFFFh
XPROT ___:007E0751
XPROT ___:007E0751 hash_loop:;                             CODE XREF: XPROT ___:007E0761
XPROT ___:007E0751                 xor     eax, eax
XPROT ___:007E0753                 mov     al, [esi]
XPROT ___:007E0755                 xor     al, cl
XPROT ___:007E0757                 inc     esi
XPROT ___:007E0758                 mov     eax, [edi+eax*4]
XPROT ___:007E075B                 shr     ecx, 8
XPROT ___:007E075E                 xor     ecx, eax
XPROT ___:007E0760                 dec     edx
XPROT ___:007E0761                 jnz     hash_loop
XPROT ___:007E0767                 mov     eax, ecx
XPROT ___:007E0769                 not     eax
XPROT ___:007E076B                 cmp     [ebp+ValidHashValue], eax; Here and comparison..
XPROT ___:007E0771                 jz      loc_7E0781; well here conditional transition.
XPROT ___:007E0777                 mov     dword ptr [ebp+1D71831h], 1
XPROT ___:007E0781
XPROT ___:007E0781 loc_7E0781:;                             CODE XREF: XPROT ___:007E0771
XPROT ___:007E0781                 popa

Made unconditional transition to the address 007E0771h will resolve any updatings in procedure of creation of import, that very much even it is good. For example it allows a program - example to display rather humiliating окошко with an inscription " dump me!!! " And heading OEP near 42A37Ah. And it is valid OEP lays absolutely beside, to the address 42A373h. But the address on which it is transferred managements after working off of a code of a protector is little bit above, it is connected to protection of a code about(near) OEP, details will be considered below when it will be told about protection of a code.

        Now we shall engage in reception of addresses of imported functions that it was possible using imprec, to restore a directory of import. Since functions kernel32, user32 and advapi32 there should be a group of comparisons and transitions which should be found and corrected are protected only. I think for этогол such group will leave:

XPROT ___:007E08A9 loc_7E08A9:;                             CODE XREF: XPROT ___:007E0828  j;
As on a palm four transitions which editing will lead to to the pure(clean) table lay;
import and the table of transitions (is more true almost pure(clean), one function nevertheless придёться to distinguish
manually;
in this case this function - GetStartupInfoA
XPROT ___:007E08A9                 cmp     dword ptr [ebp+1D70A05h], 1
XPROT ___:007E08B0                 jz      lScrambled0
XPROT ___:007E08B6                 cmp     ecx, [ebp+BaseOfKernel32]
XPROT ___:007E08BC                 jz      lScrambled0
XPROT ___:007E08C2                 cmp     ecx, [ebp+BaseOfUser32]
XPROT ___:007E08C8                 jz      lScrambled0
XPROT ___:007E08CE                 cmp     ecx, [ebp+BaseOfAdvapi32]
XPROT ___:007E08D4                 jz      lScrambled0
XPROT ___:007E08DA
XPROT ___:007E08DA lNoScrambled:;                           CODE XREF: XPROT ___:007E08FD
XPROT ___:007E08DA;                                         XPROT ___:007E0922...
XPROT ___:007E08DA                 lea     ebx, [ebp+GetProcAddressX0]
XPROT ___:007E08E0                 call    ebx
XPROT ___:007E08E2                 mov     edi, eax;
Here all is simple, the correct address of function enters the name and is transferred somewhere;
Further - on creation of transition and element IAT. Management should get here
XPROT ___:007E08E4                 mov     [ebp+AddressOfImportFunction], eax
XPROT ___:007E08EA                 jmp     loc_7E0B4A

Having replaced each transition by six instructions nop we achieve creation of the pure(clean) table of import and transitions. To find IAT here it is not difficult, it is necessary to look only field Base Of Data in PE heading, usually the table of import there and lays. Now at last it is possible to restore import, but неободимо also to reorient transitions in the table that they specified elements IAT instead of in emptiness. For this purpose in archive the small utility also lays. After all it it is possible to tell, that the first stage of unpacking is completed, but XtremeProtector also has taken care of protection of the code. It is necessary to work further receiving all code in an open kind.

5. Protection of a code of a protector, scrambled a code
        As there will be an active research of a code of a protector it is necessary to tell a little that prevents his(its) research longer. First of all it is a scrambled-code, i.e. a code which is strongly diluted with dust. I bring some kinds of dust below:

--------------------------------------------------------------------------------
push    eXX
push        eXX...
sidt
[esp    - 2]; Kept IDT address is
not used...
pop     eXX...
pop
eXX
--------------------------------------------------------------------------------
push    eax
push    edx...
rdtsc;
Reading of the counter of steps of the processor, also is
not used...
pop     edx...
pop
eax
--------------------------------------------------------------------------------
pusha...
popa
--------------------------------------------------------------------------------

Also there are senseless conditional and unconditional transitions, instructions of a kind mov eax, eax. Except for a scrambled-code also there are designs of the following kind:
--------------------------------------------------------------------------------
push    eXX
call    proc0
db    0XXh; Garbage byte
jmp     [esp - 0Ch]

proc0:
pop     eXX
mov     [esp-8], eXX;
displacement concerning "garbage" байта Here increases,
management
add     [esp-8], 20h
inc     eXX there is then transferred; Detour garbage байта
push    eXX
retn
--------------------------------------------------------------------------------

Try потрассировать on F8 such code in Softice and will see something strange, instructions jmp [esp-0Ch] are farther to pass will fail, who it can can explain?

Is present as well such code (deciphering ahead a double word):
push    ebx
push    edx
push    edx; Registers естесственно can be and others
sidt    [esp - 2]

;Usually in ebx it turns out 0Ch or 1Ch, that corresponds(meets) to displacement of parameters int1 or int3 in IDT
mov     ebx, XXXXXXXX
xor     ebx, XXXXXXXX; Instead of xor there can be other arithmetic instruction
pop     edx
add     edx, ebx

;The key is written directly in IDT, all the same debugging interruptions are
cut down mov     dword ptr [edx], XXXXXXXX
mov     edx, [edx]
call    $ +5
pop     ebx
add     ebx, XX
xor     [ebx], edx; Decoding of a part of a code ahead...
xor
[ebx],     edx; Here restoration for an opportunity of repeated execution(performance) of
a code push    0FFFFFFFFh

;There обработчиков int1 addresses and int3 become equal to the transmitted parameter
call    proc0
pop     edx
pop     ebx

This code also is diluted with a significant amount of garbage instructions.

Also it is necessary to mention two kinds ring0-дишифровщиков a code. They are too complex(difficult), therefore their code I shall not result. The plug-in for IDA in archive allows to replace the most widespread scrambled-code with group nop'ов, and supports one of ring0-дешифровщиков. It(he) strongly facilitates research, in fact scrambled the code meets in the procedures responsible for decoding of a code, the driver xprotector.sys, and it is a lot of where still.

6. Full restoration of a code of the program
        Received in the previous steps дамп it is not started at all, a mistake, which reason - too much an absent code which now and we shall restore at once gives out. The first, than costs(stands) занятся, so it подгрузить отсутсвующий a code which sites are obviously visible in PE Tools in an option dump region. Something similar on CopyMem II in Armadillo, but only with that difference, that process one, and exceptions processes a code of a protector. One more difference from CopyMem II - sites of a code are deciphered at attempt of performance, instead of at attempt of any access to memory. The way of decoding is easy enough, we transfer management to such site of memory, and the protector after processing exception should cause in any case function ZwContinue for продолженя performance. The first and unique parameter at it(her) - the index on structure CONTEXT. That management was not transferred further, it is necessary to intercept simply her(it) in the same way, as ZwAllocateVirtualMemory at creation of import and to reorient EIP for the subsequent execution(performance) of a cycle. The received pieces of a code (all in the size 2000h, i.e. two pages) to put(fold) in the allocated(removed) area of memory, and after the termination(ending) of a cycle simply to resolve access to memory and to copy them on a place. Such way also is used in a source code. All this to make it is necessary, because XProtector at opening one pair pages, can close another.

        There are also three more designs for protection of a code, shall consider all over again designs, and then ways of reception of a code.

call    XXXXXXXX; the Address of procedure of decoding, in this case - 7DC1BBh
dd      0XXh; the Identifier of a stream which all this will
decipher dd      0;    0 - decoding, 1 - an
encryption dd      0XXh; length of
a code db      06Fh; garbage byte...-;
Further the ciphered code.

The finishing part can will be distinguished. If the ciphered code is carried out only once, it(he) затирается by zero:
pusha
call    $ +5
pop     edi
sub     edi, 0XXh
mov     ecx, 0XXh; Here and above 0XXh - length of the ciphered code increased on 1
xor     eax, eax
rep stosb
popa

And here if the code is executed repeatedly from such затирания anything good will not leave, therefore end of a code such:
call    XXXXXXXX; the Address of procedure of enciphering of a code - another, here it(he) is equal 007C0D1Bh
dd      0XXh
dd      1
dd      0XXh
db      06Fh

The principle of action of these procedures consists in filling variables with the data on the address, length, и.т.д. Then procedure causes function SetEvent and is started up in an infinite cycle jmp eax. The deciphering stream fulfils and transfers management to the deciphered code by means of an adapter. Теоритически besides to change EIP in the other stream call SetThreadContext is necessary. All again solves interception native api, this time ZwSetContextThread. It is enough to change EIP for the adapter and to continue a cycle of restoration of a code since it(he) remains in an open kind. Designs such should be found direct search, better and to not think up. Also it is necessary to provide cleaning of a code from calls and parameters of encryption / decoding of a code and replacement in his(its) zero. Now we pass further.

        By consideration of procedure of creation of import it was possible to notice, that instead of function wsprintfA its(her) real address, and at all(even not) a scrambled-adapter, and any suspicious code is put not. And in the code of the program there are not less suspicious calls wsprintfA strange parameters. Work of this function it is possible to observe under a debugger, or, that it is easier, under the emulator x86 in IDA. To result here details there is no sense since to decipher the sites of a code opened by this function simply elementary - transfer(pass) management on such call and change the address of return. These calls also are necessary for cleaning, as an opening call:

push    78263845h;
All XX - parameters of
decoding push    XX
push    0; 0 - an opening call, decoding of
a code push    XXXXXXXX
push    XXXXXXXX;
78263845h is a constant ('x*8E' or 'E8*x'), on it(her);
обработчик wsprintfA learns(finds out), that it is necessary to do(make) - to pass on real wsprintfA;
or to decipher a
code push    78263845h
call    XXXXXXXX; обработчика wsprintfA Address (the address of transition jmp on him(it) is more exact)

And closing:
push    78263845h
push    XX
push    1; 1 - a closing call, enciphering of
a code push    XXXXXXXX
push    XXXXXXXX
push    78263845h
call    XXXXXXXX

And at last last most complex(difficult) stage - restoration of a stolen code, and it(him) steal not on OEP, and on all section of a code. It is done(made) such with the help sdk XProtectora for protection of any important sites of a code, we shall tell checks of the entered password.

        All these protection of a code are found out at attempt of start of the unpacked program with cut off section XPROT. Here for example we shall try to open a file for protection, the program will take off on 435569h address on wrong опкоде. Here general structure of such protection of a code:

jmp     invalid_opcode
db      "xpro" It simply the
signature dd      00 - the beginning, 1 - the termination(ending).
dd      0
db      "xpro"
invalid_opcode:...
Anyone опкод, causing the sixth exception (invalid opcode)

At the end of this site there is the same, only with unit instead of zero. For reception of a code придёться to look, where management after processing exception gets. It appears, that EIP varies, and management is transferred somewhere far in virtual memory. We shall look, that there such. The beginning does not represent anything interesting, expectation of occurrence of the two to the address 2F103CCh is simple. Decoding laying ahead of a code (the code resulted below is processed by a plug-in from archive) further begins:
seg007:02F10039                 call    loc_2F1004F; the Beginning of
decoding seg007:02F10039;---------------------------------------------------------------------------seg007:02F1003E
db                 75h, 0Ah, 7Bh, 98h, 0F1h, 0D6h, 57h, 44h, 2Dh, 62h
seg007:02F1003E                 db 0F3h, 0B0h, 29h, 0AEh, 4Fh, 0DCh, 0E5h
seg007:02F1004F;---------------------------------------------------------------------------seg007:02F1004F
seg007:02F1004F
loc_2F1004F:;                            CODE XREF: seg007:02F10039
seg007:02F1004F                 push    edi
seg007:02F10050                 jmp     loc_2F1005C
seg007:02F10050;---------------------------------------------------------------------------seg007:02F10055
db                 0E3h, 0E0h, 99h, 5Eh, 3Fh, 0Ch, 55h
seg007:02F1005C;---------------------------------------------------------------------------seg007:02F1005C
seg007:02F1005C
loc_2F1005C:;                            CODE XREF: seg007:02F10050
seg007:02F1005C                 pop     ebx
seg007:02F1005D                 pop     edx
seg007:02F1005E                 jmp     loc_2F10069
seg007:02F1005E;---------------------------------------------------------------------------seg007:02F10063
db                 0E6h, 27h, 0D4h, 7Dh, 72h, 0C3h
seg007:02F10069;---------------------------------------------------------------------------seg007:02F10069
seg007:02F10069
loc_2F10069:;                            CODE XREF: seg007:02F1005E

;In a stack the address of return after performance of the instruction call loc_2F1004F
seg007:02F10069                 add     edx, 1F1h
seg007:02F10069 lays;---------------------------------------------------------------------------seg007:02F1006F
db                 13h dup (90h)
seg007:02F10082;---------------------------------------------------------------------------seg007:02F10082
mov                 esi,     2Fh; '/'
seg007:02F10087                 mov     bl, dh
seg007:02F10089
seg007:02F10089 loc_2F10089:;                            CODE XREF: seg007:02F1016B  j
seg007:02F10089                 push    dword ptr [edx]
seg007:02F1008B                 and     ebx, 1B9E6815h
seg007:02F10091                 pop     ecx; In ecx - the ciphered double word
seg007:02F10092                 mov     ebx, 67DD3A64h
seg007:02F10097                 add     ecx, 99117BDh; Action 1
seg007:02F1009D                 sbb     bx, 8085h
seg007:02F100A2                 push    edi
seg007:02F100A3                 sub     bh, 83h; 'â'
seg007:02F100A6                 pop     ebx
seg007:02F100A7                 add     ecx, 2130E1B2h; Action 2
seg007:02F100AD                 mov     ebx, 3EADBF30h
seg007:02F100B2                 add     ecx, 48408503h; Action 3
seg007:02F100B8                 jmp     loc_2F100D1
seg007:02F100B8;---------------------------------------------------------------------------seg007:02F100BD
db                 5Ch, 65h, 3Ah, 0EBh, 48h, 0E1h, 6, 0C7h, 0F4h, 1Dh
seg007:02F100BD                 db 92h, 63h, 60h, 19h, 0DEh, 0BFh, 8Ch, 0D5h, 0EAh, 0DBh
seg007:02F100D1;---------------------------------------------------------------------------seg007:02F100D1
seg007:02F100D1
loc_2F100D1:;                            CODE XREF: seg007:02F100B8  j
seg007:02F100D1                 mov     ebx, 40853042h
seg007:02F100D6                 push    ecx
seg007:02F100D7                 jmp     loc_2F100EF
seg007:02F100D7;---------------------------------------------------------------------------seg007:02F100DC
db                 0AFh, 0BCh, 45h, 9Ah, 0CBh, 0A8h, 0C1h, 66h, 0A7h, 54h
seg007:02F100DC                 db 0FDh, 0F2h, 43h, 0C0h, 0F9h, 3Eh, 9Fh, 0ECh, 0B5h
seg007:02F100EF;---------------------------------------------------------------------------seg007:02F100EF
seg007:02F100EF
loc_2F100EF:;                            CODE XREF: seg007:02F100D7  j
seg007:02F100EF                 pop     dword ptr [edx]; Record on a place of 4 deciphered bytes
seg007:02F100F1                 sbb     bx, 1D97h
seg007:02F100F6                 sub     edx, 2
seg007:02F100F9                 pusha
seg007:02F100F9;---------------------------------------------------------------------------seg007:02F100FA
byte_2F100FA    db 16h dup (90h)
seg007:02F10110;---------------------------------------------------------------------------seg007:02F10110
mov                 bh,     31h; '1'
seg007:02F10112                 jmp     loc_2F1011F
seg007:02F10112;---------------------------------------------------------------------------seg007:02F10117
db                 50h, 49h, 4Eh, 6Fh, 7Ch, 5, 5Ah, 8Bh
seg007:02F1011F;---------------------------------------------------------------------------seg007:02F1011F
seg007:02F1011F
loc_2F1011F:;                            CODE XREF: seg007:02F10112  j
seg007:02F1011F                 popa
seg007:02F10120                 dec     edx
seg007:02F10121                 dec     edx; Reduction of the address on 4 (sub edx, 2; dec edx; dec edx)
seg007:02F10122                 js      loc_2F1012E
seg007:02F10128
seg007:02F10128 loc_2F10128:
seg007:02F10128                 xor     ebx, 72129B9h
seg007:02F1012E
seg007:02F1012E loc_2F1012E:;                            CODE XREF: seg007:02F10122  j
seg007:02F1012E                 sub     esi, 1
seg007:02F10131                 jnz     loc_2F1014D; esi - the
counter seg007:02F10137
seg007:02F10137 loc_2F10137:
seg007:02F10137                 jmp     loc_2F10177; Transition to the deciphered code

Such decodings of a code meet very much frequently in the code of a protector. To decipher, very conveniently to use the emulator x86. We put it(him) on the beginning (02F10039), and on 02F10137 address It is possible to put брэйкпоинт and to start the emulator a command(team) run, or to put on this address the cursor and to give a command(team) run to cursor. The code ahead will be deciphered without problems. Now it is possible to look it(him) further. The command(team) to the address 02F101C5 - a call подпроцедуры almost in the beginning of page very interestingly looks. We shall look at this procedure:
seg007:02F10004                 pop     ebp
seg007:02F10005                 call    $ +5
seg007:02F1000A                 pop     eax
seg007:02F1000B                 push    eax
seg007:02F1000C                 sub     eax, 0Ah

;We read displacement of the stolen code from the address of return from the given procedure
seg007:02F10011                 mov     eax, [eax]
seg007:02F10013                 add     ebp, eax
seg007:02F10015                 pop     eax
seg007:02F10016                 add     eax, 16h;
Also we write down the address as argument of a command(team) push to the address 02F10020
seg007:02F1001B                 mov     [eax+1], ebp
seg007:02F1001E                 popf
seg007:02F1001F                 popa
seg007:02F10020                 push    2F101CAh
seg007:02F10025                 retn; Actually transition on краденный a code

Now means so, all procedures of such type are identical, it is possible to pass on a code, to make changes to procedure in the beginning of page. Only so simply here to not bring, the address of transition (argument of a command(team) push) each time is rewritten. But it is possible to take advantage of other circumstance, after the instruction ret we have a correct context of a stream, i.e. all values of registers and a stack same as before occurrence of exception, differently краденный the code would be carried out incorrectly. If to clean(remove) a command(team) push to the address 02F10020 the command(team) retn will transfer management to the address which is in a stack at occurrence of exception. Using these data, simply we change опкод commands(teams) push imm32 on mov eax, imm32. And at processing intercepted ZwContinue we shall add in a stack the address of return which will return us on a cycle touching such protective designs, and after return to register EAX we shall receive краденного address of a code! Here such simple change all is solved, and it is not necessary to decipher and restore anything краденный a code manually. It are necessary to find out his(its) length only. It is simple, since after a code such instructions follow:
seg007:02F10225                 push    eax
seg007:02F10226                 push    eax
seg007:02F10227                 mov     eax, 355C4h;
Displacement is relative ImageBase. Further the address, where
подадает management after working off краденного a
code seg007:02F1022C                 mov     [esp+4], eax
seg007:02F10230                 pop     eax is formed

Further a code, which зашифровывался earlier зашифровывается back, it for a reuse of a code. And even further it is seen here it:
seg007:02F10388                 call    near ptr byte_2F10394
seg007:02F10388;---------------------------------------------------------------------------seg007:02F1038D
db                 83h, 0, 39h, 7Eh, 0DFh, 2Ch, 0F5h
seg007:02F10394 byte_2F10394    db 1Ah dup (90h);         CODE XREF: seg007:02F10388  p
seg007:02F103AE;---------------------------------------------------------------------------seg007:02F103AE
pop                 esi     seg007:02F103AF
call                 $    +5
seg007:02F103B4                 pop     ebp
seg007:02F103B5                 add     ebp, 18h; ebp = 2F103CCh;
  Record of unit to the address 2F103CCh - an element of
synchronization seg007:02F103BB                 mov     dword ptr [ebp+0], 1
seg007:02F103C2                 mov     eax, [ebp+4];
  Record in a stack of the address of
return seg007:02F103C5                 add     [esp+24h], eax
seg007:02F103C9                 popf
seg007:02F103CA                 popa;
   Well and actually return
seg007:02F103CB                 retn
seg007:02F103CB;---------------------------------------------------------------------------seg007:02F103CC
dd                 2
seg007:02F103D0                 dd 400000h
seg007:02F103D4                 db 38h; 8

Problem in that it is necessary to repeat actions of this code (to write down 1 to the address 2F103CCh), differently a cycle обламается for the lack of synchronization. Also in all it присутсвует one strangeness, last such краденный the block is restored incorrectly (00436086 address), is necessary to restore it(him) separately, for example at the following start, and to replace a piece in дампе. Specially for this purpose in a source code the opportunity of record in a log-file of all addresses is stipulated, whence have filched a code. It is necessary to see(overlook) all addresses and if somewhere the code looks incorrectly needs to begin search not all over again the section of a code, and from that address from a file. At unpacking XProtector'á both 1.07, and 1.08 last is incorrectly restored only краденный the block. If at last all blocks are restored correctly, that unpacking is completed.

7. Definition of presence XProtector'á in memories and his(its) elimination
        Now with a kind the program functions normally, but it is necessary to start the information(inquiry) as she(it) will take off. The reason for this - not protection of a code, and a straight line call on an adapter around IAT and tables of transitions. Fortunately such only 4, all of them are concentrated in one place. Their addresses - 439B59h, 439BA5h, 439BC7h and 439BD7h. To look, that it for functions, it is enough to remove(take off) дамп where the table of import has been corrected, there they will be directed directly on API functions. It is possible to open in IDA libraries kernel32.dll and advapi32.dll and to look, that it for functions. And it is possible to make it in a debugger. By the way, it is possible to notice, that before everyone call'ом or the ambassador there is an instruction nop, it means, that on this place there was a 6-byte command(team), i.e. call mem32. So, functions the following:

439B59h - GetProcAddress
439BA5h - RegOpenKeyExA
439BC7h - RegQueryValueExA
439BD7h - RegCloseKey

Now finding these functions in a directory of import correct instructions. The information(inquiry) began to open, and in general the program functions completely, only here it is wrong. It is expressed that packed unpacked XProtector'ом programs do not work. This protection against unpacking appears actually hardly probable not the most powerful since it is necessary to test very actively the unpacked program and if the mistake it is necessary реверсить any more a protector and not protection of the program, and its(her) basic code is found. Besides, here the mistake is shown at all in the program, that even more complicates business. Research in this case is too unpleasant, therefore I shall result it(him) in strongly short variant.

        The packed program takes off on интсрукции, using the register ebp as displacement. And displacement has not changed. Look at 401A6Eh address in the unpacked program, you увидете code XProtecor'á without scrambled a code, and the main thing with displacement concerning where the code now and lays. I.e. at packing displacement should will change, and they do not vary. At packing XProtector the length of the instruction, и.т.д supports the special table where the address of the instruction is stored(kept). During any moment this table should be processed and filled by correct displacement. The beginning of the table is to the address 45295Eh. With the help xref'ов it is possible to see(overlook) everything, that procedure to the address 42BB7Fh just that is necessary is done(made) with the table, and. There there is a check of an element of the table, calculation of displacement and record of it(him) not a place (in the ready instruction which is located in packed exe). And record looks very interestingly:

CODE ____:0042BC16 loc_42BC16:;                             CODE XREF: accept_relocations+78
CODE ____:0042BC16                 lea     esi, ds:4511CEh
CODE ____:0042BC1C                 sub     esi, 0Eh; esi = 4511C0h

  ;And to this address the address belonging to a stack, very interestingly lays..
CODE ____:0042BC1F                 mov     esi, [esi]
CODE ____:0042BC21                 cmp     dword ptr [esi+4], 1

  ;And if there in a stack not unit changes of displacement are not kept!
CODE ____:0042BC25                 jnz     short loc_42BC2B
CODE ____:0042BC27                 mov     [ecx+eax+1], ebx
CODE ____:0042BC2B
CODE ____:0042BC2B loc_42BC2B:;                             CODE XREF: accept_relocations+A6;
  Further goes затирание an element of
table CODE ____:0042BC2B                 mov     eax, 0FFFFFFFFh
CODE ____:0042BC30                 mov     ecx, 5
CODE ____:0042BC35                 rep stosd
CODE ____:0042BC37                 jmp     loc_42BBAF

In as, means XProtector has thrust in a stack unit, has written down in section of the data the address and checks it(him). Check xref'ов on 4511C0h still more some similar situations. Editing of transitions here will not help, therefore we do(make) so: we write to the address 4511C0h value 4511C0h, and on following DWORD'Ò we write down unit. Since following DWORD too differs on time of performance (value 80000002h) that it too is finished after unit for secure. And at last we receive completely the efficient unpacked program, work is finished!

        The research certainly retold above is obscure and labour-consuming, therefore I offer other way: to stop the packed program on OEP and to look, than the stack differs. If differences obvious, as in this case it is necessary to look for the address of a stack where distinctions contain on a exe-file. After that it is possible to correct the unpacked file. Also in addition to all this it is possible to tell, that in XProtector 1.08 this opening with the table of displacement in general have cleaned(removed) and ставнение stacks and search of the address on a file where distinctions are found remains the only thing.

8. Analytics (termination(ending))
        So, after overcoming protection of all levels, it is possible to tell, that XtremeProtector it is literally in all surpasses other protectors. It is difficult to find such protection where it was so difficult to remove(take off) дамп and to restore section of a code (Starforce it is not counted), to restore import, and especially to find detection of the packer in memory. At XProtector'á very big prospects of development, it is interesting, how the following version of a protector will look? Whether Остануться there though any openings? In fact on search of openings and строися all unpacking. Present, as though it was necessary мучаться with import if it was impossible to find procedure of his(its) creation by simple interception API. Similarly and with restoration of a code. And if there was no such opportunity the basic and the method of research of protection in a forehead was unique. All this can be compared to opportunities of selection of a key in cryptography. It(He) can be picked up перебором all variants or that is better and faster, use by any vulnerability in algorithm. Rescues only what to protect the program, not having left any opportunity for fast breaking it is practically impossible. Authors XtremeProtector'á have tried to make it and it almost was possible to them.

        And in summary it would be desirable to tell, that on such protection as XtremeProtector it is not a pity to waste time, in fact it is possible to learn(find out) a lot of new, both about new ways of protection, and about internal device Windows, and it can very much it is useful.

Archive with tools and source codes here
dragon, [email]c_dragon@mail.ru[/email]
14 August, 2004.

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
太多了,看不懂
2004-10-8 22:53
0
雪    币: 1
活跃值: (344)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
用M$ office 提供的翻译服务译的
2005-7-24 00:07
0
游客
登录 | 注册 方可回帖
返回
//