Log in

View Full Version : Unpacking nTitles


bboitano
May 24th, 2007, 04:07
I have looked at both of MaDMAn_H3rCuL3s' ARTeam tutorials for the nTitles verifier but am having a problem with one particular application. I'm not sure if it is a new version of nTitles as it was released sometime after MaDMAn's last tutorial

So far I have seen the dump in memory (with the incomplete IAT) when using the imagehlp.MapAndLoad API.

This is what I get :
Code:
004142EF |. FF15 0C365700 CALL DWORD PTR DS:[<&imagehlp.MapAndLoad>] ; imagehlp.MapAndLoad

And the stack :

0012E7F4 0012E938 |Arg1 = 0012E938 ASCII "xxxxxxxx.dat"
0012E7F8 00000000 |Arg2 = 00000000
0012E7FC 0012E808 |Arg3 = 0012E808
0012E800 00000000 |Arg4 = 00000000
0012E804 00000001 \Arg5 = 00000001


I follow the instructions to let it unload and then to search for the REP MOVS DWORD ... but the next occurance of that sort of command is far away (0x200) from where we are currently debugging and executed long after the actual app is launched.

It appears that nTitles is using CreateProcessA to create a suspended thread

Code:
00412B93 . FF15 1C335700 CALL DWORD PTR DS:[<&KERNEL32.CreateProcessA>] ; \CreateProcessA

Stack again :

0012E820 00000000 |ModuleFileName = NULL
0012E824 0012E91C |CommandLine = "xxxxxxxx.dat "
0012E828 00000000 |pProcessSecurity = NULL
0012E82C 00000000 |pThreadSecurity = NULL
0012E830 00000000 |InheritHandles = FALSE
0012E834 00000004 |CreationFlags = CREATE_SUSPENDED
0012E838 00000000 |pEnvironment = NULL
0012E83C 00000000 |CurrentDir = NULL
0012E840 0012E8D4 |pStartupInfo = 0012E8D4
0012E844 0012E874 \pProcessInfo = 0012E874

To which it then writes to after opening the process
Code:

00412C80 . FF15 20335700 CALL DWORD PTR DS:[<&KERNEL32.ReadProcessMemory>] ; \ReadProcessMemory

Stack:

0012E834 000000DC |hProcess = 000000DC
0012E838 00401000 |pBaseAddress = 401000
0012E83C 01060020 |Buffer = 01060020
0012E840 000EB000 |BytesToRead = EB000 (962560.)
0012E844 0012E860 \pBytesRead = 0012E860

Buffer (first few bytes) looks like this :
Code:

01060000 50 00 B2 00 50 00 B2 00 00 00 00 00 00 00 00 00 P..P..........
01060010 00 C0 0E 00 00 C0 0E 00 00 10 00 00 00 0B 00 00 ........ ..
01060020 6A FF 68 88 2D 4E 00 64 A1 00 00 00 00 50 64 89 jh-N.d....Pd
01060030 25 00 00 00 00 83 EC 1C 8A 44 24 2C 53 55 8B E9 %....D$,SU
01060040 56 57 8D 7D 0C 33 F6 56 8B CF 89 6C 24 18 88 07 VW}.3Vωl$
01060050 E8 CB 2D 00 00 8A 4C 24 3C 8D 5D 1C 89 74 24 34 -..L$<]t$4
01060060 88 0B 89 73 04 89 73 08 89 73 0C 8D B5 FC 0A 00 sss...
01060070 00 8D 54 24 11 52 8B CE C6 44 24 38 01 89 74 24 .T$RD$8t$
01060080 1C E8 CA 28 00 00 8D 44 24 12 8D 4E 10 50 C6 44 (..D$NPD
01060090 24 38 02 E8 B8 28 00 00 8D 54 24 13 8D 4E 20 52 $8(..T$N R
010600A0 C6 44 24 38 03 E8 A6 28 00 00 8D 4E 30 C6 44 24 D$8(..N0D$


I notice we have the 20h offset that appears in the 2nd of the ARTeam Tutorials but from the address 401000h, it does looke like it is writing the code section in memory of the other process.

Shortly after it closes the handles to that thread and resumes it - launching my target app.

However, I don't know where I am going wrong in any of the stages below :

1. I've tried just dumping the .dat and changing to .exe as some simpler nTitles ones apparently do that
2. Tried dumping the process before it is resumed (I thought this should be the virgin app ... but no )
3. Tried dumping the process after it is resumed and fixing it up with ImpRec but that is not working either

And I did try searching for nTitles, but got no hits

Any help/pointers etcetera most gratefully received.

bb

evlncrn8
May 24th, 2007, 08:13
hmm reminds me of a similar protection,
try hooking createprocess, grab the filename, copy the file somewhere
hook writeprocessmemory, catch the area its writing to (most likely its the entry point of the suspended process), get the amount of data its writing, copy it somewhere..
open the file you copied, convert the va from the writeprocessmemory data to an offset, seek to this offset in the file, and write the data you caught from the writeprocessmemory hook, save the file.. hopefully job done (and especially - no need to repair imports and all that nonsense if you're lucky)

then work from the file you just repaired, it might have 'callbacks' etc to the parent process (check the params on createprocess - watch what goes on.. especially if its a debug launch...)

bboitano
May 24th, 2007, 08:44
Thanks evlncrn8 for the hints - I'll try that this evening.

And thank you for not pointing out that I pasted the ReadProcessMemory snippet, not the WriteProcessMemory one ...

evlncrn8
May 24th, 2007, 16:46
heh i never even noticed, but hey, its an easy mistake to make..

bboitano
May 25th, 2007, 05:07
Righty then

Now I've solved the problem, I feel it only fair to exlapin what I did so that others may benefit too.

evlncrn8's idea looked like the best approach but unfortunately, I couldn't get it to work initially. I'm not sure, but is there a size limitation for the OllyDBG binary copy and paste? I'm sure it would have worked had I resorted to other tools to make the necessary changes.

In the end I used MaRKuS TH-DJM's brilliant Olly Advanced to inject EBFE into the process just after the WriteProcessMemory call and then dumped the looping image using LordPE.

Restoring the original bytes for EBFE to 558B sorted the 'problem' completely.

Once again my thanks to evlncrn8 for the help and for taking the time to reply. Cheers buddy!

Now, if you would just care to explain in a little more detail what 'callbacks' are and how I should check them ...

bb

blabberer
May 25th, 2007, 09:42
Quote:

evlncrn8's idea looked like the best approach but unfortunately, I couldn't get it to work initially. I'm not sure, but is there a size limitation for the OllyDBG binary copy and paste?


none as far as i know but lets confirm

load ollydbg on ollydbg and do alt+m and sort the memory map by size
we see shell32.dll s .rsrc size is maximum

lets try copy paste this

here are the results

Code:

Memory map, item 0
Address=775CD000
Size=005E0000 (6160384.)
Owner=SHELL32 773D0000
Section=.rsrc
Contains=resources
Type=Imag 01001002
Access=R
Initial access=RWE

the last recognizable bytes are here
77BAC96C /74 00 JE SHORT SHELL32.77BAC96E
77BAC96E \6900 6F006E00 IMUL EAX, DWORD PTR DS:[EAX], 6E006F
77BAC974 0000 ADD BYTE PTR DS:[EAX], AL
77BAC976 0000 ADD BYTE PTR DS:[EAX], AL
77BAC978 0904B0 OR DWORD PTR DS:[EAX+ESI*4], EAX
77BAC97B 04 00 ADD AL, 0

lets select the entire area and do a binary copy

ollydbg warns us with huge copy dialog and asks for confirmation and also suggests an alternative see picture below

we simply ignore and click yes

ollydbg says proceding at your own risk

and starts a progress bar

after few minutes we have the entire section in clip board

lets paste it to notepad

and check its size

test:/>dir "full bincopy.txt"
Volume in drive C has no label.
Volume Serial Number is 276D-07F3


05/25/2007 08:01 PM 18,673,666 full bincopy.txt
1 File(s) 18,673,666 bytes
0 Dir(s) 2,091,540,480 bytes free

test:/>

binary copied file do contain our last recognized bytes

72 00 61 00 6E 00 73 00 6C 00 61 00 74 00 69 00 6F 00 6E 00 00 00 00 00 09 04 B0 04 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

so it successfully binary copy pasted 37 mb

was your size greater than this ?

if so you could have also asked ollydbg to create backup save backup to file

this makes a bin file (not ascii representation of hex as in binary copy paste but actual hex)

which could be spliced into any file


evlncrn8
May 25th, 2007, 12:46
well generally i'd use olly to see whats going on
then code a tool to do the hooks, dumping etc..
much much easier, and a bit more control too

lordpe was an overkill, all you had to do was to
break on the createprocess, and open the folder in
explorer, and copy the file, from then all you have
to do is patch in the bytes... without having to fix
the imports most likely with lord pe...

bboitano
May 28th, 2007, 03:33
blabberer, thanks for checking that out for me. It does in fact confirm what I suspected - that it was me being a bit of a noob after all.

The reason I asked was that I tried a couple of times to copy and paste the new code over the old code and it appeared only to do the first few hundred bytes or so. The end of the section remained the same so naturally I assumed that it must be Olly. Of course it couldn't be me making a hash of it could it now

Next time I'll try the bin file approach.

evlncrn8 - I think your method would have worked if I was more competent - thanks again for your suggestion.

bb

evlncrn8
May 30th, 2007, 07:02
oh the callbacks...
sometimes the child process (spawned from the main process.. in this case via CreateProcessA) tries to communicate back to its parent...

for example, safedisc launches a parent 'debugging' process..
when the child hits an int 3 (or some other exception), the parent is notified and fixes up the child (puts the toys back in the pram is probably the best expression), tells the child all is ok, and lets the child continue..

so the child could..

1. cause an exception
2. SendMessage back to the parent window (if there is one) to ask for 'special' data
3. use a mapped file for communications from child->parent (and vice versa)

and so on...

so, depending on the protection you might also have to solve these as well...
it might not be the case in your example however... but if you get weird shit happening, its most likely the reason (well that, and / or a badly rebuilt import table)...