Posted about 1 year ago, by Ksbunker

I post this here because, lets face it, zonehacks is all about doing things we wern't meant to be able to do, exploiting, etc... it all comes to security. The following code is written in asm, however, it can with very little work be ported to any language, at least that's the intention.

Like ALL protections, this can be circumvented and rendered useless. But I find it best to use the analogy of a lock on a door in describing the purpose and effectiveness of protections against intruders.

There are of course locksmiths out there that can pick the lock on a door, but does that mean the door should be left unlocked and opened for all who choose to enter? Of course not. Any protection is only as good as the level of ability of the intruder. While a simple lock may not stop (or in best case, delay) a locksmith, it will stop 90% of the people out there. So just as a simple lock stops 90% of people, simple protections (such as this) stop 90% of the people trying to gain access to your hardwork.

Enough rambling, the code. 

[code]


.386
.model flat, stdcall
option casemap :none   ; case sensitive

; ###############################

include \masm32\include\windows.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\imagehlp.inc

includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\imagehlp.lib

; ################################

GetCheckSum PROTO :DWORD

.data

PECheckSum dd 0
szFailed db "CheckSums did NOT match, file has been modified!", 0
szSuccess db "CheckSums MATCH, continue!", 0
szBuffer db 256h dup(0)

.code

start:

push 0
call GetModuleHandle
mov edx, eax                 ;00400000
mov ecx, [edx+3Ch]      ;Offset to PE signature
add ecx, edx                  ;ecx=PE Header
add ecx, 58h                  ;ecx=CheckSum
mov eax, dword ptr [ecx]
mov PECheckSum, eax               ;save contents to PECheckSum

Invoke GetModuleFileName, 0, ADDR szBuffer, 256h
Invoke GetCheckSum, ADDR szBuffer
cmp eax, [PECheckSum]             ;does PECheckSum = Our Generated CheckSum
jne @notequal

Invoke MessageBox, 0, ADDR szSuccess, 0, MB_OK
Invoke ExitProcess, 0

@notequal:
Invoke MessageBox, 0, ADDR szFailed, 0, MB_OK
invoke ExitProcess, 0

GetCheckSum PROC FileName:DWORD
.data
  dwHeader dd 0
  dwCheckSum dd 0
.code
  Invoke MapFileAndCheckSum, FileName, addr dwHeader, addr dwCheckSum
  cmp eax, CHECKSUM_SUCCESS
  jne @error
  mov eax, [dwCheckSum]
  ret
@error:
  mov eax, 0
  ret
GetCheckSum EndP

end start

[/code]

 

How it works. It relies on a label in the PE Header called 'CheckSum', all PE files automatically generate this value during compile-time. It is a value unique to the data sequence (in this case the .TEXT or .CODE section), so it can be used as a simple yet effective means to compare whether someone has tampered with (y)our code. NOW, this by itself is not enough, we must be able to generate this checksum during run-time so that we can compare the run-time checksum against the compile-time checksum, if the file(s) are 100% the same, the checksums should and will match. HOWEVER, in the event someone has patched any portion of your code, the run-time generated checksum will be different to that of the compile-time checksum.

Fortunately for us, we know the API used by Windows developers to generate the PE Header Checksum, and even more fortunate, we have access to it. It resides in the library 'imagehlp.dll' and is called 'MapFileAndCheckSum'.

Perhaps in a follow up thread/post I will explain how to defeat this form of protection. But i'll be impressed if someone else posts a how-to.

Cheers, Ksbunker.

Author Info Comment