Patching EXEs
[I wrote this to the other list. I'd better cross post it here. Don't want
to miss any one.]
George Henry said a while back something about patching EXEs. Below are two
programs which achieve this.
GENPATCH.EX
takes two files, the old one and the new one and produces a patch file
>GENPATCH old.exe new.exe patch.dat
The patch file was produced using print.e so isn't space-saving at all.
Perhaps one could come up with a binary form, e.g.
OFFSET 1 x DWORD
NUMBER_OF_BYTES 1 x WORD
BYTES NUMBER_OF_BYTES x BYTE
PATCHIT.EX
takes the patch data, the old file and produces a new file
>PATCHIT patch.dat old.exe new.exe
Initial tests work ok but, of course, if it trashes your life's work, sad.
The code is very raw and took about an hour and a half to figure out. I'd
really appreciate some constructive criticism -- how I could have done it
better, faster, tighter etc.
Bruce M. Axtens
--
"Who of us is mature enough for offspring before the offspring themselves
arrive? The value of marriage is not that adults produce children but that
children produce adults" -- Peter de Vries
GENPATCH.EX
<CODE>
-- genpatch
include get.e
include print.e
--with trace
--trace(2)
puts( 1, "GENPATCH v1.0 (c) Copyright Bruce M. Axtens, 2001.\n" )
sequence patchBlock
patchBlock = {}
integer storeCount
storeCount = 0
integer storeNum
storeNum = -1
procedure store( integer offset, integer byte )
if offset = storeNum + 1 then
patchBlock[ length( patchBlock ) ][ 2 ] &= byte
storeNum = offset
else
patchBlock = append( patchBlock, { offset, {byte} } )
storeNum = offset
end if
end procedure
sequence cl
sequence bin1, bin2, patch
cl = command_line()
if length( cl ) < 5 then
puts( 1, "Syntax:\n\tgenpatch <binary1> <binary2> <patchname>\n" )
abort( 1 )
end if
bin1 = cl[ 3 ]
bin2 = cl[ 4 ]
patch = cl[ 5 ]
integer hbin1, hbin2, hpatch
hbin1 = open( bin1, "rb" )
if hbin1 = -1 then
puts( 1, "Could not open " & bin1 & "\n" )
abort( 2 )
end if
hbin2 = open( bin2, "rb" )
if hbin2 = -1 then
puts( 1, "Could not open " & bin2 & "\n" )
abort( 3 )
end if
hpatch = open( patch, "w" )
constant EOBIN1 = 1, EOBIN2 = 2
sequence res
integer bin1byte, bin2byte
integer status
integer offset
offset = 1
while 1 do
res = get_bytes( hbin1, 1 )
if length( res ) = 0 then
status = EOBIN1
exit
end if
bin1byte = res[ 1 ]
res = get_bytes( hbin2, 1 )
if length( res ) = 0 then
status = EOBIN2
exit
end if
bin2byte = res[ 1 ]
if bin1byte != bin2byte then
store( offset, bin2byte )
storeCount += 1
end if
offset += 1
end while
trace(2)
if status = EOBIN1 then
while 1 do
res = get_bytes( hbin2, 1 )
if length( res ) = 0 then
exit
end if
store( offset, res[ 1 ] )
storeCount += 1
offset += 1
end while
elsif status = EOBIN2 then
--
end if
close( hbin1 )
close( hbin2 )
print( hpatch, patchBlock )
close( hpatch )
printf( 1, "%d changes after comparing %s with %s stored in %s.\n", {
storeCount, bin1, bin2, patch } )
</CODE>
PATCHIT.EX
<CODE>
include get.e
--with trace
--trace(2)
puts( 1, "PATCHIT v1.0 (c) Copyright Bruce M. Axtens, 2001.\n" )
integer patchCount
patchCount = 0
sequence patchBlock
sequence cl
sequence patch, bin1, bin2
cl = command_line()
if length( cl ) < 5 then
puts( 1, "Syntax:\n\tpatchit <patchname> <binary1> <binary2>\n" )
abort( 1 )
end if
patch = cl[ 3 ]
bin1 = cl[ 4 ]
bin2 = cl[ 5 ]
integer hbin1, hbin2, hpatch
hbin1 = open( bin1, "rb" )
if hbin1 = -1 then
puts( 1, "Could not open " & bin1 & "\n" )
abort( 2 )
end if
hbin2 = open( bin2, "wb" )
if hbin2 = -1 then
puts( 1, "Could not open " & bin2 & "\n" )
abort( 3 )
end if
hpatch = open( patch, "r" )
patchBlock = get( hpatch )
if patchBlock[ 1 ] != GET_SUCCESS then
puts( 1, "Could not load the patch information\n" )
abort( 4 )
end if
patchBlock = patchBlock[ 2 ]
sequence res
atom bin1byte
integer offset
offset = 0
integer patched
patched = 0
integer eopatch
eopatch = 0
integer looper
looper = 1
trace(2)
while 1 do
for i = 1 to looper do
res = get_bytes( hbin1, 1 )
offset += 1
end for
if length( res ) = 0 then
exit
end if
bin1byte = res[ 1 ]
patched = 0
for i = 1 to length( patchBlock ) do
if patchBlock[ i][ 1 ] > offset then
looper = 1
exit
end if
if offset = patchBlock[ i ][ 1 ] then
puts( hbin2, patchBlock[ i ][ 2 ] )
patchCount += 1
looper = length( patchBlock[ i ][ 2 ] )
patchBlock = patchBlock[ 2 .. length( patchBlock ) ]
if length( patchBlock ) = 0 then
eopatch = 1
end if
patched = 1
exit
end if
end for
if patched = 0 then
puts( hbin2, bin1byte )
end if
if eopatch then
exit
end if
end while
close( hbin1 )
if length( patchBlock ) > 0 then
puts( hbin2, patchBlock[ length( patchBlock ) ][ 2 ] )
patchCount += 1
end if
close( hbin2 )
close( hpatch )
printf( 1, "%d patches in %s applied to %s to give %s.\n", { patchCount,
patch, bin1, bin2 } )
</CODE>
|
Not Categorized, Please Help
|
|