54 lines
2.8 KiB
Python
54 lines
2.8 KiB
Python
"""Validate NSIS CRC, complete solid-deflate stream, and every application file."""
|
|
from pathlib import Path
|
|
import hashlib,json,struct,zlib
|
|
|
|
folder=Path(__file__).parent
|
|
root=Path('C:/wechat_rpa')
|
|
installer=root/'dist/installer/甄AI客服-安装包-v1.4.25.exe'
|
|
application=root/'dist/ZhenAI-WeCom-Assistant-v1.4.25'
|
|
size=installer.stat().st_size
|
|
with installer.open('rb') as stream:
|
|
prefix=stream.read(200000)
|
|
start=prefix.find(b'NullsoftInst')-8
|
|
assert start>=512 and start%512==0
|
|
flags,magic,a,b,c,header_size,following=struct.unpack('<7I',prefix[start:start+28])
|
|
assert magic==0xdeadbeef and following==size-start
|
|
stream.seek(size-4); expected_crc=struct.unpack('<I',stream.read(4))[0]
|
|
stream.seek(512); left=size-516; crc=0
|
|
while left:
|
|
chunk=stream.read(min(left,1024*1024)); assert chunk
|
|
left-=len(chunk); crc=zlib.crc32(chunk,crc)
|
|
assert crc==expected_crc, 'Installer CRC mismatch'
|
|
stream.seek(start+28); left=size-start-32
|
|
decoder=zlib.decompressobj(-15)
|
|
buffer=b''; remaining=None; block_hash=None; hashes=set(); blocks=0; total=0; header=None
|
|
while left:
|
|
chunk=stream.read(min(left,65536)); assert chunk
|
|
left-=len(chunk); buffer+=decoder.decompress(chunk)
|
|
while True:
|
|
if remaining is None:
|
|
if len(buffer)<4: break
|
|
remaining=struct.unpack('<I',buffer[:4])[0];buffer=buffer[4:]
|
|
if blocks==0: assert remaining==header_size
|
|
block_hash=hashlib.sha256(); blocks+=1
|
|
n=min(remaining,len(buffer)); block_hash.update(buffer[:n]);remaining-=n;total+=n;buffer=buffer[n:]
|
|
if remaining: break
|
|
hashes.add(block_hash.hexdigest()); remaining=None
|
|
assert decoder.eof and not decoder.unused_data and not buffer and remaining is None, 'Incomplete NSIS block stream'
|
|
assert blocks>3000
|
|
files=[p for p in application.rglob('*') if p.is_file()]
|
|
missing=[]
|
|
for file in files:
|
|
with file.open('rb') as stream: digest=hashlib.file_digest(stream,'sha256').hexdigest()
|
|
if digest not in hashes: missing.append(str(file.relative_to(application)))
|
|
assert not missing, f'Application files missing or changed: {missing}'
|
|
assert len(files)>4000
|
|
result={'version':'1.4.25','installerCrc32':f'{crc:08x}','crcPassed':True,
|
|
'completeDeflateStream':True,'completeLengthPrefixedBlocks':True,
|
|
'blocks':blocks,'applicationFilesMatchedBySha256':len(files),'missingFiles':missing,
|
|
'installerSha256':hashlib.sha256(installer.read_bytes()).hexdigest(),
|
|
'validationMethod':'NSIS CRC, complete raw-deflate blocks, and all application payload SHA256 hashes',
|
|
'installed':False,'realMessagesSent':0}
|
|
(folder/'nsis-payload-integrity.json').write_text(json.dumps(result,ensure_ascii=False,indent=2),encoding='utf-8')
|
|
print(json.dumps(result,ensure_ascii=False))
|