Log in

View Full Version : Need help circumventing WinAPI


Darkelf
January 24th, 2007, 20:31
Hi,

I'm new to this board and must say that I'm impressed so far. People get really good help here - just in case they ask the right questions .
I hope I can also answer some questions people may have and give them good advice. But for now I´m the one who has to ask a question. Not on reversing but on programming.
I wonder how it can be realized to circumvent an API-Call. Hooking is not what I mean. I mean doing things that are usually done with a call, without a call - get it?
Let me explain this a bit further. If you code in uuhm... C, and you want to list the contents of a directory, you would probably write something like this:

Code:

HANDLE handle;
WIN32_FIND_DATA wfd;

handle=FindFirstFile("C:\\*",&wfd);

do
{
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
printf("Directory found: %s\n", wfd.cFileName);
else
printf("%s\n", wfd.cFileName);
}
while (FindNextFile(handle,&wfd));
FindClose(handle);


You see, it needs a call to FindFirstFile, FindNextFile to do the listing. Even when you not call something from the API directly, it will be used internaly. For example:

Code:

if(fopen_s(&infile, name, "rb")
printf("\nCan't open file";
else
{
lit = fgetc(infile);
while(!feof(infile))
{
putchar(lit);
lit = fgetc(infile);
}
fclose(infile);
}


In this case ReadFile is called. You must think now that I'm stupid posting this simple things here. But I think the answer to my question is not that simple. The question is again: How can I open a file on disk directly, without using an API-Call? I searched through the net and found simply nothing.
I guess it can only be down low-level (assebly) and I furthermore guess it depends on the filesystem used. But all in all I have no idea where to start.
Any help would be apprechiated.

Best regards
Darkelf

btw. I know it's possible, because some rootkit-detectiontools are using such technique, in order to compare the list of files they get by using the API with the list they get doing it manually. I just want to know how.

naides
January 24th, 2007, 21:28
Your question is not simple at all, and I am certain other, more expert people will give you more technical answers but I will give you my take on it.

"How can I open a file on disk directly, without using an API-Call?"

Between the hardware, meaning the actual bytes in the magnetic media and what you eventually read as "bytes contained in a file", there are multiple layers.
The closer you are to the user32 windows API, the more universal and abstract is your act of "open a file in the disk" is. On the other hand, the closer you are to the hardware, meaning "coding or reading to the bare metal", the more concrete, the more hardware specific and the least universal your protocol or code is.


For instance the high level win32 API -openfile- will open a file in whatever is mapped to to a windows file descriptor, be it PATA, SATA RAID VIRTUAL memory, DYNAMIC, ONLINE, CD DVD ISO FAT32 etc. you care not about the details, You ask for a file, you get it, the minutia are encapsulated by an onion of abstraction layers.

If you go down to directed reading the data form a disk, you need to know a lot more detail: is it a PATA drive? what sector? what plate? what speed? what is DMA? where will the buffer be located?, for how long?
You see, reading from a PATA is not the same as reading from a SATA. and Seagate reading may have idiosyncrasies that a Western drive does not have.

If you want to dive into direct hardware control, like rootkit coders do, you will lose the universality of abstraction. You will lose the "adapter" factor that manufacturer drivers and OS low level routines offer by doing all the dirty work and all the micromanagement for you.

What rootkits coders do is to recapitulate and emulate (often poorly, I must add) similar functionality to what the OS, HAL and low level API would do for you.

I hope this makes sense

Kayaker
January 24th, 2007, 22:26
Hi,

Welcome to the board. A few alternatives perhaps, not taking into account some of the good points brought up by naides..

user mode - CreateFile, OpenFile, FindFirstFile/FindNextFile
user mode (ntdll) - NtCreateFile, NtOpenFile, NtQueryDirectoryFile

kernel mode - ZwOpenFile, ZwCreateSection, ZwMapViewOfSection, ZwQueryDirectoryFile
kernel mode (IRP based) - IRP_MJ_CREATE, IRP_MJ_READ, IRP_MJ_QUERY_DIRECTORY, IRP_MJ_DIRECTORY_CONTROL/IRP_MN_QUERY_DIRECTORY

Can you go deeper than this? Have a look at this paper by Joanna Rutkowska where she discusses this general idea and suggests you could even use the IN/OUT machine instructions with the presumed intent of reading files directly from the HDD:

http://invisiblethings.org/papers/crossview_detection_thoughts.pdf

Cheers,
Kayaker

disavowed
January 25th, 2007, 02:52
I think your question is best answerred with another question: Why do you want to avoid calling API functions?
This will help us to better answer your question.

Darkelf
January 25th, 2007, 06:50
Hi and thank you for your answers.

First of all, I would like to answer disavowed's questions. I want to avoid calling API functions because I want to learn how it can be done - no other reason. I've read an article about rootkit detection and there it says that some tools read directly from disc, just as I wrote in my first post. I found the idea fascinating and started a search - with no result . I don't want to do something evil if you meant that. Promise.

@naides, Kayaker

again, thank you very much for your answers and the link.
I already expected, that it would be a very specific task and that I probably have to rewrite the things a API call would do, writing my own ISR and so on. I'm reading Intel's Software Developers Manual at the moment. Maybe I find something in the instruction's set, but I will have a break and read Joanna's paper first. Very impressive lady, indeed.

Thank you guys. I will tell you here, if I succeed (just in case you're interested).

Have a nice day
Darkelf

dELTA
January 29th, 2007, 06:44
One middle way would be to open the harddisk directly with the CreateFile command (I have some faint recollection though that this was made impossible from XP SP2, wasn't it?) and parse the file system structures yourself. With NTFS this is probably living hell, but with FAT32 it's quite easy.

As you see, there are many different levels to attack, just as usual in the wonderful world of reversing. One misconception I see in your statements though is that assembler code is more "low-level" and powerful than normal compiled programs when it comes to circumventing operating system APIs etc, and I remember this confusion from my early reversing days too.

In this case it is more a matter of privileges in the operating system, rather than what programming language you use to write the program. So, rather than "I guess I must use a program written in assembler to circumvent this", it's a matter of "I must use a ring 0 driver to circumvent this, even though this driver can be written in C or whatever".

autarky
January 29th, 2007, 09:51
Quote:
[Originally Posted by dELTA;64045]One middle way would be to open the harddisk directly with the CreateFile command (I have some faint recollection though that this was made impossible from XP SP2, wasn't it?) and parse the file system structures yourself. With NTFS this is probably living hell, but with FAT32 it's quite easy.


You can still open physical disks and volumes with CreateFile, even on Vista. However, you need to be admin, and on Vista (X64 at least) you are not allowed to write directly to the area comprising the mounted system volume on a disk (to avoid people writing into the pagefile). Reading is still ok. See "Physical Disks and Volumes" on the following page:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/createfile.asp

Beyond that, NTFS isn't too bad to deal with. There is some low-level functionality exposed by DeviceIoControl that can make things easier (such as getting physical disk information). See "Remarks" on the following page:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/deviceiocontrol.asp

The documentation I've come across is pretty helpful though inaccurate in places, though that's not normally that important. I've written a tool that parses through the MFT and can find files on disk (in that particular case, the SAM), and read them. The only complicated aspects are dealing with fragmented files (which isn't too bad), and compressed or encrypted files (which is a bit more complicated). If you're curious, have a look at something like WinHex, or FlexHex, as they allow you to read the raw contents of a disk. Winhex also supports templates to allow the formatting of some internal NTFS structures so it is easier to see what the actually mean.

You may want to take a look at the following for stuff from the Linux NTFS project (which has some pretty helpful source code), and the PDF file particularly helpful:

http://www.linux-ntfs.org/

http://data.linux-ntfs.org/ntfsdoc.pdf

I'm looking into what functionality the disk and scsi miniport drivers provide with respect to low level disk access, but haven't got very far yet. There is also a user mode DLL (untfs.dll) that understands NTFS and is used by scandisk, or whatever it's called on NT, but that is undocumented. It is also on my (long) list of things to stare at at some point - the export symbols are pretty helpful.

Quote:
[Originally Posted by Darkelf]
I want to avoid calling API functions because I want to learn how it can be done - no other reason. I've read an article about rootkit detection and there it says that some tools read directly from disc, just as I wrote in my first post. I found the idea fascinating and started a search - with no result.


I know someone who has done that for an AV rootkit scanner - I think he just wrote a device driver based on the Linux NTFS stuff. It's not that difficult, especially if you're not interested in read/write access, just that the file physically exists on disk.

Darkelf
January 29th, 2007, 21:04
Hi there,

I was unable to login for the last few days, so I answer that late.
I will read all the papers you provided me with. I hope I get it, 'cause at the moment my head feels like a pumkin.

@dELTA

I must confess I really was of the opinion that Assembler is more "low-level" than any other language. I know C is called the "high-level-assembler" but I thought Assembler has even a bit more to offer. Thanks for bringing light to the darkness.

Best regards
Darkelf

dELTA
January 30th, 2007, 02:48
Assembler is of course more "low-level" in some ways (namely the way that you could make much more specific programs in less codelines, must specify everything yourself without help from pre-made structures etc), which is exactly why it's easy to be fooled into thinking that you could also get higher privileges in situations like this with it, compared to e.g. C. You can't, and that was my only point, and helpful tip.