Kr0n0
August 9th, 2002, 23:29
hello fellow reversers
i was trying to reverse a prog, but it showed me that i was not good enought to reverse it, so i learnt about PE file structure, still it kicked me, so i decided to learn about unpacking and decrypting.
my first victim was good old UPX 1.20w, i packed notepad and decided to unpack it WITHOUT generic unpackers neither "upx -d" switch neither in Procdump,
i searched the web(blah blah blah fire up procdump dump it and fix EOP) and the forum(use procdump or -d)
my idea of manual unpacking, is with softice(debugger
, icedump(dump sections), hexeditor(assemble all stuff). because this is how one learns!
IMO i think a reverser should dump/decrypt manually a protection at least once. and hexassemble it at least once in a lifetime
i'll paste here my walktrough (i wrote this stuff like a tutorial, personal notes... so don't pay attention
, please correct me if something is incorrect
ps: i got all the packers+cryptors on protools, and i wanted to know IYO what packers(cryptors go last
should i go for next, i'm doing a progression that's why i started with UPX (the easiest 
ps2: about import rebuild.. for the ".import_section" work does it have to be exacly like the original, or can the order of the imported functions be another(being a correct one, corresponding to true values)
ps3: i read a thread about UPX+NT, that i don't remember exactly, but does UPX fux0res the ".relocations_section". if not htf do i restore the old .reloc
ps4: how can i merge resources from the packed .EXE with the .resources it unpacked. i tried to grab the resources from packed.exe(icon+version_info), but it said "i'm too stupid i can't recognised the reloc section, even thought it is there"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
UPX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
tools needed: softice, icedump, frogice, ultraedit32(or other nice hexeditor), PE knowledge, lots of girls (i'm hopping you don't need a tutorial on what to do with them
compact notepad.exe using default options with UPX 1.20w
size optional header - 0xE0
size of code - 0x4000
size of data - 0x1000
base of code - 0xb000
base of data - 0xf000
section alignment - 0x1000
file alignment - 0x200
EP(entry point) - RVA 0xe8f0
IMAGE_DIRECTORY_ENTRY_IMPORT: - RVA 0xfc14 ; - size 0x170. file offset - 0x4a14
upx0
{
virtual size - 0xa000
virtual address - 0x1000
size raw data - 0x0
pointer raw data - 0x200
}
upx1
{
virtual size - 0x4000
virtual address - 0xb000
size raw data - 0x3c00
pointer raw data - 0x200
}
.rsrc
{
virtual size - 0x1000
virtual address - 0xf000
size raw data - 0xe00
pointer raw data - 0x3e00
}
018F:0040E9C2 5E POP ESI <- finished unpacking itself... or so it seems
018F:0040E9C3 89F7 MOV EDI,ESI
018F:0040E9C5 B9DE000000 MOV ECX,000000DE
018F:0040E9CA 8A07 MOV AL,[EDI]
018F:0040E9CC 47 INC EDI
018F:0040E9CD 2CE8 SUB AL,E8
018F:0040E9CF 3C01 CMP AL,01 <- but if you look carefully, you notice the LOOP at :0040E9F4, it's playing with the .text
018F:0040E9D1 77F7 JA 0040E9CA
018F:0040E9D3 803F05 CMP BYTE PTR [EDI],05
018F:0040E9D6 75F2 JNZ 0040E9CA
018F:0040E9D8 8B07 MOV EAX,[EDI]
018F:0040E9DA 8A5F04 MOV BL,[EDI+04]
018F:0040E9DD 66C1E808 SHR AX,08
018F:0040E9E1 C1C010 ROL EAX,10
018F:0040E9E4 86C4 XCHG AL,AH
018F:0040E9E6 29F8 SUB EAX,EDI
018F:0040E9E8 80EBE8 SUB BL,E8
018F:0040E9EB 01F0 ADD EAX,ESI
018F:0040E9ED 8907 MOV [EDI],EAX
018F:0040E9EF 83C705 ADD EDI,05
018F:0040E9F2 89D8 MOV EAX,EBX
018F:0040E9F4 E2D9 LOOP 0040E9CF <- don't know HTF this LOOP worked!? but it's used to do some rearrangements on the .text
018F:0040E9F6 8DBE00C00000 LEA EDI,[ESI+0000C000]
018F:0040E9FC 8B07 MOV EAX,[EDI] <- :d edi, to check out imported functions, and just below the PE header
018F:0040E9FE 09C0 OR EAX,EAX this is the right place to dump
018F:0040EA00 743C JZ 0040EA3E <- as it finished all imported functions from all DLLs ???
018F:0040EA02 8B5F04 MOV EBX,[EDI+04]
018F:0040EA05 8D843014EC0000 LEA EAX,[ESI+EAX+0000EC14]
018F:0040EA0C 01F3 ADD EBX,ESI
018F:0040EA0E 50 PUSH EAX
018F:0040EA0F 83C708 ADD EDI,08
018F:0040EA12 FF96A0EC0000 CALL [ESI+0000ECA0] <- LoadLibraryA
018F:0040EA18 95 XCHG EAX,EBP
018F:0040EA19 8A07 MOV AL,[EDI]
018F:0040EA1B 47 INC EDI
018F:0040EA1C 08C0 OR AL,AL
018F:0040EA1E 74DC JZ 0040E9FC <- if AL == 0, pass to next DLL
018F:0040EA20 89F9 MOV ECX,EDI
018F:0040EA22 57 PUSH EDI
018F:0040EA23 48 DEC EAX
018F:0040EA24 F2AE REPNZ SCASB <- advances EDI pointer to next imported function
018F:0040EA26 55 PUSH EBP
018F:0040EA27 FF96A4EC0000 CALL [ESI+0000ECA4] <- GetProcAddress
018F:0040EA2D 09C0 OR EAX,EAX
018F:0040EA2F 7407 JZ 0040EA38 <- if ZERO... error
018F:0040EA31 8903 MOV [EBX],EAX
018F:0040EA33 83C304 ADD EBX,04
018F:0040EA36 EBE1 JMP 0040EA19
018F:0040EA38 FF96A8EC0000 CALL [ESI+0000ECA8] <- ExitProcess
018F:0040EA3E 61 POPAD
018F:0040EA3F E98826FFFF JMP 004010CC <- EntryPoint of unpacked EXE
(look at memory contexts... we're at 0040EA3F and JMP to 004010CC; besides remember when we dumped the .text
:/dump 401000 3e9c c:\_text.PE <- OK!
:/dump 405000 084c c:\_data.PE <- OK!
:/dump 406000 0de8 c:\_idata.PE <- NOT OK! we have to rebuild this!!! it's the import data [**]
:/dump 407000 4fb8 c:\_rscr.PE <- NOT OK! this one is messed up! [***]
:/dump 40c000 0a9c c:\_reloc.PE <- NOT OK! it was only 0x0!! how do we rebuild this? [****]
:/dump 40d000 7e0 c:\_import.PE <- NOT OK! imported functions names [**]
:/dump 40d7e4 1260 c:\_header.PE <- OK!
:/dump 40f000 1000 c:\_UPXrscr.PE <- .rscr that UPX didn't unpack [***]
:/dump 4062e0 240 c:\_IAT.PE <- IAT, Import Address Table [**]
-> get yourself a good hex editor, i use UltraEdit32
make a copy of packedpad.exe
paste the _pehead.PE over packedpad.exe
since file aligment is 0x1000, you have to fill it with 0x0 to file offset 0xfff
now it's time to paste the sections, the first one it's .text, check it's 'PointerToRawData', it points to 0x1000, so we paste the _text.PE at 0x1000 (remember 'PointerToRawData' is at 'start_of_section_header' + 0x14)
after that we have to do file padding, filling it with 0x0, until file offset 0x4fff
looking at PE header again we see .data, and 'PointerToRawData' is 0x5000... what a surprise
, paste _data.PE at 0x5000
fill it up with 0x0 to file offset 0x5fff
paste the rebuilt .idata at 0x6000 and do file alignment
fixed _rscr.PE is to be pasted at 0x7000, file align it
last one is fixed _reloc.PE at 0xc000
i was trying to reverse a prog, but it showed me that i was not good enought to reverse it, so i learnt about PE file structure, still it kicked me, so i decided to learn about unpacking and decrypting.
my first victim was good old UPX 1.20w, i packed notepad and decided to unpack it WITHOUT generic unpackers neither "upx -d" switch neither in Procdump,
i searched the web(blah blah blah fire up procdump dump it and fix EOP) and the forum(use procdump or -d)
my idea of manual unpacking, is with softice(debugger

IMO i think a reverser should dump/decrypt manually a protection at least once. and hexassemble it at least once in a lifetime

i'll paste here my walktrough (i wrote this stuff like a tutorial, personal notes... so don't pay attention

ps: i got all the packers+cryptors on protools, and i wanted to know IYO what packers(cryptors go last


ps2: about import rebuild.. for the ".import_section" work does it have to be exacly like the original, or can the order of the imported functions be another(being a correct one, corresponding to true values)
ps3: i read a thread about UPX+NT, that i don't remember exactly, but does UPX fux0res the ".relocations_section". if not htf do i restore the old .reloc
ps4: how can i merge resources from the packed .EXE with the .resources it unpacked. i tried to grab the resources from packed.exe(icon+version_info), but it said "i'm too stupid i can't recognised the reloc section, even thought it is there"
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
UPX;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
tools needed: softice, icedump, frogice, ultraedit32(or other nice hexeditor), PE knowledge, lots of girls (i'm hopping you don't need a tutorial on what to do with them

compact notepad.exe using default options with UPX 1.20w
size optional header - 0xE0
size of code - 0x4000
size of data - 0x1000
base of code - 0xb000
base of data - 0xf000
section alignment - 0x1000
file alignment - 0x200
EP(entry point) - RVA 0xe8f0
IMAGE_DIRECTORY_ENTRY_IMPORT: - RVA 0xfc14 ; - size 0x170. file offset - 0x4a14
upx0
{
virtual size - 0xa000
virtual address - 0x1000
size raw data - 0x0
pointer raw data - 0x200
}
upx1
{
virtual size - 0x4000
virtual address - 0xb000
size raw data - 0x3c00
pointer raw data - 0x200
}
.rsrc
{
virtual size - 0x1000
virtual address - 0xf000
size raw data - 0xe00
pointer raw data - 0x3e00
}
018F:0040E9C2 5E POP ESI <- finished unpacking itself... or so it seems

018F:0040E9C3 89F7 MOV EDI,ESI
018F:0040E9C5 B9DE000000 MOV ECX,000000DE
018F:0040E9CA 8A07 MOV AL,[EDI]
018F:0040E9CC 47 INC EDI
018F:0040E9CD 2CE8 SUB AL,E8
018F:0040E9CF 3C01 CMP AL,01 <- but if you look carefully, you notice the LOOP at :0040E9F4, it's playing with the .text
018F:0040E9D1 77F7 JA 0040E9CA
018F:0040E9D3 803F05 CMP BYTE PTR [EDI],05
018F:0040E9D6 75F2 JNZ 0040E9CA
018F:0040E9D8 8B07 MOV EAX,[EDI]
018F:0040E9DA 8A5F04 MOV BL,[EDI+04]
018F:0040E9DD 66C1E808 SHR AX,08
018F:0040E9E1 C1C010 ROL EAX,10
018F:0040E9E4 86C4 XCHG AL,AH
018F:0040E9E6 29F8 SUB EAX,EDI
018F:0040E9E8 80EBE8 SUB BL,E8
018F:0040E9EB 01F0 ADD EAX,ESI
018F:0040E9ED 8907 MOV [EDI],EAX
018F:0040E9EF 83C705 ADD EDI,05
018F:0040E9F2 89D8 MOV EAX,EBX
018F:0040E9F4 E2D9 LOOP 0040E9CF <- don't know HTF this LOOP worked!? but it's used to do some rearrangements on the .text
018F:0040E9F6 8DBE00C00000 LEA EDI,[ESI+0000C000]
018F:0040E9FC 8B07 MOV EAX,[EDI] <- :d edi, to check out imported functions, and just below the PE header
018F:0040E9FE 09C0 OR EAX,EAX this is the right place to dump
018F:0040EA00 743C JZ 0040EA3E <- as it finished all imported functions from all DLLs ???
018F:0040EA02 8B5F04 MOV EBX,[EDI+04]
018F:0040EA05 8D843014EC0000 LEA EAX,[ESI+EAX+0000EC14]
018F:0040EA0C 01F3 ADD EBX,ESI
018F:0040EA0E 50 PUSH EAX
018F:0040EA0F 83C708 ADD EDI,08
018F:0040EA12 FF96A0EC0000 CALL [ESI+0000ECA0] <- LoadLibraryA
018F:0040EA18 95 XCHG EAX,EBP
018F:0040EA19 8A07 MOV AL,[EDI]
018F:0040EA1B 47 INC EDI
018F:0040EA1C 08C0 OR AL,AL
018F:0040EA1E 74DC JZ 0040E9FC <- if AL == 0, pass to next DLL
018F:0040EA20 89F9 MOV ECX,EDI
018F:0040EA22 57 PUSH EDI
018F:0040EA23 48 DEC EAX
018F:0040EA24 F2AE REPNZ SCASB <- advances EDI pointer to next imported function
018F:0040EA26 55 PUSH EBP
018F:0040EA27 FF96A4EC0000 CALL [ESI+0000ECA4] <- GetProcAddress
018F:0040EA2D 09C0 OR EAX,EAX
018F:0040EA2F 7407 JZ 0040EA38 <- if ZERO... error
018F:0040EA31 8903 MOV [EBX],EAX
018F:0040EA33 83C304 ADD EBX,04
018F:0040EA36 EBE1 JMP 0040EA19
018F:0040EA38 FF96A8EC0000 CALL [ESI+0000ECA8] <- ExitProcess
018F:0040EA3E 61 POPAD
018F:0040EA3F E98826FFFF JMP 004010CC <- EntryPoint of unpacked EXE
(look at memory contexts... we're at 0040EA3F and JMP to 004010CC; besides remember when we dumped the .text

:/dump 401000 3e9c c:\_text.PE <- OK!
:/dump 405000 084c c:\_data.PE <- OK!
:/dump 406000 0de8 c:\_idata.PE <- NOT OK! we have to rebuild this!!! it's the import data [**]
:/dump 407000 4fb8 c:\_rscr.PE <- NOT OK! this one is messed up! [***]
:/dump 40c000 0a9c c:\_reloc.PE <- NOT OK! it was only 0x0!! how do we rebuild this? [****]
:/dump 40d000 7e0 c:\_import.PE <- NOT OK! imported functions names [**]
:/dump 40d7e4 1260 c:\_header.PE <- OK!
:/dump 40f000 1000 c:\_UPXrscr.PE <- .rscr that UPX didn't unpack [***]
:/dump 4062e0 240 c:\_IAT.PE <- IAT, Import Address Table [**]
-> get yourself a good hex editor, i use UltraEdit32
make a copy of packedpad.exe
paste the _pehead.PE over packedpad.exe
since file aligment is 0x1000, you have to fill it with 0x0 to file offset 0xfff
now it's time to paste the sections, the first one it's .text, check it's 'PointerToRawData', it points to 0x1000, so we paste the _text.PE at 0x1000 (remember 'PointerToRawData' is at 'start_of_section_header' + 0x14)
after that we have to do file padding, filling it with 0x0, until file offset 0x4fff
looking at PE header again we see .data, and 'PointerToRawData' is 0x5000... what a surprise

fill it up with 0x0 to file offset 0x5fff
paste the rebuilt .idata at 0x6000 and do file alignment
fixed _rscr.PE is to be pasted at 0x7000, file align it
last one is fixed _reloc.PE at 0xc000