The most important part of the program is the string-search-part.
The easiest way to check the entire file for a string, is to use the REPZ
SCASB. To completely understand how to use this command, read the followin
theory first :
REPNZ SCAS m32 ; Find EAX, starting at ES:[(E)DI]
Description
Repeats a string instruction the number of times
specified in the count register ((E)CX) or until the indicated condition
of the ZF flag is no longer met. The REP (repeat), REPE (repeat while
equal), REPNE (repeat while not equal), REPZ (repeat while zero), and
REPNZ (repeat while not zero) mnemonics are prefixes that can be added
to one of the string instructions. The REP prefix can be added to the
INS, OUTS, MOVS, LODS, and STOS instructions, and the REPE, REPNE, REPZ,
and REPNZ prefixes can be added to the CMPS and SCAS instructions. (The
REPZ and REPNZ prefixes are synonymous forms of the REPE and REPNE prefixes,
respectively.) The behavior of the REP prefix is undefined when used with
non-string instructions.
The REP prefixes apply only to one string instruction
at a time. To repeat a block of instructions, use the LOOP instruction
or another looping construct.
All of these repeat prefixes cause the associated instruction to be repeated
until the count in register (E)CX is decremented to 0 (see the following
table). (If the current address-size attribute is 32, register ECX is
used as a counter, and if the address-size attribute is 16, the CX register
is used.) The REPE, REPNE, REPZ, and REPNZ prefixes also check the state
of the ZF flag after each iteration and terminate the repeat loop if the
ZF flag is not in the specified state. When both termination conditions
are tested, the cause of a repeat termination can be determined either
by testing the (E)CX register with a JECXZ instruction or by testing the
ZF flag with a JZ, JNZ, and JNE instruction.
Did you get all this? Let's quickly summarize this :
ECX = FileSize
EDI = Pointer to the data that needs to be examined (our File)
ESI = The string we are looking for
AL = First byte of data in EDI
The command continues until ECX = 0 (Entire file has been searched) or
until the Zero-flag is set. (when we have a match)
the pointer in EDI is incremented every cycle.
Here is the Search Algorithm:
mov edi,pointer-to-memoryblock ;move pointer to memory to edi
mov ecx,FileSize ;move Filesize to ecx
mov esi,offset string ;set ESI to the Opcode string we search
mov al, byte ptr [esi] ;move the first byte of the string to AL
SEARCH :
repnz scasb ;repeat until ECX=0 or AL equals
;the value of the byte [EDI], EDI is
;incremented by 1 every run
cmp ecx,0 ;If ECX=0, no matching string is found
jz NOT_IN_HERE
FOUND_A_MATCH : ;found matching byte
pushad ;save registers
dec edi ;EDI-1 because REPZ added 1 byte to much
mov ecx,StrLen ;ECX = length of the string
repz cmpsb ;repeat until the values in the memory of
;[EDI] and [ESI] are not equal, or ecx=0 cmp ecx,0 ;If ecx = 0, we have found the correct string jz PATCH_IT
popad ;Restore registers for continuing search jmp SEARCH ;go on with search
PATCH_IT :
dec edi ;EDI - 1 inc ecx ;ECX + 1 mov eax,fsize sub eax,ecx ;compute the File Offset to patch
...
NOT_IN_HERE :
...
|
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
LOCAL wc:WNDCLASSEX ; create local variables on
stack
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX ; fill values in
members of wc
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,eax
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc ; register our
window class
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,
CW_USEDEFAULT,280,150,NULL,NULL,hInstance,NULL ; Create the window
mov hwnd,eax
invoke ShowWindow, hwnd,CmdShow ; display our window
invoke UpdateWindow, hwnd
.WHILE TRUE ; The MessageLoop
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
.IF uMsg==WM_CREATE
; Create the 2 buttons, and 2 editboxes
invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,\
WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\
ES_AUTOHSCROLL,\
30,15,210,20,hWnd,StringID,hInstance,NULL
mov hwndString,eax
invoke CreateWindowEx,WS_EX_CLIENTEDGE, ADDR EditClassName,NULL,\
WS_CHILD or WS_VISIBLE or WS_BORDER or ES_LEFT or\
ES_AUTOHSCROLL,\
30,40,210,20,hWnd,NStringID,hInstance,NULL
mov hwndNString,eax
invoke SetFocus, hwndString
invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonOpen,\
WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,\
50,70,85,20,hWnd,ButtonOpenID,hInstance,NULL
mov hwndOpen,eax
invoke CreateWindowEx,NULL, ADDR ButtonClassName,ADDR ButtonPatch,\
WS_CHILD or WS_VISIBLE or BS_DEFPUSHBUTTON,\
150,70,85,20,hWnd,ButtonPatchID,hInstance,NULL
mov hwndPatch,eax
.ELSEIF uMsg==WM_COMMAND
mov eax,wParam
mov edx,wParam
shr edx,16
.IF dx==BN_CLICKED
.IF ax==ButtonOpenID ; Open button clicked?
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFile, OFFSET FilePath
mov ofn.lpstrFilter, OFFSET FilterString
mov ofn.nMaxFile,MAXSIZE
mov ofn.Flags, OFN_FILEMUSTEXIST or \
OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
OFN_EXPLORER or OFN_HIDEREADONLY
mov ofn.lpstrTitle, OFFSET Caption
invoke GetOpenFileName, ADDR ofn
.IF eax == TRUE
; Open the file
invoke CreateFile, ofn.lpstrFile, 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 GetFileSize, hFile, NULL
mov FSize, eax ; Save FileSize
Invoke GlobalAlloc, GMEM_FIXED, FSize
mov FPointer, eax
.IF eax == NULL ; If no pointer, error message
push MB_OK OR MB_ICONINFORMATION
push OFFSET NoMem
push OFFSET Error
JMP MESSAGE
.ENDIF
Invoke ReadFile, hFile,FPointer,FSize, ADDR Numb, NULL
.ELSE ;If no valid handle, error message
push MB_OK OR MB_ICONINFORMATION
push OFFSET NoFile
push OFFSET Error
jmp MESSAGE
.ENDIF
.ENDIF
.ELSEIF ax == ButtonPatchID ; Patch Button Pressed?
Invoke GetDlgItemText,hWnd,StringID,ADDR StringBuf,MAXSTR
; Get String1
mov StrLenA, eax ; Save string length
Invoke Convert,ADDR StringBuf, ADDR OString ; Convert
to bytes
Invoke GetDlgItemText,hWnd,NStringID,ADDR NStringBuf,MAXSTR ;Get
string2
.IF eax != StrLenA ; both strings equal?
push MB_OK OR MB_ICONINFORMATION ; If not, error
message
push OFFSET Error
push OFFSET NotEqual
JMP MESSAGE
.ENDIF
Invoke Convert,ADDR NStringBuf, ADDR NString ; Convert
to bytes
mov edi,FPointer ;move pointer to memory to edi
mov ecx,FSize ;move Filesize to ecx
mov esi,offset OString ;set ESI to the Opcode string
we search
mov al, byte ptr [esi] ;move the first byte of the
string to AL
SEARCH :
repnz scasb ;repeat until ECX=0 or AL equals
;the value of the byte [EDI], EDI is
;incremented by 1 every run
cmp ecx,0 ;If ECX=0, no matching string is found
jz NOT_FOUND
FOUND_A_MATCH : ;found matching byte
push ecx ;save registers
push edi
push esi
dec edi ;EDI-1 because REPZ added 1 byte to much
mov ecx,StrLen ;ECX = length of the string
repz cmpsb ;repeat until the values in the memory
o ;[EDI] and [ESI] are not equal, or ecx=0
cmp ecx,0 ;If ecx = 0, we have found the correct
string
jz PATCH_IT
pop esi ;Restore registers for continuing search
pop edi
pop ecx
jmp SEARCH ;go on with search
PATCH_IT :
pop esi
pop edi
pop ecx
dec edi ;EDI - 1
inc ecx ;ECX + 1
mov eax,FSize
sub eax,ecx ;compute the File Offset to patch (FileSize
- Remaining bytes (ecx) = Offset to patch)
Invoke SetFilePointer, hFile, eax, NULL, FILE_BEGIN
Invoke WriteFile, hFile,offset NString, StrLen, ADDR Numb, NULL
mov eax, Numb
.IF eax == StrLen ; bytes written = Bytes to write
?
push MB_OK ; If so, success-message
push OFFSET AppName
push OFFSET Done
JMP MESSAGE
.ELSE
push MB_OK OR MB_ICONINFORMATION ; If not, error
message
push OFFSET Error
push OFFSET WrFile
.ENDIF
NOT_FOUND :
push MB_OK OR MB_ICONINFORMATION ; If no handle,
error message
push OFFSET Error
push OFFSET NotFound
MESSAGE :
push NULL
Call MessageBox
.ENDIF
.ENDIF
.ELSEIF uMsg==WM_DESTROY ; Close program
invoke CloseHandle, hFile ; Release handle
invoke GlobalFree, Fpointer ; Release memory block
invoke ExitProcess,eax ; Exit
invoke PostQuitMessage,NULL
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
|