Monday, March 5, 2012

How to launch a kernel thread in windows


#include <wdm.h>

HANDLE  ThreadHandle;
struct TAPESH
{
LARGE_INTEGER tickCount;
unsigned long incrementCount;
} tapeshobj[30000];

volatile LARGE_INTEGER makeItLarge;
unsigned long Its_your_life = 0;
int i = 0;

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
DbgPrint("Driver unloading\n");
}

VOID LoopFunction()
{
while (1)
{
for (i = 0; i < 30000; ++i)
{
//KeQueryTickCount(&makeItLarge);
makeItLarge = KeQueryPerformanceCounter(NULL);
tapeshobj[i].tickCount = makeItLarge;
tapeshobj[i].incrementCount = Its_your_life++;

}
}
}

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{

DbgPrint("Driver loading\n");
DriverObject->DriverUnload = DriverUnload;

if (PsCreateSystemThread(
&ThreadHandle,
(ACCESS_MASK) 0L,
NULL,
NULL,
NULL,
( PKSTART_ROUTINE ) LoopFunction,
NULL
  ) == STATUS_SUCCESS)
{
DbgPrint((" Thread Success "));
}
else
{
DbgPrint((" Thread Failed "));
}


return STATUS_SUCCESS;
}

Monday, February 13, 2012

Print all permutation

Although it's just a program (algorithm) , but I took lot of time to solve this. So, feel worth to post it here.

Question : given a string like 'abc' print all combinations
ans,  :  abc acb bac bca cab cba


============


void printall(char *str, char *ptr)
{
if (*(ptr+1) == '\0')
{
cout << str << endl;
}
else
{
for (char* swap = ptr; *swap != '\0'; ++swap)
{
char temp = *swap;
*swap = *ptr;
*ptr = temp;

printall(str, ptr+1);

temp = *ptr;
*ptr = *swap;
*swap = temp;
}
}
}

int main(int argc, char **argv)
{
char str[2056] = "abcd";
printall(str, str);
}

Saturday, January 28, 2012

Analyzing DUMP for stack corruption because of string overflow

Today i am going to show an example on how to analyze the DMP file where it is showing the stack corruption.
So, here is my test code:


void fun(int argc, char** argv)
{
if (argc != 2)
{
cout << "Incorrect param" << endl;
return;
}

char str[4];
strcpy(str, argv[1]);

cout << "String passed : " << str << endl;
}

int main(int argc, char** argv)
{
fun(argc, argv);

return 0;
}


And this is how i executed this,

test.exe abcdefghijklmnopqrstuvwxyz
String passed : abcdefghijklmnopqrstuvwxyz
<Program crashed here>


Ofcourse, i am passing a big string (more than the space avialble) and this will cause stack coupption, now look at dump and see how we can get it from DMP

I use kvn command and this is what i got...


0:000> kvn
 # ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0012f95c 00412d9c 0041156b 00000001 00000002 ntdll!DbgBreakPoint
01 0012fd84 00412095 0041156b 00411598 0012fe8c test!_RTC_StackFailure+0x10c (FPO: [Non-Fpo]) (CONV: cdecl)
02 0012fda4 0041156b 10574ac8 10574ac8 0012ff68 test!_RTC_CheckStackVars+0x45 (FPO: [Non-Fpo]) (CONV: fastcall)
03 0012fe8c 706f6e6d 74737271 78777675 3a007a79 test!fun+0xab (FPO: [Non-Fpo]) (CONV: cdecl) [c:\documents and settings\tapesh.maheshwari\my documents\visual studio 2005\projects\test\test\test.cpp @ 28]
04 0012ff68 00412596 00000002 00365778 003633e0 0x706f6e6d
05 0012ffb8 004123dd 0012fff0 7c817077 3a0cf126 test!__tmainCRTStartup+0x1a6 (FPO: [Non-Fpo]) (CONV: cdecl) [f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 597]
06 0012ffc0 7c817077 3a0cf126 01ccddaf 7ffd7000 test!mainCRTStartup+0xd (FPO: [Non-Fpo]) (CONV: cdecl) [f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 414]
07 0012fff0 00000000 00411177 00000000 78746341 kernel32!BaseProcessStart+0x23 (FPO: [Non-Fpo])


Please note the BOLD part, this is where WinDBG failed to get the correct function. It means corruption has happened till this point and 'return address' has been overwritten. Let's choose the ChieldEBP of one above and use DD command (because we all know that return address is just before EBP).


0:000> dds 0012fe8c 
0012fe8c  6c6b6a69
0012fe90  706f6e6d
0012fe94  74737271 msctf!TF_CreateCicLoadMutex+0x286
0012fe98  78777675
0012fe9c  3a007a79
0012fea0  01ccddaf
0012fea4  7ffd7000
0012fea8  cccccccc
0012feac  cccccccc
0012feb0  cccccccc
0012feb4  cccccccc
0012feb8  cccccccc
0012febc  cccccccc
0012fec0  cccccccc
0012fec4  cccccccc
0012fec8  cccccccc
0012fecc  cccccccc
0012fed0  cccccccc
0012fed4  cccccccc
0012fed8  cccccccc
0012fedc  cccccccc
0012fee0  cccccccc
0012fee4  cccccccc
0012fee8  cccccccc
0012feec  cccccccc
0012fef0  cccccccc
0012fef4  cccccccc
0012fef8  cccccccc
0012fefc  cccccccc
0012ff00  cccccccc
0012ff04  cccccccc
0012ff08  cccccccc

So, it means the BOLD part should actually contains the 'return address', which is having '706f6e6d' and stack is also pointing to this address. So, it's clear that return address has been overwritten by value 706f6e6d

But, there could be more memory which is overwritten (hopefully), so we can actually try to see 50 more and 50 less address also

0:000> dds 0012fe90-50 0012fe90+50
0012fe40  cccccccc
0012fe44  cccccccc
0012fe48  cccccccc
0012fe4c  cccccccc
0012fe50  cccccccc
0012fe54  cccccccc
0012fe58  cccccccc
0012fe5c  cccccccc
0012fe60  cccccccc
0012fe64  cccccccc
0012fe68  cccccccc
0012fe6c  cccccccc
0012fe70  cccccccc
0012fe74  cccccccc
0012fe78  cccccccc
0012fe7c  cccccccc
0012fe80  cccccccc
0012fe84  64636261
0012fe88  68676665
0012fe8c  6c6b6a69
0012fe90  706f6e6d
0012fe94  74737271 msctf!TF_CreateCicLoadMutex+0x286
0012fe98  78777675
0012fe9c  3a007a79
0012fea0  01ccddaf
0012fea4  7ffd7000
0012fea8  cccccccc
0012feac  cccccccc
0012feb0  cccccccc
0012feb4  cccccccc
0012feb8  cccccccc
0012febc  cccccccc
0012fec0  cccccccc
0012fec4  cccccccc
0012fec8  cccccccc
0012fecc  cccccccc
0012fed0  cccccccc
0012fed4  cccccccc
0012fed8  cccccccc
0012fedc  cccccccc
0012fee0  cccccccc

Please note the BOLD part, this is part which seems to be overwritten. Let's try the DA command (show the memory as string) on the beginning of the potential overwritten data...

0:000> da 0012fe84  
0012fe84  "abcdefghijklmnopqrstuvwxyz"

WOW !! we got the same string which got overwritten (started from address 0012fe84 and goes to 0012fea4 ) over EBP and return address.... corrupting everything :)


Where memory manger store the size of heap allocation for array

Wondering why you need not to pass the allocated byte size during 'delete' call for an array ?
I was aware that it's stored somewhere behind the pointer but never dig into it. Today i thought to give it a try on my windows m/c (windows XP SP3).

This is the code i wrote :


struct a
{
int m;
float f;
};


void fun(int argc, char** argv)
{
int *i = new int[30];
char *c = new char[15];
a *b = new a[10];
        cout << "fun" << endl;
}

and called function 'fun' from main(). I used WinDbg and step all these allocations and come to 'cout' statement (just a dummy statement, we will not use it). At this point of time, i can see all the local pointer variables and where they point to.

This is what i got.


0:000> dv
           argc = 0n2
           argv = 0x00365df0
              c = 0x00365f70 "???"
              b = 0x00365fc0
              i = 0x00365eb8


So, i got the c, b and i pointer address. I use dd command to dump the memory with offset of 10.


0:000> dd 0x00365f70 - 10
00365f60  0000000f 00000001 00000079 fdfdfdfd
00365f70  cdcdcdcd cdcdcdcd cdcdcdcd fdcdcdcd
00365f80  abfdfdfd abababab feababab feeefeee
00365f90  00000000 00000000 000a0012 001c0706
00365fa0  00365f50 00000000 00000000 00000000
00365fb0  00000050 00000001 0000007a fdfdfdfd
00365fc0  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00365fd0  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd

0:000> dd 0x00365fc0 - 10
00365fb0  00000050 00000001 0000007a fdfdfdfd
00365fc0  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00365fd0  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00365fe0  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00365ff0  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00366000  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00366010  fdfdfdfd abababab abababab feeefeee
00366020  00000000 00000000 001201fb 00ee14ee

0:000> dd 0x00365eb8 - 10
00365ea8  00000078 00000001 00000078 fdfdfdfd
00365eb8  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00365ec8  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00365ed8  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00365ee8  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00365ef8  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00365f08  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd
00365f18  cdcdcdcd cdcdcdcd cdcdcdcd cdcdcdcd

please note the bold value in hexadecimal. This is same as total bytes allocation requested during 'new' function call. So, this is the location from where 'delete' got the total size allocation value (just 16 bit behind) :).

Saturday, January 21, 2012

How to write a multipart HTTP post request using simple HTML page

I found that it can be easily done in simple HTML page.


<html>
<body>
<form method="post" action="http://www.google.com" enctype="multipart/form-data">
<input type="text" name="mytext">
<input type="submit">
<input type="file" name="myfile">
</form>
</body>
</html>

Just write the above text and save the file as HTML file. Remember that the request itself will not work because GOOGLE will not support this post request, so change it so some valid URL. Here the enctype part enforce the content-type to be Multipart