+HCU's special Project: 'Our protections'
tough
SELF32: THE SOLUTION

by +RCG, 14 January 1998
cracker

I have chosen this path to introduce +RCG's new essays because I believe that our readers would be good adviced to 'deepen' first +RCG's self32 protection (and to study +Zer0's solution to it) before attempting to go further.

SELF32: THE SOLUTION

The protection was perfectly explained by +Zer0, so I
will only comment how I was able to Create a Self-Modificable
code on the fly (I publish this because now I have some new info
and I can create real encrypted programms not using crafty
methods as you will see.) 


How can we create a self-modificable code?

Look at this:

Code Segment
	Call	GetUserNAme
	Call	GetUserCode
	Call	Get_Password_With_Name_and_Code
	Call	Decrypt_Code
	Call	LoadDecryptedCode
	Jump	Decrypted_Code

Decrypted_Code:
	dd	1000h dup (90)	;nops or whatever you like

LoadDecryptedCode:
        push    L NULL
        push    L FILE_ATTRIBUTE_NORMAL
        push    L OPEN_EXISTING
        push    L NULL
        push    L NULL
        push    L GENERIC_READ+GENERIC_WRITE               
        push    offset DecryptedFileName
        call    CreateFileA             ;Open file
        cmp     eax,-1
        je      File_Error
        mov     File_Handle,eax
                
        push    L NULL
        push    offset NbytesReaded
        push    L NumBytesToRead                     
        push    offset Decrypted_Code	<==This is the bug
        push    [File_Handle]
        call    ReadFile
        cmp     eax,FALSE
        je      File_Error
	ret
File_Error:
	xor	eax,eax
	ret

ENDS


How W95 prevents this?

	*Remember Kernel is at Segment 137h ==> Privilege
	 level 3. (137h=......11b) ==> 11b=3h

Setting a bpx at Readfile we will get this Code:

	esp+18:null
	esp+14:offset NbytesReaded
	esp+10:NumBytesToRead
	esp+0C:Destination (Decrypted_Code)
	esp+08:File_Handle
	esp+04:Return address
	esp+00:BFF76ED7 (for ReadFile)

Exported fn(): ReadFile - Ord:0241h
:BFF75806    push BFF76ED7	;go here at ret to read
:BFF7580B    jmp BFF75812
Exported fn(): WriteFile - Ord:02E2h
:BFF7580D    push BFF76E80	;or here to write
:BFF75812    mov eax, dword ptr [esp+14]  ;NBytesReaded
:BFF75816    push 00000004
:BFF75818    push eax
:BFF75819    call BFF784F0   ;IsBadHugeWritePtr
:BFF7581E    test eax, eax
:BFF75820    jne BFF7582D
:BFF75822    mov eax, dword ptr [esp+14]
:BFF75826    mov dword ptr [eax], 00000000 ;Clear NbytesReaded
:BFF7582C    ret	==> Go to Read/Write
:BFF7582D    pop eax
:BFF7582E    push 00000057
:BFF75830    call BFF7DACA   ;SetLastError
:BFF75835    sub eax, eax
:BFF75837    ret 0014

ReadFile (BFF76ED7):
:BFF76ECF    add esp, 00000004
:BFF76ED2    jmp BFF75B2E
.
.
:BFF76ED7    sub edx, edx	;ReadFile goes here
:BFF76ED9    push BFF9DF58	;this let the stack equal
:BFF76EDE    push dword ptr fs:[edx] ;This add 4, so:

		esp+1C:null                    
		esp+18:offset NbytesReaded     
		esp+14:NumBytesToRead          
		esp+10:Destination (Decrypted_Code)
		esp+0C:File_Handle             
		esp+08:Return address          
		esp+04:BFF76ED7 (for ReadFile) 
		esp+00:dword ptr fs:[edx]

:BFF76EE1    mov dword ptr fs:[edx], esp
:BFF76EE4    mov eax, dword ptr [esp+10]  ;Destination
:BFF76EE8    mov ecx, dword ptr [esp+14]  ;NbytesToRead
:BFF76EEC    jcxz BFF76F05	;Read zero bytes?
:BFF76EEE    dec ecx
:BFF76EEF    lea ecx, dword ptr [ecx+eax] ;ecx=end of destination
:BFF76EF2    add byte ptr [ecx], 00  ;E Voila!!!!
			  ;if destination is code segment then
			  ;write into it is forbidden and 
			  ;an exception is generated and trapped
			  ;by the OS giving us the error code.
:BFF76EF5    cmp eax, ecx ;Is end of dest.=begin of dest.
:BFF76EF7    je BFF76F05
:BFF76EF9    add byte ptr [eax], 00  ;try to write at
:BFF76EFC    add eax, 00001000       ;next page of 4Kb
:BFF76F01    cmp eax, ecx 	     ;Finished?	
:BFF76F03    jb BFF76EF9
:BFF76F05    mov ecx, dword ptr [esp+18]  ;NbytesReaded
:BFF76F09    add dword ptr [ecx], 00000000 ;Again with
					   ;NbytesReaded
:BFF76F0C    mov ecx, dword ptr [esp+1C]  ;Overlapped struct
:BFF76F10    jcxz BFF76F19		;if null go and read
:BFF76F12    add byte ptr [ecx], 00	;else check begin and
:BFF76F15    add byte ptr [ecx+13], 00  ;end of structure
:BFF76F19    pop dword ptr fs:[edx]
:BFF76F1C    add esp, 00000004	;restore true return address
:BFF76F1F    jmp BFF7583A    ;go read


All right, now we know where is the problem, so we can
try to jump directly to BFF7583A.

How to get the correct jump?...look!!!

GetJmp:
        mov     esi,[CFile]	;ReadFile jmp offset in data.
        mov     esi,[esi]	;ReadFile jmp offset in program.
        mov     esi,[esi]	;ReadFile jmp in dll (1st push)
        mov     esi,[esi+1]	;Get 2nd push value (BFF76ED7) 
NOK:    mov     al,[esi]	
        cmp     al,0E9h		;check for jmp opcode
        je      OK
        inc     esi
        jmp     NOK
OK:     mov     CFile,esi	;now esi is the direct jmp. add.
        ret

Final comment, try to put any address like C0110000 (VxD
addresses) and you will see there are no problems, you
can modify VxD without restrictions (is this a bug?).... and
we can prevent SoftIce using this 'bug'....work on it!!!!!!

My Kernel Version is 4.00.950  but I have downloaded other
versions and all worked.... also I have discovered that some
versions were patched preventing this fact (why?????).

Well, like +Zer0 said this way is a little hard to implement
in High Level Languages, but now we are going to implement
it very easily.

tough
Back to Our protections
No, no, no! I want to go FURTHER and read +RCG's new essay:
CRYPTOGRAPHY AND MATHEMATICS OF CHAOS!
No, no, no! I want to go FURTHER and read +RCG's new essay:
A FIRST INTRODUCTION TO VxD!