Log in

View Full Version : CreateFile logging


sabbato753
May 26th, 2010, 16:06
Hello,

Let me start by promising that I've a) searched, and b) read the FAQ. Then I searched again. And once more to be sure I wasn't being daft.

The executable I'm working on (Delphi 7, no packing) has a TON of CreateFileA loops at start as it loads up scripts, graphics, etc. from the HDD. Somewhere in this, it also loads up a DAT file with some type of hash of the key. I'd love to see how it uses this file, but it loads it in along with more than 500 other entries.

The DAT file is not referenced directly anywhere in the program, and is not a searchable string. The name is actually computed in a loop that's a bit beyond my understanding. as are most of the program jumps (stack/register calculated instead of hard links). This is making following the program's path very difficult for me.

What I'd like to do is find an Olly plugin that allows me to enter a filename and break on the first entry to that file (so I can see where it maps it in memory). I've put a note in that forum in case anyone can direct me.

In the meantime, I was wondering if anyone had a better suggestion. I've tried:
1) Searching for the filename as a string in IDA and Olly. No dice.
2) Using the MemoryWatch plugin to watch registers and info pane for the name of the file (in ascii). No dice...but I'm not sure why on this one?
3) Searching for parts of the file in the memory of the program in hex (no dice, I guess the file is modified or dumped very quickly after it's loaded).

MUCH of the program reuses its code (yay Delphi!), so things like button presses, typing, etc. all go through the same bits of code over and over...including the massive file-load at the start. The program also doesn't do its own serial check- it tries to send off to the net, so I can't even just find that "thanks for registering!" piece and find out where that modifies.

So, I'm at a bit of a loss as to where to go from here. I know that it checks the registration on startup, that it uses this one file to do it and that it loads that file in amongst a bunch of others. That seems to be my best guess as to where flip switches.

Any better ideas?

Darkelf
May 26th, 2010, 17:10
That might be quite easy.
Rename the file and see if that throws an exception. If so, hit F12 while in Olly and open the call stack (Alt+K). Find from where the exception is called and search your way back to the last CreateFile call. This is where your .dat-file is opened.
If that file is essential for the program, it will work that way. If not, give Conditional Branch Logger a try. Let Olly run up to where all the files are opened. One time with the .dat-file in place, one time without and compare the logs.
Be creative

Best regards
darkelf

aqrit
May 26th, 2010, 20:05
use a compiler and start hooking functions NtCreateFile, NtOpenFile, NtReadFile, etc.
examine the args and "int 3" when you find something of interest

FrankRizzo
May 26th, 2010, 21:43
I would give Dede a run through the app, and see if it makes things any more understandable. I tend to throw a bunch of tools at Delphi apps, and kinda aggregate the info from them into a picture of what's really going on. You might find that Dede makes the code a little more understandable.

BoB
May 27th, 2010, 01:01
Set breakpoint on Kernel32.dll CreateFileW, on a line so you can see the stack entries for filename, press F9 until you see it. Then remove breakpoint, set new breakpoints on SetFilePointer and ReadFile apis, and trace back to the code that called CreateFile api.
Memorize EAX value (file handle) and trace or run to either setting position in file (SetFilePointer) or reading from the file (ReadFile), now you can see where the file is read from, how much is read, where the file data is read to, etc etc

Or, you could use FileMon

Have fun!
BoB

niaren
May 27th, 2010, 06:27
Maybe you can use conditional breakpoints in Olly....
If you have the commandbar plugin you can write something like this in the commandbar edit box

bp CreateFileA, string [[ESP+04]], "filename.dat"

to obtain a file handle. Then

bp ReadFile, [[ESP+04]]==filehandlevalue

More details here: http://forum.exetools.com/showthread.php?t=2380&goto=nextnewest

Good luck!

sabbato753
May 27th, 2010, 07:55
Thanks all! I'm going to give a few of these a try, but I wanted to give a quick individual response too -

@DarkElf - Love this idea, trying it first - simple and quite possibly effective. The issue will be whether it considers it essential, or whether any key other than valid is just treated as invalid. We'll see!

@agrit - I'm not sure if I understand what you mean...could you try to explain more in depth?

@FrankRizzo - Thanks for that suggestion. I tried DeDe, I probably should have mentioned that, but I agree that piecing all the parts of delphi together is a many-tool job. Unfortunately, DeDe chokes on this. I read somewhere that there are ways of getting around that, but I think that's beyond my level at the moment.

@BoB - Heh. This was actually my first go-round. Actually, I still have the breakpoints set that you are mentioning. Issue is, there's over 500 files loaded before and another 200 after. I got bleary-eyed after hitting F9 so much. Will FileMon give me that much info? I guess I have to look at it closer - I didn't think of it because I knew it was opened, and roughly where, so I guess I undervalued that tool!

@niaren - I like this solution - it sounds quite elegant. I think I need to look at CommandBar. I remember softice from back when I dabbled in this oh so long ago...but if I can do that, it should make a LOT of things easier for me going forward. New toys!

I'll be trying these all in the next few hours...so I guess we'll see! Even if I find it one way, I'll try to get there a couple other ways to learn these techniques. Thanks!

squidge
May 27th, 2010, 14:31
Try WinAPIOverride32, it'll give you info like this if you ask it to monitor CreateFileA calls:

2 In CreateFileA(lpFileName:0x001238BC:"C:\WINDOWS\PROG.INI",dwDesiredAccess: 0x80000000,dwShareMode: 0x3,lpSecurityAttributes:0x00000000: Bad Pointer,dwCreationDisposition: 0x3,dwFlagsAndAttributes: 0x0,hTemplateFile: 0x00000000) 0x00000FCC 0x00425D53 PROG.EXE + 0x00025D53 0x000008F0 0x000006BC 0x00000000 EAX=0x001238bc, EBX=0x00126a08, ECX=0x00000003, EDX=0x00000000, ESI=0x00126a08, EDI=0x00620f20, EFL=0x00000246, ESP=0x00123860, EBP=0x001238a0 EAX=0x00000fcc, EBX=0x00126a08, ECX=0x7c91005d, EDX=0x0a160001, ESI=0x00126a08, EDI=0x00620f20, EFL=0x00000293, ESP=0x0012387c, EBP=0x001238a0 -1.#IND 20:27:50:536:632,8 69 kernel32.dll CreateFileA C:\PROG.EXE

Plus, there's window at the side which gives more info on each API call.

Indy
May 30th, 2010, 17:37
ProcessHandleTracing.

Kayaker
May 30th, 2010, 18:36
Quote:
[Originally Posted by Indy;86685]ProcessHandleTracing.


Good thought. As in !htrace?

Pushing the Limits of Windows: Handles
http://blogs.technet.com/b/markrussinovich/archive/2009/09/29/3283844.aspx

http://msdn.microsoft.com/en-us/library/ff563208(VS.85).aspx

Indy
May 30th, 2010, 23:15
Kayaker
Yes, exactly that. It also can make procmon Sysinternals(Mark Russinovich). Logger keeps backtrace, but the main thing is to obtain control of a call services and a portion kernel backtrace that allows it to detect hooks
If the running of logging, the reference invalid handle will generate #STATUS_INVALID_HANDLE. This exception can be handled. Handle is replaced(magic) with the disability in return from the function which created it:
http://files.virustech.org/indy/Code/LDR/Exts/ ("http://files.virustech.org/indy/Code/LDR/Exts/")
Here an example of detecting interception of the kernel:
http://files.virustech.org/indy/Code/IcpSfc/ ("http://files.virustech.org/indy/Code/IcpSfc/")

BanMe
June 21st, 2010, 10:41
umm...
Code:

void Log_CreateFile(
__in LPCTSTR lpFileName,
__in DWORD dwDesiredAccess,
__in DWORD dwShareMode,
__in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
__in DWORD dwCreationDisposition,
__in DWORD dwFlagsAndAttributes,
__in_opt HANDLE hTemplateFile
)
{
if(strcmp((char*)(lpFileName+strlen(lpFileName)-3)),"dat" == 0)
{
printf("File Name: %s \n Return address from %s: %p\n",lpFileName, __FUNCTION__, _ReturnAddress());
__asm jmp Orig_CreateFileFile+5;
}
__asm jmp Orig_CreateFileFile+5;
}






regards BanMe