TouchIT() : Sets Compilation time and Checksum for AutoHotkey executables
Posted: 10 Sep 2017, 10:07
Quick tip:
When you want to modify a file (with File object) without affecting the file's last modified timestamp,
the following couple of lines can be used to save/restore timestamps.
TouchIT() - Touch Internal Timestamp.
The function was named after MS-DOS' touch.exe, a derivative of UNIX touch command
The compilation timestamp is stored as unix time, a UINT. The value represents the seconds elapsed since the year 1970.
The constant number 11644473600 is the seconds elapsed between the years 1601 and 1970.
Couple of read-only helper functions:
PE_CompilationTime()
Returns Compilation time as local time in YYYYMMDDHHMMSS format
PE_CheckSum()
While writing these function, I used the following command line tool to crosscheck the results:
checksum.exe (32 KiB), download from http://www.the-sz.com/products/checksum/
The site has a good collection of tools.. Yet to try them. Homepage: http://www.the-sz.com/products/
When you want to modify a file (with File object) without affecting the file's last modified timestamp,
the following couple of lines can be used to save/restore timestamps.
Code: Select all
; Save File timestamps
DllCall( "GetFileTime", "Ptr",File.__Handle, "Int64P",T1, "Int64P",T2, "Int64P",T3 )
; Restore File timestamps
DllCall( "SetFileTime", "Ptr",File.__Handle, "Int64P",T1, "Int64P",T2, "Int64P",T3 )
TouchIT() - Touch Internal Timestamp.
The function was named after MS-DOS' touch.exe, a derivative of UNIX touch command
The compilation timestamp is stored as unix time, a UINT. The value represents the seconds elapsed since the year 1970.
The constant number 11644473600 is the seconds elapsed between the years 1601 and 1970.
Code: Select all
/*
TouchIt() sets PE compilation timestamp to file's modified timestamp and fills in the PE checksum.
Written specifically for AutoHotkey 1.1 complied scripts, by SKAN, 06-Sep-2017.
Note: PE Modification is NOT allowed in AutoHotkey 1.0 (Classic) executables.
*/
TouchIT( PEfile) {
Local File, T1:=0, T2:=0, T3:=0, Chk1:=0, Chk2:=0
File := FileOpen(PEfile,"rw")
If ! IsObject(File)
Return
; Save File timestamps
DllCall( "GetFileTime", "Ptr",File.__Handle, "Int64P",T1, "Int64P",T2, "Int64P",T3 )
If ( File.ReadUSHORT()<>0x5A4D ) ; Is IMAGE_DOS_HEADER.e_magic = 'MZ' ?
Return File.Close() + ""
File.Seek(60,0) ; Seek IMAGE_DOS_HEADER.e_lfanew
File.Seek(File.ReadUINT(),0) ; Seek IMAGE_NT_HEADERS
If ( File.ReadUINT()<>0x00004550 ) ; Is IMAGE_NT_HEADERS.Signature = 'PE' ?
Return File.Close() + ""
File.Seek(4,1) ; Seek IMAGE_FILE_HEADER.TimeDateStamp
File.WriteUINT(T3//10000000-11644473600)
File.Seek(12+64,1) ; Seek IMAGE_OPTIONAL_HEADER.CheckSum
DllCall( "ImageHlp.dll\MapFileAndCheckSumA", "AStr",PEfile, "PtrP",Chk1, "PtrP",Chk2 )
File.WriteUINT(Chk2) ; Update checksum
; Restore File timestamps
DllCall( "SetFileTime", "Ptr",File.__Handle, "Int64P",T1, "Int64P",T2, "Int64P",T3 )
File.Close()
Return True
}
Couple of read-only helper functions:
PE_CompilationTime()
Returns Compilation time as local time in YYYYMMDDHHMMSS format
Code: Select all
PE_CompilationTime( PEfile ) { ; By SKAN | 10-Sep-2017
Local Bin, File := FileOpen(PEfile,"r"), nFILETIME := 0
If ! IsObject(File)
Return
File.RawRead(Bin,2048), File.Close()
If ( NumGet(Bin,0,"UShort")<>0x5A4D || NumGet(Bin,NumGet(Bin,60,"UInt"),"UInt")<>0x00004550 ) ;'MZ' and 'PE'
Return
nFILETIME := ( (NumGet(Bin,NumGet(Bin,60,"UInt")+8,"UInt")+11644473600 )*10000000 ) ; UNIXTIME to FILETIME
DllCall( "FileTimeToLocalFileTime", "Int64P",nFILETIME, "Int64P",nFILETIME ) ; FILETIME UTC to local
DllCall( "FileTimeToSystemTime", "Int64P",nFILETIME, "Ptr",&Bin ) ; Bin is SYSTEMTIME
Return Format( "{1:04}{2:02}{3:02}{4:02}{5:02}{6:02}", NumGet(Bin,00,"UShort"), NumGet(Bin,02,"UShort")
, NumGet(Bin,06,"UShort"), NumGet(Bin,08,"UShort"), NumGet(Bin,10,"UShort"), NumGet(Bin,12,"UShort") )
}
Code: Select all
PE_CheckSum( PEfile ) { ; By SKAN | 10-Sep-2017
Local Chk1:=0, Chk2:=0
If ( DllCall( "ImageHlp.dll\MapFileAndCheckSumA", "AStr",PEfile, "PtrP",Chk1, "PtrP",Chk2 ) = 0 )
Return ( Chk1 = Chk2 ? "Checksum okay!" : "Checksum incorrect!" )
. ( "`nCurrent Checksum: " Format( "0x{:08X}", Chk1 ) )
. ( "`nCorrect Checksum: " Format( "0x{:08X}", Chk2 ) )
}
While writing these function, I used the following command line tool to crosscheck the results:
checksum.exe (32 KiB), download from http://www.the-sz.com/products/checksum/
The site has a good collection of tools.. Yet to try them. Homepage: http://www.the-sz.com/products/