Log in

View Full Version : Weird DLL disassembly output in IDA.


5aLIVE
October 27th, 2009, 14:30
I've got a DLL I'd like to take a look at.

When I load it into IDA it applies the SEH for VC7/8 FLIRT signature.

Looking at the segmentation window I see the following:

.idata 00401000
.text 00401190
.data 00416000

Thats doesn't seem right to me, the IAT begins were the code section normally begins (00401000). The .idata section is handled as code instead of data, and the code section has blocks of data double words in it.

Viewing the Functions window in IDA shows a lot of unidentified sub_xxxxxx functions which is to be expected but no recognised library functions are shown like strcpy and strlen and so on. I'm assuming this must be because a suitable FLIRT signature hasn't been applied automatically?

Loading the DLL into stud_PE and other similar tools can't detect the type of compiler used.

Can anyone tell me what steps I need to take to make IDA produce a more intelligible disassembly please?

LordPE shows that DLL has a Security Directory is registered in the PE header. I'm not sure if that is significant or not. I thought I would mention it just in case.


Thanks for any help.

Regards,
5aLIVE.

naides
October 27th, 2009, 15:10
First weird thing I notice is that IDA is mapping the DLL in the memory area typical for the main exe. By default it maps it to 10000000. What gives??

I would load the application that uses the .dll in Olly, look at the memory map and see where in memory this .dll ends up being loaded. . .

5aLIVE
October 27th, 2009, 16:41
Here is the memory map info for the main exe and the DLL.

The main exe:
Base=00400000
Size=00054000 (344064.)
Entry=00404174 <ModuleEntryPoint>

and the DLL::
Base=02430000
Size=0001B000 (110592.)
Entry=0243B316 <ModuleEntryPoint>

The above looks okay to my untrained eye, although I could be wrong.

When looking at memory mapping of the DLL in question using OllyDbg I saw this:

Address=02431000
Size=00015000 (86016.)
Owner=MyDLL 02430000
Section=.text
Contains=code,imports,exports
Type=Imag 01001002

I've never seen the code section combined with import and export sections before. Do I need to fix up the DLL PE in some way? Or is there something else I need to look at?

EDIT:Using ImpREC and attaching to this dll, I can see it imports by ordinal from msvcr80.dll and msvcp80.dll which I believe are used in Microsoft Visual Studio 2005. These ordinal contains some calls of interest such as strcmp, strcpy and so on.

I tried fixing the "dump" (which was a copy of the origianl DLL) and loading this into IDA.
The MSVC imports can now be seen in the Imports window of IDA.
Hmm. I've screwed up somewhere along the way. I tried repeating the above step and I could find any valid imports which makes me think it must be packed. I'll continue with this when I'm not so tired.

Here are the imports when view in PE Explorer:
RPCRT4,Kernel32,USER32, comdlg32, and ADVAPI32.

Entering an OEP into ImpREC and doing an IAT auto search show the following valid imports:
ADVAPI32, Kernel32, msvcp80, msvcpr80, shell32 and user32.

So somethings not right...The number and type of inports don't match either.



The disassembly still remains garbled however too.

evlncrn8
October 28th, 2009, 04:49
tried scanning the file(s) with protection id or similar? (to see if it has some packer etc..?)

5aLIVE
October 28th, 2009, 06:10
@evlncrn8 yes I did try this, both stud_PE and PEiD cannot find anything.

It's definitely packed with something. I'm not sure what though, I 'll try and find the OEP.

It doesn't have an separate section for an unpacking stub.

The EP looks like this:
Code:

0087B316 > $ 5353 PUSH EBX ; MyDLL.<ModuleEntryPoint>
0087B317 . 5555 PUSH EBP
0087B318 . 5656 PUSH ESI
0087B319 . 5757 PUSH EDI
0087B31A . E9 DD420000E9 JMP 0087F5FCH
0087B31F 1313 ADC EAX , DWORD PTR [EDX]
0087B321 3838 CMP BH , BH ; CHAR '8'
0087B323 7474 JE 0087B349H ; CHAR 't'
0087B325 0404 ADD AL , 8BH
0087B327 4C4C DEC ESP ; CHAR 'L'
0087B328 2424 AND AL , 10H ; CHAR '$'
0087B32A 8B8B5424 MOV EDX , DWORD PTR [ESP+0CH]
0087B32E E8E8BDD201 CALL 168985F0H
0087B333 2929960E96CC SUB DWORD PTR [ESI-333369F2H] , EDX ; CHAR ')'


The code below the jump at 0087B31A is greyed out is that because it hasn't been analysed or something?

Which jumps to here:
Code:

0087F5FC > 2BC92B SUB ECX , ECX
0087F5FE . BE E2438800BE MOV ESI , 008843E2H
0087F603 . BF 16B38700BF MOV EDI , 0087B316H
0087F608 . B1 09B1 MOV CL , 09H
0087F60A . F3:A4 MOVSB
0087F60C . B8 9A8C8700B8 MOV EAX , 00878C9AH
0087F611 . 4949 DEC ECX
0087F612 > B9 F60000FFB9 MOV ECX , FF0000F6H
0087F617 . FFC1FF INC ECX
0087F619 . 8B188B MOV EBX , DWORD PTR [EAX]
0087F61B . 2BC92B SUB ECX , ECX
0087F61D . C1CB 10C1 ROR EBX , 10H
0087F620 . 86CF86 XCHG BH , CL
0087F622 . 2ACB2A SUB CL , BL
0087F624 . C1C3 10C1 ROL EBX , 10H
0087F627 . 02CB02 ADD CL , BL
0087F629 . 2ACF2A SUB CL , BH
0087F62B . 81C3 302CFEFF8>ADD EBX , FFFE2C30H
0087F631 . 891889 MOV DWORD PTR [EAX] , EBX
0087F633 . 8D4408 048D LEA EAX , DWORD PTR [EAX+ECX+04H]
0087F637 . 3D DF4388003D CMP EAX , 008843DFH
0087F63C .^72 D472 JC 0087F612H
0087F63E . 2D E23301002D SUB EAX , 000133E2H
0087F643 .^EB CDEB JMP 0087F612H


The above loop appears to be decrypting the code,import section. Which would suggest self-modifying code right? How do I go about finding the OEP for something like this?

Setting a hw breakpoint on KERNEL32.GetProcAddress and the analysing the code give more intelligible results. I still can't find the OEP though...

TBone
October 28th, 2009, 13:05
Your analysis of the code looks right to me. I can't see much of it, but from what you've shown, this looks like a pretty simple unpacker/decrypter. There are some simple loops visible, but no obvious sign of crazy branching anti-tracing code. It's probably somebody's little "homebrew" packer, which is why nothing is shown in PEID, etc. This may also explain why it gives the packed DLL such a goofy base address. Home-grown packers can do some pretty funny things.

Code:
0087B316 > $ 5353 PUSH EBX ; MyDLL.<ModuleEntryPoint>
0087B317 . 5555 PUSH EBP
0087B318 . 5656 PUSH ESI
0087B319 . 5757 PUSH EDI
0087B31A . E9 DD420000E9 JMP 0087F5FCH

To me, this looks like typical behavior for a naive packer. It's PUSHing a few important "contextual" registers onto the stack. It probably intends to POP them back to the CPU state after it's done unpacking, just before it transfers control to the unpacked app.

So my advice is to use a generic unpacking trick that works with most simple packers:

Step through until you reach PUSH EDI, and look at where it will be pushed to (ESP). After it pushes, set a hardware memory breakpoint (on access) at that stack address. Then just run the code. If this is just a simple packer, you should land at a POP EDI instruction (or similar) somewhere at the end of the packer code. The jump to the OED will probably be nearby. Just step through the code until you reach it.

5aLIVE
October 28th, 2009, 16:51
Thank you for the detailed answer, I've tried your suggestion of stepping through until I reach the PUSH EDI instruction, the trouble is that the unpacking loop goes through the entire code section so single stepping would take for ever.

So I new I need to set some sort of conditional break point to help in this task. So that what I did, I set ESP!=current address
and executed a run trace, Olly breaks at a similar decryption loop so I updated the conditional breakpoint accordingly.

Stepped through a bit of code (with no PUSHAD instruction if I remember correctly and landed here:
Code:

0087B047 /$ 5555 PUSH EBP
0087B048 |. 8BEC8B MOV EBP , ESP
0087B04A |. 5151 PUSH ECX
0087B04B |. 8B45 0C8B MOV EAX , DWORD PTR [EBP+0CH]
0087B04E |. 83F8 0183 CMP EAX , 01H
0087B051 |. 5353 PUSH EBX
0087B052 |. 5656 PUSH ESI
0087B053 |. 5757 PUSH EDI
0087B054 |. 0F85 170100000>JNE 0087B171H
0087B05A |. 8B1D A01087008>MOV EBX , DWORD PTR [008710A0H] ; kernel32.GetProcessHeap
0087B060 |. BF 94000000BF MOV EDI , 00000094H
0087B065 |. 5757 PUSH EDI ; /HeapSize => 94 (148.)
0087B066 |. 6A 006A PUSH 00H ; |Flags = 0
0087B068 |. FFD3FF CALL EBX ; |[GetProcessHeap
0087B06A |. 5050 PUSH EAX ; |hHeap
0087B06B |. FF15 74108700F>CALL DWORD PTR [00871074H] ; \HeapAlloc
0087B071 |. 8BF08B MOV ESI , EAX
0087B073 |. 85F685 TEST ESI , ESI
0087B075 |. 75 0775 JNE 0087B07EH
0087B077 |> 33C033 XOR EAX , EAX
0087B079 |. E9 9B010000E9 JMP 0087B219H
0087B07E |> 5656 PUSH ESI ; /pVersionInformation
0087B07F |. 893E89 MOV DWORD PTR [ESI] , EDI ; |
0087B081 |. FF15 64108700F>CALL DWORD PTR [00871064H] ; \GetVersionExA
0087B087 |. 85C085 TEST EAX , EAX


I though that this could be the OEP? I tried dumping the process at this point but the plugin reports that it is unable to read the memory of the debugged process for every section. So in effect it only dumps the PE header and nothing else.

Loading up ImpREC and searching for the IAT at this point reveals nothing but invalid functions.

So I am making a little headway here although I'm not quite there.

TBone
October 28th, 2009, 17:12
Oh, no I don't mean to single-step through the unpacker code. That would take forever. What I'm saying is:

Code:

0087B316 > $ 5353 PUSH EBX ; MyDLL.<ModuleEntryPoint>
0087B317 . 5555 PUSH EBP
0087B318 . 5656 PUSH ESI
0087B319 . 5757 PUSH EDI
0087B31A . E9 DD420000E9 JMP 0087F5FCH ; <-- Pause here

0087B316 is the module entry point. Just single-step 4 times until you are at 0087B31A (the jump to the packer code). Don't jump yet. While it is paused there, Go set a memory breakpoint at [SS:ESP-4], which should be the location where EDI was PUSHed in the previous instruction. Now just run the program -- don't single-step or trace anymore. When it tries to POP that value back into EDI, it will hit your memory breakpoint and stop on its own. This should occur at the end of the unpacker code, and the only thing left to step through by hand is just a tiny little portion before you reach the OEP.

Stronger/smarter packers will use a different method for saving the processor state before unpacking and restoring it afterwards. But if this is just a simple packer, it should work. It's the same trick that would you use if you were manually unpacking UPX, except that UPX uses a full-blown PUSHAD/POPAD instead. The concept is the same, though.

5aLIVE
October 29th, 2009, 11:25
Okay, I follow you now. I performed the "ESP trick" as you describe and this lands me at the code shown below.

This appears to perform another level of decryption of the code section.
Code:

00884015 . 5F5F POP EDI ; MyDLL.0087404C
00884016 . 5E5E POP ESI
00884017 . 5D5D POP EBP
00884018 . 5B5B POP EBX
00884019 . 4848 DEC EAX
0088401A > B8 F6B30058B8 MOV EAX , 5800B3F6H
0088401F . FFC0FF INC EAX
00884021 . 8B028B MOV EAX , DWORD PTR [EDX]
00884023 . 31C931 XOR ECX , ECX
00884025 . C1C8 10C1 ROR EAX , 10H
00884028 . 86CC86 XCHG AH , CL
0088402A . 02C802 ADD CL , AL
0088402C . 8AE88A MOV CH , AL
0088402E . 24 0124 AND AL , 01H
00884030 . C0ED 01C0 SHR CH , 01H
00884033 . C1C0 10C1 ROL EAX , 10H
00884036 . 02C802 ADD CL , AL
00884038 . 02CC02 ADD CL , AH
0088403A . 05 20FF860005 ADD EAX , 0086FF20H
0088403F . 890289 MOV DWORD PTR [EDX] , EAX
00884041 . 8D540A 048D LEA EDX , DWORD PTR [EDX+ECX+04H]
00884045 . 81FA 524088008>CMP EDX , 00884052H
0088404B .^72 CD72 JC 0088401AH
0088404D . 81EA 553001008>SUB EDX , 00013055H
00884053 .^EB C5EB JMP 0088401AH
00884055 . 66:8B41 0866 MOV AX , WORD PTR [ECX+08H]
00884059 . C3C3 RET


0088404D . 81EA 553001008>SUB EDX , 00013055H <- I set a hw bp on execute here.

We jump to here after the hw bp triggers:
Code:

0088401A > B8 16B38700B8 MOV EAX , 0087B316H EAX = 878AE0
0088401F .^FFE0FF JMP EAX ; MyDLL.<ModuleEntryPoint>

Notice that the above code has changed since it was last executed.

So we jump back to the EP which now looks like this:
Code:

0087B316 >/$ 837C24 08 0183 CMP DWORD PTR [ESP+08H] , 01H
0087B31B |. 75 0575 JNE 0087B322H
0087B31D |. E8 1A400000E8 CALL 0087F33CH
0087B322 |> FF7424 04FF PUSH DWORD PTR [ESP+04H]
0087B326 |. 8B4C24 108B MOV ECX , DWORD PTR [ESP+10H]
0087B32A |. 8B5424 0C8B MOV EDX , DWORD PTR [ESP+0CH]
0087B32E |. E8 EDFEFFFFE8 CALL 0087B220H
0087B333 |. 5959 POP ECX
0087B334 \. C2 0C00C2 RETN 000CH


The function called from address 0087B31D is show below:
Code:

0087F33C /$ 5555 PUSH EBP
0087F33D |. 8BEC8B MOV EBP , ESP
0087F33F |. 83EC 1083 SUB ESP , 10H
0087F342 |. A1 C4628800A1 MOV EAX , DWORD PTR [008862C4H]
0087F347 |. 8365 F8 0083 AND DWORD PTR [EBP-08H] , 00H
0087F34B |. 8365 FC 0083 AND DWORD PTR [EBP-04H] , 00H
0087F34F |. 5353 PUSH EBX
0087F350 |. 5757 PUSH EDI
0087F351 |. BF 4EE640BBBF MOV EDI , BB40E64EH
0087F356 |. 3BC73B CMP EAX , EDI
0087F358 |. BB 0000FFFFBB MOV EBX , FFFF0000H
0087F35D |. 74 0D74 JE 0087F36CH
0087F35F |. 85C385 TEST EBX , EAX
0087F361 |. 74 0974 JE 0087F36CH
0087F363 |. F7D0F7 NOT EAX
0087F365 |. A3 C8628800A3 MOV DWORD PTR [008862C8H] , EAX
0087F36A |. EB 60EB JMP 0087F3CCH
0087F36C |> 5656 PUSH ESI
0087F36D |. 8D45 F88D LEA EAX , DWORD PTR [EBP-08H]
0087F370 |. 5050 PUSH EAX ; /pFileTime
0087F371 |. FF15 1C118700F>CALL DWORD PTR [0087111CH] ; \GetSystemTimeAsFileTime
0087F377 |. 8B75 FC8B MOV ESI , DWORD PTR [EBP-04H]
0087F37A |. 3375 F833 XOR ESI , DWORD PTR [EBP-08H]
0087F37D |. FF15 18118700F>CALL DWORD PTR [00871118H] ; [GetCurrentProcessId
0087F383 |. 33F033 XOR ESI , EAX
0087F385 |. FF15 98108700F>CALL DWORD PTR [00871098H] ; [GetCurrentThreadId
0087F38B |. 33F033 XOR ESI , EAX
0087F38D |. FF15 14118700F>CALL DWORD PTR [00871114H] ; [GetTickCount
0087F393 |. 33F033 XOR ESI , EAX
0087F395 |. 8D45 F08D LEA EAX , DWORD PTR [EBP-10H]
0087F398 |. 5050 PUSH EAX ; /pPerformanceCount
0087F399 |. FF15 10118700F>CALL DWORD PTR [00871110H] ; \QueryPerformanceCounter
0087F39F |. 8B45 F48B MOV EAX , DWORD PTR [EBP-0CH]
0087F3A2 |. 3345 F033 XOR EAX , DWORD PTR [EBP-10H]
0087F3A5 |. 33F033 XOR ESI , EAX
0087F3A7 |. 3BF73B CMP ESI , EDI
0087F3A9 |. 75 0775 JNE 0087F3B2H
0087F3AB |. BE 4FE640BBBE MOV ESI , BB40E64FH
0087F3B0 |. EB 0BEB JMP 0087F3BDH
0087F3B2 |> 85F385 TEST EBX , ESI
0087F3B4 |. 75 0775 JNE 0087F3BDH
0087F3B6 |. 8BC68B MOV EAX , ESI
0087F3B8 |. C1E0 10C1 SHL EAX , 10H
0087F3BB |. 0BF00B OR ESI , EAX
0087F3BD |> 8935 C46288008>MOV DWORD PTR [008862C4H] , ESI
0087F3C3 |. F7D6F7 NOT ESI
0087F3C5 |. 8935 C86288008>MOV DWORD PTR [008862C8H] , ESI
0087F3CB |. 5E5E POP ESI
0087F3CC |> 5F5F POP EDI
0087F3CD |. 5B5B POP EBX
0087F3CE |. C9C9 LEAVE
0087F3CF \. C3C3 RET


Now I'm lost.

TBone
October 29th, 2009, 12:12
Hmm... you may not be as lost as you think you are

It seems to me that after the second round of decoding when it jumps back to the (now modified) EP, you probably are at the OEP of the DLL. Most packers create their own code section and change the entry point of the exe/dll to the start of their unpacker code. It looks like this one keeps the OEP, and instead overwrites the first few instructions there with a little stub of code that jumps away to the packer's code section for unpacking. After unpacking, the original code is restored to the entry point. It transfers control to the original app by simply jumping back to the restored EP.

Or at least, that would be my guess. The very last code section you quoted definitely looks like initialization stuff. Remember, this is a DLL, not an EXE. The OEP is probably not going to look quite the same as it would for an EXE. Usually, all it needs to do is some minor initialization stuff. It's not that weird to see a function at the OEP that only does a few things before returning.

Now that you've gone through the unpacking once, you can do it a lot faster now. Start the app and set a hardware breakpoint on execute at the EP (0087B316). It has to be hardware because we know that this section of code will be modified by the unpacker. Setting a software breakpoint would mess it up. Now just run the program until it breaks to the EP again. You should be looking at your decrypted EP. Try dumping and rebuilding the imports from there.

5aLIVE
October 29th, 2009, 12:56
That certainly sounds encouraging, I had wondered about the possibility of the EP becoming the OEP but wasn't sure if this was possible.

Your suggestion of creating a hardware breakpoint on execution certainly helps speed up the process of manually unpacking.
However, there is a snag, I am unable to dump the different memory sections to a file as the dumper reports that it is unable to read the memory.

I also tried using LordPE to create a full dump, it reports that the dumping was done but it doesn't create a file for some odd reason. ImpREC is unable to find the IAT at this OEP.

Looking at the memory map of the DLL shows that Access is set to Read and Initial Access set to RWE for all sections which I take to be common access rights.

update: I am now able to dump from memory, initially I was seeing a "Bad DOS signature" error message when attempting to dump to file. I fixed this by deselecting the 'paste header from disk' option.

Now something rather odd happens, if I load my dumped DLL into IDA, I can see string references and other details identical to those find in loaddll.exe supplied in OllyDbg (I have selected the appropriate DLL from the drop down menu as show below although I have hidden it for obvious reasons.

TBone
October 29th, 2009, 13:19
I'm not sure what's going on there. :/

Run notepad.exe. Can you use LordPE to dump kernel32.dll (or whatever)?

If that works, then what does LordPE show for the imagebase of your target DLL? Check Olly's executable window -- does LordPE's imagebase for the DLL match its base in Olly?

You could also probably do it with the OllyDump plugin, but that's designed more for dumping EXEs, rather than their DLLs. There'd be some extra footwork involved in getting the section table built since the one it builds automatically is for the main module instead of the DLL. It can also do some basic import fixing, but I usually disable that and handle it with ImpRec.

5aLIVE
October 29th, 2009, 13:51
Opening notpad and dumping kernel32.dll works fine using LordPE.

LordPE shows the imagebase of the target DLL as :00870000 which is incorrect, it should be 04000000...
Oh no, Olly shows the imagebase as 00870000 too. The image base of 00400000 is that of the loaddll.exe file.

So the imagebase of Olly and LordPE match. Its the PE dumper plugin that is wrong. Or is it? the base address of 00870000 can be seen at the top in brackets next to the name of the target DLL.

I'm getting a little confused here, so it would appear that I need to update the image base field in the PE Dumper plugin so that I dump the target DLL and not the loaddll.exe file, right? I'll try that in a sec.

update.1: Come to think of it, an image base of 00400000 is typical for a DLL in my limited experience. The plugin won't allow me to modify the base address.

update.2: I'm thinking that the mismatch of base addresses shown in the PE Dumper plugin
(00870000 vs 00400000) may have something to do with the PE header. Maybe I need to fix this?

update.3: Using OllyDump by Gigapede allows me to set the start address (image base) to 00870000. Loading this new dump into IDA shows the message that the entry point 00CEB316 is not loaded into the database. I'm not sure if selecting yes to load the missing data changes the disassembly listing.

IDA is still unable to detect the compiler used, also the header data is shown at the start of the listing which isn't normal in my experience.

However, I can see some meaningful strings and the function and names look good too.
I've done something right, I think I'm just one step away from getting the listing I would expect to see. I'm just not sure what else I need to do to fix this.

Heres what I see at the beginning of the listing:
Code:

HEADER:00870000 ; Segment type: Pure data
HEADER:00870000 HEADER segment page public 'DATA' use32
HEADER:00870000 assume cs:HEADER
HEADER:00870000 ;org 870000h
HEADER:00870000 __ImageBase db 4Dh ; M
HEADER:00870001 db 5Ah ; Z
HEADER:00870002 db 90h ; É
H


These recent findings makes me think I haven't found the correct OEP but I have unpacked the binary.

5aLIVE
October 30th, 2009, 06:32
I decided to take a look in the program directory at other DLLs to see if there where weren't packed. I found one and loaded it into IDA to see what it entry point looked like.

And here it is:
Code:

.text:004E9791 cmp [esp+fdwReason], 1
.text:004E9796 jnz short loc_4E979D
.text:004E9798 call ___security_init_cookie
.text:004E979D
.text:004E979D loc_4E979D: ; CODE XREF: DllEntryPoint+5^j
.text:004E979D push [esp+hinstDLL] ; hinstDLL
.text:004E97A1 mov ecx, [esp+4+lpReserved]
.text:004E97A5 mov edx, [esp+4+fdwReason]
.text:004E97A9 call ___DllMainCRTStartup
.text:004E97AE pop ecx
.text:004E97AF retn 0Ch
.text:004E97AF DllEntryPoint end


Comparing this to my dumped target DLL:
Code:

0087B316 >/$ 837C24 08 0183 CMP DWORD PTR [ESP+08H] , 01H
0087B31B |. 75 0575 JNE 0087B322H
0087B31D |. E8 1A400000E8 CALL 0087F33CH
0087B322 |> FF7424 04FF PUSH DWORD PTR [ESP+04H]
0087B326 |. 8B4C24 108B MOV ECX , DWORD PTR [ESP+10H]
0087B32A |. 8B5424 0C8B MOV EDX , DWORD PTR [ESP+0CH]
0087B32E |. E8 EDFEFFFFE8 CALL 0087B220H
0087B333 |. 5959 POP ECX
0087B334 \. C2 0C00C2 RETN 000CH

We see that it is identical, so I did find the DLL after all. You were right all along TBone.

I'm still unsure what I need to do to fix the dumped PE file so that IDA produces a disassembly listing the same as the "virgin" DLL though.

This little exercise also revealed to me that the DLL will be compiled with MS Visual C 2-8/net runtime.

Hmm. I am unable to dump the "virgin" DLL using OllyDump or LordPE for the same reasons as previously described. Only this time LordPE reports that it cannot grab the process memory.
The problem seems to be directly related to the image base address.

5aLIVE
October 30th, 2009, 08:13
Well what do you know, I was able to dump it properly by using the main executable of the target app. This now loads the image base at 010B0000 and I can get a clean dump. The nice thing I discovered is that the file is linked with debug information too.

[update.1]
I've just been looking through the resource section and contains the icons from the target apps main exe which I used as a loader. I also noticed that the dumped dll has a single dumped export called Start which matches the EP. I would expect to see the DLLEntrypoint as an export here using IDA.

This tells me that the DLL has been dumped as if it were an EXE rather than a DLL. The file size is close to that of the original DLL only a little bigger it. Its not anywhere near the size of the target apps exe.

Gah! Theres something else I need to do to fix this. Any ideas?

Somethings still screwed up here, it turns out the the debug info is for the main exe and Start export is identical to of the target app exe. So I haven't dumped what I thought I had after all.
Trying LordPE again to do a full dump and it still writes nothing!

[update.2]
I now have now been able to dump the DLL successfully using LordPE. By rebooting the machine into safe mode allowed LordPE to dump the process to file. Upon rebooting the machine and attempting to move or renam the dumped file causes NOD32 to detect a variant of the Win32/Kryptk.APK trojan. So it must have been deleting this as soon as it was created and not warning me of the perceived threat.

I am now able to load the dump into IDA and everything is how it should be. What a pain! At least I have learned a few things on my journey with this.

Thanks for the help along the way guys.

TBone
October 30th, 2009, 11:39
Edit: Whoops, you wrote Update 2 of your last post while I was composing this. I guess it was the computer, not the procedure, then . I think I'll leave this up here, though, because it's a handy trick anyway.

Well, I'm glad you found the OEP. I wasn't really sure about that; it was just an intuitive guess.

I'm not sure what's going on with the dumping process. At this point, I can't tell if the problem is procedural, or if there's just something wrong with your computer. To be honest, I never have done much DLL dumping. And moreover, it's probably been close to a year since I've done any reversing, so I'm really rusty on the details of things like that.

I'm not sure about your most recent dump, but the earlier problems may have something to do with trying to dump it from loaddll.exe. There's nothing necessarily "wrong" with loaddll.exe, it just adds more "moving parts", IMHO. You might try this method instead:

DLL files are valid PE executables. The only reason that the windows PE loader won't run a DLL file directly is that it has IMAGE_FILE_DLL set in the header. Toggle that bit with your favorite PE editor and you can just load and run it directly without the need for a "host" EXE. Try loading it directly in Olly and unpack/dump/repair it that way. Just remember to set IMAGE_FILE_DLL in your rebuilt dump when you're done. IIRC, LoadLibrary doesn't care, but other things might.

WaxfordSqueers
November 1st, 2009, 01:49
Quote:
[Originally Posted by 5aLIVE;83517] However, there is a snag, I am unable to dump the different memory sections to a file as the dumper reports that it is unable to read the memory.
sometimes when you are dumping, segments of memory can be paged out to disk. In that case, the dumper can't dump because there is nothing to dump.

The solution is to dump chunks of memory by stepping through it till you find which segments are not there. For example, if you do a D 04000000, then do a 'page down' through it, and you come to a section with all ?????....that section is paged out and the dumper can't read it. In softice you can use a pagein command to reload that memory section. You may have to dump your memory in chunks and reconnect it externally piece by piece.

I would agree that single-stepping can be tedious, but sometimes you have to byte the bullet and do it. I think single stepping reveals not only the structure of the code, it also reveals its detail. Although setting BP's on known functions can be infinitely faster, one tends to lose the intimacy with the code that single stepping supplies.

SS is particularly handy when you keep notes and print out sections of the code for reference.

I would certainly not contemplate single stepping through 100,000 bytes of code, but I would do it long enough to get a feel for what the code was telling me. Eventually loops become apparent and one can jump past scads of code at a time.