WORK IN PROGRESS
This was one of those projects that I was really into for a while, but I’ve moved on to other things. I made it partway through the tutorial. I had planned to go and do a manual rewrite of the IAT later after the tutorial.
Intro to the Scenario
You’re reversing a piece of packed malware as most packed malware is and you want to be able to properly perform static analysis and disassembly on it. The problem is it’s packed, which means that the original IAT (Import Address Table) and the OEP (Original Entry Point) are destroyed. A lot of tutorials discuss finding the OEP of easy packers, like UPX, manually. What about the hard stuff? This tutorial walks through how I find the OEP of a piece of malware I’ve recently been reversing that has a non-standard packer.
The Malware (careful – this is the actual malware)
If any of these links break, let me know, but all these tools should also be publicly available from a quick google search.
I did this all on a Windows 7 Pro x86 VM on VMware. You’ll want to set up some sort of VM to do your trial runs in. I’ll assume you’re already familiar with Olly itself and how to run it. To install ollydump and HideOD just unzip them and inside should be a dll file. Copy that dll file and paste it into the root directory of your olly install and that “installs” them. Easy enough. For the malware to actually behave the way it is supposed to, you’ll have to set up your VM with a default gateway, a fake DNS server, and a dummy listener on port 80. However, none of that is necessary for this tutorial.
Chapter 18 of Practical Malware Analysis
My Random Notes on the Malware – These are just random thoughts as I was going through the malware. No guarantees on accuracy as I may have changed my mind after I wrote something.
After you’ve finished static analysis of the malware, chances are the next thing you’ll do is throw it in a debugger to begin dynamic analysis. Right away, you’ll hit a wall. It crashes as soon as you run it!?
This is because the malware is running some sort ant-debugging routine. Fortunately, it isn’t anything sophisticated. As part of the process environment block (PEB) there is a bit that denotes whether the process is being debugged. Not surprisingly, malware can check this and determine whether you’ve attached a debugger. In this case the malware seems to be intentionally crashing itself if it detects that it is being debugged. You can hide yourself by using the plugin HideOD. Go to plugins, HideOD, option, and select “Auto Run HideOD” and “HideNtDebugBit”. This will ensure that this bit isn’t set in the PEB along with a couple of other things. When you rerun the malware, it should run properly.
Finding the OEP
Unfortunately, for more sophisticated malware, finding the OEP is nontrivial. A lot of tutorials trivialize the task and say something like, “Just run Ollydump’s Find OEP by Section Hop.” That isn’t going to work here.
How Ollydump’s Find OEP by Section Hop Works
If you aren’t already familiar, make sure you understand tracing.
Ollydump is a fairly prolific tool and it helps to know how this functionality works. Generally, Ollydump finds the OEP by leveraging a simple heuristic. Usually, the unpacking stub is in one section and the executable is packed into another section. Ollydump detects when there is an execution transfer from one section to another section and breaks there. It does this for either the trace into or trace over methods. Below are the differences between the two methods of finding the OEP:
Find OEP by Section Hop (Trace Into) – Does a regular trace into. As soon as there is a jump from one section to another, it is labeled as the OEP.
Find OEP by Section Hop (Trace Over) – The stepover method will step-over any call instructions. Calls are often used to execute code in another section, and this method is designed to prevent OllyDbg from incorrectly labeling those calls the OEP. However, there’s a problem. Malware frequently will make calls that don’t return in order to defeat disassemblers. If this method encounters a call that doesn’t return it will never find the OEP.
Why Won’t Ollydump do the Job?
Now that I’ve explained how Ollydump works, you may have some guesses as to why it won’t find the OEP. In this case the trace into method won’t work because there are several loops within the malware that will take so long with a trace that you and I will be dead before it finishes. There are also plenty of calls that never return, which will defeat the second method. Between the two, Ollydump’s find the OEP by section hop isn’t going to work.
Finding the OEP
The following isn’t so much as designed to provide a methodology for finding the OEP, but to share with you how I did just for example’s sake.
1. I started by just stepping through the code. You’ll probably notice that the malware uses the default image address of 00400000. If you weren’t already familiar with that, you may want to check out the MSDN articles above. Below is the initial start of the program:
004012E4 /> 68 E7EFBFFF PUSH FFBFEFE7
004012E9 |. F71424 NOT DWORD PTR SS:[ESP]
004012EC |. C3 RETN
004012ED >|$ 8BF7 /MOV ESI,EDI
004012EF |. 2BFE |SUB EDI,ESI
004012F1 |. 8B35 5C204000 |MOV ESI,DWORD PTR DS:[<&APPHELP.SdbCreateMsiTransformFile>] ; APPHELP.SdbCreateMsiTransformFile
004012F7 |. 68 B6244000 |PUSH Case_071.004024B6 ; /pModule = “APPHELP.dll”
004012FC |. A1 04204000 |MOV EAX,DWORD PTR DS:[<&KERNEL32.GetModuleHandleW>] ; |
00401301 |. FFD0 |CALL EAX ; \GetModuleHandleW
00401303 |. 33FE |XOR EDI,ESI
00401305 |. 1BF8 |SBB EDI,EAX
00401307 |. 81FF 00000100 |CMP EDI,10000
0040130D EB 15 JMP SHORT Case_071.00401324
0040130F |. 0340 3C |ADD EAX,DWORD PTR DS:[EAX+3C]
00401312 |. 2D 7CFFFFFF |SUB EAX,-84
00401317 |. B3 20 |MOV BL,20
00401319 |. 3A18 |CMP BL,BYTE PTR DS:[EAX]
0040131B |. 73 05 |JNB SHORT Case_071.00401322
0040131D |. BE B6244000 |MOV ESI,Case_071.004024B6 ; UNICODE “APPHELP.dll”
00401322 |>^76 C0 |JBE SHORT Case_071.004012E4 ; |
00401324 |> FF15 18204000 |CALL DWORD PTR DS:[<&KERNEL32.Sleep>] ; \Sleep
0040132A \.^EB C1 \JMP SHORT Case_071.<ModuleEntryPoint>
The malware doesn’t really start until the bolded retn instruction is executed. After the retn is executed you’ll be confronted with something strange:
00401018 E8 DB E8
00401019 03 DB 03
0040101A 00 DB 00
0040101B 00 DB 00
0040101C 00 DB 00
0040101D 01 DB 01
0040101E 00 DB 00
0040101F 00 DB 00
00401020 59 DB 59 ; CHAR ‘Y’
00401021 55 DB 55 ; CHAR ‘U’
00401022 8D DB 8D
00401023 2C DB 2C ; CHAR ‘,’
00401024 24 DB 24 ; CHAR ‘$’
00401025 83 DB 83
00401026 EC DB EC
00401027 34 DB 34 ; CHAR ‘4’
00401028 56 DB 56 ; CHAR ‘V’
00401029 FF DB FF
0040102A 36 DB 36 ; CHAR ‘6’
0040102B FF DB FF
0040102C 36 DB 36 ; CHAR ‘6’
0040102D 50 DB 50 ; CHAR ‘P’
0040102E FF DB FF
0040102F 36 DB 36 ; CHAR ‘6’
00401030 3E DB 3E ; CHAR ‘>’
What does this mean!? Olly has misidentified code as data!