Log in

View Full Version : Help with unpacking UPX


Scally
July 12th, 2001, 12:02
Hi folks, I’ve never had much luck with unpacking in the past & following some of the threads on these groups, I’ve tried to unpack various progs(usu notepad) and follow through several tuts. One of these threads suggested that UPX was an easy one to learn from & so I was pleased to come across a file (GENViewer Legacy Edition - (1.9MB) -
http://www.legacyfamilytree.com/_downld/Addons/GenViewerLegacyEdition.exe) packed with UPX 1.07 – according to fileinfo.
I’ve tried using sice/procdump as per various tut’s but I suspect that there’s a problem with the import table as looking in sice (after the dump & changing the ep) the prog crashes when it should be redirected by a call to [Kernel32!Getmodulehandlea]

Can anyone tell me where I’m going wrong? What I did is below:

1. Changed Characteristics of upx0 to 20, so sice could break
2. Opened in symbol loader at pushad
3. Scrolled down to popad, breakpointed
4. F5, so sice broke on popad
5. F10 to step onto the JMP (@ 686D54 JMP 5979AC)
6. F10 to get to the jump
7. Bc to clear bpoints
8. Typed A (enter) JMP EIP (enter) (esc)
9. F5 to exit sice
10. Start procdump, rt click on gvleg.exe
11. Choose full dump & save file as dump.exe
12. Choose kill task
13. Edit pe header – image base=10000, so new eip= 5979ac-10000 = 5879ac
Result prog crashes before it opens in sym loader.
Changing the image base to 400000 enabled me to start the prog but where it should be calling Kernel, it goes to other code
Any constructive help welcom
TIA
Scally

cluesurf
July 12th, 2001, 12:22
Quote:
Scally (07-12-2001 10:02):
Hi folks, I’ve never had much luck with unpacking in the past & following some of the threads on these groups, I’ve tried to unpack various progs(usu notepad) and follow through several tuts. One of these threads suggested that UPX was an easy one to learn from & so I was pleased to come across a file (GENViewer Legacy Edition - (1.9MB) -
http://www.legacyfamilytree.com/_downld/Addons/GenViewerLegacyEdition.exe) packed with UPX 1.07 – according to fileinfo.
I’ve tried using sice/procdump as per various tut’s but I suspect that there’s a problem with the import table as looking in sice (after the dump & changing the ep) the prog crashes when it should be redirected by a call to [Kernel32!Getmodulehandlea]

Can anyone tell me where I’m going wrong? What I did is below:

1. Changed Characteristics of upx0 to 20, so sice could break
2. Opened in symbol loader at pushad
3. Scrolled down to popad, breakpointed
4. F5, so sice broke on popad
5. F10 to step onto the JMP (@ 686D54 JMP 5979AC)
6. F10 to get to the jump
7. Bc to clear bpoints
8. Typed A (enter) JMP EIP (enter) (esc)
9. F5 to exit sice
10. Start procdump, rt click on gvleg.exe
11. Choose full dump & save file as dump.exe
12. Choose kill task
13. Edit pe header – image base=10000, so new eip= 5979ac-10000 = 5879ac
Result prog crashes before it opens in sym loader.
Changing the image base to 400000 enabled me to start the prog but where it should be calling Kernel, it goes to other code
Any constructive help welcom
TIA
Scally


Hi Scally, dump it with Pe editor from Yoda
imagebase should be 400000 in most pe files
oep=5979ac-400000=1979ac
just my 2 cents
cluesurf

qferret
July 12th, 2001, 21:51
Well, I tried downloading it to take a peek, but the entire site seems to be down :-(

Anyway....it looks like you pretty much have the method for UPX down.....only thing I can think of from your post is ...are you sure it's the right popad? (There are a few in the unpacking routine)

The loader usually gets loaded at a fairly high mem address & writes the proggy to the preferred image base. (usually 400000). So if your tracing through code @ say 550000+ (solely an example), and come across a popad closely followed by a JMP to say 410EB0.....that's probably the one you want.

Dunno if that's the prob, but since I couldn't d/l it, that's the best I could come up with ;-)

Hope it helps

?ferret

qferret
July 12th, 2001, 21:55
as far as it crashing.....UPX doesn't mangle imports, so it's gotta be the dump....sounds like you're dumping before Kernel32 imports are resolved

Scally
July 13th, 2001, 17:40
Yeah,
Cluesurf: Tnx, I tried shifting the ep to 400000 - thats how I got it to run at all in
sice but the first dll call it made wasto a mem address that had 00 in it & it should have been to the sig of a kernel32 mod.

qferret: Tnx, I'll try stepping from after the point I saw the popad. What you said does make sense but the packed version is openable with wdasm & there's no popad with an unconditional jump after (higher than) the one at 296d54 (686d54 in sice) to jmp 1a79ac. I know it may jump back & I'll check this out. Btw, I couldn't d/l from the url anymore myself. Looks like you gotta go thru the page at:
h*tp://www.legacyfamilytree.com/GENViewerDownload.asp
Even that didn't work every time but the main site url seems to:
http://www.legacyfamilytree.com then downloads, then genviewer.
I agree it sounds like mis op on my part. Is there a definitive way of finding a packed progs ep?
Scally

Kayaker
July 14th, 2001, 01:44
Hi Scally,

Interesting app. I was able to d/l it from the 1st link you gave, the site itself is in ether but the exe d/l OK directly.

The 10,000 ImageBase may be a little trick thrown in to fool auto-dumpers like Procdump and bad-boy crackers. Whether it was intentional or not I'm not sure, or just that it had something to do with UPX being run on NT. If you look at the packed file in PEditor (in the Directory Table Viewer) you see there is an entry for BaseRelocations. Interesting. If you unpack it with the UPX -d switch you see that while there is a .reloc section, the BaseRelocations entry is empty. Plus, except for the ImageBase of 10000, all the sections indicate a base address of 400000. More interesting.

If you change the ImageBase to 400000 in the -d unpacked file it crashes because the pointers to the Import table are screwed up as you mentioned. They are off by 400000 - 10000 = 3F000. So I guess the original program was designed to load at 400000, after being packed it's set to load at 10000, but it can't so UPX uses the base relocations to fix up a few addresses.

I've been doing some reading on base relocations, since it's not something we're normally concerned about, and there's some good explanations of it in "Peering Inside the PE: A Tour of the Win32 Portable Executable File Format" by Matt Pietrek as well as the Luevelsmeyer doc, if you're interested in exploring it further. To quote:

"When the linker creates an executable, it assumes that the file will be memory-mapped to a specific location in memory. That address is stored in this field, assuming a load address allows linker optimizations to take place. If the file really is memory-mapped to that address by the loader, the code doesn't need any patching before it can be run. In executables produced for Windows NT, the default image base is 0x10000. For DLLs, the default is 0x400000. In Chicago, the address 0x10000 can't be used to load 32-bit EXEs because it lies within a linear address region shared by all processes. Because of this, Microsoft has changed the default base address for Win32 executables to 0x400000. Older programs that were linked assuming a base address of 0x10000 will take longer to load under Chicago because the loader needs to apply the base relocations.

When the linker creates an EXE file, it makes an assumption about where the file will be mapped into memory. Based on this, the linker puts the real addresses of code and data items into the executable file. If for whatever reason the executable ends up being loaded somewhere else in the virtual address space, the addresses the linker plugged into the image are wrong. The information stored in the .reloc section allows the PE loader to fix these addresses in the loaded image so that they're correct again. On the other hand, if the loader was able to load the file at the base address assumed by the linker, the .reloc section data isn't needed and is ignored. The entries in the .reloc section are called base relocations since their use depends on the base address of the loaded image."

In any case, it would be interesting if someone with NT could pack a file with UPX and see if the base address changes, or whether this was done by hand. There are only 4 addresses fixed up in the BaseRelocations section in the packed file (starts at raw offset B1D5C). Or maybe someone has an explanation for this.


In any case, it's easy to manually dump it if you use 400000 as the base address at dumping time. UPX is simple to trace because you can set a bpx on the diagnostic LOOP statement which you can find a few screens down in Softice. Just double click on it to set the bp and press F5. From there it's a short trace to the POPAD just before the jmp to OEP. Here you can dump it as a raw /dump or a /pedump with Icedump, or setting the 'jmp eip' and doing a full dump with Procdump or PEditor might work as well.

The trick is getting the ImageBase right. Since little can hide from Softice, use "map32" to get a true memory map of the file that Procdump or PEditor doesn't give you:

:map32 gvleg
Owner Obj Name Obj# Address Size Type
GVLEG UPX0 0001 016F:00401000 001D8000 UDATA RW
GVLEG UPX1 0002 016F:005D9000 000AE000 IDATA RW
GVLEG .rsrc 0003 016F:00687000 00004000 IDATA RW

Since this is obviously a regular PE file with ImageBase 400000, you just need to use this when specifying the dump parameters. I had no problems getting a working dump with

/pedump 400000 1979ac filename

Ciao,
Kayaker

Scally
July 14th, 2001, 06:47
Hi Kayaker,
You done it again! I think the programmer was being cute. Having got it dumped, it looks like the Delphi resources have been compressed. There's a reference to 'Victor Kasend* reSource Compres*ion' that I found with exescope but can't get onto the site that Dogpile finds (ht*p://torry.spang.org/listk.htm). Dede processes the file but shows no info.
Scally

Scally
July 16th, 2001, 12:12
Well, I spent almost all day tryin to follow this one - with no luck - As none of the delphi decomp's seem to work except exe2dpr trial version, I'm kinda stuck.
I've stepped thru it from getwindowtexta at the reg box, from the beginning to try to find the days left in a register (or address in a register) in hex & dec & still can't see it. I tried going back from the invalid code message with wm_lbuttonup but just got lost in the code.
Would really appreciate the guidance of someone familiar with delphi.
Scally