Patching a Program Without Source Code
codexon.com
codexon.com
One of our drivers emulated the Novell IPX/SPX API on the PC and it worked great. Except for one piece of software which would crash (it was a 3270 emulator). I was task with debugging this problem.
It turned out that an optimization in our code meant that if you sent a packet to yourself it would be never actually go into the network. We'd simply immediately deliver it. The real NE2000 driver would send the packet on the network and then receive it.
This piece of software was using a packet sent to itself as a test of network connectivity and because of the way in which the code was written the packet had to be received with a short delay. Basically, the software called Send_Packet and when that API returned it would clear a flag and then it would hang around and wait for the flag to change.
The flag would be changed inside the ESR (sort of interrupt service routine) registered by the software for receiving packets.
Trouble was our optimization meant that the ESR was called while Send_Packet was executing (i.e. before it returned) and hence the flag was always zero and the software died.
The solution was... to ship our network driver with special code that I wrote that would examine the code of all programs that registered ESR for packet receipt. By examining the ESR routine code I would determine whether this particular piece of software was running and patch it to get around this problem.
(Yes, you did read that right: we shipped a network driver that would patch host software live.)
We could have added a flag for 'really transmit' this to the hand-off but we were obsessed with speed and memory utilization (this is back in the days of extended memory and all that fun) and so this relatively large change to our code to fix one piece of software was deemed unacceptable.
And yes we did fake the network test because the adapter would give us network status so the software ended up getting the right result.
Fortunately, the replacement for this system was already in development. Unfortunately, we had to patch the system on two occasions before its replacement was ready. Fortunately we were able to make both fixes by patching the binary - once to change a hard-coded encryption key that was linked in to the executable, and once to change a printf format string that was causing a critical bug in production.
The day we finally launched the replacement system and retired the un-buildable codebase was the biggest relief of my career. (Not least because only the team and our immediate manager were ever told about the problem.)
That was a failure, but one innovation, given that Reader checked the integrity of its code against patching... I simply ran Reader, waited 500 milliseconds, then patched it in memory, after the code that checked!
Any time I wanted to break somewhere, I'd inject an infinite loop and watch for the CPU to redline. Then I'd break in, pause the execution, replace the loop with the original instructions, step through it, put the loop back in, and do whatever I wanted to do. This eventually became an automated "nondebugger", which I've since used in various hostile environments.
It's amazing the random things you'll come up with after a few days of way too little sleep and way too much caffeine.
In that case you simply write down binary signatures surrounding your patch, open executable with any hex editor, find those signatures and patch. Then do binary diff, save it into CRK file and distribute.
PS. I wonder why this guy copied EDX into ECX instead of just doing PUSHF...
$ perl -i.bak -p0777e \
'print STDERR s/\xe4\x0a\x00\x2d/\xde\xad\xbe\xef/g + 0 . "\n"' a.out
1
$ cmp -l a.out.bak a.out
50161 344 336
50162 12 255
50163 0 276
50164 55 357
$
Perl prints the number of substitutions done. If it's 1, all's well.