[masm32] crack (patch)

Description

Ceci est la source d'un crack écrit en Win32ASM (MASM32), possédant la plupart
des fonctionnalités habituelles : recherche du fichier, patch, backup et
restauration.

ATTENTION: je tiens à préciser que ce n'est pas illégal.
En effet, j'ai mis cette source pour que certains comprennent le principe de
fonctionnement d'un crack. Moi-même cela m'a longtemps fasciné (qui n'a jamais
rêvé de faire des cracks comme ceux du mythique SuperGégé ?), et je pense que ça
peut être intéressant.
Un crack est une type de patch un peu particulier, et j'ai aussi prévu cette
source pour faire des patchs (utilisation d'un thread pour les modifications
importantes des fichiers).

De plus cela constitue une bonne initiation à la programmation avec l'API
Windows (gestion des dialogues, des contrôles, écriture dans un fichier,
etc...). En gros les 10 premiers tutoriaux d'Iczelion sont couverts.

J'ai essayé de commenter le code (en anglais, désolé), mais j'espère que ça en
aidera quelques-uns ;-)

Source / Exemple :


;; Pastille                                                                   ;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; Author: Dean                                                               ;
 ; Date  : 04.25.2003                                                         ;
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;                                                http://kickme.to/charloweb  ;;

.486
.model flat, stdcall
option casemap: none

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\gdi32.inc
include \masm32\include\comdlg32.inc ; For the GetOpenFileName function
include \masm32\include\shell32.inc  ; For the ShellExecute function
include \masm32\include\imagehlp.inc ; For the MapFileAndCheckSumA function

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\imagehlp.lib

HyperlinkProc PROTO : DWORD, : DWORD, : DWORD, : DWORD
DlgProc       PROTO : DWORD, : DWORD, : DWORD, : DWORD
PatchThread   PROTO : DWORD

.const

; The resource IDs
IDI_TARGETFILE  equ 100
IDB_AUTHOR      equ 200
IDC_NAME        equ 300
IDC_CONTACT     equ 301
IDC_AUTHOR      equ 302
IDC_RELEASEDATE equ 303
IDC_TARGET      equ 304
IDC_TARGETFILE  equ 305
IDC_BROWSE      equ 306
IDC_BACKUP      equ 307
IDC_PATCH       equ 308
IDC_EXIT        equ 309

; Custom messages for the patch thread
WM_BEGINPATCH equ WM_USER + 100h
WM_ENDPATCH   equ WM_USER + 101h

; <ReleaseSettings>

; The name and the filename of the target
TargetName     equ 'TextFile'
TargetFileName equ 'textfile.txt'

; The size and the new size of the target file (if it is the same, set it to TargetFileSize)
TargetFileSize    equ 26
TargetFileNewSize equ 4

; The checksum of the target file
TargetFileCheckSum equ 0CD93h

; The offsets and the new bytes
Offsets  equ 0, 1, 2, 3
NewBytes equ 44h, 65h, 61h, 6Eh

; The author and the release date
Author      equ 'Dean', 0
ReleaseDate equ 'Apr 23rd 2003'

; </ReleaseSettings>

; <AdvancedSettings>

; The title and the name of the patch
PatchTitle equ 'Charloweb presents:'
PatchName  equ TargetName, ' crack'

; The contact URI
ContactURI equ 'http://kickme.to/charloweb'

; The text of the labels
AuthorLabelText      equ 'Author: ', Author
ReleaseDateLabelText equ 'Release date: ', ReleaseDate
TargetLabelText  equ 'Target file:'

; The text of the buttons (use & to make a shortcut)
BrowseButtonText equ 'Br&owse...'
BackupButtonText equ 'Create &backup file'
PatchButtonText  equ 'Apply &patch'
ExitButtonText   equ 'E&xit'

; The title and the filter string of the "open" dialog box
OpenTitle        equ 'Select the target file:'
OpenFilterString equ TargetName, ' (', TargetFileName, ')', 0, TargetFileName, 0, 'All files (*.*)', 0, '*.*', 0

; The extension of the backup file
BackupFileExt equ '.bak', 0

; The title of the message boxes
WarningTitle equ 'Warning'
ErrorTitle   equ 'Error'
InfoTitle    equ 'Information'

; The messages of error
BackupErrorMsg   equ 'The backup file cannot be created. Continue anyway?'
OpeningErrorMsg  equ 'The file does not exists or cannot be opened.'
FileSizeErrorMsg equ 'The file has not got the right size.'
CheckSumErrorMsg equ 'The file has already been modified or the checksum cannot be computed.'
RestoreErrorMsg  equ 'The file cannot be restored.'

; Restoration message
RestoreMsg equ 'The file has already been patched. Would you like to restore it?'

; The messages of success
PatchSuccessMsg   equ 'The file has been successfully patched!'
RestoreSuccessMsg equ 'The file has been successfully restored!'

; </AdvancedSettings>

.data

; Settings
nOffsets               DWORD Offsets
nNewBytes              BYTE  NewBytes
szTargetFileName       CHAR  TargetFileName, 0
szPatchTitle           CHAR  PatchTitle, 0
szPatchName            CHAR  PatchName, 0
szContactURI           CHAR  ContactURI, 0
szAuthorLabelText      CHAR  AuthorLabelText, 0
szReleaseDateLabelText CHAR  ReleaseDateLabelText, 0
szTargetLabelText      CHAR  TargetLabelText, 0
szBrowseButtonText     CHAR  BrowseButtonText, 0
szBackupButtonText     CHAR  BackupButtonText, 0
szPatchButtonText      CHAR  PatchButtonText, 0
szExitButtonText       CHAR  ExitButtonText, 0
szOpenTitle            CHAR  OpenTitle, 0
szOpenFilterString     CHAR  OpenFilterString, 0
szBackupFileExt        CHAR  BackupFileExt, 0
szWarningTitle         CHAR  WarningTitle, 0
szErrorTitle           CHAR  ErrorTitle, 0
szInfoTitle            CHAR  InfoTitle, 0
szBackupErrorMsg       CHAR  BackupErrorMsg, 0
szOpeningErrorMsg      CHAR  OpeningErrorMsg, 0
szFileSizeErrorMsg     CHAR  FileSizeErrorMsg, 0
szCheckSumErrorMsg     CHAR  CheckSumErrorMsg, 0
szRestoreErrorMsg      CHAR  RestoreErrorMsg, 0
szRestoreMsg           CHAR  RestoreMsg, 0
szPatchSuccessMsg      CHAR  PatchSuccessMsg, 0
szRestoreSuccessMsg    CHAR  RestoreSuccessMsg, 0

; Other variables
szDlgName    CHAR 'PASTILLE', 0
szOpenCmd    CHAR 'open', 0
bPatch       BOOL TRUE
bRestore     BOOL FALSE

.data?

; Handles
hInstance   HINSTANCE ?
hIcon       HICON     ?
hHandCursor HCURSOR   ?
hTargetFile HANDLE    ?
hBackupFile HANDLE    ?

; The variables of command-line arguments
argc DWORD ?
argv DWORD 16 dup(?)

; Path and filename buffers
szTargetFile CHAR MAX_PATH dup(?)
szBackupFile CHAR MAX_PATH dup(?)

; Checksum values
nHeaderSum DWORD ?
nCheckSum  DWORD ?

; Other variables
Ofn            OPENFILENAME <?>
BoldFont       LOGFONT      <?>
nPatchThreadID DWORD        ?
nBytesWritten  DWORD        ?

.code

start:

; Get the handle of the application instance
INVOKE GetModuleHandle, NULL
mov hInstance, eax

; Get the command-line and process it
; It is a code of comrade <comrade2k@hotmail.com>
INVOKE GetCommandLine
mov esi, eax
mov edi, OFFSET argv
xor ecx, ecx
xor ebx, ebx
xor edx, edx

@@cmss:
mov eax, esi
mov dl, 20h
cmp byte ptr [esi], 22h
sete cl
lea edx, [edx + ecx * 2]
add eax, ecx
stosd

@@cm00:
inc esi
cmp byte ptr [esi], 0
je @@cm01
cmp byte ptr [esi], dl
jne @@cm00
mov byte ptr [esi], 0
add esi, ecx
inc esi
cmp byte ptr [esi], 0
je @@cm01
inc [argc]
jmp @@cmss

@@cm01:
inc [argc]

; Load the icon and the cursor resources
INVOKE LoadIcon, hInstance, IDI_TARGETFILE
mov hIcon, eax
INVOKE LoadCursor, NULL, IDC_HAND
mov hHandCursor, eax

; Display the dialog box
INVOKE DialogBoxParam, hInstance, ADDR szDlgName, NULL, ADDR DlgProc, NULL

; When all the operations are done, terminate the process
INVOKE ExitProcess, eax

; The link procedure, used to change the cursor when the link is rolled over
HyperLinkProc PROC hWnd: DWORD, uMsg: DWORD, wParam: DWORD, lParam: DWORD

  .IF uMsg == WM_SETCURSOR
    INVOKE SetCursor, hHandCursor
  .ELSE
    INVOKE GetWindowLong, hWnd, GWL_USERDATA
    INVOKE CallWindowProc, eax, hWnd, uMsg, wParam, lParam
    ret
  .ENDIF

  xor eax, eax
  ret
HyperLinkProc ENDP

; The main procedure
DlgProc PROC hWnd: DWORD, uMsg: DWORD, wParam: DWORD, lParam: DWORD

  .IF uMsg == WM_INITDIALOG

    ; Change the icon of the dialog
    INVOKE SendMessage, hWnd, WM_SETICON, ICON_BIG, hIcon

    ; Attach the HyperLink procedure to the contact label
    INVOKE GetDlgItem, hWnd, IDC_CONTACT
    push eax
    INVOKE SetWindowLong, eax, GWL_WNDPROC, ADDR HyperLinkProc
    pop edx
    INVOKE SetWindowLong, edx, GWL_USERDATA, eax

    ; Fill all fields of text with the settings
    INVOKE SetWindowText, hWnd, ADDR szPatchTitle
    INVOKE SetDlgItemText, hWnd, IDC_NAME, ADDR szPatchName
    INVOKE SetDlgItemText, hWnd, IDC_CONTACT, ADDR szContactURI
    INVOKE SetDlgItemText, hWnd, IDC_AUTHOR, ADDR szAuthorLabelText
    INVOKE SetDlgItemText, hWnd, IDC_RELEASEDATE, ADDR szReleaseDateLabelText
    INVOKE SetDlgItemText, hWnd, IDC_TARGET, ADDR szTargetLabelText
    INVOKE SetDlgItemText, hWnd, IDC_BROWSE, ADDR szBrowseButtonText
    INVOKE SetDlgItemText, hWnd, IDC_BACKUP, ADDR szBackupButtonText
    INVOKE SetDlgItemText, hWnd, IDC_PATCH, ADDR szPatchButtonText
    INVOKE SetDlgItemText, hWnd, IDC_EXIT, ADDR szExitButtonText

    ; Set the "target file" edit box with the command-line argument or the
    ; target filename by default
    .IF argc > 1
      INVOKE SetDlgItemText, hWnd, IDC_TARGETFILE, argv + 04h
    .ELSE
      INVOKE SetDlgItemText, hWnd, IDC_TARGETFILE, ADDR szTargetFileName
    .ENDIF

    ; Check the "backup" checkbox
    INVOKE CheckDlgButton, hWnd, IDC_BACKUP, BST_CHECKED

  .ELSEIF uMsg == WM_CTLCOLORSTATIC
    INVOKE GetDlgCtrlID, lParam

    .IF eax == IDC_NAME

      ; Set the font of the title
      INVOKE SendMessage, hWnd, WM_GETFONT, 0, 0
      INVOKE GetObject, eax, SIZEOF LOGFONT, ADDR BoldFont
      mov BoldFont.lfWeight, FW_BOLD
      INVOKE CreateFontIndirect, ADDR BoldFont
      INVOKE SelectObject, wParam, eax

    .ELSEIF eax == IDC_CONTACT

      ; Change the color of the link
      INVOKE SetBkMode, wParam, TRANSPARENT
      INVOKE SetTextColor, wParam, 770000h
      INVOKE GetSysColor, COLOR_BTNFACE
      INVOKE CreateSolidBrush, eax
      ret

    .ENDIF

  .ELSEIF uMsg == WM_COMMAND
    mov eax, wParam
    mov edx, wParam
    shr edx, 16

    .IF dx == BN_CLICKED

      .IF ax == IDC_CONTACT

        ; Open the contact URI
        INVOKE ShellExecute, hWnd, ADDR szOpenCmd, ADDR szContactURI, NULL, NULL, 0

      .ELSEIF ax == IDC_BROWSE

        ; Fill the "open" dialog structure and display the window
        mov Ofn.lStructSize, SIZEOF Ofn
        push hWnd
        pop Ofn.hwndOwner
        mov Ofn.lpstrFilter, OFFSET szOpenFilterString
        INVOKE lstrcpy, ADDR szTargetFile, ADDR szTargetFileName
        mov Ofn.lpstrFile, OFFSET szTargetFile
        mov Ofn.nMaxFile, SIZEOF szTargetFile
        mov Ofn.lpstrTitle, OFFSET szOpenTitle
        mov Ofn.Flags, OFN_HIDEREADONLY
        INVOKE GetOpenFileName, ADDR Ofn

        .IF eax == TRUE

          ; Set the "target file" edit box with the fullpath and the name of the file
          INVOKE SetDlgItemText, hWnd, IDC_TARGETFILE, ADDR szTargetFile

        .ENDIF

      .ELSEIF ax == IDC_PATCH

        ; Create a new thread which executes the operations
        INVOKE CreateThread, NULL, 0, ADDR PatchThread, hWnd, 0, ADDR nPatchThreadID
        INVOKE CloseHandle, eax

      .ELSEIF ax == IDC_EXIT
        INVOKE SendMessage, hWnd, WM_CLOSE, 0, 0
      .ENDIF

    .ENDIF

  .ELSEIF uMsg == WM_BEGINPATCH

    ; Disable the "patch" button
    INVOKE GetDlgItem, hWnd, IDC_PATCH
    INVOKE EnableWindow, eax, FALSE

  .ELSEIF uMsg == WM_ENDPATCH

    ; Enable the "patch" button
    INVOKE GetDlgItem, hWnd, IDC_PATCH
    INVOKE EnableWindow, eax, TRUE

  .ELSEIF uMsg == WM_CLOSE
    INVOKE EndDialog, hWnd, 0
  .ENDIF

  xor eax, eax
  ret
DlgProc ENDP

; The patch procedure
PatchThread PROC hWnd: DWORD
  INVOKE PostMessage, hWnd, WM_BEGINPATCH, 0, 0

  INVOKE GetDlgItemText, hWnd, IDC_TARGETFILE, ADDR szTargetFile, SIZEOF szTargetFile

  ; Obtain the backup file name
  INVOKE lstrcpy, ADDR szBackupFile, ADDR szTargetFile
  INVOKE lstrcat, ADDR szBackupFile, ADDR szBackupFileExt

  ; If the backup file already exists, ask the user if he wants to restore
  INVOKE CreateFile, ADDR szBackupFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL

  .IF eax != INVALID_HANDLE_VALUE
    mov hBackupFile, eax
    INVOKE GetFileSize, hBackupFile, NULL
    push eax
    INVOKE CloseHandle, hBackupFile
    pop eax

    .IF eax == TargetFileSize
      INVOKE MapFileAndCheckSumA, ADDR szBackupFile, ADDR nHeaderSum, ADDR nCheckSum

      .IF eax == CHECKSUM_SUCCESS

        .IF nCheckSum == TargetFileCheckSum
          mov bRestore, TRUE

          INVOKE MessageBox, hWnd, ADDR szRestoreMsg, ADDR szInfoTitle, MB_ICONINFORMATION OR MB_YESNO

          .IF eax == IDYES
            INVOKE MoveFileEx, ADDR szBackupFile, ADDR szTargetFile, MOVEFILE_REPLACE_EXISTING

            .IF eax != 0
              INVOKE MessageBox, hWnd, ADDR szRestoreSuccessMsg, ADDR szInfoTitle, MB_ICONINFORMATION OR MB_OK
            .ELSE
              INVOKE MessageBox, hWnd, szRestoreErrorMsg, ADDR szErrorTitle, MB_ICONERROR OR MB_OK
            .ENDIF
              
          .ENDIF

        .ENDIF

      .ENDIF

    .ENDIF

  .ENDIF

  ; Patch the file
  .IF bRestore == FALSE
    ; Open the file specified in the "target" edit box
    INVOKE CreateFile, ADDR szTargetFile, GENERIC_READ OR GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL

    .IF eax != INVALID_HANDLE_VALUE
      mov hTargetFile, eax

      ; Get the target file size
      INVOKE GetFileSize, hTargetFile, NULL

      .IF eax == TargetFileSize

        ; Computes the file checksum
        INVOKE MapFileAndCheckSumA, ADDR szTargetFile, ADDR nHeaderSum, ADDR nCheckSum

        .IF eax == CHECKSUM_SUCCESS

          .IF nCheckSum == TargetFileCheckSum
            INVOKE IsDlgButtonChecked, hWnd, IDC_BACKUP

            .IF eax == BST_CHECKED

              ; Create the backup file
              INVOKE CopyFile, ADDR szTargetFile, ADDR szBackupFile, 0

              .IF eax == 0
                INVOKE MessageBox, hWnd, ADDR szBackupErrorMsg, ADDR szWarningTitle, MB_ICONWARNING OR MB_OKCANCEL

                .IF eax == IDCANCEL
                  mov bPatch, FALSE
                .ENDIF

              .ENDIF

            .ENDIF

            .IF bPatch == TRUE
              xor ecx, ecx
              lea eax, nOffsets
              lea edx, nNewBytes

              patch:

              ; Save the registers
              pushad
              pushad

              ; Move to the offset
              INVOKE SetFilePointer, hTargetFile, [eax + ecx * 4], NULL, FILE_BEGIN

              ; Restore the registers
              popad

              ; Write the new byte
              add edx, ecx
              INVOKE WriteFile, hTargetFile, edx, 1, ADDR nBytesWritten, NULL

              ; Restore the registers
              popad

              inc ecx
              cmp ecx, SIZEOF nNewBytes
              je endpatch

              jmp patch

              endpatch:

              ; Truncate the file to the new file size
              INVOKE SetFilePointer, hTargetFile, TargetFileNewSize, NULL, FILE_BEGIN
              INVOKE SetEndOfFile, hTargetFile

              ; Display the message of success
              INVOKE MessageBox, hWnd, ADDR szPatchSuccessMsg, ADDR szInfoTitle, MB_ICONINFORMATION OR MB_OK

            .ENDIF

            mov bPatch, TRUE
          .ELSE
            INVOKE MessageBox, hWnd, ADDR szCheckSumErrorMsg, ADDR szErrorTitle, MB_ICONERROR OR MB_OK
          .ENDIF

        .ELSE
          INVOKE MessageBox, hWnd, ADDR szCheckSumErrorMsg, ADDR szErrorTitle, MB_ICONERROR OR MB_OK
        .ENDIF

      .ELSE
        INVOKE MessageBox, hWnd, ADDR szFileSizeErrorMsg, ADDR szErrorTitle, MB_ICONERROR OR MB_OK
      .ENDIF

      INVOKE CloseHandle, hTargetFile
    .ELSE
      INVOKE MessageBox, hWnd, ADDR szOpeningErrorMsg, ADDR szErrorTitle, MB_ICONERROR OR MB_OK
    .ENDIF

  .ENDIF

  mov bRestore, FALSE

  INVOKE PostMessage, hWnd, WM_ENDPATCH, 0, 0
  INVOKE ExitThread, 0
  xor eax, eax
  ret
PatchThread ENDP

END start

Conclusion :


Si vous avez des remarques, des questions, des suggestions, n'hésitez pas à
ajouter un commentaire !

Vous pouvez aussi aller sur mon site pour les mises à jour (bien que j'uploade
régulièrement sur AsmFr.Com) :

http://kickme.to/charloweb (voir "Pastille").

UPDATE DU 11.08.2003 :
------------------------------------------------------------
Suite à plusieurs demandes, j'ai ajouté une vieille version du patch, plus simplifiée.
Celle-ci se trouve dans le fichier "old.zip".

Il faudrait que je fasse une grosse update et ajouter la 2.0, mais je n'ai pas le temps. Vous pouvez me contacter par mail si vous voulez que je vous envoie les sources mises à jour !

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.