JMC31337 Posted December 15, 2013 Author Posted December 15, 2013 (edited) heres the next step of loading ntdll, getting the GetProcaddress of RtlInitUnicodeString, which is giving me a real nice tough time under ASM just to copy a UNICODE string into another variable (without using any sysenter call): //http://www.cnblogs.com/cfas/archive/2013/05/31.html /* Typedef Definition CHAR char PSTR or LPSTR char* PCSTR or LPCSTR const char* PWSTR or LPWSTR wchar_t* PCWSTR or LPCWSTR const wchar_t* */ #define DWORD unsigned long #define WORD unsigned short #define BOOL unsigned long #define PSTR const char* #define PWSTR wchar_t* #define PCSTR const char* DWORD getproc; //GetProcAddress mem address DWORD ll; //LoadLib mem address DWORD k32; //kernel32 base address DWORD ntdllx; //ntdll base address DWORD rtluni; //RtlInitUnicodeString address PWSTR NTOSKRNL=L"ntsokrnl.exe"; //char *xnt = "ntoskrnl.exe"; PWSTR file = L"\\??\\C:\\testXXX.txt"; PWSTR test; char *non_paged_memory; int main() { asm("push ebp"); //setup a new stack frame asm("mov esp,ebp"); //setup a new stack frame asm("xor eax,eax"); //clear eax register asm("xor ebx,ebx"); //clear ebx register asm("xor ecx,ecx"); //clear ecx register asm("xor edx,edx"); //clear edx register //GET k32 BaseAddr asm( "mov esi, dword ptr fs:[0]\n" //standard way for use to walk the TEB/PEB table "lodsd\n" "cdq\n" "lodsd\n" //looking for the kernel32.dll base address "@base_loop:\n" //k32 holds the GetProcAddress API "dec eax\n" "cmp dword ptr [eax], 0x00905a4d\n" "jnz @base_loop\n" ); asm( "mov _k32,eax" //now we have our variable _k32 holding the base address //of the kernel32.dll ); asm( "mov edi,dword ptr _k32\n" // k32 = edi = eax = Kernel32 BaseAddress "mov eax,dword ptr [eax + 0x3C]\n" // offset to start of PE header "mov edx,dword ptr [eax + 0x78 + edi]\n" // IMAGE_EXPORT_DIRECTORY--->RVA "add edx,edi\n" // IMAGE_EXPORT_DIRECTORY--->VA = edx "mov ecx,dword ptr [edx + 0x18]\n" // ecx = NumberOfNames "mov ebx,dword ptr [edx + 0x20]\n" // ebx = AddressOfNames "add ebx,edi\n" "_Index:\n" "dec ecx\n" // ecx --- NumberOfNames ???? ---- ???????? "mov esi,dword ptr [ebx + ecx * 4]\n" // Name -- RVA "add esi,edi\n" "cmp dword ptr [esi],0x50746547\n" //PteG "jnz _Index\n" "cmp dword ptr [esi + 0x04],0x41636f72\n" //Acor "jnz _Index\n" "cmp dword ptr [esi + 0x08],0x65726464\n" //erdd "jnz _Index\n" "cmp word ptr [esi + 0x0C],0x7373\n" //ss "jnz _Index\n" "mov ebx,dword ptr [edx + 0x24]\n" // AddressOfNameOridinals --- ????? "add ebx,edi\n" "mov cx, word ptr [ebx + ecx * 2]\n" "mov ebx,dword ptr [edx + 0x1C]\n" // ebx = AddressOfFunctions "add ebx,edi\n" "mov eax,dword ptr [ebx + ecx * 4]\n" "add eax,edi\n" "mov _getproc, eax\n" //API ADDRESS TO GetProcAddress -> getproc variable "pop ebp\n" //clean up "mov ebp,esp\n" //clean up our stack "mov edi,eax\n" //edi held our k32 base address //so now it holds the value of eax //eax = getproc edi now = getproc "push 0x00\n" //00000000 .... "push 0x41797261\n" //41797261 aryA "push 0x7262694C\n" //7262694C Libr "push 0x64616F4C\n" //64616F4C Load "push esp\n" //esp now points to the loadlibraryA API ASCII that we just set on the stack "push _k32\n" //push the k32 base address "call get_eip\n" //we need to know where we are at //so we get our current EIP position "add edx,0x18\n" //add the edx = eip + 0x18 so that we may end up in a NOP SLED //without this we sysenter loop "push edx\n" //this is our sysenter return to stack address "lea ebp,[esp+0x1C]\n" //make sure our EBP points to the prior stack frame //RETURN from Xsys.00401290 to Xsys.004011E7 //completely seperate of the sysenter return we just pushed "push [_getproc]\n" //push the GetProcADdress API "mov edx,esp\n" //SYSENTER requires up to use this esp into edx //here the esp holds our GetPRoc API that we just pushed to stack //now edx holds the API address and needs to in order for sysenter //to call it correctly "pop ebp\n" //remove that extra pushed GetProcADdress API value from the stack "sysenter\n" //call the GetProcAddress "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" //NOP SLED!!!! "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "mov _ll,eax\n" //STORE the LoadLibarary Mem Address into variable ll "add esp,0x10\n" //cleanup "push 0x0000004C\n" //0000004C L... "push 0x4C442E4C\n" //4C442E4C L.DL "push 0x4C44544E\n" //4C44544E NTDL "xor eax,eax\n" //here we clear the eax, and i dunno why, but it had to be done.. //did we have to use lea ebp,[esp+0x1C] previously instead of xor eax? //i was too lazy to find out "push esp\n" //esp points to our NTDLL.DLL that we just pushed onto the stack "call get_eip\n" "add edx,0x18\n" "push edx\n" "push [_ll]\n" "mov edx,esp\n" "pop ebp\n" "SYSENTER\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" //NOP SLED!!!! "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "mov _ntdllx,eax\n" //EAX after the call will now hold the ntdll base address set _ntdllx = to eax // [_ntdllx] = 7c90000 [_k32] = 7c80000 "add esp,0x0C\n" //cleanup "mov edi,dword ptr _ntdllx\n" // k32 = edi = eax = Kernel32 BaseAddress "mov eax,dword ptr [eax + 0x3C]\n" // offset to start of PE header "mov edx,dword ptr [eax + 0x78 + edi]\n" // IMAGE_EXPORT_DIRECTORY--->RVA "add edx,edi\n" // IMAGE_EXPORT_DIRECTORY--->VA = edx "mov ecx,dword ptr [edx + 0x18]\n" // ecx = NumberOfNames "mov ebx,dword ptr [edx + 0x20]\n" // ebx = AddressOfNames "add ebx,edi\n" "_Index3:\n" "dec ecx\n" // ecx --- NumberOfNames ???? ---- ???????? "mov esi,dword ptr [ebx + ecx * 4]\n" // Name -- RVA "add esi,edi\n" "cmp dword ptr [esi],0x496C7452\n" //PteG "jnz _Index3\n" "cmp dword ptr [esi + 0x04],0x5574696E\n" //Acor "jnz _Index3\n" "cmp dword ptr [esi + 0x08],0x6F63696E\n" //erdd "jnz _Index3\n" "cmp dword ptr [esi + 0x0C],0x74536564\n" //ss "jnz _Index3\n" "cmp dword ptr [esi + 0x10],0x676E6972\n" //ss "jnz _Index3\n" "cmp word ptr [esi + 0x14],0x5200\n" //ss "jnz _Index3\n" "mov ebx,dword ptr [edx + 0x24]\n" // AddressOfNameOridinals --- ????? "add ebx,edi\n" "mov cx, word ptr [ebx + ecx * 2]\n" "mov ebx,dword ptr [edx + 0x1C]\n" // ebx = AddressOfFunctions "add ebx,edi\n" "mov eax,dword ptr [ebx + ecx * 4]\n" "add eax,edi\n" "mov _rtluni, eax\n" //API ADDRESS TO RtlInitUni "ret\n" //breakpoint for debugging purposes "ret\n" //easy to find a double ret in olly ); //our basic get EIP method asm ( "get_eip:\n" "mov edx, [esp]\n" "ret\n" ); } Edited December 15, 2013 by JMC31337
JMC31337 Posted December 15, 2013 Author Posted December 15, 2013 (edited) Anyone tell me why my RtlIniUnicodeString destination variable needs a [_test+4] in order to formulate a proper UNICODE string on the stack before i try to use SYSENTER to hit that RtlInitUnicodeString API? "mov _rtluni, eax\n" //API ADDRESS TO RtlInitUni "push ebp\n" "mov ebp, esp\n" "sub esp, 0x10\n" "push esi\n" "push 0\n" "push 0x00780074\n" "push 0x00730065\n" "push 0x0074002e\n" "push 0x00580058\n" "push 0x00580074\n" "push 0x00730065\n" "push 0x0074005c\n" "push 0x003A0043\n" "push 0x005C003F\n" "push 0x003F005C\n" "push esp\n" "lea eax,_test\n" "push eax\n" "call [_rtluni]\n" //test call rtl address "push [_test+4]\n" //variable [_test+4] has the copied unicode stringCPU DisasmAddress  Hex dump      Command                  Comments00401466  |.  FF35 28404000 PUSH DWORD PTR DS:[404028]        ; UNICODE "\??\C:\testXXX.testx" CPU DumpAddress  Hex dump                     ASCII00404024  28 00 2A 00 |38 FF 22 00|             (.*.8". here the proper address is 0022FF38 holding the newly copied Unicode string that was pushed on the stack and ran against the Rtl API but it stores an extra 4 bytes: 002A0028 and so in oder to push the 404028 Unicode String on the stack i needed +4why?  PS: Yes this was my first Unicode experience, im a lamer neewbie when it comes to the Unicode Edited December 15, 2013 by JMC31337
deepzero Posted December 15, 2013 Posted December 15, 2013 because RtlInitUnicdoeString's first arguments is a PUNICODE_STRING, ie a pointer to a UNICODE_STRING struct. That struct happens to be 8 bytes long (sizeof(UNICODE_STRING) == 8). Find the struct here:  http://msdn.microsoft.com/en-us/library/ms648420%28v=vs.85%29.aspx Note that such UnicdeStrings may not be null-terminated.
JMC31337 Posted December 16, 2013 Author Posted December 16, 2013 (edited) Thnx DeepZero....  i'm going  for a min:   typedef struct _UNICODE_STRING { USHORT Length;USHORT MaximumLength;PWSTR  Buffer;} UNICODE_STRING, *PUNICODE_STRING;  The RtlInitUnicodeString routine is obsolete and is exported only to support existing driver binaries. Drivers should use the safe-string routines RtlUnicodeStringInit andRtlUnicodeStringInitEx instead.  RtlInitUnicodeString: SourceString [in, optional] A pointer to a null-terminated wide-character string. This string is used to initialize the counted string pointed to by DestinationString.  So because I pushed a Null-terminated string on the stack it knew where the string bytes stopped. Had I used one of the other UnicodeString API I would have to specify that length with the above UNICODE_STRING struct correct; an unsigned short value/variable set to length?  And can you simply use that API to recast a  basic ASCII STRING to UNICODE?  the reason i ask is because i see many exploit vectors when it comes to UNICODE string-length exploits they seem to be setup by their nature as very long. Edited December 16, 2013 by JMC31337
JMC31337 Posted December 16, 2013 Author Posted December 16, 2013 (edited) and heres the sysenter portion: //http://www.cnblogs.com/cfas/archive/2013/05/31.html /* Typedef Definition CHAR char PSTR or LPSTR char* PCSTR or LPCSTR const char* PWSTR or LPWSTR wchar_t* PCWSTR or LPCWSTR const wchar_t* */ #define DWORD unsigned long #define WORD unsigned short #define BOOL unsigned long #define PSTR const char* #define PWSTR wchar_t* #define PCSTR const char* DWORD getproc; //GetProcAddress mem address DWORD ll; //LoadLib mem address DWORD k32; //kernel32 base address DWORD ntdllx; //ntdll base address DWORD rtluni; //RtlInitUnicodeString address PWSTR NTOSKRNL=L"ntsokrnl.exe"; //char *xnt = "ntoskrnl.exe"; //PWSTR file = L"\\??\\C:\\testXXX.txt"; PWSTR test; char *non_paged_memory; int main() { asm("push ebp"); //setup a new stack frame asm("mov esp,ebp"); //setup a new stack frame asm("xor eax,eax"); //clear eax register asm("xor ebx,ebx"); //clear ebx register asm("xor ecx,ecx"); //clear ecx register asm("xor edx,edx"); //clear edx register //GET k32 BaseAddr asm( "mov esi, dword ptr fs:[0]\n" //standard way for use to walk the TEB/PEB table "lodsd\n" "cdq\n" "lodsd\n" //looking for the kernel32.dll base address "@base_loop:\n" //k32 holds the GetProcAddress API "dec eax\n" "cmp dword ptr [eax], 0x00905a4d\n" "jnz @base_loop\n" ); asm( "mov _k32,eax" //now we have our variable _k32 holding the base address //of the kernel32.dll ); asm( "mov edi,dword ptr _k32\n" // k32 = edi = eax = Kernel32 BaseAddress "mov eax,dword ptr [eax + 0x3C]\n" // offset to start of PE header "mov edx,dword ptr [eax + 0x78 + edi]\n" // IMAGE_EXPORT_DIRECTORY--->RVA "add edx,edi\n" // IMAGE_EXPORT_DIRECTORY--->VA = edx "mov ecx,dword ptr [edx + 0x18]\n" // ecx = NumberOfNames "mov ebx,dword ptr [edx + 0x20]\n" // ebx = AddressOfNames "add ebx,edi\n" "_Index:\n" "dec ecx\n" // ecx --- NumberOfNames ???? ---- ???????? "mov esi,dword ptr [ebx + ecx * 4]\n" // Name -- RVA "add esi,edi\n" "cmp dword ptr [esi],0x50746547\n" //PteG "jnz _Index\n" "cmp dword ptr [esi + 0x04],0x41636f72\n" //Acor "jnz _Index\n" "cmp dword ptr [esi + 0x08],0x65726464\n" //erdd "jnz _Index\n" "cmp word ptr [esi + 0x0C],0x7373\n" //ss "jnz _Index\n" "mov ebx,dword ptr [edx + 0x24]\n" // AddressOfNameOridinals --- ????? "add ebx,edi\n" "mov cx, word ptr [ebx + ecx * 2]\n" "mov ebx,dword ptr [edx + 0x1C]\n" // ebx = AddressOfFunctions "add ebx,edi\n" "mov eax,dword ptr [ebx + ecx * 4]\n" "add eax,edi\n" "mov _getproc, eax\n" //API ADDRESS TO GetProcAddress -> getproc variable "pop ebp\n" //clean up "mov ebp,esp\n" //clean up our stack "mov edi,eax\n" //edi held our k32 base address //so now it holds the value of eax //eax = getproc edi now = getproc "push 0x00\n" //00000000 .... "push 0x41797261\n" //41797261 aryA "push 0x7262694C\n" //7262694C Libr "push 0x64616F4C\n" //64616F4C Load "push esp\n" //esp now points to the loadlibraryA API ASCII that we just set on the stack "push _k32\n" //push the k32 base address "call get_eip\n" //we need to know where we are at //so we get our current EIP position "add edx,0x18\n" //add the edx = eip + 0x18 so that we may end up in a NOP SLED //without this we sysenter loop "push edx\n" //this is our sysenter return to stack address "lea ebp,[esp+0x1C]\n" //make sure our EBP points to the prior stack frame //RETURN from Xsys.00401290 to Xsys.004011E7 //completely seperate of the sysenter return we just pushed "push [_getproc]\n" //push the GetProcADdress API "mov edx,esp\n" //SYSENTER requires up to use this esp into edx //here the esp holds our GetPRoc API that we just pushed to stack //now edx holds the API address and needs to in order for sysenter //to call it correctly "pop ebp\n" //remove that extra pushed GetProcADdress API value from the stack "sysenter\n" //call the GetProcAddress "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" //NOP SLED!!!! "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "mov _ll,eax\n" //STORE the LoadLibarary Mem Address into variable ll "add esp,0x10\n" //cleanup "push 0x0000004C\n" //0000004C L... "push 0x4C442E4C\n" //4C442E4C L.DL "push 0x4C44544E\n" //4C44544E NTDL "xor eax,eax\n" //here we clear the eax, and i dunno why, but it had to be done.. //did we have to use lea ebp,[esp+0x1C] previously instead of xor eax? //i was too lazy to find out "push esp\n" //esp points to our NTDLL.DLL that we just pushed onto the stack "call get_eip\n" "add edx,0x18\n" "push edx\n" "push [_ll]\n" "mov edx,esp\n" "pop ebp\n" "SYSENTER\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" //NOP SLED!!!! "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "mov _ntdllx,eax\n" //EAX after the call will now hold the ntdll base address set _ntdllx = to eax // [_ntdllx] = 7c90000 [_k32] = 7c80000 "add esp,0x0C\n" //cleanup "mov edi,dword ptr _ntdllx\n" // k32 = edi = eax = Kernel32 BaseAddress "mov eax,dword ptr [eax + 0x3C]\n" // offset to start of PE header "mov edx,dword ptr [eax + 0x78 + edi]\n" // IMAGE_EXPORT_DIRECTORY--->RVA "add edx,edi\n" // IMAGE_EXPORT_DIRECTORY--->VA = edx "mov ecx,dword ptr [edx + 0x18]\n" // ecx = NumberOfNames "mov ebx,dword ptr [edx + 0x20]\n" // ebx = AddressOfNames "add ebx,edi\n" "_Index3:\n" "dec ecx\n" // ecx --- NumberOfNames ???? ---- ???????? "mov esi,dword ptr [ebx + ecx * 4]\n" // Name -- RVA "add esi,edi\n" "cmp dword ptr [esi],0x496C7452\n" //PteG "jnz _Index3\n" "cmp dword ptr [esi + 0x04],0x5574696E\n" //Acor "jnz _Index3\n" "cmp dword ptr [esi + 0x08],0x6F63696E\n" //erdd "jnz _Index3\n" "cmp dword ptr [esi + 0x0C],0x74536564\n" //ss "jnz _Index3\n" "cmp dword ptr [esi + 0x10],0x676E6972\n" //ss "jnz _Index3\n" "cmp word ptr [esi + 0x14],0x5200\n" //ss "jnz _Index3\n" "mov ebx,dword ptr [edx + 0x24]\n" // AddressOfNameOridinals --- ????? "add ebx,edi\n" "mov cx, word ptr [ebx + ecx * 2]\n" "mov ebx,dword ptr [edx + 0x1C]\n" // ebx = AddressOfFunctions "add ebx,edi\n" "mov eax,dword ptr [ebx + ecx * 4]\n" "add eax,edi\n" "mov _rtluni, eax\n" //API ADDRESS TO RtlInitUni "push ebp\n" "mov ebp, esp\n" "sub esp, 0x10\n" "push esi\n" "push 0\n" "push 0x00780074\n" "push 0x00730065\n" "push 0x0074002e\n" "push 0x00580058\n" "push 0x00580074\n" "push 0x00730065\n" "push 0x0074005c\n" "push 0x003A0043\n" "push 0x005C003F\n" "push 0x003F005C\n" "push esp\n" "lea eax,_test\n" "push eax\n" "call get_eip\n" "add edx,0x18\n" "push edx\n" "push [_rtluni]\n" "mov edx,esp\n" "pop ebp\n" "SYSENTER\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" //NOP SLED!!!! "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" //"call [_rtluni]\n" //test call rtl address //variable [_test+4] has the copied unicode string "ret\n" //breakpoint for debugging purposes "ret\n" //easy to find a double ret in olly ); //our basic get EIP method asm ( "get_eip:\n" "mov edx, [esp]\n" "ret\n" ); }ZwCreateFile and this is over... (we knew it wasnt an exploit for the beginning)maybe a separate thread for some of the ideas spawned from this thread would be cool to try Edited December 16, 2013 by JMC31337
JMC31337 Posted December 18, 2013 Author Posted December 18, 2013 (edited) okay so after an hour in front of Ollydbg, finally fig'd out how to setup proper structure blocks: of course this will all be trimmed down and typedefs removed... etc etc... the structure is between FFFFFFFF chunks (maybe i dont have to push FF's but i did as thats how olly showed it to be)and all that needs to be done is aim the memory address (for the structure) to the first parameter of the structure and i guess the system does the rest for us, like loading all the values of the structure that needs to be loaded, as it does here for OBJECT_ATTRIBUTES  (the first FFFFFFFF to FFFFFFFF  chunk of data) and again thnx to deepzero for explaining that +4 question i had above...    "because RtlInitUnicdoeString's first arguments is a PUNICODE_STRING, ie a pointer to a UNICODE_STRING struct. That struct happens to be 8 bytes long (sizeof(UNICODE_STRING) == 8). Find the struct here:" we dont want the [edx+4] when it comes time to setup the OBJECT_ATTRIBUTES with the UNICODE filename and pathwe will want to use the [edx]  pointer to the unicode filename/path #include <windows.h> #include <stdio.h> #include <stdlib.h> typedef unsigned long ULONG; typedef unsigned long DWORD; typedef struct _IO_STATUS_BLOCK{ DWORD Status; ULONG Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; IO_STATUS_BLOCK IoStatusBlock; typedef struct UNICODE_STRING{ USHORT Length; USHORT MaxLen; USHORT *Buffer; } UNICODE_STRING,*PUNICODE_STRING; typedef VOID (__stdcall *RTLINITUNICODESTRING)( IN OUT PUNICODE_STRING DestinationString, IN PCWSTR SourceString); void *hfile; int main() { HINSTANCE hNtDll; hNtDll = LoadLibrary ("ntdll"); RTLINITUNICODESTRING RtlInitUnicodeString; UNICODE_STRING ObjectName; RtlInitUnicodeString = (RTLINITUNICODESTRING)GetProcAddress (hNtDll,"RtlInitUnicodeString"); RtlInitUnicodeString(&ObjectName,L"\\??\\C:\\testXXX.testx"); asm ( "add esp,0x1c\n" "push 0xFFFFFFFF\n" //CHUNK OF OBJ_ATTRIBS STRUCT DATA "push 0x0\n" "push 0x0\n" "push 0x40\n" "push 0x0022FF68\n" "push 0x0\n" "push 0x18\n" "push 0xFFFFFFFF\n" //CHUNK OF OBJ_ATTRIB STRUCT DATA "push 0xFFFFFFFF\n" "push 0x0\n" "push 0x0\n" "push 0x40\n" "push 0x05\n" "push 0x02\n" "push 0x80\n" "push 0x0\n" "lea eax, [_IoStatusBlock]\n" "push eax\n" "push 0x0022FF40\n" //<------FIRST PARAM OF OBJ_ATTRIB STRUCT DATA "push 0x10000000\n" "lea eax, [_hfile]\n" "push eax\n" "mov eax,0x7C90D0AE\n" "call eax\n" ); return 0; }IOSTATUS_BLOCKS.. gonna need to take a look at that in more depth Edited December 18, 2013 by JMC31337
JMC31337 Posted December 19, 2013 Author Posted December 19, 2013 (edited) finally done... true no ntoskrnl kernel APi are being used but maybe someday ill get around to trying to load a sys driver as generic flash and etc etc ... this doesnt cleanly exit because i was too lazy...  THIS CREATES A 0-BYTE FILE on the C:\ drive as testxxx.testx  and Ultimately, in order to avoid that IO_STATUS_BLOCK i somehow get away with casting the IO_STATUS_BLOCK structure as a void *  (pointer) /* Typedef Definition CHAR char PSTR or LPSTR char* PCSTR or LPCSTR const char* PWSTR or LPWSTR wchar_t* PCWSTR or LPCWSTR const wchar_t* */ #define DWORD unsigned long #define WORD unsigned short #define BOOL unsigned long #define PSTR const char* #define PWSTR wchar_t* #define PCSTR const char* DWORD getproc; //GetProcAddress mem address DWORD ll; //LoadLib mem address DWORD k32; //kernel32 base address DWORD ntdllx; //ntdll base address DWORD rtluni; //RtlInitUnicodeString address DWORD zwcf; void *hfile2; PWSTR test; int main() { asm("push ebp"); //setup a new stack frame asm("mov esp,ebp"); //setup a new stack frame asm("xor eax,eax"); //clear eax register asm("xor ebx,ebx"); //clear ebx register asm("xor ecx,ecx"); //clear ecx register asm("xor edx,edx"); //clear edx register //GET k32 BaseAddr asm( "mov esi, dword ptr fs:[0]\n" //standard way for use to walk the TEB/PEB table "lodsd\n" "cdq\n" "lodsd\n" //looking for the kernel32.dll base address "@base_loop:\n" //k32 holds the GetProcAddress API "dec eax\n" "cmp dword ptr [eax], 0x00905a4d\n" "jnz @base_loop\n" ); asm( "mov _k32,eax" //now we have our variable _k32 holding the base address //of the kernel32.dll ); asm( "mov edi,dword ptr _k32\n" // k32 = edi = eax = Kernel32 BaseAddress "mov eax,dword ptr [eax + 0x3C]\n" // offset to start of PE header "mov edx,dword ptr [eax + 0x78 + edi]\n" // IMAGE_EXPORT_DIRECTORY--->RVA "add edx,edi\n" // IMAGE_EXPORT_DIRECTORY--->VA = edx "mov ecx,dword ptr [edx + 0x18]\n" // ecx = NumberOfNames "mov ebx,dword ptr [edx + 0x20]\n" // ebx = AddressOfNames "add ebx,edi\n" "_Index:\n" "dec ecx\n" // ecx --- NumberOfNames ???? ---- ???????? "mov esi,dword ptr [ebx + ecx * 4]\n" // Name -- RVA "add esi,edi\n" "cmp dword ptr [esi],0x50746547\n" //PteG "jnz _Index\n" "cmp dword ptr [esi + 0x04],0x41636f72\n" //Acor "jnz _Index\n" "cmp dword ptr [esi + 0x08],0x65726464\n" //erdd "jnz _Index\n" "cmp word ptr [esi + 0x0C],0x7373\n" //ss "jnz _Index\n" "mov ebx,dword ptr [edx + 0x24]\n" // AddressOfNameOridinals --- ????? "add ebx,edi\n" "mov cx, word ptr [ebx + ecx * 2]\n" "mov ebx,dword ptr [edx + 0x1C]\n" // ebx = AddressOfFunctions "add ebx,edi\n" "mov eax,dword ptr [ebx + ecx * 4]\n" "add eax,edi\n" "mov _getproc, eax\n" //API ADDRESS TO GetProcAddress -> getproc variable "pop ebp\n" //clean up "mov ebp,esp\n" //clean up our stack "mov edi,eax\n" //edi held our k32 base address //so now it holds the value of eax //eax = getproc edi now = getproc "push 0x00\n" //00000000 .... "push 0x41797261\n" //41797261 aryA "push 0x7262694C\n" //7262694C Libr "push 0x64616F4C\n" //64616F4C Load "push esp\n" //esp now points to the loadlibraryA API ASCII that we just set on the stack "push _k32\n" //push the k32 base address "call get_eip\n" //we need to know where we are at //so we get our current EIP position "add edx,0x18\n" //add the edx = eip + 0x18 so that we may end up in a NOP SLED //without this we sysenter loop "push edx\n" //this is our sysenter return to stack address "lea ebp,[esp+0x1C]\n" //make sure our EBP points to the prior stack frame //RETURN from Xsys.00401290 to Xsys.004011E7 //completely seperate of the sysenter return we just pushed "push [_getproc]\n" //push the GetProcADdress API "mov edx,esp\n" //SYSENTER requires up to use this esp into edx //here the esp holds our GetPRoc API that we just pushed to stack //now edx holds the API address and needs to in order for sysenter //to call it correctly "pop ebp\n" //remove that extra pushed GetProcADdress API value from the stack "sysenter\n" //call the GetProcAddress "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" //NOP SLED!!!! "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "mov _ll,eax\n" //STORE the LoadLibarary Mem Address into variable ll "add esp,0x10\n" //cleanup "push 0x0000004C\n" //0000004C L... "push 0x4C442E4C\n" //4C442E4C L.DL "push 0x4C44544E\n" //4C44544E NTDL "xor eax,eax\n" //here we clear the eax, and i dunno why, but it had to be done.. //did we have to use lea ebp,[esp+0x1C] previously instead of xor eax? //i was too lazy to find out "push esp\n" //esp points to our NTDLL.DLL that we just pushed onto the stack "call get_eip\n" "add edx,0x18\n" "push edx\n" "push [_ll]\n" "mov edx,esp\n" "pop ebp\n" "SYSENTER\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" //NOP SLED!!!! "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "mov _ntdllx,eax\n" //EAX after the call will now hold the ntdll base address set _ntdllx = to eax // [_ntdllx] = 7c90000 [_k32] = 7c80000 "add esp,0x0C\n" //cleanup "mov edi,dword ptr _ntdllx\n" // k32 = edi = eax = Kernel32 BaseAddress "mov eax,dword ptr [eax + 0x3C]\n" // offset to start of PE header "mov edx,dword ptr [eax + 0x78 + edi]\n" // IMAGE_EXPORT_DIRECTORY--->RVA "add edx,edi\n" // IMAGE_EXPORT_DIRECTORY--->VA = edx "mov ecx,dword ptr [edx + 0x18]\n" // ecx = NumberOfNames "mov ebx,dword ptr [edx + 0x20]\n" // ebx = AddressOfNames "add ebx,edi\n" "_Index3:\n" "dec ecx\n" // ecx --- NumberOfNames ???? ---- ???????? "mov esi,dword ptr [ebx + ecx * 4]\n" // Name -- RVA "add esi,edi\n" "cmp dword ptr [esi],0x496C7452\n" //IltR "jnz _Index3\n" "cmp dword ptr [esi + 0x04],0x5574696E\n" //Utin "jnz _Index3\n" "cmp dword ptr [esi + 0x08],0x6F63696E\n" //ocin "jnz _Index3\n" "cmp dword ptr [esi + 0x0C],0x74536564\n" //Sedo "jnz _Index3\n" "cmp dword ptr [esi + 0x10],0x676E6972\n" //nirt "jnz _Index3\n" "cmp word ptr [esi + 0x14],0x5200\n" //G "jnz _Index3\n" "mov ebx,dword ptr [edx + 0x24]\n" // AddressOfNameOridinals --- ????? "add ebx,edi\n" "mov cx, word ptr [ebx + ecx * 2]\n" "mov ebx,dword ptr [edx + 0x1C]\n" // ebx = AddressOfFunctions "add ebx,edi\n" "mov eax,dword ptr [ebx + ecx * 4]\n" "add eax,edi\n" "mov _rtluni, eax\n" //API ADDRESS TO RtlInitUni "push ebp\n" "mov ebp, esp\n" "sub esp, 0x10\n" "push esi\n" "push 0\n" "push 0x00780074\n" "push 0x00730065\n" "push 0x0074002e\n" "push 0x00580058\n" "push 0x00580074\n" // \\??\\C:\\testXXX.txt "push 0x00730065\n" "push 0x0074005c\n" "push 0x003A0043\n" "push 0x005C003F\n" "push 0x003F005C\n" "push esp\n" "lea eax,_test\n" "push eax\n" "call get_eip\n" "add edx,0x18\n" "push edx\n" "push [_rtluni]\n" "mov edx,esp\n" "pop ebp\n" "SYSENTER\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" //NOP SLED!!!! "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" "nop\n" //"call [_rtluni]\n" //test call rtl address //"push [_test+4]\n" //variable [_test+4] has the copied unicode string "add esp,0x60\n" //================================================== //OBTAIN THAT ZwCreateFile Mem Address "mov eax,edi\n" "mov edi,[_ntdllx]\n" // edi = NtDLL BaseAddress "mov eax,dword ptr [eax + 0x3C]\n" // offset to start of PE header "mov edx,dword ptr [eax + 0x78 + edi]\n" // IMAGE_EXPORT_DIRECTORY--->RVA "add edx,edi\n" // IMAGE_EXPORT_DIRECTORY--->VA = edx "mov ecx,dword ptr [edx + 0x18]\n" // ecx = NumberOfNames "mov ebx,dword ptr [edx + 0x20]\n" // ebx = AddressOfNames "add ebx,edi\n" "_Index4:\n" "dec ecx\n" // ecx --- NumberOfNames ???? ---- ???????? "mov esi,dword ptr [ebx + ecx * 4]\n" // Name -- RVA "add esi,edi\n" "cmp dword ptr [esi + 0x00],0x7243775A\n" //rCwZ "jnz _Index4\n" "cmp dword ptr [esi + 0x04],0x65746165\n" //etae "jnz _Index4\n" "cmp dword ptr [esi + 0x08],0x656c6946\n" //eliF "jnz _Index4\n" "cmp byte ptr [esi + 0x0C],0x00\n" // "jnz _Index4\n" "mov ebx,dword ptr [edx + 0x24]\n" // AddressOfNameOridinals --- ????? "add ebx,edi\n" "mov cx, word ptr [ebx + ecx * 2]\n" "mov ebx,dword ptr [edx + 0x1C]\n" // ebx = AddressOfFunctions "add ebx,edi\n" "mov eax,dword ptr [ebx + ecx * 4]\n" "add eax,edi\n" "mov _zwcf,eax\n" //zwcreatefile mem adddress = [_zwcf] "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "pop ebp\n" "push [_test+4]\n" "push [_test]\n" //our OBJECT_ATTRIBUTES structure (Rohitab Cheetah!) "push 0xFFFFFFFF\n" "push 0x0\n" "push 0x0\n" "push 0x40\n" "lea eax, [esp+0x10]\n" "push eax\n" "push 0x0\n" "push 0x18\n" "push 0xFFFFFFFF\n" "push 0xFFFFFFFF\n" "push 0x0\n" "push 0x0\n" "push 0x40\n" "push 0x05\n" "push 0x02\n" "push 0x80\n" "push 0x0\n" "lea eax, [_hfile2]\n" //for some reason IO_STATUS_BLOCK STRUCT can be the VOID *hfile //interesting and clever trick to avoid setting the // IO_STATUS_BLOCK typedefs and structs "push eax\n" "lea eax, [esp+0x28]\n" "push eax\n" "push 0x10000000\n" "lea eax, [_hfile2]\n" "push eax\n" "call get_eip\n" "mov eax,edx\n" "push eax\n" "xor eax,eax\n" "push [_zwcf]\n" "mov edx,esp\n" "pop ebp\n" "sysenter\n" "ret\n" //breakpoint for debugging purposes "ret\n" //easy to find a double ret in olly ); //our basic get EIP method asm ( "get_eip:\n" "mov edx, [esp]\n" "ret\n" ); } ohh and btw! one other call is that get_eip  function... so i didnt really achieve a 100 over 100 as i wanted.. more of a 95% for using that gimmick get_eip  PS: thnx to Russia and China as they were the only countries that actually had anything on the complexities of the ZwCreateFile in assembly ... Edited December 19, 2013 by JMC31337
JMC31337 Posted December 21, 2013 Author Posted December 21, 2013 (edited) To conclude all of this: Loading drivers and Native applications from kernel mode, without touching registry  http://www.nvlabs.in/index.php?/archives/6-Loading-drivers-and-Native-applications-from-kernel-mode,-without-touching-registry.html  true, you'll need "admin" privs to load any drivers up or mess with any services" but this is handy info to have and learn nonetheless...(picked up a few trial evaluation ISO of XP VISTA WIN7 and 2003 Enterprise ISO to use under vmware; which is a great testing ground for just about anything, including breaking out of virtualized environments)  this is a great site to get all of those old versions of windows ISO to load into vmware http://winworldpc.com/library_m2.shtml Edited December 21, 2013 by JMC31337
JMC31337 Posted December 28, 2013 Author Posted December 28, 2013 (edited) Probably because they default to the industry standard protocol to be compliant. The drivers are likely for accessing custom features and firmware... Â Ted. Â yup you're right... Overview of the Driver Selection Process http://msdn.microsoft.com/en-us/library/ff549553.aspx Edited December 28, 2013 by JMC31337
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now