unpacking.with.upx

Upload: patelpratik1972

Post on 14-Apr-2018

215 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/29/2019 Unpacking.with.UPX

    1/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    - Introduction

    Welcome, to the first part in hopefully a series of tutorials that will try to explain unpacking to

    beginners.

    These tutorials assume that you have basic assembly knowledge, know at least the

    very basics of the PE file format, and OllyDbg knowledge. Basically you just want

    to know how to analyse a file that has been packed, right ;-)

    I remember when I still was a beginner, and was literally struggling with some

    ( minimally customised ) version of UPX. I just didnt get it what was going on, and how I could

    possibly defeat this without stepping through every instruction until I got some code that actually

    made sense. I was looking at a maze of ( conditional ) jumps and instructions that didnt seem tomake sense at all.

    Now that I am more experienced ( but still consider myself a beginner ), I want to try and give

    something back to the community mainly to the beginners who can debug and crack / reverse,

    but are unexperienced with packers, just like I was a while ago.

    I will combine theory ( in a simple way, I wont go too deep into it ) with some practical experience

    by providing you with executables packed with some packers of increasing difficulty that we

    are going to tackle in these tutorials. The theory should give you some insight into whats going on

    and what we need to know, and the packed executables make sure you have some real-world

    practice example.

  • 7/29/2019 Unpacking.with.UPX

    2/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    - Theory

    What is a packer you might ask. Roughly said, a packer is a program that aims to minimise the sizeof another executable ( basically any valid PE file such as .exes , .dlls etc. ).

    Compare it to for instance WinZip and WinRar. They compress folders, applications, files to often

    much smaller filesizes.

    The only difference between your everyday packer and WinZip for instance, is that WinZip puts all

    the files into one single archive ( the .zip file ) , and the packer can only compress one single file.

    There are exceptions to the rule though ;-)

    Another difference is that generally when you pack a couple of files with WinZip,

    you will need the WinZip application itself in order to extract all the files from

    the .zip archive with the exception of self-extracting archives.

    Executable packers ( PE packers, or just packers in general ) fall into the category of

    self-extracting packers.

    They compress a file, but also include a routine that unpacks the file, once its loaded in memory.

    This routine is called the unpacking stub.

    What the packer essentially does, is compress code, data, resources etc. that the target executable is

    made up of ( through the use of some compression library, a lot of custom ( non-commercial )

    packers tend to use the same compression library, cant remember off the top of my head which one,

    but its not important ;-).

    The packer will also add code that will de-compress the compressed data/code to

    its original executable state. This is the unpacking stub that I told you about.

    This makes sure the application gets decompressed before it is ran :-).

    Ill try to explain it a bit more clearly with a couple of simple images on the next page.

  • 7/29/2019 Unpacking.with.UPX

    3/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Here you have your average, big executable :-)

    And here is our good friend, the packer :-)

    The packer will try and compress the executable, and also add a bit of code that will unpack the

    compressed executable at runtime.

    As you can see, the total executable ( compressed executable + unpacking stub ) is much smaller

    than the uncompressed executable. And as strange as it may seem, some packers are that good,that they actually increase the speed of which applications gets loaded!

    I hope this has explained to you why packers are being used. Mainly for file compression.

  • 7/29/2019 Unpacking.with.UPX

    4/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    As explained above, the packer will have to attach this unpacking stub to the executable somehow.

    As far as I understand this correctly myself, the packer will create a new section inside the

    executable ( read up on the PE file format if you dont know what a section is ), where it will placeits unpacking stub. It will then also change the entry point of the application ( the address of the

    first instruction to be executed once the file is loaded into memory ) to the start of the unpacking

    stub.

    So once the application gets loaded, the unpacking stub starts decompressing the executable, and

    once its done, it will jump to the original beginning of the executable, the so-called Original Entry

    Point, or OEP. Its called original because this was the entry point before the program was packed.

    That should explain the basics of the packer, and the unpacking stub. Hopefully I didnt forget

    anything.

    Now that we know something about out enemy, were going to look at a program that has been

    packed. In our case, the packer is UPX. UPX is considered to be the most easiest packer to defeat,

    so thats where well be starting.

    UPX is created by Markus, Lszl and John ( http://upx.sourceforge.net ).

    UPX is an open-source packer, which stands for Ultimate Packer for eXecutables.

    And I must say, it really does what it says on the box ;-)

    A compression ratio of 49.11% of the original size , thats not bad! Not bad at all.

    We will be analysing a harmless file packed with UPX, and I hope that you will not use this

    knowledge explained in this tutorial for personal advantages such as illegally obtaining registered

    copies of commercial programs through breaking their protection and cracking them.

    If you really like a program, support the author by legally buying it.

  • 7/29/2019 Unpacking.with.UPX

    5/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    - Whats needed?

    PEiD 0.94OllyDbg 1.10

    OllyDump plugin

    AnalyseThis plugin

    ImpRec 1.6f

    Unpackme ( unpackme_upx.exe )

    - Getting started

    There is a nifty application made by snaker / Qwerton / Jibz called PEiD.

    It can identify byte signatures ( specific sequences of bytes ) that get generated by packers.

    PEiD has a database of signatures of most ( if not nearly all ) packers out there today.

    And if its still unknown, once can expand the database themselves by making an entry in the

    database file, entering the byte sequence at the entrypoint of the packed application, and the name

    of the packer.

    Run PEiD, and drag the unpackme inside the PEiD window. PEiD will show you this:

    PEiD identifies the present packer as UPX 0.89.6 1.02 / 1.05 1.24 . I have packed it with

    UPX 2.01w actually, so the signature in PEiD will probably have to get updated.

    This program tells us that we are dealing with a packed executable. Now were going to load the

    application inside Olly, and see what it looks like.

  • 7/29/2019 Unpacking.with.UPX

    6/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Right, OllyDbg presents us with this MessageBox.

    This message will almost always appear when you are dealing with an application that has been

    packed. Just click on yes and Olly will try and analyse the code as good as possible for you :-)

    Heres what youll be looking at

    As you can see, alot of ( conditional ) jumps, arithmetic instructions ( add, inc, sub, adc ) and the

    likes. It deffinately doesnt look like plain code does it?

  • 7/29/2019 Unpacking.with.UPX

    7/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Right click somewhere in Olly, and select Search for > All referenced text strings.

    Olly will spit out the following:

    Not a single valid string. Not strange, considering the entire program ( including data such as

    strings ) have been compressed. We cant analyse what this file may possibly do when its in its

    packed state can we ;-) ?

    - Unpacking the application

    Okay, lets get started then. Im already going to skip something for the second part of this

    tutorial series. You notice the first instruction to be executed is PUSHAD.

    This is a very common instruction that is very often one of the first instructions of a packed

    executable. Im not going to explain what the exact use this instruction has for packers, so just

    forget about it for now ;-) I will try and explain it as good as possible in the next tutorial.

    The way were going to tackle this packer, is by simple tracing through the executable, looking

    for obvious things that could tell us that weve hit the Original Entry Point ( OEP ) and the

    application is unpacked.

  • 7/29/2019 Unpacking.with.UPX

    8/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    One thing that I have noticed, is that code has a tendency of flowing downwards, rather than

    upwards. Were going to use this little trick to our advantage :-)

    Again, we start out here:

    Start stepping in Olly. Nothing interesting happens until we hit the JMP,

    and we jump to 1020C62h, a couple of instructions below.

    Now we end up in a maze of conditional jumps. What Ive discovered is that generally, code tends

    to flow downwards. Yeah, so what? I hear you say. Well, if we hit a jump that jumps downwards,

    were ok. If we hit a jump that jumps upwards, something will still have to be done before were

    allowed to go past this point so to speak.

    So what do we do? We start stepping until we hit the second conditional jump at 01020C69h.

    It will jump upwards allright so lets give it a go. A simple method of getting to the point where

    the jump will not be taken upwards but the code will just skip the jump, is to set a breakpoint belowthe conditional jump, and hit Run ( F9 ).

    What will happen is that Olly will freely run and execute instruction by instruction and because

    this is way faster than stepping through every single instruction manually, waiting untill you hit

    the conditional jump, only to discover that youre in a loop and will break at the breakpoint when

    the jump upwards will no longer be taken.

  • 7/29/2019 Unpacking.with.UPX

    9/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Lets try it :-). Set a breakpoint ( F2 ) on the instruction below the 2nd conditional jump at 1020C69h.

    Now hit Run, youll see that Olly breaks at the breakpoint. Right, that didnt look that usefull so far.

    Trust me, once we hit bigger loops it will be usefull ;-). Keep on stepping until you hit another

    conditional jump that will jump upwards.

    Youll find that to be here:

    You know what to do :-) Set a breakpoint on the JNZ at 1020CCEh, and hit Run.

    Keep on stepping again until you hit the next jump that will go upwards, but dont go too fast ;-).

    Youll find that next situation to be here:

  • 7/29/2019 Unpacking.with.UPX

    10/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Ive already commented it :-x , but the instruction below the conditional jump that goes upwards,

    is an unconditional jump that jumps upwards aswell!

    Right, the solution for this might be quite logical, but try and follow anyways ;-)

    If you look at just the JNZ and the JMP at respectively 1020CF4h and 1020CF6h, there is no way

    how were ever going to get past this point. If the conditional jump gets taken, we jump upwards.

    In the case that the jump will not be taken, the unconditional jump will jump up anyways!

    So there has to be another element that takes us past this jump pair. Lets take a look a bit more

    upwards.

    Right, the only jump that takes us past the unconditional jump, is the JBE at 1020CEBh.

    The easy way out will be to put a breakpoint at where the JBE will jump to when it gets taken.

    This is at 1020CFCh so lets breakpoint that and hit Run again.

    You might break on a previous breakpoint aswell, so its a good exercise to remove breakpoints

    when you dont need them anymore.

    Good, we break where we wanted to :-). Lets continue Heres the next jump that goes upwards.

    Breakpoint the ADD EDI,ECX instruction below, and run. Yup, we break once more... continue.

    Right below that is an unconditional jump that goes upwards again! Right, the same problem as

    weve encountered before, so lets take a look for a jump that jumps past this unconditional jump.

  • 7/29/2019 Unpacking.with.UPX

    11/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Ive found that jump to be quite a bit upwards, here it is:

    As you can see, it jumps to 1020D12h, so set a breakpoint there, and hit Run and continue stepping.

    Heres where youll end up then:

    The JA will jump upwards, but the JNZ below will jump upwards aswell but only if the jump will

    actually get taken. So lets save us a little time and just set a breakpoint below the JNZ, and hit Run.

    Good, the breakpoint breaks again, continue stepping again.

    Damn! Im getting quite sick of this already, arent you yet? ;-) Heres another loop:

    We dont have to worry about the JE below it, it jumps downwards :-). Set a Breakpoint below the

    LOOPD instruction and hit Run. Good, we break.

    Continue stepping downwards, well hit our first call! Wohooo :-P

  • 7/29/2019 Unpacking.with.UPX

    12/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    The call is a call to LoadLibrary here the unpacking stub will load needed libraries for the

    executable.

    Look closely if you will :-).

    The call to LoadLibrary takes one parameter that gets pushed on the stack. Thatll be the

    PUSH EAX a couple of instructions above the call. So in EAX we can see the library thats about to

    be loaded.

    The JE below will form a loop, that will decide whether more libraries will get loaded ( the jump

    gets taken ), or that all the needed libraries have been loaded.

    So set a breakpoint below the JE and hit run. Ive taken a little peek for you, but it seemed that the

    JE didnt get taken so there probably is another jump that decides whether we jump up a

    little ( and load more libraries ) or not.

    Start stepping again till you hit the next jump. That should be here:

    Its unconditional so were going to have to find a jump that jumps past this.

    If you want, you can keep on stepping this piece of code with F8 some interesting things will be

    shown to you if you take a close look at the code in Olly and the registers ;-)

    Right, the jump were looking for is the JE right above the JMP :-) , so breakpoint whereits jumping to, and hit run.

  • 7/29/2019 Unpacking.with.UPX

    13/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Hehe :-) this is unexpecting, the program ran! So what does this mean? We were actually fooled by

    this jump :-D.

    There has to be another jumplets search for it. Close the application and restart it in Olly.

    Check the last image to see where you were so you dont have to step through everything again ;-).

    Here is the good jump we were looking for:

    So set a breakpoint on the instruction where the jump jumps to, and hit Run. Good, we break.

    After some more stepping ( and finally no more conditional jumps ;-) youll end up at a pair of calls

    ( just step over them with F8 ) and youll end up here:

    Sick and tired of it yet? I nearly am ;-) , but luckily were nearly there. Hang on.

    Right, this one is simple again, just set a breakpoint below the JNZ, and run. The breakpoint breaks.

    Keep tracing until you hit the JMP 1012475. After executing that instruction, youll end up here:

  • 7/29/2019 Unpacking.with.UPX

    14/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    I have to apologise for the very bad example though, but the unpacking stub is done now, and has

    jumped to the OEP.

    Normally, youd very clearly see when youve hit the OEP. Please refer to my other document for a

    couple of guidelines to see whether youve hit the OEP or not. Ill include another applicationpacked with UPX for you ( test_upx.exe ), where youll see the difference more clearly.

    ( Hint: After youve hit that final unconditional jump, youll see calls to GetVersion, and

    GetCommandLineA indicating youve hit the entrypoint of a program compiled with visual

    studio 6 there are some other indications as explained in the document).

    - Dumping the application from memory to disk

    Back on track though. We now have an uncompressed ( unpacked ) copy of the application inmemory. What we do is dump this application from memory to disk.

    Now why would we do that? When we dump the application once its unpacked, we have an

    on-disk copy of the unpacked program that we now have in memory! That means weve reached

    our goal.

    Now, how do we perform this dump ? There is a usefull Olly plugin called OllyDump by

    Gigapede. Im assuming that you already know where to find this, and have this plugin loaded.

    When youre at the OEP, click on the Plugins menu, and select OllyDump > Dump debugged

    process. Youll be confronted with the following window:

    Right, more stuff Im going to have to explain :-).

  • 7/29/2019 Unpacking.with.UPX

    15/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    For starters, remember that all you need to do now is fill in the new entry point of the unpacked

    application in memory ( which is where were at now, at 01012475h, but we need it as RVA this

    calculation is as simple as Virtual Address Imagebase. So thats 01012475h 01000000 = 12475h. )

    And dont forget to untick the Rebuild import box in the bottom of the window.

    Ill explain why in a bit.

    Click the Dump button after youve filled in the OEP and unticked the box, and enter a filename to

    dump the file ,thats currently in memory, to.

    Now try to run the dumped file, youll see that it will crash even before it has started :-(

    - Rebuilding the IAT

    Now why would this happen? Ok ok, Ive wasted your time long enough :-P Ill tell you.Its because the application cant find any of its needed imports. The packer probably compressed

    the import table ( or at least has done something to it ) , and now the dumped file does not have a

    valid import address table ( IAT ) , so it any attempts to call any windows API function will fail

    and probably make the application crash.

    If Im going too fast here, an import is a function that is being used from an external program

    ( mostly .dlls ). A good example of this is for instance kernel32.dll.

    Kernel32.dll exports a function, for instance GetProcAddress. When a program wants to use

    GetProcAddress, it will have to import this function. If you want to know more about the IAT,

    read up on the PE file format :-).

    So, our goal is clear here, we have to fix the IAT somehow. Inside the PE Header is a pointer to the

    IAT. Olly is a fabulous debugger, allowing us to view each and single member of the PE header.

    Click on the blue [ M ] button in Olly, that opens the Memory Map.

    Then youll be confronted with a window that shows all the modules that have been loaded into the

    applications address space. Olly has nicely divided them all into sections, and it also identified the

    PE header for each module for us.

  • 7/29/2019 Unpacking.with.UPX

    16/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    What were looking for is the PE header of our application.

    Ive marked it for you, double click on it.

    Well then see the DOS header we have been looking for.

    Its not really that visible here, but if you know the PE file format, youll know that inside the DOS

    header is a pointer to the PE header. Just scroll down, youll see it ;-).

    There it is, according to this, the PE header is at F0h. Now we scroll down to the PE header.

    Ive already marked what we are looking for on the next page, you can see that the PE header really

    starts at F0h.

  • 7/29/2019 Unpacking.with.UPX

    17/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    The import table address is a pointer to the IAT. So at 010277F8h should be our IAT. Close the

    Memory window and press CTRL + G in Olly. Enter 010277F8h and hit enter. Youll end up here:

    Looks nice and structured to me :-), but is this really code and not data? We cant analyse this,

    because its outside of the code segment.

  • 7/29/2019 Unpacking.with.UPX

    18/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Thats what well be using the AnalyseThis plugin for. Right click any of the code, and select

    Analyse This.

    Right ;-) We get a totally different picture now:

    Even more things to explain ;-).

    You see all the IMAGE_IMPORT_DESCRIPTOR structures? Well, for each .dll that this program

    imports functions from, there is an IMAGE_IMPORT_DESCRIPTOR structure.

    You dont need to know what all the members in the struct are for, but what you do need to know

    is that there is an additional structure filled with all zeroes you can see that in the image.

    So this program imports functions from 7 .dlls, minus one! Remember, one was filled with all

    zeroes, so it imports functions from 6 .dlls.

    If you scroll down a little, you can see all the .dll names and functions that get imported.

  • 7/29/2019 Unpacking.with.UPX

    19/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Right, youll have to forgive me, but Ive already forgotten what actually is going on here :-(

    What you have to remember though, that once youve unpacked and dumped a program,

    its imports are not correct anymore, and will have to get fixed. You can do this manually, butMackT / uCF created a very nice application for this, called ImpRec.

    What this program essentially does is fix the IAT for you, so youll have a working dump.

    Right, lets cut the cr*p and give it a go :-) , Ive been awake for far too long.

    I assume you still have Olly running while at the OEP of the unpacked program dont forget that.

    In the drop-down box in Imprec called Attach to an active process, select the process youve loaded

    in Olly.

    Then in the bottom right corner, in the OEP box, enter the OEP of the unpacked program.

    You can check this in Olly, its 12475h remember? Fill it in, and hit IAT AutoSearch.

  • 7/29/2019 Unpacking.with.UPX

    20/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    You will see that ImpRec has found something:

    It thinks the IAT is at 1000h. Click on OK. Youll see that ImpRec has filled in some information:

    Now all you need to do is click on Get Imports, and ImpRec will try and see if there really are valid

    imports at 1000h untill 1228h ( start at 1000h, size 228h ).

  • 7/29/2019 Unpacking.with.UPX

    21/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Well, it seems that ImpRec has found imports from 6.dlls, just as I told you before. And it appears

    they are all valid aswell.

    To make sure, click on Show Invalid. You will see nothing happens so dont worry about that for

    now ;-).

    Now click on Fix Dump, and point ImpRec to the file that youve dumped from Ollys memory.

    Try to run the file now youll see that ImpRec appended an underscore to the filename.

  • 7/29/2019 Unpacking.with.UPX

    22/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    Anthracene - 2006

    Wooohoooo, it runs :-D. It seems that ImpRec did its job correctly.

    If you want to check, you saw that ImpRec found an IAT at 1000h, go to Olly and in the dump

    window, go to 01001000h. Youll see some pointers to API functions in the dump, separated byzeroes when the functions are from a different .dll.

    Now youll have to excuse me again for the bad example, but I dont know what exactly is wrong

    here either :-(.

    If you load the unpacked and fixed dump in Olly, youll still see that there still are no valid strings!

    If you look at a calc.exe that hasnt been packed before though youll see that it looks the same,

    so I guess this has nothing to do with the program not fully being decompressed. This is what theuncompressed program actually looks like, I guess.

    - Conclusion

    Right, what have we ( hopefully :-x ) learned:

    1. What a packer is, and what it does2. How we can identify if a program is packed3. How we can unpack a very simple packer like UPX4. Why the dumped file will crash when we run it5. What we have to do to fix this by using ImpRec

    In short, what we have done is this:

    We determined what packer we were dealing with. When you get more experienced, youll get to

    know more packers, and when you identify one, youll already know how to deal with specific

    packers.

    Then we had to figure out a way how we could know that we were at the OEP, and the program

    was unpacked in memory. For starters, we used a bit of logic and simple tracing for this.

    Once were at the OEP and the program was unpacked, we had to dump the program from

    memory to disk.

    Then we had to rebuild the import table with ImpRec because the packer had messed with the IAT.

  • 7/29/2019 Unpacking.with.UPX

    23/23

    Beginner Unpacking Tutorials #1 UPX 2.01w

    I could have expanded this tutorial about 10 pages more, but 23 pages just dealing with UPX and

    rebuilding the imports are enough I think :-P.

    In my next tutorial, I will show you an easier way to unpack programs that have been packed with

    UPX ;-) until then, keep practicing until you get the hang of it. If you want, you can try the other

    program that Ive included aswell and see if you can unpack that aswell its the same UPX ;-).

    Untill then, happy unpacking and good luck. Take care of yourselves.

    - Credits and thanks

    Myself ( writing this tutorial, aiming at giving something back to the beginners out there )

    ARTeam ( basically everyone posting there and sharing knowledge )

    Oleh Yuschuk ( for the best, and also non-commercial, usermode debugger out there )

    Snaker, Qwerton, Jibz ( PEiD )

    Gigapede ( OllyDump plugin )

    Joe Stewart ( AnalyseThis plugin )

    MackT/uCF ( ImpRec )