4. It wouldn't be my place to direct you to a good OllyDbg tut, as I haven't used one for the longest time. There are hundreds out there though. Maybe somebody else will have a recommendation.
2. I still don't understand why you need to use UPX at all. You can patch any PE as you like without needing to compress it.
To save a patch to disk in OllyDbg, highlight the code that you have modified, right-click, 'Copy to executable', 'Selection'. When you close the window that appears you will be prompted to save. This will be your patched file.
1. You're welcome
3. Two points; the first one is just for completeness.
3a. To find the position of a specific function in the IAT, you can do the following:
First find the bounds of the IAT: Locate any CALL DWORD PTR DS:[<&dll.fn>]. This DWORD pointer is almost certainly inside your IAT. For example:
00451211 FF15 18974A00 CALL DWORD PTR DS:[<&kernel32.GetVersion>]
You can extract the numerical address from the opcode. FF15 is 'CALL DWORD PTR', and 18974A00 is the little-endian DWORD for the IAT pointer. Split this into bytes and reverse the order to get 004A9718 (i.e. convert to big-endian). Now this address is firmly inside this target's IAT. If you 'Goto' this address within the dump window (in 16 byte hex mode), you'll see a bunch of dwords, many of them starting with 77 or 7C. This is your IAT. Use your head to work out where it starts (often 1000 aligned) and where it ends (two nulls in a row, if the IAT is intact).
Now to find where a given function pointer lives inside this IAT, you can simply perform a memory search (in the dump window) over the appropriate range. Find out the address of Sleep, pad it out with zeros into a DWORD, reverse the bytes as before and hit the search button. The rest should be obvious.
However, you say that Sleep isn't imported in your target. You can verify this using your PE editor - if it doesn't appear under kernel32's thunk then indeed, you'll have to rethink. As before, you can inject a reference into your IT and let Windows take care of the rest, but this is tricky when you have no nicely-placed data-caves to work with. So I propose a couple of alternatives:
3b. Perhaps it's a little irresonsible of me to throw the deep end at you, but if you don't want to mess about with the IT, you can get the address of Sleep manually:
If your target imports the function GetProcAddress then you're in luck. If not, you may want to get UPX to use a higher compression level, because if UPX does compress the IAT, it will need to import GetProcAddress (in its own IAT) to finish the job.
Once you have access to GetProcAddress and GetModuleHandleA (which I'd imagine it will import for you too), you can simply get your EP patch to grab the address of Sleep on the fly:
Code:
PUSH 0 ; Terminating null
PUSH 6C6C642E ; ASCII ".dll"
PUSH 32336C65 ; ASCII "el32"
PUSH 6E72656B ; ASCII "kern"
PUSH 0 ; Terminating null
PUSH 70 ; ASCII "p"
PUSH 65656C53 ; ASCII "Slee"
LEA EDX, DWORD PTR SS:[ESP+C]
PUSH EDX ; Push "kernel32.dll"
CALL DWORD PTR DS:[<GetModuleHandleA>] ; Get the base of kernel32.dll
PUSH ESP ; Push "Sleep"
PUSH EAX ; Push Kernel32.dll
CALL DWORD PTR DS:[<GetProcAddress>] ; Get the address of Sleep
ADD ESP, 1C ; Remove strings from the stack
MOV DWORD PTR DS:[xxxxxxxx], EAX ; Save the address of Sleep
This snippet will get the address of Sleep for you on the fly and save it into xxxxxxxx (which you should set to be some null in the IAT, perhaps). All you need to do is fill in the IAT locations of GetModuleHandleA and GetProcAddress. I've encoded the names (of Sleep and Kernel32.dll) as DWORDS - this is what all those PUSHes are.
This may all seem a lot more complicated, and I guess it is, but it doesn't involve changing your IT. The choice is yours, really.
Another thought would be to use ImpRec to do all the hard work for you. If you don't have this tool, get it. It's essential for just about any unpacking job. The idea goes something like: Fire up your target and patch the address of Sleep into the null entry following the kernel32 thunk. Now use ImpRec to rip a copy of the IAT and cut the thunk after your new entry. Now 'Fix Dump' on your target. This will add an extra IT to the end of your file, which you said you didn't want, but you should be able to work around this by telling ImpRec to generate new imports by ordinal (hence making the IT smaller than the existing one) and then planting the new IT directly over the old one.
Maybe I should stop typing now. I'm sorry if this is too much for you, but better too much than too little, right?
Keep us posted on your progress
Admiral