Make a standalone patch
 
1. General Theory


Once you patched a program you cracked, you might want to share it. Instead of uploading the entire executable, you can make a small patch that changes the neccessary bytes.

Now how are we going to do that?

=> First we have to look for the file we have to patch. Most patches suppose that the file is in the same directory.

=> If it's there, we have to open it.

=> Next we should check if it's the exact same file as the one we cracked. We could eg. check the size, or some random bytes, or even better, the bytes we are going to patch.

=> If it is the same, we can do the neccessary adjustments : )
Put the filepointer on the right position, and write the new opcodes to it.

=> Close the file, and give a message about the status.

 

Take a program you just cracked, or use this example I will use.
Let's code this...

2. API Theory


What API's will we need to code this?

First of all, we will have to open the executable. The suitable API is :

HANDLE CreateFile(

LPCTSTR lpFileName, // pointer to name of the file
DWORD dwDesiredAccess, // access (read-write) mode
DWORD dwShareMode, // share mode
LPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributes
DWORD dwCreationDistribution, // how to create
DWORD dwFlagsAndAttributes, // file attributes
HANDLE hTemplateFile // handle to file with attributes to copy
);

This API is used for opening, or creating a file.
dwDesiredAccess should be 'GENERIC_WRITE OR GENERIC_READ' because we want to read and write from/to the file.
dwShareMode = 'FILE_SHARE_WRITE OR FILE_SHARE_READ'
dwCreationDistribution = 'OPEN_EXISTING' We only want to open a file that is there. If it's not there, the function will fail, and we can give an Error Message.
Check your WIN32.HLP for details. If you don't have this API library, get it in the Reference section.
As you can see the API returns the handle of the file we requested. We need this handle for the next step : writing to the file.

BOOL WriteFile(

HANDLE hFile, // handle to file to write to
LPCVOID lpBuffer, // pointer to data to write to file
DWORD nNumberOfBytesToWrite, // number of bytes to write
LPDWORD lpNumberOfBytesWritten, // pointer to number of bytes written
LPOVERLAPPED lpOverlapped // pointer to structure needed for overlapped I/O
);


We will use this API to write the two bytes to the file (in the right place, of course :)
The handle hFile is the one CreateFile has returned.

lpOverlapped should point to an OVERLAPPED structure. We need this to put the filepointer at the right offset.

typedef struct _OVERLAPPED { // o
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
} OVERLAPPED;

Offset will contain the position where we want to write.

3. The Target


The Target is crackme5.exe, let's say we don't find a valid serial, and we want to patch it.
Of course you are a good cracker : ) and you found the bytes to patch quickly.
Here they are :

Offset 53Fh : 74h, 15h -> 90h, 90h

That's all the information we need : )

4. The Code

; Find the complete source and binary here.

.386
.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib


.data
FileName db "Crackme5.exe",0
AppName db "Crackme 5 Patch",0
Done db "File patched succesfully !",0
NoFile db "Can't find crackme5.exe !",0
ReFile db "Wrong version of crackme5.exe !",0
WrFile db "Error writing to crackme5.exe !",0
RBuffer db 75h, 15h
WBuffer db 90h,90h
OffsetPos OVERLAPPED <NULL,NULL,53Fh,NULL,NULL>

.data?

hInstance HINSTANCE ?
CommandLine LPSTR ?
hwndname HWND ?
hFile HANDLE ?
Numb dd ?
Buffer db 2 dup(?)

.const

.code
start:

invoke GetModuleHandleA, NULL
mov hInstance,eax

invoke CreateFile,ADDR FileName, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ OR FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL

.IF eax!=INVALID_HANDLE_VALUE

mov hFile, eax ; Store handle of file
Invoke ReadFile, hFile, ADDR Buffer, 2, ADDR Numb, ADDR OffsetPos ; Read the 2 bytes we are going to patch
mov ax, word ptr [Buffer]
.IF ax == word ptr [RBuffer] ; If they are the right ones (75h,15h) we replace them :-)
Invoke WriteFile, hFile, ADDR WBuffer, 2, ADDR Numb, ADDR OffsetPos ; Write the new bytes (90h 90h)
.IF Numb == 2 ; If the number of bytes written = 2, give Done Message
push MB_OK
push OFFSET AppName
push OFFSET Done ; Push Done-Message
.ELSE ; If number of Bytes != 2, Give Error-writing-Message
push MB_OK OR MB_ICONINFORMATION
push OFFSET AppName
push OFFSET WrFile
.ENDIF
.ELSE ; If the 2 bytes read are not the right ones, Give Error-Version-Message
push MB_OK OR MB_ICONINFORMATION
push OFFSET AppName
push OFFSET ReFile
.ENDIF

.ELSE ; If the handle was not returned, Give Error-NoFile-Message
push MB_OK OR MB_ICONINFORMATION
push OFFSET AppName
push OFFSET NoFile
.ENDIF

push NULL
Call MessageBox
invoke CloseHandle, hFile ; Close File
invoke ExitProcess,eax ; Exit

end start


If you understand the code above, which is self-explanatory, you can try to make a simular patch for another target.

Now you can make a simple WIN32ASM-patch. Of course we can also make a more user-friendly version eg. with an open-dialogbox to select the target. But that will be covered in a next tutorial about the subject : )

If you have questions, remarks about this tutorial, mail me!

Greetings,

Detten
Detn@hotmail.com