Hi all!

Does anyone know how to calculate the checksum stored in all PE's????? I know I can use imagehlp.dll, but I would like to do it "manually".

I believe I saw a thread that showed how to do it on the old messageboard, but the site is gone now :(

Posted on 2001-11-14 15:31:47 by Delight
Its something like this:

; Zero out the current checksum
mov ecx, file_len
mov edx, file_pos_in_mem
shr ecx, 1 ; We deal with 16 bit chunks
xor eax, eax

adc ax, [ecx + edx - 2]
dec ecx
jnz @B

adc eax, file_len

I can't remember my code exactly, if you can find the MS version (which is completely different because they used a compiler, and its too dumb to notice the carry flag :P ), you should see that its similar.

Posted on 2001-11-15 04:22:24 by Mirno
Mirno, the reason the code in imagehlp is so b0rked is, as far as I
can see, not because of a stupid compiler, but because m$ is trying
to obfuscate their code and make it hard to see what is going on.
The code in ntoskrnl (I believe) that does PE verification is a lot simpler.

This code, I believe, should work just fine:

MicrosoftCheckSum2 PROC C uses esi, buf:dword, len:dword
mov ecx, [len] ; buffer length
mov edx, [buf] ; edx is pointer to our buffer base
shr ecx, 1 ; we're summing WORDs, not bytes
xor eax, eax ; EAX holds the checksum

clc ; Clear the carry flag ready for later...
adc ax, [edx + (ecx * 2) - 2]
dec ecx
jnz @@theLoop

adc eax, [len]
MicrosoftCheckSum2 ENDP

It is an optimized version of m$ code that I, ahem, tripped over.
I can't remember if this is my original code or one of the optimized
versions from the thread on the old messageboard.
Posted on 2001-11-15 07:44:17 by f0dder
Thanks, it works perfectly!!! :alright:

Posted on 2001-11-15 09:37:25 by Delight
It looks like the code I wrote on the old message board!

As someone pointed out to me, the CLC isn't needed as the XOR clears the carry flag too.

The final revision of my code was about twice as fast as the MS version! Just goes to show that hand optimising can be REALLY fast (its all down to treating the carry flag like a 17th bit, which the compiler cannot do)!

Posted on 2001-11-15 09:56:13 by Mirno
:confused: What would you use Checksum for? Does it allow you to check if the file has been modified or been corrupted?

Posted on 2001-11-15 11:08:01 by JamesE
Yes, James. The M$ checksum is not a very good one, though. But
it is required on NT kernel drivers, so it's good to be able to compute it.
(Link /release also computes this checksum, I believe... at least
there's a way to make link compute it). There are also other places
where this checksum is used, though not many. And anyway, it's
always nice to be able to, ahem, trip over some code and use it
Posted on 2001-11-15 11:14:14 by f0dder
Today,I tried this code:

.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\masm32.inc

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

MicrosoftCheckSum2 PROTO C :dword,:dword
filename db '\windows\system32\kernel32.dll',0
buffer dd ?
hFile dd ?
filelen dd ?
numb db 20 dup(?)
invoke _lopen,addr filename,OF_READ
mov hFile,eax
invoke GetFileSize,eax,0
mov filelen,eax
invoke Alloc,eax
mov buffer,eax
invoke _lread,hFile,buffer,filelen
invoke _lclose,hFile

invoke MicrosoftCheckSum2,buffer,filelen
invoke dw2hex,eax,addr numb
invoke StdOut,addr numb
invoke Free,buffer
invoke ExitProcess,0

MicrosoftCheckSum2 PROC C uses esi, buf:dword, len:dword
mov ecx, [len]
mov edx, [buf]
shr ecx, 1
xor eax, eax

adc ax, [edx + (ecx * 2) - 2]
dec ecx
jnz @@theLoop
adc eax, [len]
MicrosoftCheckSum2 ENDP
end start

My O.S. is Win XP Pro.The real checksum value for kernel32.dll
is E4460 on my system;but instead of this,I get
E88CE. Why I get this incorrect value?:confused:

I get incorrect values for other files also.
Posted on 2003-04-12 06:50:22 by Vortex
Do you zero the checksum of the file first?

The checksum is always computed against a file with a zero checksum....
If you've not blanked the 32bit value, you'll get a different (and wrong) value.

Posted on 2003-04-12 07:55:43 by Mirno

O.K. I will try it later.

Thanks for your interest,


Posted on 2003-04-12 12:48:04 by Vortex

mov edi,buffer
assume edi:ptr IMAGE_DOS_HEADER
add edi,[edi].e_lfanew
assume edi:ptr IMAGE_NT_HEADERS
lea ebx,[edi].OptionalHeader.CheckSum
mov dword ptr [ebx],0

Thanks Mirno,now the algo works fine:alright:


Posted on 2003-04-13 07:14:33 by Vortex
You have garbage in your ASSEMBLY MicrosoftCheckSum2 code:
push ebp; mov ebp,esp; push esi; pop esi; leave; clc

Align 16 ; I include Align 16
MSCheckSum2 PROC buf:dword, len:dword ; before speed optimized code!!!
db 3Eh
mov ecx, [esp+8] ; ecx->len
db 3Eh
mov edx, [esp+4] ; edx->lpbuf
db 3Eh
shr ecx, 1 ;
db 3Eh
xor eax, eax ; xor eax, eax clear carry flag!
@Loop: ;
adc ax, [edx + (ecx * 2) - 2] ;
dec ecx ;
jnz @Loop ;
adc eax, [esp+8] ; len
ret 2*4 ;
MSCheckSum2 ENDP ;
OPTION PROLOGUE:PROLOGUEDEF ; turn back on the defaults

Posted on 2003-04-13 09:52:50 by lingo12
lingo,you fool,why should I need speed optimisation for such a short code?
Secondly,the original algo is presented by f0dder,sol lingo,please pay attention to your statements!


Posted on 2003-04-13 11:21:05 by Vortex
Thanks arkadash,
Yes, I'm a fool to waste advice on your professional x286 code

Posted on 2003-04-13 14:42:44 by lingo12
lingo12, notice how in your optimized version the loop code crosses a 16 byte boundary? This could have an adverse effect on some processors. Add four bytes before the PROC to align the loop. IIRC, a dword can be added at each loop and combined prior to the sum of the size.
Posted on 2003-04-13 15:52:55 by bitRAKE
Thanks bitRAKE,
Of course you are right but I posted the code without four additional
bytes to manipulate the start instructions lengths because
I'm not the author, I think about Mirno but not sure..
It is easy and I will edit my post immediately

Posted on 2003-04-13 18:14:06 by lingo12

It is easy and I will edit my post immediately
Posted on 2003-04-13 18:39:56 by bitRAKE

Read carefully the post of bitRAKE (comments on your optimisation)
this will teach you to think twice before you
pretend to be the master of asm!

Posted on 2003-04-14 02:30:40 by Vortex

Bad habits are the hardest to lose. :grin:
Posted on 2003-04-14 04:03:35 by Maverick
hrm, what's with the DS: overrides in lingos code?
Posted on 2003-04-14 04:41:23 by f0dder